CmRTTIField.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #pragma once
  2. #include <string>
  3. #include <boost/function.hpp>
  4. #include <boost/any.hpp>
  5. #include <boost/static_assert.hpp>
  6. #include "CmPrerequisitesUtil.h"
  7. #include "CmIReflectable.h"
  8. #include "CmManagedDataBlock.h"
  9. #include "CmException.h"
  10. namespace CamelotEngine
  11. {
  12. class RTTITypeBase;
  13. struct RTTIField;
  14. template<class T>
  15. struct SerializableSimpleType
  16. {
  17. //BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, // We need this hacky check, otherwise if we only use "false" compiler will evaluate the template and trigger this message
  18. // "Provided data type isn't marked as serializable. Declare SerializableSimpleType template specialization to define a unique ID and needed methods for the type.");
  19. enum { id = 0 };
  20. enum { hasDynamicSize = 0 };
  21. static void toMemory(T& data, char* memory)
  22. {
  23. memcpy(memory, &data, sizeof(T));
  24. }
  25. static void fromMemory(T& data, char* memory)
  26. {
  27. memcpy(&data, memory, sizeof(T));
  28. }
  29. static UINT32 getDynamicSize(T& data)
  30. {
  31. assert(false);
  32. return sizeof(T);
  33. }
  34. };
  35. #define CM_SERIALIZABLE_SIMPLE_TYPE(type, type_id) \
  36. template<> struct SerializableSimpleType<##type##> \
  37. { enum { id=##type_id }; enum { hasDynamicSize = 0 }; \
  38. static void toMemory(##type##& data, char* memory) \
  39. { memcpy(memory, &data, sizeof(##type##)); } \
  40. static void fromMemory(##type##& data, char* memory) \
  41. { memcpy(&data, memory, sizeof(##type##)); } \
  42. static UINT32 getDynamicSize(##type##& data) \
  43. { assert(false); return sizeof(##type##); } \
  44. };
  45. CM_SERIALIZABLE_SIMPLE_TYPE(UINT8, 1);
  46. CM_SERIALIZABLE_SIMPLE_TYPE(UINT16, 2);
  47. CM_SERIALIZABLE_SIMPLE_TYPE(UINT32, 3);
  48. CM_SERIALIZABLE_SIMPLE_TYPE(UINT64, 4);
  49. CM_SERIALIZABLE_SIMPLE_TYPE(INT8, 5);
  50. CM_SERIALIZABLE_SIMPLE_TYPE(INT16, 6);
  51. CM_SERIALIZABLE_SIMPLE_TYPE(INT32, 7);
  52. CM_SERIALIZABLE_SIMPLE_TYPE(INT64, 8);
  53. CM_SERIALIZABLE_SIMPLE_TYPE(float, 9);
  54. CM_SERIALIZABLE_SIMPLE_TYPE(double, 10);
  55. CM_SERIALIZABLE_SIMPLE_TYPE(bool, 11);
  56. /**
  57. * @brief Strings need to copy their data in a slightly more intricate way than just memcpy.
  58. */
  59. template<> struct SerializableSimpleType<String>
  60. {
  61. enum { id = 20 }; enum { hasDynamicSize = 1 };
  62. static void toMemory(String& data, char* memory)
  63. {
  64. UINT32 size = getDynamicSize(data);
  65. memcpy(memory, &size, sizeof(UINT32));
  66. memory += sizeof(UINT32);
  67. memcpy(memory, data.data(), size);
  68. }
  69. static void fromMemory(String& data, char* memory)
  70. {
  71. UINT32 size;
  72. memcpy(&size, memory, sizeof(UINT32));
  73. memory += sizeof(UINT32);
  74. size -= sizeof(UINT32);
  75. char* buffer = new char[size + 1]; // TODO - Use a better allocator
  76. memcpy(buffer, memory, size);
  77. buffer[size] = '\0';
  78. data = String(buffer);
  79. delete[] buffer;
  80. }
  81. static UINT32 getDynamicSize(String& data)
  82. {
  83. UINT64 dataSize = data.size() * sizeof(String::value_type) + sizeof(UINT32);
  84. #if CM_DEBUG_MODE
  85. if(dataSize > std::numeric_limits<UINT32>::max())
  86. {
  87. CM_EXCEPT(InternalErrorException, "Data overflow! Size doesn't fit into 32 bits.");
  88. }
  89. #endif
  90. return (UINT32)dataSize;
  91. }
  92. };
  93. /**
  94. * @brief Types of fields we can serialize:
  95. *
  96. * - Simple - Native data types, POD (Plain old data) structures, or in general types we don't want to (or can't) inherit from IReflectable.
  97. *
  98. * - DataBlock - Array of bytes of a certain size. When returning a data block you may specify if its managed or unmanaged.
  99. * Managed data blocks have their buffers deleted after they go out of scope. This is useful if you need to return some
  100. * temporary data. On the other hand if the data in the block belongs to your class, and isn't temporary, keep the data unmanaged.
  101. *
  102. * - Complex - Field that is of IReflectable type. Cannot be a pointer to IReflectable and must be actual value type.
  103. *
  104. * - ComplexPtr - A pointer to IReflectable.
  105. */
  106. enum SerializableFieldType
  107. {
  108. SerializableFT_Plain,
  109. SerializableFT_DataBlock,
  110. SerializableFT_Reflectable,
  111. SerializableFT_ReflectablePtr
  112. };
  113. /**
  114. * @brief Structure that keeps meta-data concerning a single class field.
  115. */
  116. struct CM_UTILITY_EXPORT RTTIField
  117. {
  118. boost::any valueGetter;
  119. boost::any valueSetter;
  120. boost::any arraySizeGetter;
  121. boost::any arraySizeSetter;
  122. std::string mName;
  123. UINT16 mUniqueId;
  124. bool mIsVectorType;
  125. SerializableFieldType mType;
  126. bool isSimpleType() { return mType == SerializableFT_Plain; }
  127. bool isDataBlockType() { return mType == SerializableFT_DataBlock; }
  128. bool isComplexType() { return mType == SerializableFT_Reflectable; }
  129. bool isComplexPtrType() { return mType == SerializableFT_ReflectablePtr; }
  130. virtual UINT32 getArraySize(void* object) = 0;
  131. virtual void setArraySize(void* object, UINT32 size) = 0;
  132. virtual UINT32 getTypeSize() = 0;
  133. virtual bool hasDynamicSize() = 0;
  134. /**
  135. * @brief Throws an exception if this field doesn't contain a simple value.
  136. *
  137. * @param array If true then the field must support simple array types.
  138. */
  139. void checkIsSimple(bool array);
  140. /**
  141. * @brief Throws an exception if this field doesn't contain a complex value.
  142. *
  143. * @param array If true then the field must support complex array types.
  144. */
  145. void checkIsComplex(bool array);
  146. /**
  147. * @brief Throws an exception if this field doesn't contain a complex pointer value.
  148. *
  149. * @param array If true then the field must support complex array types.
  150. */
  151. void checkIsComplexPtr(bool array);
  152. /**
  153. * @brief Throws an exception depending if the field is or isn't an array.
  154. *
  155. * @param array If true, then exception will be thrown if field is not an array.
  156. * If false, then it will be thrown if field is an array.
  157. */
  158. void checkIsArray(bool array);
  159. /**
  160. * @brief Throws an exception if this field doesn't contain a data block value.
  161. */
  162. void checkIsDataBlock();
  163. protected:
  164. void initAll(boost::any valueGetter, boost::any valueSetter, boost::any arraySizeGetter, boost::any arraySizeSetter,
  165. std::string mName, UINT16 mUniqueId, bool mIsVectorType, SerializableFieldType type)
  166. {
  167. this->valueGetter = valueGetter;
  168. this->valueSetter = valueSetter;
  169. this->arraySizeGetter = arraySizeGetter;
  170. this->arraySizeSetter = arraySizeSetter;
  171. this->mName = mName;
  172. this->mUniqueId = mUniqueId;
  173. this->mIsVectorType = mIsVectorType;
  174. this->mType = type;
  175. }
  176. };
  177. }