BsBinarySerializer.cpp 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252
  1. #include "BsBinarySerializer.h"
  2. #include "BsException.h"
  3. #include "BsDebug.h"
  4. #include "BsIReflectable.h"
  5. #include "BsRTTIType.h"
  6. #include "BsRTTIField.h"
  7. #include "BsRTTIPlainField.h"
  8. #include "BsRTTIReflectableField.h"
  9. #include "BsRTTIReflectablePtrField.h"
  10. #include "BsRTTIManagedDataBlockField.h"
  11. #include "BsMemorySerializer.h"
  12. #include <unordered_set>
  13. /**
  14. * @brief A macro that represents a block of code that gets used a lot inside
  15. * encodeInternal. It checks if the buffer has enough space, and if it does
  16. * it copies the data from the specified location and increments the needed
  17. * pointers and counters. If there is not enough space the buffer is flushed
  18. * (hopefully to make some space). If there is still not enough space the entire
  19. * encoding process ends.
  20. *
  21. * @param dataPtr Pointer to data which to copy.
  22. * @param size Size of the data to copy
  23. */
  24. #define COPY_TO_BUFFER(dataIter, size) \
  25. if((*bytesWritten + size##) > bufferLength) \
  26. { \
  27. mTotalBytesWritten += *bytesWritten; \
  28. buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength); \
  29. if(buffer == nullptr || bufferLength < size##) return nullptr; \
  30. *bytesWritten = 0; \
  31. } \
  32. \
  33. memcpy(buffer, dataIter##, size##); \
  34. buffer += size##; \
  35. *bytesWritten += size##;
  36. namespace BansheeEngine
  37. {
  38. BinarySerializer::BinarySerializer()
  39. :mLastUsedObjectId(1)
  40. {
  41. }
  42. void BinarySerializer::encode(IReflectable* object, UINT8* buffer, UINT32 bufferLength,
  43. UINT32* bytesWritten, std::function<UINT8*(UINT8*, UINT32, UINT32&)> flushBufferCallback, bool shallow)
  44. {
  45. mObjectsToEncode.clear();
  46. mObjectAddrToId.clear();
  47. mLastUsedObjectId = 1;
  48. *bytesWritten = 0;
  49. mTotalBytesWritten = 0;
  50. UINT8* bufferStart = buffer;
  51. Vector<std::shared_ptr<IReflectable>> encodedObjects;
  52. UINT32 objectId = findOrCreatePersistentId(object);
  53. // Encode primary object and its value types
  54. buffer = encodeInternal(object, objectId, buffer, bufferLength, bytesWritten, flushBufferCallback, shallow);
  55. if(buffer == nullptr)
  56. {
  57. BS_EXCEPT(InternalErrorException,
  58. "Destination buffer is null or not large enough.");
  59. }
  60. // Encode pointed to objects and their value types
  61. UnorderedSet<UINT32> serializedObjects;
  62. while(true)
  63. {
  64. auto iter = mObjectsToEncode.begin();
  65. bool foundObjectToProcess = false;
  66. for(iter; iter != mObjectsToEncode.end(); ++iter)
  67. {
  68. auto foundExisting = serializedObjects.find(iter->objectId);
  69. if(foundExisting != serializedObjects.end())
  70. continue; // Already processed
  71. std::shared_ptr<IReflectable> curObject = iter->object;
  72. UINT32 curObjectid = iter->objectId;
  73. serializedObjects.insert(curObjectid);
  74. mObjectsToEncode.erase(iter);
  75. buffer = encodeInternal(curObject.get(), curObjectid, buffer,
  76. bufferLength, bytesWritten, flushBufferCallback, shallow);
  77. if(buffer == nullptr)
  78. {
  79. BS_EXCEPT(InternalErrorException,
  80. "Destination buffer is null or not large enough.");
  81. }
  82. foundObjectToProcess = true;
  83. // Ensure we keep a reference to the object so it isn't released.
  84. // The system assigns unique IDs to IReflectable objects based on pointer
  85. // addresses but if objects get released then same address could be assigned twice.
  86. // Note: To get around this I could assign unique IDs to IReflectable objects
  87. encodedObjects.push_back(curObject);
  88. break; // Need to start over as mObjectsToSerialize was possibly modified
  89. }
  90. if(!foundObjectToProcess) // We're done
  91. break;
  92. }
  93. // Final flush
  94. if(*bytesWritten > 0)
  95. {
  96. mTotalBytesWritten += *bytesWritten;
  97. buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength);
  98. }
  99. *bytesWritten = mTotalBytesWritten;
  100. encodedObjects.clear();
  101. mObjectsToEncode.clear();
  102. mObjectAddrToId.clear();
  103. }
  104. std::shared_ptr<IReflectable> BinarySerializer::decode(UINT8* data, UINT32 dataLength)
  105. {
  106. if (dataLength == 0)
  107. return nullptr;
  108. SPtr<SerializedObject> intermediateObject = _decodeIntermediate(data, dataLength);
  109. if (intermediateObject == nullptr)
  110. return nullptr;
  111. return _decodeIntermediate(intermediateObject);
  112. }
  113. SPtr<IReflectable> BinarySerializer::_decodeIntermediate(const SPtr<SerializedObject>& serializedObject)
  114. {
  115. mObjectMap.clear();
  116. SPtr<IReflectable> output;
  117. RTTITypeBase* type = IReflectable::_getRTTIfromTypeId(serializedObject->getRootTypeId());
  118. if (type != nullptr)
  119. {
  120. output = type->newRTTIObject();
  121. auto iterNewObj = mObjectMap.insert(std::make_pair(serializedObject, ObjectToDecode(output, serializedObject)));
  122. decodeInternal(output, serializedObject);
  123. iterNewObj.first->second.isDecoded = true;
  124. }
  125. // Go through the remaining objects (should be only ones with weak refs)
  126. for (auto iter = mObjectMap.begin(); iter != mObjectMap.end(); ++iter)
  127. {
  128. ObjectToDecode& objToDecode = iter->second;
  129. if (objToDecode.isDecoded)
  130. continue;
  131. decodeInternal(objToDecode.object, objToDecode.serializedObject);
  132. objToDecode.isDecoded = true;
  133. }
  134. mObjectMap.clear();
  135. return output;
  136. }
  137. UINT8* BinarySerializer::encodeInternal(IReflectable* object, UINT32 objectId, UINT8* buffer, UINT32& bufferLength,
  138. UINT32* bytesWritten, std::function<UINT8*(UINT8*, UINT32, UINT32&)> flushBufferCallback, bool shallow)
  139. {
  140. RTTITypeBase* si = object->getRTTI();
  141. bool isBaseClass = false;
  142. // If an object has base classes, we need to iterate through all of them
  143. do
  144. {
  145. si->onSerializationStarted(object);
  146. // Encode object ID & type
  147. ObjectMetaData objectMetaData = encodeObjectMetaData(objectId, si->getRTTIId(), isBaseClass);
  148. COPY_TO_BUFFER(&objectMetaData, sizeof(ObjectMetaData))
  149. int numFields = si->getNumFields();
  150. for(int i = 0; i < numFields; i++)
  151. {
  152. RTTIField* curGenericField = si->getField(i);
  153. // Copy field ID & other meta-data like field size and type
  154. int metaData = encodeFieldMetaData(curGenericField->mUniqueId, curGenericField->getTypeSize(),
  155. curGenericField->mIsVectorType, curGenericField->mType, curGenericField->hasDynamicSize(), false);
  156. COPY_TO_BUFFER(&metaData, META_SIZE)
  157. if(curGenericField->mIsVectorType)
  158. {
  159. UINT32 arrayNumElems = curGenericField->getArraySize(object);
  160. // Copy num vector elements
  161. COPY_TO_BUFFER(&arrayNumElems, NUM_ELEM_FIELD_SIZE)
  162. switch(curGenericField->mType)
  163. {
  164. case SerializableFT_ReflectablePtr:
  165. {
  166. RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
  167. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  168. {
  169. std::shared_ptr<IReflectable> childObject;
  170. if (!shallow)
  171. childObject = curField->getArrayValue(object, arrIdx);
  172. UINT32 objId = registerObjectPtr(childObject);
  173. COPY_TO_BUFFER(&objId, sizeof(UINT32))
  174. }
  175. break;
  176. }
  177. case SerializableFT_Reflectable:
  178. {
  179. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  180. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  181. {
  182. IReflectable& childObject = curField->getArrayValue(object, arrIdx);
  183. buffer = complexTypeToBuffer(&childObject, buffer, bufferLength,
  184. bytesWritten, flushBufferCallback, shallow);
  185. if(buffer == nullptr)
  186. {
  187. si->onSerializationEnded(object);
  188. return nullptr;
  189. }
  190. }
  191. break;
  192. }
  193. case SerializableFT_Plain:
  194. {
  195. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  196. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  197. {
  198. UINT32 typeSize = 0;
  199. if(curField->hasDynamicSize())
  200. typeSize = curField->getArrayElemDynamicSize(object, arrIdx);
  201. else
  202. typeSize = curField->getTypeSize();
  203. if ((*bytesWritten + typeSize) > bufferLength)
  204. {
  205. UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
  206. curField->arrayElemToBuffer(object, arrIdx, tempBuffer);
  207. buffer = dataBlockToBuffer(tempBuffer, typeSize, buffer, bufferLength, bytesWritten, flushBufferCallback);
  208. if (buffer == nullptr || bufferLength == 0)
  209. {
  210. bs_stack_free(tempBuffer);
  211. si->onSerializationEnded(object);
  212. return nullptr;
  213. }
  214. bs_stack_free(tempBuffer);
  215. }
  216. else
  217. {
  218. curField->arrayElemToBuffer(object, arrIdx, buffer);
  219. buffer += typeSize;
  220. *bytesWritten += typeSize;
  221. }
  222. }
  223. break;
  224. }
  225. default:
  226. BS_EXCEPT(InternalErrorException,
  227. "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
  228. ", Is array: " + toString(curGenericField->mIsVectorType));
  229. }
  230. }
  231. else
  232. {
  233. switch(curGenericField->mType)
  234. {
  235. case SerializableFT_ReflectablePtr:
  236. {
  237. RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
  238. std::shared_ptr<IReflectable> childObject;
  239. if (!shallow)
  240. childObject = curField->getValue(object);
  241. UINT32 objId = registerObjectPtr(childObject);
  242. COPY_TO_BUFFER(&objId, sizeof(UINT32))
  243. break;
  244. }
  245. case SerializableFT_Reflectable:
  246. {
  247. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  248. IReflectable& childObject = curField->getValue(object);
  249. buffer = complexTypeToBuffer(&childObject, buffer, bufferLength,
  250. bytesWritten, flushBufferCallback, shallow);
  251. if(buffer == nullptr)
  252. {
  253. si->onSerializationEnded(object);
  254. return nullptr;
  255. }
  256. break;
  257. }
  258. case SerializableFT_Plain:
  259. {
  260. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  261. UINT32 typeSize = 0;
  262. if(curField->hasDynamicSize())
  263. typeSize = curField->getDynamicSize(object);
  264. else
  265. typeSize = curField->getTypeSize();
  266. if ((*bytesWritten + typeSize) > bufferLength)
  267. {
  268. UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
  269. curField->toBuffer(object, tempBuffer);
  270. buffer = dataBlockToBuffer(tempBuffer, typeSize, buffer, bufferLength, bytesWritten, flushBufferCallback);
  271. if (buffer == nullptr || bufferLength == 0)
  272. {
  273. bs_stack_free(tempBuffer);
  274. si->onSerializationEnded(object);
  275. return nullptr;
  276. }
  277. bs_stack_free(tempBuffer);
  278. }
  279. else
  280. {
  281. curField->toBuffer(object, buffer);
  282. buffer += typeSize;
  283. *bytesWritten += typeSize;
  284. }
  285. break;
  286. }
  287. case SerializableFT_DataBlock:
  288. {
  289. RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
  290. ManagedDataBlock value = curField->getValue(object);
  291. // Data block size
  292. UINT32 dataBlockSize = value.getSize();
  293. COPY_TO_BUFFER(&dataBlockSize, sizeof(UINT32))
  294. // Data block data
  295. UINT8* dataToStore = value.getData();
  296. buffer = dataBlockToBuffer(dataToStore, dataBlockSize, buffer, bufferLength, bytesWritten, flushBufferCallback);
  297. if (buffer == nullptr || bufferLength == 0)
  298. {
  299. si->onSerializationEnded(object);
  300. return nullptr;
  301. }
  302. break;
  303. }
  304. default:
  305. BS_EXCEPT(InternalErrorException,
  306. "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
  307. ", Is array: " + toString(curGenericField->mIsVectorType));
  308. }
  309. }
  310. }
  311. si->onSerializationEnded(object);
  312. si = si->getBaseClass();
  313. isBaseClass = true;
  314. } while(si != nullptr); // Repeat until we reach the top of the inheritance hierarchy
  315. return buffer;
  316. }
  317. SPtr<SerializedObject> BinarySerializer::_encodeIntermediate(IReflectable* object, bool shallow)
  318. {
  319. // TODO: This is a hacky way of generating an intermediate format to save development time and complexity.
  320. // It is hacky because it requires a full on encode to binary and then decode into intermediate. It should
  321. // be better to modify encoding process so it outputs the intermediate format directly (similar to how decoding works).
  322. // This also means that once you have an intermediate format you cannot use it to encode to binary.
  323. MemorySerializer ms;
  324. UINT32 dataLength = 0;
  325. UINT8* data = ms.encode(object, dataLength, &bs_alloc, shallow);
  326. BinarySerializer bs;
  327. SPtr<SerializedObject> obj = bs._decodeIntermediate(data, dataLength, true);
  328. bs_free(data);
  329. return obj;
  330. }
  331. SPtr<SerializedObject> BinarySerializer::_decodeIntermediate(UINT8* data, UINT32 dataLength, bool copyData)
  332. {
  333. UINT32 bytesRead = 0;
  334. mInterimObjectMap.clear();
  335. SPtr<SerializedObject> rootObj;
  336. bool hasMore = decodeIntermediateInternal(data, dataLength, bytesRead, rootObj, copyData);
  337. while (hasMore)
  338. {
  339. UINT8* dataPtr = data + bytesRead;
  340. SPtr<SerializedObject> dummyObj;
  341. hasMore = decodeIntermediateInternal(dataPtr, dataLength, bytesRead, dummyObj, copyData);
  342. }
  343. return rootObj;
  344. }
  345. bool BinarySerializer::decodeIntermediateInternal(UINT8* data, UINT32 dataLength, UINT32& bytesRead, SPtr<SerializedObject>& output, bool copyData)
  346. {
  347. if ((bytesRead + sizeof(ObjectMetaData)) > dataLength)
  348. {
  349. BS_EXCEPT(InternalErrorException,
  350. "Error decoding data.");
  351. }
  352. ObjectMetaData objectMetaData;
  353. objectMetaData.objectMeta = 0;
  354. objectMetaData.typeId = 0;
  355. memcpy(&objectMetaData, data, sizeof(ObjectMetaData));
  356. data += sizeof(ObjectMetaData);
  357. bytesRead += sizeof(ObjectMetaData);
  358. UINT32 objectId = 0;
  359. UINT32 objectTypeId = 0;
  360. bool objectIsBaseClass = false;
  361. decodeObjectMetaData(objectMetaData, objectId, objectTypeId, objectIsBaseClass);
  362. if (objectIsBaseClass)
  363. {
  364. BS_EXCEPT(InternalErrorException, "Encountered a base-class object while looking for a new object. " \
  365. "Base class objects are only supposed to be parts of a larger object.");
  366. }
  367. RTTITypeBase* rtti = IReflectable::_getRTTIfromTypeId(objectTypeId);
  368. SerializedSubObject* serializedSubObject = nullptr;
  369. if (rtti != nullptr)
  370. {
  371. if (objectId > 0)
  372. {
  373. auto iterFind = mInterimObjectMap.find(objectId);
  374. if (iterFind == mInterimObjectMap.end())
  375. {
  376. output = bs_shared_ptr_new<SerializedObject>();
  377. mInterimObjectMap.insert(std::make_pair(objectId, output));
  378. }
  379. else
  380. output = iterFind->second;
  381. }
  382. else // Not a reflectable ptr referenced object
  383. output = bs_shared_ptr_new<SerializedObject>();
  384. output->subObjects.push_back(SerializedSubObject());
  385. serializedSubObject = &output->subObjects.back();
  386. serializedSubObject->typeId = objectTypeId;
  387. }
  388. while (bytesRead < dataLength)
  389. {
  390. int metaData = -1;
  391. if ((bytesRead + META_SIZE) > dataLength)
  392. {
  393. BS_EXCEPT(InternalErrorException,
  394. "Error decoding data.");
  395. }
  396. memcpy((void*)&metaData, data, META_SIZE);
  397. if (isObjectMetaData(metaData)) // We've reached a new object or a base class of the current one
  398. {
  399. if ((bytesRead + sizeof(ObjectMetaData)) > dataLength)
  400. {
  401. BS_EXCEPT(InternalErrorException,
  402. "Error decoding data.");
  403. }
  404. ObjectMetaData objMetaData;
  405. objMetaData.objectMeta = 0;
  406. objMetaData.typeId = 0;
  407. memcpy(&objMetaData, data, sizeof(ObjectMetaData));
  408. UINT32 objId = 0;
  409. UINT32 objTypeId = 0;
  410. bool objIsBaseClass = false;
  411. decodeObjectMetaData(objMetaData, objId, objTypeId, objIsBaseClass);
  412. // If it's a base class, get base class RTTI and handle that
  413. if (objIsBaseClass)
  414. {
  415. if (rtti != nullptr)
  416. rtti = rtti->getBaseClass();
  417. // Saved and current base classes don't match, so just skip over all that data
  418. if (rtti == nullptr || rtti->getRTTIId() != objTypeId)
  419. {
  420. rtti = nullptr;
  421. }
  422. if (rtti != nullptr)
  423. {
  424. output->subObjects.push_back(SerializedSubObject());
  425. serializedSubObject = &output->subObjects.back();
  426. serializedSubObject->typeId = objTypeId;
  427. }
  428. data += sizeof(ObjectMetaData);
  429. bytesRead += sizeof(ObjectMetaData);
  430. continue;
  431. }
  432. else
  433. {
  434. // Found new object, we're done
  435. return true;
  436. }
  437. }
  438. data += META_SIZE;
  439. bytesRead += META_SIZE;
  440. bool isArray;
  441. SerializableFieldType fieldType;
  442. UINT16 fieldId;
  443. UINT8 fieldSize;
  444. bool hasDynamicSize;
  445. bool terminator;
  446. decodeFieldMetaData(metaData, fieldId, fieldSize, isArray, fieldType, hasDynamicSize, terminator);
  447. if (terminator)
  448. {
  449. // We've processed the last field in this object, so return. Although we return false we don't actually know
  450. // if there is an object following this one. However it doesn't matter since terminator fields are only used
  451. // for embedded objects that are all processed within this method so we can compensate.
  452. return false;
  453. }
  454. RTTIField* curGenericField = nullptr;
  455. if (rtti != nullptr)
  456. curGenericField = rtti->findField(fieldId);
  457. if (curGenericField != nullptr)
  458. {
  459. if (!hasDynamicSize && curGenericField->getTypeSize() != fieldSize)
  460. {
  461. BS_EXCEPT(InternalErrorException,
  462. "Data type mismatch. Type size stored in file and actual type size don't match. ("
  463. + toString(curGenericField->getTypeSize()) + " vs. " + toString(fieldSize) + ")");
  464. }
  465. if (curGenericField->mIsVectorType != isArray)
  466. {
  467. BS_EXCEPT(InternalErrorException,
  468. "Data type mismatch. One is array, other is a single type.");
  469. }
  470. if (curGenericField->mType != fieldType)
  471. {
  472. BS_EXCEPT(InternalErrorException,
  473. "Data type mismatch. Field types don't match. " + toString(UINT32(curGenericField->mType)) + " vs. " + toString(UINT32(fieldType)));
  474. }
  475. }
  476. SPtr<SerializedInstance> serializedEntry;
  477. bool hasModification = false;
  478. int arrayNumElems = 1;
  479. if (isArray)
  480. {
  481. if ((bytesRead + NUM_ELEM_FIELD_SIZE) > dataLength)
  482. {
  483. BS_EXCEPT(InternalErrorException,
  484. "Error decoding data.");
  485. }
  486. memcpy((void*)&arrayNumElems, data, NUM_ELEM_FIELD_SIZE);
  487. data += NUM_ELEM_FIELD_SIZE;
  488. bytesRead += NUM_ELEM_FIELD_SIZE;
  489. SPtr<SerializedArray> serializedArray;
  490. if (curGenericField != nullptr)
  491. {
  492. serializedArray = bs_shared_ptr_new<SerializedArray>();
  493. serializedArray->numElements = arrayNumElems;
  494. serializedEntry = serializedArray;
  495. hasModification = true;
  496. }
  497. switch (fieldType)
  498. {
  499. case SerializableFT_ReflectablePtr:
  500. {
  501. RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
  502. for (int i = 0; i < arrayNumElems; i++)
  503. {
  504. if ((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
  505. {
  506. BS_EXCEPT(InternalErrorException,
  507. "Error decoding data.");
  508. }
  509. int childObjectId = 0;
  510. memcpy(&childObjectId, data, COMPLEX_TYPE_FIELD_SIZE);
  511. data += COMPLEX_TYPE_FIELD_SIZE;
  512. bytesRead += COMPLEX_TYPE_FIELD_SIZE;
  513. if (curField != nullptr)
  514. {
  515. SPtr<SerializedObject> serializedArrayEntry = nullptr;
  516. if (childObjectId > 0)
  517. {
  518. auto findObj = mInterimObjectMap.find(childObjectId);
  519. if (findObj == mInterimObjectMap.end())
  520. {
  521. serializedArrayEntry = bs_shared_ptr_new<SerializedObject>();
  522. mInterimObjectMap.insert(std::make_pair(childObjectId, serializedArrayEntry));
  523. }
  524. else
  525. serializedArrayEntry = findObj->second;
  526. }
  527. SerializedArrayEntry arrayEntry;
  528. arrayEntry.serialized = serializedArrayEntry;
  529. arrayEntry.index = i;
  530. serializedArray->entries[i] = arrayEntry;
  531. }
  532. }
  533. break;
  534. }
  535. case SerializableFT_Reflectable:
  536. {
  537. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  538. for (int i = 0; i < arrayNumElems; i++)
  539. {
  540. if (curField != nullptr)
  541. {
  542. UINT32 bytesReadStart = bytesRead;
  543. SPtr<SerializedObject> serializedArrayEntry;
  544. decodeIntermediateInternal(data, dataLength, bytesRead, serializedArrayEntry, copyData);
  545. SerializedArrayEntry arrayEntry;
  546. arrayEntry.serialized = serializedArrayEntry;
  547. arrayEntry.index = i;
  548. serializedArray->entries[i] = arrayEntry;
  549. UINT32 complexTypeSize = bytesRead - bytesReadStart;
  550. data += complexTypeSize;
  551. }
  552. }
  553. break;
  554. }
  555. case SerializableFT_Plain:
  556. {
  557. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  558. for (int i = 0; i < arrayNumElems; i++)
  559. {
  560. UINT32 typeSize = fieldSize;
  561. if (hasDynamicSize)
  562. memcpy(&typeSize, data, sizeof(UINT32));
  563. if (curField != nullptr)
  564. {
  565. SPtr<SerializedField> serializedField = bs_shared_ptr_new<SerializedField>();
  566. if (copyData)
  567. {
  568. serializedField->value = (UINT8*)bs_alloc(typeSize);
  569. memcpy(serializedField->value, data, typeSize);
  570. serializedField->ownsMemory = true;
  571. }
  572. else
  573. serializedField->value = data;
  574. serializedField->size = typeSize;
  575. SerializedArrayEntry arrayEntry;
  576. arrayEntry.serialized = serializedField;
  577. arrayEntry.index = i;
  578. serializedArray->entries[i] = arrayEntry;
  579. }
  580. data += typeSize;
  581. bytesRead += typeSize;
  582. }
  583. break;
  584. }
  585. default:
  586. BS_EXCEPT(InternalErrorException,
  587. "Error decoding data. Encountered a type I don't know how to decode. Type: " + toString(UINT32(fieldType)) +
  588. ", Is array: " + toString(isArray));
  589. }
  590. }
  591. else
  592. {
  593. switch (fieldType)
  594. {
  595. case SerializableFT_ReflectablePtr:
  596. {
  597. RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
  598. if ((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
  599. {
  600. BS_EXCEPT(InternalErrorException,
  601. "Error decoding data.");
  602. }
  603. int childObjectId = 0;
  604. memcpy(&childObjectId, data, COMPLEX_TYPE_FIELD_SIZE);
  605. data += COMPLEX_TYPE_FIELD_SIZE;
  606. bytesRead += COMPLEX_TYPE_FIELD_SIZE;
  607. if (curField != nullptr)
  608. {
  609. SPtr<SerializedObject> serializedField = nullptr;
  610. if (childObjectId > 0)
  611. {
  612. auto findObj = mInterimObjectMap.find(childObjectId);
  613. if (findObj == mInterimObjectMap.end())
  614. {
  615. serializedField = bs_shared_ptr_new<SerializedObject>();
  616. mInterimObjectMap.insert(std::make_pair(childObjectId, serializedField));
  617. }
  618. else
  619. serializedField = findObj->second;
  620. }
  621. serializedEntry = serializedField;
  622. hasModification = true;
  623. }
  624. break;
  625. }
  626. case SerializableFT_Reflectable:
  627. {
  628. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  629. if (curField != nullptr)
  630. {
  631. UINT32 bytesReadStart = bytesRead;
  632. SPtr<SerializedObject> serializedChildObj;
  633. decodeIntermediateInternal(data, dataLength, bytesRead, serializedChildObj, copyData);
  634. serializedEntry = serializedChildObj;
  635. hasModification = true;
  636. UINT32 complexTypeSize = bytesRead - bytesReadStart;
  637. data += complexTypeSize;
  638. }
  639. break;
  640. }
  641. case SerializableFT_Plain:
  642. {
  643. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  644. UINT32 typeSize = fieldSize;
  645. if (hasDynamicSize)
  646. memcpy(&typeSize, data, sizeof(UINT32));
  647. if (curField != nullptr)
  648. {
  649. SPtr<SerializedField> serializedField = bs_shared_ptr_new<SerializedField>();
  650. if (copyData)
  651. {
  652. serializedField->value = (UINT8*)bs_alloc(typeSize);
  653. memcpy(serializedField->value, data, typeSize);
  654. serializedField->ownsMemory = true;
  655. }
  656. else
  657. serializedField->value = data;
  658. serializedField->size = typeSize;
  659. serializedEntry = serializedField;
  660. hasModification = true;
  661. }
  662. data += typeSize;
  663. bytesRead += typeSize;
  664. break;
  665. }
  666. case SerializableFT_DataBlock:
  667. {
  668. RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
  669. if ((bytesRead + DATA_BLOCK_TYPE_FIELD_SIZE) > dataLength)
  670. {
  671. BS_EXCEPT(InternalErrorException,
  672. "Error decoding data.");
  673. }
  674. // Data block size
  675. UINT32 dataBlockSize = 0;
  676. memcpy(&dataBlockSize, data, DATA_BLOCK_TYPE_FIELD_SIZE);
  677. data += DATA_BLOCK_TYPE_FIELD_SIZE;
  678. bytesRead += DATA_BLOCK_TYPE_FIELD_SIZE;
  679. if ((bytesRead + dataBlockSize) > dataLength)
  680. {
  681. BS_EXCEPT(InternalErrorException,
  682. "Error decoding data.");
  683. }
  684. // Data block data
  685. if (curField != nullptr)
  686. {
  687. SPtr<SerializedField> serializedField = bs_shared_ptr_new<SerializedField>();
  688. if (copyData)
  689. {
  690. serializedField->value = (UINT8*)bs_alloc(dataBlockSize);
  691. memcpy(serializedField->value, data, dataBlockSize);
  692. serializedField->ownsMemory = true;
  693. }
  694. else
  695. serializedField->value = data;
  696. serializedField->size = dataBlockSize;
  697. serializedEntry = serializedField;
  698. hasModification = true;
  699. }
  700. data += dataBlockSize;
  701. bytesRead += dataBlockSize;
  702. break;
  703. }
  704. default:
  705. BS_EXCEPT(InternalErrorException,
  706. "Error decoding data. Encountered a type I don't know how to decode. Type: " + toString(UINT32(fieldType)) +
  707. ", Is array: " + toString(isArray));
  708. }
  709. }
  710. if (hasModification)
  711. {
  712. SerializedEntry entry;
  713. entry.fieldId = curGenericField->mUniqueId;
  714. entry.serialized = serializedEntry;
  715. serializedSubObject->entries.insert(std::make_pair(curGenericField->mUniqueId, entry));
  716. }
  717. }
  718. return false;
  719. }
  720. void BinarySerializer::decodeInternal(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& serializableObject)
  721. {
  722. UINT32 numSubObjects = (UINT32)serializableObject->subObjects.size();
  723. Vector<RTTITypeBase*> rttiTypes;
  724. for (UINT32 subObjectIdx = 0; subObjectIdx < numSubObjects; subObjectIdx++)
  725. {
  726. const SerializedSubObject& subObject = serializableObject->subObjects[subObjectIdx];
  727. RTTITypeBase* rtti = IReflectable::_getRTTIfromTypeId(subObject.typeId);
  728. if (rtti == nullptr)
  729. continue;
  730. rtti->onDeserializationStarted(object.get());
  731. rttiTypes.push_back(rtti);
  732. UINT32 numFields = rtti->getNumFields();
  733. for (UINT32 fieldIdx = 0; fieldIdx < numFields; fieldIdx++)
  734. {
  735. RTTIField* curGenericField = rtti->getField(fieldIdx);
  736. auto iterFindFieldData = subObject.entries.find(curGenericField->mUniqueId);
  737. if (iterFindFieldData == subObject.entries.end())
  738. continue;
  739. SPtr<SerializedInstance> entryData = iterFindFieldData->second.serialized;
  740. if (curGenericField->isArray())
  741. {
  742. SPtr<SerializedArray> arrayData = std::static_pointer_cast<SerializedArray>(entryData);
  743. UINT32 arrayNumElems = (UINT32)arrayData->numElements;
  744. curGenericField->setArraySize(object.get(), arrayNumElems);
  745. switch (curGenericField->mType)
  746. {
  747. case SerializableFT_ReflectablePtr:
  748. {
  749. RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
  750. for (auto& arrayElem : arrayData->entries)
  751. {
  752. SPtr<SerializedObject> arrayElemData = std::static_pointer_cast<SerializedObject>(arrayElem.second.serialized);
  753. RTTITypeBase* childRtti = nullptr;
  754. if (arrayElemData != nullptr)
  755. childRtti = IReflectable::_getRTTIfromTypeId(arrayElemData->getRootTypeId());
  756. if (childRtti != nullptr)
  757. {
  758. auto findObj = mObjectMap.find(arrayElemData);
  759. if (findObj == mObjectMap.end())
  760. {
  761. SPtr<IReflectable> newObject = childRtti->newRTTIObject();
  762. findObj = mObjectMap.insert(std::make_pair(arrayElemData, ObjectToDecode(newObject, arrayElemData))).first;
  763. }
  764. ObjectToDecode& objToDecode = findObj->second;
  765. bool needsDecoding = (curField->getFlags() & RTTI_Flag_WeakRef) == 0 && !objToDecode.isDecoded;
  766. if (needsDecoding)
  767. {
  768. decodeInternal(objToDecode.object, objToDecode.serializedObject);
  769. objToDecode.isDecoded = true;
  770. }
  771. curField->setArrayValue(object.get(), arrayElem.first, objToDecode.object);
  772. }
  773. else
  774. {
  775. curField->setArrayValue(object.get(), arrayElem.first, nullptr);
  776. }
  777. }
  778. }
  779. break;
  780. case SerializableFT_Reflectable:
  781. {
  782. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  783. for (auto& arrayElem : arrayData->entries)
  784. {
  785. SPtr<SerializedObject> arrayElemData = std::static_pointer_cast<SerializedObject>(arrayElem.second.serialized);
  786. RTTITypeBase* childRtti = nullptr;
  787. if (arrayElemData != nullptr)
  788. childRtti = IReflectable::_getRTTIfromTypeId(arrayElemData->getRootTypeId());
  789. if (childRtti != nullptr)
  790. {
  791. SPtr<IReflectable> newObject = childRtti->newRTTIObject();
  792. decodeInternal(newObject, arrayElemData);
  793. curField->setArrayValue(object.get(), arrayElem.first, *newObject);
  794. }
  795. }
  796. break;
  797. }
  798. case SerializableFT_Plain:
  799. {
  800. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  801. for (auto& arrayElem : arrayData->entries)
  802. {
  803. SPtr<SerializedField> fieldData = std::static_pointer_cast<SerializedField>(arrayElem.second.serialized);
  804. if (fieldData != nullptr)
  805. {
  806. curField->arrayElemFromBuffer(object.get(), arrayElem.first, fieldData->value);
  807. }
  808. }
  809. }
  810. break;
  811. }
  812. }
  813. else
  814. {
  815. switch (curGenericField->mType)
  816. {
  817. case SerializableFT_ReflectablePtr:
  818. {
  819. RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
  820. SPtr<SerializedObject> fieldObjectData = std::static_pointer_cast<SerializedObject>(entryData);
  821. RTTITypeBase* childRtti = nullptr;
  822. if (fieldObjectData != nullptr)
  823. childRtti = IReflectable::_getRTTIfromTypeId(fieldObjectData->getRootTypeId());
  824. if (childRtti != nullptr)
  825. {
  826. auto findObj = mObjectMap.find(fieldObjectData);
  827. if (findObj == mObjectMap.end())
  828. {
  829. SPtr<IReflectable> newObject = childRtti->newRTTIObject();
  830. findObj = mObjectMap.insert(std::make_pair(fieldObjectData, ObjectToDecode(newObject, fieldObjectData))).first;
  831. }
  832. ObjectToDecode& objToDecode = findObj->second;
  833. bool needsDecoding = (curField->getFlags() & RTTI_Flag_WeakRef) == 0 && !objToDecode.isDecoded;
  834. if (needsDecoding)
  835. {
  836. decodeInternal(objToDecode.object, objToDecode.serializedObject);
  837. objToDecode.isDecoded = true;
  838. }
  839. curField->setValue(object.get(), objToDecode.object);
  840. }
  841. else
  842. {
  843. curField->setValue(object.get(), nullptr);
  844. }
  845. }
  846. break;
  847. case SerializableFT_Reflectable:
  848. {
  849. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  850. SPtr<SerializedObject> fieldObjectData = std::static_pointer_cast<SerializedObject>(entryData);
  851. RTTITypeBase* childRtti = nullptr;
  852. if (fieldObjectData != nullptr)
  853. childRtti = IReflectable::_getRTTIfromTypeId(fieldObjectData->getRootTypeId());
  854. if (childRtti != nullptr)
  855. {
  856. SPtr<IReflectable> newObject = childRtti->newRTTIObject();
  857. decodeInternal(newObject, fieldObjectData);
  858. curField->setValue(object.get(), *newObject);
  859. }
  860. break;
  861. }
  862. case SerializableFT_Plain:
  863. {
  864. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  865. SPtr<SerializedField> fieldData = std::static_pointer_cast<SerializedField>(entryData);
  866. if (fieldData != nullptr)
  867. {
  868. curField->fromBuffer(object.get(), fieldData->value);
  869. }
  870. }
  871. break;
  872. case SerializableFT_DataBlock:
  873. {
  874. RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
  875. SPtr<SerializedField> fieldData = std::static_pointer_cast<SerializedField>(entryData);
  876. if (fieldData != nullptr)
  877. {
  878. UINT8* dataCopy = curField->allocate(object.get(), fieldData->size); // TODO - Low priority. I need to read files better, so I
  879. memcpy(dataCopy, fieldData->value, fieldData->size); // can just pass the buffer pointer directly without copying (possibly large amounts of data)
  880. ManagedDataBlock value(dataCopy, fieldData->size); // Not managed because I assume the owner class will decide whether to delete the data or keep it
  881. curField->setValue(object.get(), value);
  882. }
  883. break;
  884. }
  885. }
  886. }
  887. }
  888. }
  889. for (auto iterFind = rttiTypes.rbegin(); iterFind != rttiTypes.rend(); ++iterFind)
  890. {
  891. (*iterFind)->onDeserializationEnded(object.get());
  892. }
  893. }
  894. UINT32 BinarySerializer::encodeFieldMetaData(UINT16 id, UINT8 size, bool array,
  895. SerializableFieldType type, bool hasDynamicSize, bool terminator)
  896. {
  897. // If O == 0 - Meta contains field information (Encoded using this method)
  898. //// Encoding: IIII IIII IIII IIII SSSS SSSS xTYP DCAO
  899. //// I - Id
  900. //// S - Size
  901. //// C - Complex
  902. //// A - Array
  903. //// D - Data block
  904. //// P - Complex ptr
  905. //// O - Object descriptor
  906. //// Y - Plain field has dynamic size
  907. //// T - Terminator (last field in an object)
  908. return (id << 16 | size << 8 |
  909. (array ? 0x02 : 0) |
  910. ((type == SerializableFT_DataBlock) ? 0x04 : 0) |
  911. ((type == SerializableFT_Reflectable) ? 0x08 : 0) |
  912. ((type == SerializableFT_ReflectablePtr) ? 0x10 : 0) |
  913. (hasDynamicSize ? 0x20 : 0) |
  914. (terminator ? 0x40 : 0)); // TODO - Low priority. Technically I could encode this much more tightly, and use var-ints for ID
  915. }
  916. void BinarySerializer::decodeFieldMetaData(UINT32 encodedData, UINT16& id, UINT8& size,
  917. bool& array, SerializableFieldType& type, bool& hasDynamicSize, bool& terminator)
  918. {
  919. if(isObjectMetaData(encodedData))
  920. {
  921. BS_EXCEPT(InternalErrorException,
  922. "Meta data represents an object description but is trying to be decoded as a field descriptor.");
  923. }
  924. terminator = (encodedData & 0x40) != 0;
  925. hasDynamicSize = (encodedData & 0x20) != 0;
  926. if((encodedData & 0x10) != 0)
  927. type = SerializableFT_ReflectablePtr;
  928. else if((encodedData & 0x08) != 0)
  929. type = SerializableFT_Reflectable;
  930. else if((encodedData & 0x04) != 0)
  931. type = SerializableFT_DataBlock;
  932. else
  933. type = SerializableFT_Plain;
  934. array = (encodedData & 0x02) != 0;
  935. size = (UINT8)((encodedData >> 8) & 0xFF);
  936. id = (UINT16)((encodedData >> 16) & 0xFFFF);
  937. }
  938. BinarySerializer::ObjectMetaData BinarySerializer::encodeObjectMetaData(UINT32 objId, UINT32 objTypeId, bool isBaseClass)
  939. {
  940. // If O == 1 - Meta contains object instance information (Encoded using encodeObjectMetaData)
  941. //// Encoding: SSSS SSSS SSSS SSSS xxxx xxxx xxxx xxBO
  942. //// S - Size of the object identifier
  943. //// O - Object descriptor
  944. //// B - Base class indicator
  945. if(objId > 1073741823)
  946. {
  947. BS_EXCEPT(InvalidParametersException, "Object ID is larger than we can store (max 30 bits): " + toString(objId));
  948. }
  949. ObjectMetaData metaData;
  950. metaData.objectMeta = (objId << 2) | (isBaseClass ? 0x02 : 0) | 0x01;
  951. metaData.typeId = objTypeId;
  952. return metaData;
  953. }
  954. void BinarySerializer::decodeObjectMetaData(BinarySerializer::ObjectMetaData encodedData, UINT32& objId, UINT32& objTypeId, bool& isBaseClass)
  955. {
  956. if(!isObjectMetaData(encodedData.objectMeta))
  957. {
  958. BS_EXCEPT(InternalErrorException,
  959. "Meta data represents a field description but is trying to be decoded as an object descriptor.");
  960. }
  961. objId = (encodedData.objectMeta >> 2) & 0x3FFFFFFF;
  962. isBaseClass = (encodedData.objectMeta & 0x02) != 0;
  963. objTypeId = encodedData.typeId;
  964. }
  965. bool BinarySerializer::isObjectMetaData(UINT32 encodedData)
  966. {
  967. return ((encodedData & 0x01) != 0);
  968. }
  969. UINT8* BinarySerializer::complexTypeToBuffer(IReflectable* object, UINT8* buffer, UINT32& bufferLength,
  970. UINT32* bytesWritten, std::function<UINT8*(UINT8*, UINT32, UINT32&)> flushBufferCallback, bool shallow)
  971. {
  972. if (object != nullptr)
  973. {
  974. buffer = encodeInternal(object, 0, buffer, bufferLength, bytesWritten, flushBufferCallback, shallow);
  975. // Encode terminator field
  976. // Complex types require terminator fields because they can be embedded within other complex types and we need
  977. // to know when their fields end and parent's resume
  978. int metaData = encodeFieldMetaData(0, 0, false, SerializableFT_Plain, false, true);
  979. COPY_TO_BUFFER(&metaData, META_SIZE)
  980. }
  981. return buffer;
  982. }
  983. UINT8* BinarySerializer::dataBlockToBuffer(UINT8* data, UINT32 size, UINT8* buffer, UINT32& bufferLength, UINT32* bytesWritten,
  984. std::function<UINT8*(UINT8* buffer, UINT32 bytesWritten, UINT32& newBufferSize)> flushBufferCallback)
  985. {
  986. UINT32 remainingSize = size;
  987. while (remainingSize > 0)
  988. {
  989. UINT32 remainingSpaceInBuffer = bufferLength - *bytesWritten;
  990. if (remainingSize <= remainingSpaceInBuffer)
  991. {
  992. COPY_TO_BUFFER(data, remainingSize);
  993. remainingSize = 0;
  994. }
  995. else
  996. {
  997. memcpy(buffer, data, remainingSpaceInBuffer);
  998. buffer += remainingSpaceInBuffer;
  999. *bytesWritten += remainingSpaceInBuffer;
  1000. data += remainingSpaceInBuffer;
  1001. remainingSize -= remainingSpaceInBuffer;
  1002. mTotalBytesWritten += *bytesWritten;
  1003. buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength);
  1004. if (buffer == nullptr || bufferLength == 0)
  1005. return nullptr;
  1006. *bytesWritten = 0;
  1007. }
  1008. }
  1009. return buffer;
  1010. }
  1011. UINT32 BinarySerializer::findOrCreatePersistentId(IReflectable* object)
  1012. {
  1013. void* ptrAddress = (void*)object;
  1014. auto findIter = mObjectAddrToId.find(ptrAddress);
  1015. if(findIter != mObjectAddrToId.end())
  1016. return findIter->second;
  1017. UINT32 objId = mLastUsedObjectId++;
  1018. mObjectAddrToId.insert(std::make_pair(ptrAddress, objId));
  1019. return objId;
  1020. }
  1021. UINT32 BinarySerializer::registerObjectPtr(std::shared_ptr<IReflectable> object)
  1022. {
  1023. if(object == nullptr)
  1024. return 0;
  1025. void* ptrAddress = (void*)object.get();
  1026. auto iterFind = mObjectAddrToId.find(ptrAddress);
  1027. if(iterFind == mObjectAddrToId.end())
  1028. {
  1029. UINT32 objId = findOrCreatePersistentId(object.get());
  1030. mObjectsToEncode.push_back(ObjectToEncode(objId, object));
  1031. mObjectAddrToId.insert(std::make_pair(ptrAddress, objId));
  1032. return objId;
  1033. }
  1034. return iterFind->second;
  1035. }
  1036. }
  1037. #undef COPY_TO_BUFFER