BsRTTIPlainField.h 11 KB

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