BsManagedSerializableDictionary.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Serialization/BsManagedSerializableDictionary.h"
  4. #include "RTTI/BsManagedSerializableDictionaryRTTI.h"
  5. #include "BsMonoManager.h"
  6. #include "Serialization/BsScriptAssemblyManager.h"
  7. #include "Serialization/BsManagedSerializableField.h"
  8. #include "BsMonoClass.h"
  9. #include "BsMonoMethod.h"
  10. #include "BsMonoProperty.h"
  11. #include "BsMonoUtil.h"
  12. namespace bs
  13. {
  14. ManagedSerializableDictionaryKeyValue::ManagedSerializableDictionaryKeyValue(const SPtr<ManagedSerializableFieldData>& key,
  15. const SPtr<ManagedSerializableFieldData>& value)
  16. :key(key), value(value)
  17. {
  18. }
  19. RTTITypeBase* ManagedSerializableDictionaryKeyValue::getRTTIStatic()
  20. {
  21. return ManagedSerializableDictionaryKeyValueRTTI::instance();
  22. }
  23. RTTITypeBase* ManagedSerializableDictionaryKeyValue::getRTTI() const
  24. {
  25. return ManagedSerializableDictionaryKeyValue::getRTTIStatic();
  26. }
  27. inline size_t ManagedSerializableDictionary::Hash::operator()(const SPtr<ManagedSerializableFieldData>& x) const
  28. {
  29. return x->getHash();
  30. }
  31. inline bool ManagedSerializableDictionary::Equals::operator()(const SPtr<ManagedSerializableFieldData>& a, const SPtr<ManagedSerializableFieldData>& b) const
  32. {
  33. return a->equals(b);
  34. }
  35. ManagedSerializableDictionary::Enumerator::Enumerator(const ManagedSerializableDictionary* parent)
  36. : mIteratorInitialized(false), mParent(parent)
  37. {
  38. MonoArray* keysArray = nullptr;
  39. MonoArray* valuesArray = nullptr;
  40. if(parent->mGCHandle != 0)
  41. {
  42. MonoObject* managedInstance = MonoUtil::getObjectFromGCHandle(parent->mGCHandle);
  43. mNumEntries = *(UINT32*)MonoUtil::unbox(parent->mCountProp->get(managedInstance));
  44. MonoObject* keyCollection = parent->mKeysProp->get(managedInstance);
  45. MonoObject* valueCollection = parent->mValuesProp->get(managedInstance);
  46. mKeyType = parent->mDictionaryTypeInfo->mKeyType->getMonoClass();
  47. mValueType = parent->mDictionaryTypeInfo->mValueType->getMonoClass();
  48. ScriptArray keys(mKeyType, mNumEntries);
  49. ScriptArray values(mValueType, mNumEntries);
  50. UINT32 offset = 0;
  51. void* keyParams[2] = { keys.getInternal(), &offset };
  52. parent->mKeysCopyTo->invoke(keyCollection, keyParams);
  53. void* valueParams[2] = { values.getInternal(), &offset };
  54. parent->mValuesCopyTo->invoke(valueCollection, valueParams);
  55. keysArray = keys.getInternal();
  56. valuesArray = values.getInternal();
  57. }
  58. else
  59. mNumEntries = (UINT32)parent->mCachedEntries.size();
  60. // Note: Handle needed since Enumerator will be on the stack? meaning the GC should be able to find the references.
  61. if(keysArray && valuesArray)
  62. {
  63. mKeysArrayHandle = MonoUtil::newGCHandle((MonoObject*)keysArray, false);
  64. mValuesArrayHandle = MonoUtil::newGCHandle((MonoObject*)valuesArray, false);
  65. }
  66. }
  67. ManagedSerializableDictionary::Enumerator::Enumerator(const Enumerator& other)
  68. : mNumEntries(other.mNumEntries), mIteratorInitialized(false), mParent(other.mParent)
  69. {
  70. if(other.mKeysArrayHandle != 0 && other.mValuesArrayHandle != 0)
  71. {
  72. MonoObject* keysArray = MonoUtil::getObjectFromGCHandle(other.mKeysArrayHandle);
  73. mKeysArrayHandle = MonoUtil::newGCHandle(keysArray, false);
  74. MonoObject* valuesArray = MonoUtil::getObjectFromGCHandle(other.mValuesArrayHandle);
  75. mValuesArrayHandle = MonoUtil::newGCHandle(valuesArray, false);
  76. mKeyType = other.mKeyType;
  77. mValueType = other.mValueType;
  78. }
  79. }
  80. ManagedSerializableDictionary::Enumerator::~Enumerator()
  81. {
  82. if(mKeysArrayHandle != 0)
  83. MonoUtil::freeGCHandle(mKeysArrayHandle);
  84. if(mValuesArrayHandle != 0)
  85. MonoUtil::freeGCHandle(mValuesArrayHandle);
  86. }
  87. ManagedSerializableDictionary::Enumerator&
  88. ManagedSerializableDictionary::Enumerator::operator=(const Enumerator& other)
  89. {
  90. mNumEntries = other.mNumEntries;
  91. mIteratorInitialized = false;
  92. mParent = other.mParent;
  93. mKeyType = nullptr;
  94. mValueType = nullptr;
  95. if(mKeysArrayHandle != 0)
  96. {
  97. MonoUtil::freeGCHandle(mKeysArrayHandle);
  98. mKeysArrayHandle = 0;
  99. }
  100. if(mValuesArrayHandle != 0)
  101. {
  102. MonoUtil::freeGCHandle(mValuesArrayHandle);
  103. mValuesArrayHandle = 0;
  104. }
  105. if(other.mKeysArrayHandle != 0 && other.mValuesArrayHandle != 0)
  106. {
  107. MonoObject* keysArray = MonoUtil::getObjectFromGCHandle(other.mKeysArrayHandle);
  108. mKeysArrayHandle = MonoUtil::newGCHandle(keysArray, false);
  109. MonoObject* valuesArray = MonoUtil::getObjectFromGCHandle(other.mValuesArrayHandle);
  110. mValuesArrayHandle = MonoUtil::newGCHandle(valuesArray, false);
  111. mKeyType = other.mKeyType;
  112. mValueType = other.mValueType;
  113. }
  114. return *this;
  115. }
  116. SPtr<ManagedSerializableFieldData> ManagedSerializableDictionary::Enumerator::getKey() const
  117. {
  118. if (mKeysArrayHandle != 0)
  119. {
  120. MonoArray* keysArray = (MonoArray*)MonoUtil::getObjectFromGCHandle(mKeysArrayHandle);
  121. ScriptArray keys(keysArray);
  122. if(mCurrentIdx != (UINT32)-1)
  123. {
  124. void* val = (void*)keys.getRaw(mCurrentIdx, keys.elementSize());
  125. MonoObject* obj = nullptr;
  126. if (MonoUtil::isValueType(mKeyType))
  127. {
  128. if (val != nullptr)
  129. obj = MonoUtil::box(mKeyType, val);
  130. }
  131. else
  132. obj = *(MonoObject**)val;
  133. return ManagedSerializableFieldData::create(mParent->mDictionaryTypeInfo->mKeyType, obj);
  134. }
  135. else
  136. return nullptr;
  137. }
  138. else
  139. {
  140. return mCachedIter->first;
  141. }
  142. }
  143. SPtr<ManagedSerializableFieldData> ManagedSerializableDictionary::Enumerator::getValue() const
  144. {
  145. if (mValuesArrayHandle != 0)
  146. {
  147. MonoArray* valuesArray = (MonoArray*)MonoUtil::getObjectFromGCHandle(mValuesArrayHandle);
  148. ScriptArray values(valuesArray);
  149. if(mCurrentIdx != (UINT32)-1)
  150. {
  151. void* val = (void*)values.getRaw(mCurrentIdx, values.elementSize());
  152. MonoObject* obj = nullptr;
  153. if (MonoUtil::isValueType(mValueType))
  154. {
  155. if (val != nullptr)
  156. obj = MonoUtil::box(mValueType, val);
  157. }
  158. else
  159. obj = *(MonoObject**)val;
  160. return ManagedSerializableFieldData::create(mParent->mDictionaryTypeInfo->mValueType, obj);
  161. }
  162. else
  163. return nullptr;
  164. }
  165. else
  166. {
  167. return mCachedIter->second;
  168. }
  169. }
  170. bool ManagedSerializableDictionary::Enumerator::moveNext()
  171. {
  172. if (mKeysArrayHandle != 0 && mValuesArrayHandle != 0)
  173. {
  174. if((mCurrentIdx + 1) < mNumEntries)
  175. {
  176. mCurrentIdx++;
  177. return true;
  178. }
  179. return false;
  180. }
  181. else
  182. {
  183. if (!mIteratorInitialized)
  184. {
  185. mCachedIter = mParent->mCachedEntries.begin();
  186. mIteratorInitialized = true;
  187. }
  188. else
  189. ++mCachedIter;
  190. return mCachedIter != mParent->mCachedEntries.end();
  191. }
  192. }
  193. ManagedSerializableDictionary::ManagedSerializableDictionary(const ConstructPrivately& dummy)
  194. { }
  195. ManagedSerializableDictionary::ManagedSerializableDictionary(const ConstructPrivately& dummy, const SPtr<ManagedSerializableTypeInfoDictionary>& typeInfo, MonoObject* managedInstance)
  196. : mDictionaryTypeInfo(typeInfo)
  197. {
  198. mGCHandle = MonoUtil::newGCHandle(managedInstance, false);
  199. MonoClass* dictClass = MonoManager::instance().findClass(MonoUtil::getClass(managedInstance));
  200. if (dictClass == nullptr)
  201. return;
  202. initMonoObjects(dictClass);
  203. }
  204. ManagedSerializableDictionary::~ManagedSerializableDictionary()
  205. {
  206. if(mGCHandle != 0)
  207. {
  208. MonoUtil::freeGCHandle(mGCHandle);
  209. mGCHandle = 0;
  210. }
  211. }
  212. SPtr<ManagedSerializableDictionary> ManagedSerializableDictionary::createFromExisting(MonoObject* managedInstance,
  213. const SPtr<ManagedSerializableTypeInfoDictionary>& typeInfo)
  214. {
  215. if(managedInstance == nullptr)
  216. return nullptr;
  217. String elementNs;
  218. String elementTypeName;
  219. MonoUtil::getClassName(managedInstance, elementNs, elementTypeName);
  220. String fullName = elementNs + "." + elementTypeName;
  221. if(ScriptAssemblyManager::instance().getBuiltinClasses().systemGenericDictionaryClass->getFullName() != fullName)
  222. return nullptr;
  223. return bs_shared_ptr_new<ManagedSerializableDictionary>(ConstructPrivately(), typeInfo, managedInstance);
  224. }
  225. SPtr<ManagedSerializableDictionary> ManagedSerializableDictionary::createNew(const SPtr<ManagedSerializableTypeInfoDictionary>& typeInfo)
  226. {
  227. return bs_shared_ptr_new<ManagedSerializableDictionary>(ConstructPrivately(), typeInfo, createManagedInstance(typeInfo));
  228. }
  229. MonoObject* ManagedSerializableDictionary::createManagedInstance(const SPtr<ManagedSerializableTypeInfoDictionary>& typeInfo)
  230. {
  231. if (!typeInfo->isTypeLoaded())
  232. return nullptr;
  233. ::MonoClass* dictionaryMonoClass = typeInfo->getMonoClass();
  234. MonoClass* dictionaryClass = MonoManager::instance().findClass(dictionaryMonoClass);
  235. if (dictionaryClass == nullptr)
  236. return nullptr;
  237. return dictionaryClass->createInstance();
  238. }
  239. SPtr<ManagedSerializableDictionary> ManagedSerializableDictionary::createEmpty()
  240. {
  241. return bs_shared_ptr_new<ManagedSerializableDictionary>(ConstructPrivately());
  242. }
  243. MonoObject* ManagedSerializableDictionary::getManagedInstance() const
  244. {
  245. if(mGCHandle != 0)
  246. return MonoUtil::getObjectFromGCHandle(mGCHandle);
  247. return nullptr;
  248. }
  249. void ManagedSerializableDictionary::serialize()
  250. {
  251. if (mGCHandle == 0)
  252. return;
  253. MonoObject* managedInstance = MonoUtil::getObjectFromGCHandle(mGCHandle);
  254. MonoClass* dictionaryClass = MonoManager::instance().findClass(MonoUtil::getClass(managedInstance));
  255. if (dictionaryClass == nullptr)
  256. return;
  257. initMonoObjects(dictionaryClass);
  258. mCachedEntries.clear();
  259. Enumerator enumerator = getEnumerator();
  260. while (enumerator.moveNext())
  261. {
  262. SPtr<ManagedSerializableFieldData> key = enumerator.getKey();
  263. mCachedEntries.insert(std::make_pair(key, enumerator.getValue()));
  264. }
  265. // Serialize children
  266. for (auto& fieldEntry : mCachedEntries)
  267. {
  268. fieldEntry.first->serialize();
  269. fieldEntry.second->serialize();
  270. }
  271. MonoUtil::freeGCHandle(mGCHandle);
  272. mGCHandle = 0;
  273. }
  274. MonoObject* ManagedSerializableDictionary::deserialize()
  275. {
  276. MonoObject* managedInstance = createManagedInstance(mDictionaryTypeInfo);
  277. if (managedInstance == nullptr)
  278. return nullptr;
  279. ::MonoClass* dictionaryMonoClass = mDictionaryTypeInfo->getMonoClass();
  280. MonoClass* dictionaryClass = MonoManager::instance().findClass(dictionaryMonoClass);
  281. if (dictionaryClass == nullptr)
  282. return nullptr;
  283. initMonoObjects(dictionaryClass);
  284. // Deserialize children
  285. for (auto& fieldEntry : mCachedEntries)
  286. {
  287. fieldEntry.first->deserialize();
  288. fieldEntry.second->deserialize();
  289. }
  290. UINT32 idx = 0;
  291. for (auto& entry : mCachedEntries)
  292. {
  293. setFieldData(managedInstance, entry.first, entry.second);
  294. idx++;
  295. }
  296. return managedInstance;
  297. }
  298. SPtr<ManagedSerializableFieldData> ManagedSerializableDictionary::getFieldData(const SPtr<ManagedSerializableFieldData>& key)
  299. {
  300. if (mGCHandle != 0)
  301. {
  302. MonoObject* value = nullptr;
  303. void* params[2];
  304. params[0] = key->getValue(mDictionaryTypeInfo->mKeyType);
  305. params[1] = &value;
  306. MonoObject* managedInstance = MonoUtil::getObjectFromGCHandle(mGCHandle);
  307. mTryGetValueMethod->invoke(managedInstance, params);
  308. MonoObject* boxedValue = value;
  309. ::MonoClass* valueTypeClass = mDictionaryTypeInfo->mValueType->getMonoClass();
  310. if (MonoUtil::isValueType(valueTypeClass))
  311. {
  312. if (value != nullptr)
  313. boxedValue = MonoUtil::box(valueTypeClass, &value);
  314. }
  315. return ManagedSerializableFieldData::create(mDictionaryTypeInfo->mValueType, boxedValue);
  316. }
  317. else
  318. {
  319. return mCachedEntries[key];
  320. }
  321. }
  322. void ManagedSerializableDictionary::setFieldData(const SPtr<ManagedSerializableFieldData>& key, const SPtr<ManagedSerializableFieldData>& val)
  323. {
  324. if (mGCHandle != 0)
  325. {
  326. MonoObject* managedInstance = MonoUtil::getObjectFromGCHandle(mGCHandle);
  327. setFieldData(managedInstance, key, val);
  328. }
  329. else
  330. {
  331. mCachedEntries[key] = val;
  332. }
  333. }
  334. void ManagedSerializableDictionary::setFieldData(MonoObject* obj, const SPtr<ManagedSerializableFieldData>& key, const SPtr<ManagedSerializableFieldData>& val)
  335. {
  336. void* params[2];
  337. params[0] = key->getValue(mDictionaryTypeInfo->mKeyType);
  338. params[1] = val->getValue(mDictionaryTypeInfo->mValueType);
  339. mAddMethod->invoke(obj, params);
  340. }
  341. void ManagedSerializableDictionary::removeFieldData(const SPtr<ManagedSerializableFieldData>& key)
  342. {
  343. if (mGCHandle != 0)
  344. {
  345. void* params[1];
  346. params[0] = key->getValue(mDictionaryTypeInfo->mKeyType);
  347. MonoObject* managedInstance = MonoUtil::getObjectFromGCHandle(mGCHandle);
  348. mRemoveMethod->invoke(managedInstance, params);
  349. }
  350. else
  351. {
  352. auto findIter = mCachedEntries.find(key);
  353. if (findIter != mCachedEntries.end())
  354. mCachedEntries.erase(findIter);
  355. }
  356. }
  357. bool ManagedSerializableDictionary::contains(const SPtr<ManagedSerializableFieldData>& key) const
  358. {
  359. if (mGCHandle != 0)
  360. {
  361. void* params[1];
  362. params[0] = key->getValue(mDictionaryTypeInfo->mKeyType);
  363. MonoObject* managedInstance = MonoUtil::getObjectFromGCHandle(mGCHandle);
  364. MonoObject* returnVal = mContainsKeyMethod->invoke(managedInstance, params);
  365. return *(bool*)MonoUtil::unbox(returnVal);
  366. }
  367. else
  368. return mCachedEntries.find(key) != mCachedEntries.end();
  369. }
  370. ManagedSerializableDictionary::Enumerator ManagedSerializableDictionary::getEnumerator() const
  371. {
  372. return Enumerator(this);
  373. }
  374. void ManagedSerializableDictionary::initMonoObjects(MonoClass* dictionaryClass)
  375. {
  376. mAddMethod = dictionaryClass->getMethod("Add", 2);
  377. mRemoveMethod = dictionaryClass->getMethod("Remove", 1);
  378. mTryGetValueMethod = dictionaryClass->getMethod("TryGetValue", 2);
  379. mContainsKeyMethod = dictionaryClass->getMethod("ContainsKey", 1);
  380. mCountProp = dictionaryClass->getProperty("Count");
  381. mKeysProp = dictionaryClass->getProperty("Keys");
  382. mValuesProp = dictionaryClass->getProperty("Values");
  383. MonoClass* keyCollectionClass = mKeysProp->getReturnType();
  384. mKeysCopyTo = keyCollectionClass->getMethod("CopyTo", 2);
  385. MonoClass* valueCollectionClass = mValuesProp->getReturnType();
  386. mValuesCopyTo = valueCollectionClass->getMethod("CopyTo", 2);
  387. }
  388. RTTITypeBase* ManagedSerializableDictionary::getRTTIStatic()
  389. {
  390. return ManagedSerializableDictionaryRTTI::instance();
  391. }
  392. RTTITypeBase* ManagedSerializableDictionary::getRTTI() const
  393. {
  394. return ManagedSerializableDictionary::getRTTIStatic();
  395. }
  396. }