BsManagedSerializableDictionary.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsScriptEnginePrerequisites.h"
  5. #include "Reflection/BsIReflectable.h"
  6. #include "BsMonoArray.h"
  7. namespace bs
  8. {
  9. /** @addtogroup SBansheeEngine
  10. * @{
  11. */
  12. /** Contains key and value data used for serializing a managed dictionary. */
  13. struct BS_SCR_BE_EXPORT ManagedSerializableDictionaryKeyValue : public IReflectable
  14. {
  15. ManagedSerializableDictionaryKeyValue() {}
  16. ManagedSerializableDictionaryKeyValue(const SPtr<ManagedSerializableFieldData>& key,
  17. const SPtr<ManagedSerializableFieldData>& value);
  18. SPtr<ManagedSerializableFieldData> key;
  19. SPtr<ManagedSerializableFieldData> value;
  20. /************************************************************************/
  21. /* RTTI */
  22. /************************************************************************/
  23. public:
  24. friend class ManagedSerializableDictionaryKeyValueRTTI;
  25. static RTTITypeBase* getRTTIStatic();
  26. RTTITypeBase* getRTTI() const override;
  27. };
  28. /**
  29. * Allows access to an underlying managed dictionary, or a cached version of that dictionary that can be
  30. * serialized/deserialized.
  31. *
  32. * @note
  33. * This class can be in two states:
  34. * - Linked - When the object has a link to a managed object. This is the default state when a new instance
  35. * of ManagedSerializableDictionary is created. Any operations during this state will operate directly
  36. * on the linked managed object. A GC handle will be kept to the linked managed object. The handle can
  37. * be freed by transfering to serialized mode or by destroying this object.
  38. * - Serialized - When the object has no link to the managed object but instead just contains cached object
  39. * and field data that may be used for initializing a managed object. Any operations during
  40. * this state will operate only on the cached internal data.
  41. *
  42. * You can transfer an object in linked state to serialized state by calling serialize(). If an object is in serialized
  43. * state you can call deserialize() to populated a managed object from the cached data.
  44. */
  45. class BS_SCR_BE_EXPORT ManagedSerializableDictionary : public IReflectable
  46. {
  47. private:
  48. struct ConstructPrivately {};
  49. /** Generates a hash value for field data. */
  50. struct BS_SCR_BE_EXPORT Hash
  51. {
  52. inline size_t operator()(const SPtr<ManagedSerializableFieldData>& x) const;
  53. };
  54. /** Compares two field data objects. */
  55. struct BS_SCR_BE_EXPORT Equals
  56. {
  57. inline bool operator()(const SPtr<ManagedSerializableFieldData>& a, const SPtr<ManagedSerializableFieldData>& b) const;
  58. };
  59. public:
  60. typedef UnorderedMap<SPtr<ManagedSerializableFieldData>, SPtr<ManagedSerializableFieldData>> CachedEntriesMap;
  61. /**
  62. * Helper class that enumerates over all entires in a managed dictionary. Operates on managed object if the parent
  63. * dictionary is in linked state, or on cached data otherwise.
  64. */
  65. class Enumerator
  66. {
  67. public:
  68. /**
  69. * Constructs a new enumerator for a managed dictionary.
  70. *
  71. * @param[in] parent Owning dictionary object.
  72. */
  73. Enumerator(const ManagedSerializableDictionary* parent);
  74. Enumerator(const Enumerator& other);
  75. ~Enumerator();
  76. Enumerator& operator=(const Enumerator& other);
  77. /**
  78. * Returns the wrapped key data at the current enumerator position. Only valid to call this if enumerator is
  79. * valid (meaning last call to moveNext() returned true).
  80. */
  81. SPtr<ManagedSerializableFieldData> getKey() const;
  82. /**
  83. * Returns the wrapped value data at the current enumerator position. Only valid to call this if enumerator is
  84. * valid (meaning last call to moveNext() returned true).
  85. */
  86. SPtr<ManagedSerializableFieldData> getValue() const;
  87. /**
  88. * Moves the enumerator to the next position. Initially enumerator is at an invalid position and must be called
  89. * at least once before accesing its data.
  90. *
  91. * @return Returns if the enumerator is at valid position. When the enumerator returns false it means there are
  92. * no more elements to enumerate.
  93. */
  94. bool moveNext();
  95. private:
  96. uint32_t mKeysArrayHandle = 0;
  97. uint32_t mValuesArrayHandle = 0;
  98. UINT32 mNumEntries = 0;
  99. UINT32 mCurrentIdx = (UINT32)-1;
  100. ::MonoClass* mKeyType = nullptr;
  101. ::MonoClass* mValueType = nullptr;
  102. CachedEntriesMap::const_iterator mCachedIter;
  103. bool mIteratorInitialized;
  104. const ManagedSerializableDictionary* mParent;
  105. };
  106. public:
  107. ManagedSerializableDictionary(const ConstructPrivately& dummy,
  108. const SPtr<ManagedSerializableTypeInfoDictionary>& typeInfo, MonoObject* managedInstance);
  109. ManagedSerializableDictionary(const ConstructPrivately& dummy);
  110. ~ManagedSerializableDictionary();
  111. /**
  112. * Returns the internal managed instance of the dictionary. This will return null if the object is in serialized
  113. * mode.
  114. */
  115. MonoObject* getManagedInstance() const;
  116. /** Returns the type information for the internal dictionary. */
  117. SPtr<ManagedSerializableTypeInfoDictionary> getTypeInfo() const { return mDictionaryTypeInfo; }
  118. /**
  119. * Returns the dictionary value at the specified key. If the key doesn't exist the default value for the type is
  120. * returned. Operates on managed object if in linked state, or on cached data otherwise.
  121. *
  122. * @param[in] key Wrapper around the key data at which to retrieve the value.
  123. * @return A wrapper around the value in the dictionary at the specified key.
  124. */
  125. SPtr<ManagedSerializableFieldData> getFieldData(const SPtr<ManagedSerializableFieldData>& key);
  126. /**
  127. * Sets the dictionary value at the specified key. Operates on managed object if in linked state, or on cached data
  128. * otherwise.
  129. *
  130. * @param[in] key Wrapper around the key data at which to set the value.
  131. * @param[in] val Wrapper around the value to set at the specified key.
  132. */
  133. void setFieldData(const SPtr<ManagedSerializableFieldData>& key, const SPtr<ManagedSerializableFieldData>& val);
  134. /**
  135. * Deletes the key/value pair at the specified key. If the key doesn't exist this operation does nothing. Operates
  136. * on managed object if in linked state, or on cached data otherwise.
  137. *
  138. * @param[in] key Wrapper around the key data at which to delete the value.
  139. */
  140. void removeFieldData(const SPtr<ManagedSerializableFieldData>& key);
  141. /**
  142. * Checks if the dictionary contains the specified key. Operates on managed object if in linked state, or on cached
  143. * data otherwise.
  144. *
  145. * @param[in] key Wrapper around the key data which to check.
  146. */
  147. bool contains(const SPtr<ManagedSerializableFieldData>& key) const;
  148. /** Returns an enumerator object that allows you to iterate over all key/value pairs in the dictionary. */
  149. Enumerator getEnumerator() const;
  150. /**
  151. * Serializes the internal managed object into a set of cached data that can be saved in memory/disk and can be
  152. * deserialized later. The internal managed object will be freed (if no other references to it). Calling serialize()
  153. * again will have no result.
  154. */
  155. void serialize();
  156. /**
  157. * Deserializes a set of cached data into a managed object. This action may fail in case the cached data contains a
  158. * type that no longer exists in which case null is returned.
  159. *
  160. * @return Newly created object initialized with the cached data.
  161. */
  162. MonoObject* deserialize();
  163. /**
  164. * Creates a managed serializable dictionary that references an existing managed dictionary. Created object will be
  165. * in linked mode.
  166. *
  167. * @param[in] managedInstance Constructed managed instance of the dictionary to link with. Its type must
  168. * correspond with the provided type info.
  169. * @param[in] typeInfo Type information for the dictionary and its key/value pair.
  170. */
  171. static SPtr<ManagedSerializableDictionary> createFromExisting(MonoObject* managedInstance,
  172. const SPtr<ManagedSerializableTypeInfoDictionary>& typeInfo);
  173. /**
  174. * Creates a managed serializable dictionary that creates and references a brand new managed dictionary instance.
  175. *
  176. * @param[in] typeInfo Type of the dictionary to create.
  177. */
  178. static SPtr<ManagedSerializableDictionary> createNew(const SPtr<ManagedSerializableTypeInfoDictionary>& typeInfo);
  179. /**
  180. * Creates a managed dictionary instance.
  181. *
  182. * @param[in] typeInfo Type of the dictionary to create.
  183. */
  184. static MonoObject* createManagedInstance(const SPtr<ManagedSerializableTypeInfoDictionary>& typeInfo);
  185. protected:
  186. /**
  187. * Retrieves needed Mono types and methods. Should be called before performing any operations with the managed
  188. * object.
  189. */
  190. void initMonoObjects(MonoClass* dictionaryClass);
  191. /**
  192. * Sets the dictionary value at the specified key. Operates on the provided managed object.
  193. *
  194. * @param[in] obj Managed object to which to assign the data.
  195. * @param[in] key Wrapper around the key data at which to set the value.
  196. * @param[in] val Wrapper around the value to set at the specified key.
  197. */
  198. void setFieldData(MonoObject* obj, const SPtr<ManagedSerializableFieldData>& key,
  199. const SPtr<ManagedSerializableFieldData>& val);
  200. uint32_t mGCHandle = 0;
  201. MonoMethod* mAddMethod = nullptr;
  202. MonoMethod* mRemoveMethod = nullptr;
  203. MonoMethod* mTryGetValueMethod = nullptr;
  204. MonoMethod* mContainsKeyMethod = nullptr;
  205. MonoProperty* mCountProp = nullptr;
  206. MonoProperty* mKeysProp = nullptr;
  207. MonoMethod* mKeysCopyTo = nullptr;
  208. MonoProperty* mValuesProp = nullptr;
  209. MonoMethod* mValuesCopyTo = nullptr;
  210. SPtr<ManagedSerializableTypeInfoDictionary> mDictionaryTypeInfo;
  211. CachedEntriesMap mCachedEntries;
  212. /************************************************************************/
  213. /* RTTI */
  214. /************************************************************************/
  215. /** Creates an empty and uninitialized object used for serialization purposes. */
  216. static SPtr<ManagedSerializableDictionary> createEmpty();
  217. public:
  218. friend class ManagedSerializableDictionaryRTTI;
  219. static RTTITypeBase* getRTTIStatic();
  220. RTTITypeBase* getRTTI() const override;
  221. };
  222. /** @} */
  223. }