CmRTTIField.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #pragma once
  2. #include <string>
  3. #include <boost/function.hpp>
  4. #include <boost/any.hpp>
  5. #include <boost/static_assert.hpp>
  6. #include <type_traits>
  7. #include "CmPrerequisitesUtil.h"
  8. #include "CmIReflectable.h"
  9. #include "CmManagedDataBlock.h"
  10. #include "CmException.h"
  11. namespace CamelotFramework
  12. {
  13. class RTTITypeBase;
  14. struct RTTIField;
  15. /**
  16. * @brief Types of fields we can serialize:
  17. *
  18. * - Plain - Native data types, POD (Plain old data) structures, or in general types we don't want to (or can't) inherit from IReflectable.
  19. *
  20. * - DataBlock - Array of bytes of a certain size. When returning a data block you may specify if its managed or unmanaged.
  21. * Managed data blocks have their buffers deleted after they go out of scope. This is useful if you need to return some
  22. * temporary data. On the other hand if the data in the block belongs to your class, and isn't temporary, keep the data unmanaged.
  23. *
  24. * - Reflectable - Field that is of IReflectable type. Cannot be a pointer to IReflectable and must be actual value type.
  25. *
  26. * - ReflectablePtr - A pointer to IReflectable.
  27. */
  28. enum SerializableFieldType
  29. {
  30. SerializableFT_Plain,
  31. SerializableFT_DataBlock,
  32. SerializableFT_Reflectable,
  33. SerializableFT_ReflectablePtr
  34. };
  35. /**
  36. * @brief Various flags you can assign to RTTI fields.
  37. */
  38. enum RTTIFieldFlag
  39. {
  40. // This flag is only used on field types of ReflectablePtr type, and it is used
  41. // to solve circular references. Circular references cause an issue when deserializing,
  42. // as the algorithm doesn't know which object to deserialize first. By making one of
  43. // the references weak, you tell the algorithm that it doesn't have to guarantee
  44. // the object will be fully deserialized before being assigned to the field.
  45. //
  46. // In short: If you make a reference weak, when "set" method of that field is called,
  47. // it is not guaranteed the value provided is fully initialized, so you should not access any of its
  48. // data until deserialization is fully complete. You only need to use this flag if the RTTI system
  49. // complains that is has found a circular reference.
  50. RTTI_Flag_WeakRef = 0x01
  51. };
  52. /**
  53. * @brief Structure that keeps meta-data concerning a single class field.
  54. */
  55. struct CM_UTILITY_EXPORT RTTIField
  56. {
  57. boost::any valueGetter;
  58. boost::any valueSetter;
  59. boost::any arraySizeGetter;
  60. boost::any arraySizeSetter;
  61. String mName;
  62. UINT16 mUniqueId;
  63. bool mIsVectorType;
  64. SerializableFieldType mType;
  65. UINT64 mFlags;
  66. bool isPlainType() { return mType == SerializableFT_Plain; }
  67. bool isDataBlockType() { return mType == SerializableFT_DataBlock; }
  68. bool isReflectableType() { return mType == SerializableFT_Reflectable; }
  69. bool isReflectablePtrType() { return mType == SerializableFT_ReflectablePtr; }
  70. UINT64 getFlags() const { return mFlags; }
  71. virtual UINT32 getArraySize(void* object) = 0;
  72. virtual void setArraySize(void* object, UINT32 size) = 0;
  73. virtual UINT32 getTypeSize() = 0;
  74. virtual bool hasDynamicSize() = 0;
  75. /**
  76. * @brief Throws an exception if this field doesn't contain a plain value.
  77. *
  78. * @param array If true then the field must support plain array types.
  79. */
  80. void checkIsPlain(bool array);
  81. /**
  82. * @brief Throws an exception if this field doesn't contain a complex value.
  83. *
  84. * @param array If true then the field must support complex array types.
  85. */
  86. void checkIsComplex(bool array);
  87. /**
  88. * @brief Throws an exception if this field doesn't contain a complex pointer value.
  89. *
  90. * @param array If true then the field must support complex array types.
  91. */
  92. void checkIsComplexPtr(bool array);
  93. /**
  94. * @brief Throws an exception depending if the field is or isn't an array.
  95. *
  96. * @param array If true, then exception will be thrown if field is not an array.
  97. * If false, then it will be thrown if field is an array.
  98. */
  99. void checkIsArray(bool array);
  100. /**
  101. * @brief Throws an exception if this field doesn't contain a data block value.
  102. */
  103. void checkIsDataBlock();
  104. protected:
  105. void initAll(boost::any valueGetter, boost::any valueSetter, boost::any arraySizeGetter, boost::any arraySizeSetter,
  106. String mName, UINT16 mUniqueId, bool mIsVectorType, SerializableFieldType type, UINT64 flags)
  107. {
  108. this->valueGetter = valueGetter;
  109. this->valueSetter = valueSetter;
  110. this->arraySizeGetter = arraySizeGetter;
  111. this->arraySizeSetter = arraySizeSetter;
  112. this->mName = mName;
  113. this->mUniqueId = mUniqueId;
  114. this->mIsVectorType = mIsVectorType;
  115. this->mType = type;
  116. this->mFlags = flags;
  117. }
  118. };
  119. }