BsRTTIPlainField.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #pragma once
  2. #include "BsPrerequisitesUtil.h"
  3. #include "BsRTTIField.h"
  4. #include "BsException.h"
  5. namespace BansheeEngine
  6. {
  7. /** @cond INTERNAL */
  8. /** @addtogroup RTTI
  9. * @{
  10. */
  11. /**
  12. * Base class containing common functionality for a plain class field.
  13. *
  14. * @note
  15. * Plain fields are considered those that may be serialized directly by copying their memory. (All built-in types,
  16. * strings, etc.)
  17. */
  18. struct RTTIPlainFieldBase : public RTTIField
  19. {
  20. /** Throws an exception if the current field type and provided template types don't match. */
  21. template<class DataType>
  22. void checkType()
  23. {
  24. // TODO: Low priority. Because I wanted to get rid of SerializableType I have no way of checking the actual
  25. // type of the field and the type provided to get/set methods matches
  26. /*if(mType.id != SerializableType<DataType>().id)
  27. {
  28. BS_EXCEPT(InternalErrorException,
  29. "Invalid field type.",
  30. "SerializableSimpleTypeFieldBase::checkType()");
  31. }*/
  32. }
  33. /** @copydoc RTTIField::getTypeId */
  34. virtual UINT32 getTypeId()
  35. {
  36. return 0;
  37. }
  38. /** @copydoc RTTIField::hasDynamicSize */
  39. bool hasDynamicSize() override
  40. {
  41. return false;
  42. }
  43. /** Gets the dynamic size of the object. If object has no dynamic size, static size of the object is returned. */
  44. virtual UINT32 getDynamicSize(void* object)
  45. {
  46. return 0;
  47. }
  48. /**
  49. * Gets the dynamic size of an array element. If the element has no dynamic size, static size of the element
  50. * is returned.
  51. */
  52. virtual UINT32 getArrayElemDynamicSize(void* object, int index)
  53. {
  54. return 0;
  55. }
  56. /**
  57. * Retrieves the value from the provided field of the provided object, and copies it into the buffer. It does not
  58. * check if buffer is large enough.
  59. */
  60. virtual void toBuffer(void* object, void* buffer) = 0;
  61. /**
  62. * Retrieves the value at the specified array index on the provided field of the provided object, and copies it into
  63. * the buffer. It does not check if buffer is large enough.
  64. */
  65. virtual void arrayElemToBuffer(void* object, int index, void* buffer) = 0;
  66. /**
  67. * Sets the value on the provided field of the provided object. Value is copied from the buffer. It does not check
  68. * the value in the buffer in any way. You must make sure buffer points to the proper location and contains the
  69. * proper type.
  70. */
  71. virtual void fromBuffer(void* object, void* buffer) = 0;
  72. /**
  73. * Sets the value at the specified array index on the provided field of the provided object. Value is copied from
  74. * the buffer. It does not check the value in the buffer in any way. You must make sure buffer points to the proper
  75. * location and contains the proper type.
  76. */
  77. virtual void arrayElemFromBuffer(void* object, int index, void* buffer) = 0;
  78. };
  79. /** Represents a plain class field containing a specific type. */
  80. template <class DataType, class ObjectType>
  81. struct RTTIPlainField : public RTTIPlainFieldBase
  82. {
  83. /**
  84. * Initializes a plain field containing a single value.
  85. *
  86. * @param[in] name Name of the field.
  87. * @param[in] uniqueId Unique identifier for this field. Although name is also a unique identifier we want a
  88. * small data type that can be used for efficiently serializing data to disk and similar.
  89. * It is primarily used for compatibility between different versions of serialized data.
  90. * @param[in] getter The getter method for the field. Must be a specific signature: DataType(ObjectType*).
  91. * @param[in] setter The setter method for the field. Must be a specific signature: void(ObjectType*, DataType)
  92. * @param[in] flags Various flags you can use to specialize how outside systems handle this field. See "RTTIFieldFlag".
  93. */
  94. void initSingle(const String& name, UINT16 uniqueId, Any getter, Any setter, UINT64 flags)
  95. {
  96. int typeId = RTTIPlainType<DataType>::id; // Just making sure provided type has a type ID
  97. static_assert((RTTIPlainType<DataType>::hasDynamicSize != 0 || (sizeof(DataType) <= 255)),
  98. "Trying to create a plain RTTI field with size larger than 255. In order to use larger sizes for plain types please specialize " \
  99. " RTTIPlainType, set hasDynamicSize to true.");
  100. initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_Plain, flags);
  101. }
  102. /**
  103. * Initializes a plain field containing multiple values in an array.
  104. *
  105. * @param[in] name Name of the field.
  106. * @param[in] uniqueId Unique identifier for this field. Although name is also a unique identifier we want a
  107. * small data type that can be used for efficiently serializing data to disk and similar.
  108. * It is primarily used for compatibility between different versions of serialized data.
  109. * @param[in] getter The getter method for the field. Must be a specific signature: DataType(ObjectType*, UINT32)
  110. * @param[in] getSize Getter method that returns the size of an array. Must be a specific signature: UINT32(ObjectType*)
  111. * @param[in] setter The setter method for the field. Must be a specific signature: void(ObjectType*, UINT32, DataType)
  112. * @param[in] setSize Setter method that allows you to resize an array. Can be null. Must be a specific signature: void(ObjectType*, UINT32)
  113. * @param[in] flags Various flags you can use to specialize how outside systems handle this field. See "RTTIFieldFlag".
  114. */
  115. void initArray(const String& name, UINT16 uniqueId, Any getter,
  116. Any getSize, Any setter, Any setSize, UINT64 flags)
  117. {
  118. int typeId = RTTIPlainType<DataType>::id; // Just making sure provided type has a type ID
  119. static_assert((RTTIPlainType<DataType>::hasDynamicSize != 0 || (sizeof(DataType) <= 255)),
  120. "Trying to create a plain RTTI field with size larger than 255. In order to use larger sizes for plain types please specialize " \
  121. " RTTIPlainType, set hasDynamicSize to true.");
  122. initAll(getter, setter, getSize, setSize, name, uniqueId, true, SerializableFT_Plain, flags);
  123. }
  124. /** @copydoc RTTIField::getTypeSize */
  125. UINT32 getTypeSize() override
  126. {
  127. return sizeof(DataType);
  128. }
  129. /** @copydoc RTTIPlainFieldBase::getTypeId */
  130. UINT32 getTypeId() override
  131. {
  132. return RTTIPlainType<DataType>::id;
  133. }
  134. /** @copydoc RTTIPlainFieldBase::hasDynamicSize */
  135. bool hasDynamicSize() override
  136. {
  137. return RTTIPlainType<DataType>::hasDynamicSize != 0;
  138. }
  139. /** @copydoc RTTIPlainFieldBase::getDynamicSize */
  140. UINT32 getDynamicSize(void* object) override
  141. {
  142. checkIsArray(false);
  143. checkType<DataType>();
  144. ObjectType* castObject = static_cast<ObjectType*>(object);
  145. std::function<DataType&(ObjectType*)> f = any_cast<std::function<DataType&(ObjectType*)>>(valueGetter);
  146. DataType value = f(castObject);
  147. return RTTIPlainType<DataType>::getDynamicSize(value);
  148. }
  149. /** @copydoc RTTIPlainFieldBase::getArrayElemDynamicSize */
  150. UINT32 getArrayElemDynamicSize(void* object, int index) override
  151. {
  152. checkIsArray(true);
  153. checkType<DataType>();
  154. ObjectType* castObject = static_cast<ObjectType*>(object);
  155. std::function<DataType&(ObjectType*, UINT32)> f = any_cast<std::function<DataType&(ObjectType*, UINT32)>>(valueGetter);
  156. DataType value = f(castObject, index);
  157. return RTTIPlainType<DataType>::getDynamicSize(value);
  158. }
  159. /*** @copydoc RTTIPlainField::getArraySize */
  160. UINT32 getArraySize(void* object) override
  161. {
  162. checkIsArray(true);
  163. std::function<UINT32(ObjectType*)> f = any_cast<std::function<UINT32(ObjectType*)>>(arraySizeGetter);
  164. ObjectType* castObject = static_cast<ObjectType*>(object);
  165. return f(castObject);
  166. }
  167. /** @copydoc RTTIPlainField::setArraySize */
  168. void setArraySize(void* object, UINT32 size) override
  169. {
  170. checkIsArray(true);
  171. if(arraySizeSetter.empty())
  172. {
  173. BS_EXCEPT(InternalErrorException, "Specified field (" + mName + ") has no array size setter.");
  174. }
  175. std::function<void(ObjectType*, UINT32)> f = any_cast<std::function<void(ObjectType*, UINT32)>>(arraySizeSetter);
  176. ObjectType* castObject = static_cast<ObjectType*>(object);
  177. f(castObject, size);
  178. }
  179. /** @copydoc RTTIPlainFieldBase::toBuffer */
  180. void toBuffer(void* object, void* buffer) override
  181. {
  182. checkIsArray(false);
  183. checkType<DataType>();
  184. ObjectType* castObject = static_cast<ObjectType*>(object);
  185. std::function<DataType&(ObjectType*)> f = any_cast<std::function<DataType&(ObjectType*)>>(valueGetter);
  186. DataType value = f(castObject);
  187. RTTIPlainType<DataType>::toMemory(value, (char*)buffer);
  188. }
  189. /** @copydoc RTTIPlainFieldBase::arrayElemToBuffer */
  190. void arrayElemToBuffer(void* object, int index, void* buffer) override
  191. {
  192. checkIsArray(true);
  193. checkType<DataType>();
  194. ObjectType* castObject = static_cast<ObjectType*>(object);
  195. std::function<DataType&(ObjectType*, UINT32)> f = any_cast<std::function<DataType&(ObjectType*, UINT32)>>(valueGetter);
  196. DataType value = f(castObject, index);
  197. RTTIPlainType<DataType>::toMemory(value, (char*)buffer);
  198. }
  199. /** @copydoc RTTIPlainFieldBase::fromBuffer */
  200. void fromBuffer(void* object, void* buffer) override
  201. {
  202. checkIsArray(false);
  203. checkType<DataType>();
  204. ObjectType* castObject = static_cast<ObjectType*>(object);
  205. DataType value;
  206. RTTIPlainType<DataType>::fromMemory(value, (char*)buffer);
  207. if(valueSetter.empty())
  208. {
  209. BS_EXCEPT(InternalErrorException,
  210. "Specified field (" + mName + ") has no setter.");
  211. }
  212. std::function<void(ObjectType*, DataType&)> f = any_cast<std::function<void(ObjectType*, DataType&)>>(valueSetter);
  213. f(castObject, value);
  214. }
  215. /** @copydoc RTTIPlainFieldBase::arrayElemFromBuffer */
  216. void arrayElemFromBuffer(void* object, int index, void* buffer) override
  217. {
  218. checkIsArray(true);
  219. checkType<DataType>();
  220. ObjectType* castObject = static_cast<ObjectType*>(object);
  221. DataType value;
  222. RTTIPlainType<DataType>::fromMemory(value, (char*)buffer);
  223. if(valueSetter.empty())
  224. {
  225. BS_EXCEPT(InternalErrorException,
  226. "Specified field (" + mName + ") has no setter.");
  227. }
  228. std::function<void(ObjectType*, UINT32, DataType&)> f = any_cast<std::function<void(ObjectType*, UINT32, DataType&)>>(valueSetter);
  229. f(castObject, index, value);
  230. }
  231. };
  232. /** @} */
  233. /** @endcond */
  234. }