BsBinarySerializer.cpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. //__________________________ Banshee Project - A modern game development toolkit _________________________________//
  2. //_____________________________________ www.banshee-project.com __________________________________________________//
  3. //________________________ Copyright (c) 2014 Marko Pintera. All rights reserved. ________________________________//
  4. #include "BsBinarySerializer.h"
  5. #include "BsException.h"
  6. #include "BsDebug.h"
  7. #include "BsIReflectable.h"
  8. #include "BsRTTIType.h"
  9. #include "BsRTTIField.h"
  10. #include "BsRTTIPlainField.h"
  11. #include "BsRTTIReflectableField.h"
  12. #include "BsRTTIReflectablePtrField.h"
  13. #include "BsRTTIManagedDataBlockField.h"
  14. #include <unordered_set>
  15. /**
  16. * @brief A macro that represents a block of code that gets used a lot inside
  17. * encodeInternal. It checks if the buffer has enough space, and if it does
  18. * it copies the data from the specified location and increments the needed
  19. * pointers and counters. If there is not enough space the buffer is flushed
  20. * (hopefully to make some space). If there is still not enough space the entire
  21. * encoding process ends.
  22. *
  23. * @param dataPtr Pointer to data which to copy.
  24. * @param size Size of the data to copy
  25. */
  26. #define COPY_TO_BUFFER(dataIter, size) \
  27. if((*bytesWritten + size##) > bufferLength) \
  28. { \
  29. mTotalBytesWritten += *bytesWritten; \
  30. buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength); \
  31. if(buffer == nullptr || bufferLength < size##) return nullptr; \
  32. *bytesWritten = 0; \
  33. } \
  34. \
  35. memcpy(buffer, dataIter##, size##); \
  36. buffer += size##; \
  37. *bytesWritten += size##;
  38. namespace BansheeEngine
  39. {
  40. BinarySerializer::BinarySerializer()
  41. :mLastUsedObjectId(1)
  42. {
  43. }
  44. void BinarySerializer::encode(IReflectable* object, UINT8* buffer, UINT32 bufferLength, int* bytesWritten, std::function<UINT8*(UINT8*, int, UINT32&)> flushBufferCallback)
  45. {
  46. mObjectsToEncode.clear();
  47. mObjectAddrToId.clear();
  48. mLastUsedObjectId = 1;
  49. *bytesWritten = 0;
  50. mTotalBytesWritten = 0;
  51. UINT8* bufferStart = buffer;
  52. UINT32 objectId = findOrCreatePersistentId(object);
  53. // Encode primary object and its value types
  54. buffer = encodeInternal(object, objectId, buffer, bufferLength, bytesWritten, flushBufferCallback);
  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, bufferLength, bytesWritten, flushBufferCallback);
  76. if(buffer == nullptr)
  77. {
  78. BS_EXCEPT(InternalErrorException,
  79. "Destination buffer is null or not large enough.");
  80. }
  81. foundObjectToProcess = true;
  82. break; // Need to start over as mObjectsToSerialize was possibly modified
  83. }
  84. if(!foundObjectToProcess) // We're done
  85. break;
  86. }
  87. // Final flush
  88. if(*bytesWritten > 0)
  89. {
  90. mTotalBytesWritten += *bytesWritten;
  91. buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength);
  92. }
  93. *bytesWritten = mTotalBytesWritten;
  94. mObjectsToEncode.clear();
  95. mObjectAddrToId.clear();
  96. }
  97. std::shared_ptr<IReflectable> BinarySerializer::decode(UINT8* data, UINT32 dataLength)
  98. {
  99. mObjectMap.clear();
  100. // Create empty instances of all ptr objects
  101. UINT32 bytesRead = 0;
  102. UINT8* dataIter = nullptr;
  103. std::shared_ptr<IReflectable> rootObject = nullptr;
  104. do
  105. {
  106. dataIter = data + bytesRead;
  107. if(sizeof(UINT32) > dataLength)
  108. {
  109. BS_EXCEPT(InternalErrorException,
  110. "Error decoding data.");
  111. }
  112. ObjectMetaData objectMetaData;
  113. objectMetaData.objectMeta = 0;
  114. objectMetaData.typeId = 0;
  115. memcpy(&objectMetaData, dataIter, sizeof(ObjectMetaData));
  116. UINT32 objectId = 0;
  117. UINT32 objectTypeId = 0;
  118. bool isBaseClass = false;
  119. decodeObjectMetaData(objectMetaData, objectId, objectTypeId, isBaseClass);
  120. if(isBaseClass)
  121. {
  122. BS_EXCEPT(InternalErrorException, "Encountered a base-class object while looking for a new object. " \
  123. "Base class objects are only supposed to be parts of a larger object.");
  124. }
  125. std::shared_ptr<IReflectable> object = IReflectable::createInstanceFromTypeId(objectTypeId);
  126. mObjectMap.insert(std::make_pair(objectId, ObjectToDecode(objectId, object, dataIter, bytesRead)));
  127. if(rootObject == nullptr)
  128. rootObject = object;
  129. } while (decodeInternal(nullptr, dataIter, dataLength, bytesRead));
  130. // Now go through all of the objects and actually decode them
  131. for(auto iter = mObjectMap.begin(); iter != mObjectMap.end(); ++iter)
  132. {
  133. ObjectToDecode& objToDecode = iter->second;
  134. if(objToDecode.isDecoded)
  135. continue;
  136. UINT32 objectBytesRead = objToDecode.locationInFile;
  137. decodeInternal(objToDecode.object, objToDecode.locationInBuffer, dataLength, objectBytesRead);
  138. }
  139. mObjectMap.clear();
  140. return rootObject;
  141. }
  142. UINT8* BinarySerializer::encodeInternal(IReflectable* object, UINT32 objectId, UINT8* buffer, UINT32& bufferLength,
  143. int* bytesWritten, std::function<UINT8*(UINT8*, int, UINT32&)> flushBufferCallback)
  144. {
  145. static const UINT32 META_SIZE = 4; // Meta field size
  146. static const UINT32 NUM_ELEM_FIELD_SIZE = 4; // Size of the field storing number of array elements
  147. static const UINT32 COMPLEX_TYPE_SIZE = 4; // Size of the field storing the size of a child complex type
  148. RTTITypeBase* si = object->getRTTI();
  149. bool isBaseClass = false;
  150. // If an object has base classes, we need to iterate through all of them
  151. do
  152. {
  153. si->onSerializationStarted(object);
  154. // Encode object ID & type
  155. ObjectMetaData objectMetaData = encodeObjectMetaData(objectId, si->getRTTIId(), isBaseClass);
  156. COPY_TO_BUFFER(&objectMetaData, sizeof(ObjectMetaData))
  157. int numFields = si->getNumFields();
  158. for(int i = 0; i < numFields; i++)
  159. {
  160. RTTIField* curGenericField = si->getField(i);
  161. // Copy field ID & other meta-data like field size and type
  162. int metaData = encodeFieldMetaData(curGenericField->mUniqueId, curGenericField->getTypeSize(),
  163. curGenericField->mIsVectorType, curGenericField->mType, curGenericField->hasDynamicSize());
  164. COPY_TO_BUFFER(&metaData, META_SIZE)
  165. if(curGenericField->mIsVectorType)
  166. {
  167. UINT32 arrayNumElems = curGenericField->getArraySize(object);
  168. // Copy num vector elements
  169. COPY_TO_BUFFER(&arrayNumElems, NUM_ELEM_FIELD_SIZE)
  170. switch(curGenericField->mType)
  171. {
  172. case SerializableFT_ReflectablePtr:
  173. {
  174. RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
  175. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  176. {
  177. std::shared_ptr<IReflectable> childObject = curField->getArrayValue(object, arrIdx);
  178. UINT32 objId = registerObjectPtr(childObject);
  179. COPY_TO_BUFFER(&objId, sizeof(UINT32))
  180. }
  181. break;
  182. }
  183. case SerializableFT_Reflectable:
  184. {
  185. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  186. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  187. {
  188. IReflectable& childObject = curField->getArrayValue(object, arrIdx);
  189. buffer = complexTypeToBuffer(&childObject, buffer, bufferLength, bytesWritten, flushBufferCallback);
  190. if(buffer == nullptr)
  191. {
  192. si->onSerializationEnded(object);
  193. return nullptr;
  194. }
  195. }
  196. break;
  197. }
  198. case SerializableFT_Plain:
  199. {
  200. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  201. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  202. {
  203. UINT32 typeSize = 0;
  204. if(curField->hasDynamicSize())
  205. typeSize = curField->getArrayElemDynamicSize(object, arrIdx);
  206. else
  207. typeSize = curField->getTypeSize();
  208. if((*bytesWritten + typeSize) > bufferLength)
  209. {
  210. mTotalBytesWritten += *bytesWritten;
  211. buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength);
  212. if(buffer == nullptr || bufferLength < typeSize)
  213. {
  214. return nullptr;
  215. si->onSerializationEnded(object);
  216. }
  217. *bytesWritten = 0;
  218. }
  219. curField->arrayElemToBuffer(object, arrIdx, buffer);
  220. buffer += typeSize;
  221. *bytesWritten += typeSize;
  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 = curField->getValue(object);
  239. UINT32 objId = registerObjectPtr(childObject);
  240. COPY_TO_BUFFER(&objId, sizeof(UINT32))
  241. break;
  242. }
  243. case SerializableFT_Reflectable:
  244. {
  245. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  246. IReflectable& childObject = curField->getValue(object);
  247. buffer = complexTypeToBuffer(&childObject, buffer, bufferLength, bytesWritten, flushBufferCallback);
  248. if(buffer == nullptr)
  249. {
  250. si->onSerializationEnded(object);
  251. return nullptr;
  252. }
  253. break;
  254. }
  255. case SerializableFT_Plain:
  256. {
  257. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  258. UINT32 typeSize = 0;
  259. if(curField->hasDynamicSize())
  260. typeSize = curField->getDynamicSize(object);
  261. else
  262. typeSize = curField->getTypeSize();
  263. if((*bytesWritten + typeSize) > bufferLength)
  264. {
  265. mTotalBytesWritten += *bytesWritten;
  266. buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength);
  267. if(buffer == nullptr || bufferLength < typeSize)
  268. {
  269. si->onSerializationEnded(object);
  270. return nullptr;
  271. }
  272. *bytesWritten = 0;
  273. }
  274. curField->toBuffer(object, buffer);
  275. buffer += typeSize;
  276. *bytesWritten += typeSize;
  277. break;
  278. }
  279. case SerializableFT_DataBlock:
  280. {
  281. RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
  282. ManagedDataBlock value = curField->getValue(object);
  283. // Data block size
  284. UINT32 dataBlockSize = value.getSize();
  285. COPY_TO_BUFFER(&dataBlockSize, sizeof(UINT32))
  286. // Data block data
  287. UINT8* dataToStore = value.getData();
  288. UINT32 remainingSize = dataBlockSize;
  289. while(remainingSize > 0)
  290. {
  291. UINT32 remainingSpaceInBuffer = bufferLength - *bytesWritten;
  292. if(remainingSize <= remainingSpaceInBuffer)
  293. {
  294. COPY_TO_BUFFER(dataToStore, remainingSize);
  295. remainingSize = 0;
  296. }
  297. else
  298. {
  299. memcpy(buffer, dataToStore, remainingSpaceInBuffer);
  300. buffer += remainingSpaceInBuffer;
  301. *bytesWritten += remainingSpaceInBuffer;
  302. dataToStore += remainingSpaceInBuffer;
  303. remainingSize -= remainingSpaceInBuffer;
  304. mTotalBytesWritten += *bytesWritten;
  305. buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength);
  306. if(buffer == nullptr || bufferLength == 0)
  307. {
  308. si->onSerializationEnded(object);
  309. return nullptr;
  310. }
  311. *bytesWritten = 0;
  312. }
  313. }
  314. break;
  315. }
  316. default:
  317. BS_EXCEPT(InternalErrorException,
  318. "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
  319. ", Is array: " + toString(curGenericField->mIsVectorType));
  320. }
  321. }
  322. }
  323. si->onSerializationEnded(object);
  324. si = si->getBaseClass();
  325. isBaseClass = true;
  326. } while(si != nullptr); // Repeat until we reach the top of the inheritance hierarchy
  327. return buffer;
  328. }
  329. bool BinarySerializer::decodeInternal(std::shared_ptr<IReflectable> object, UINT8* data, UINT32 dataLength, UINT32& bytesRead)
  330. {
  331. static const int META_SIZE = 4; // Meta field size
  332. static const int NUM_ELEM_FIELD_SIZE = 4; // Size of the field storing number of array elements
  333. static const int COMPLEX_TYPE_FIELD_SIZE = 4; // Size of the field storing the size of a child complex type
  334. static const int DATA_BLOCK_TYPE_FIELD_SIZE = 4;
  335. bool moreObjectsToProcess = false;
  336. RTTITypeBase* si = nullptr;
  337. if(object != nullptr)
  338. {
  339. si = object->getRTTI();
  340. if(si != nullptr)
  341. si->onDeserializationStarted(object.get());
  342. }
  343. if((bytesRead + sizeof(ObjectMetaData)) > dataLength)
  344. {
  345. BS_EXCEPT(InternalErrorException,
  346. "Error decoding data.");
  347. }
  348. ObjectMetaData objectMetaData;
  349. objectMetaData.objectMeta = 0;
  350. objectMetaData.typeId = 0;
  351. memcpy(&objectMetaData, data, sizeof(ObjectMetaData));
  352. data += sizeof(ObjectMetaData);
  353. bytesRead += sizeof(ObjectMetaData);
  354. UINT32 objectId = 0;
  355. UINT32 objectTypeId = 0;
  356. bool objectIsBaseClass = false;
  357. decodeObjectMetaData(objectMetaData, objectId, objectTypeId, objectIsBaseClass);
  358. while(bytesRead < dataLength)
  359. {
  360. int metaData = -1;
  361. if((bytesRead + META_SIZE) > dataLength)
  362. {
  363. BS_EXCEPT(InternalErrorException,
  364. "Error decoding data.");
  365. }
  366. memcpy((void*)&metaData, data, META_SIZE);
  367. if(isObjectMetaData(metaData)) // We've reached a new object
  368. {
  369. if((bytesRead + sizeof(ObjectMetaData)) > dataLength)
  370. {
  371. BS_EXCEPT(InternalErrorException,
  372. "Error decoding data.");
  373. }
  374. ObjectMetaData objMetaData;
  375. objMetaData.objectMeta = 0;
  376. objMetaData.typeId = 0;
  377. memcpy(&objMetaData, data, sizeof(ObjectMetaData));
  378. UINT32 objId = 0;
  379. UINT32 objTypeId = 0;
  380. bool objIsBaseClass = false;
  381. decodeObjectMetaData(objMetaData, objId, objTypeId, objIsBaseClass);
  382. // If it's a base class, get base class RTTI and handle that
  383. if(objIsBaseClass)
  384. {
  385. if(si != nullptr)
  386. si = si->getBaseClass();
  387. // Saved and current base classes don't match, so just skip over all that data
  388. if(si == nullptr || si->getRTTIId() != objTypeId)
  389. {
  390. si = nullptr;
  391. }
  392. if(si != nullptr)
  393. {
  394. si->onDeserializationStarted(object.get());
  395. }
  396. data += sizeof(ObjectMetaData);
  397. bytesRead += sizeof(ObjectMetaData);
  398. continue;
  399. }
  400. else
  401. {
  402. if(objId != 0)
  403. {
  404. moreObjectsToProcess = true; // New object, break out of this method and begin processing it from scratch
  405. goto exit;
  406. }
  407. // Objects with ID == 0 represent complex types serialized by value, but they should only get serialized
  408. // if we encounter a field with one, not by just iterating through the file.
  409. BS_EXCEPT(InternalErrorException, "Object with ID 0 encountered. Cannot proceed with serialization.");
  410. }
  411. }
  412. data += META_SIZE;
  413. bytesRead += META_SIZE;
  414. bool isArray;
  415. SerializableFieldType fieldType;
  416. UINT16 fieldId;
  417. UINT8 fieldSize;
  418. bool hasDynamicSize;
  419. decodeFieldMetaData(metaData, fieldId, fieldSize, isArray, fieldType, hasDynamicSize);
  420. RTTIField* curGenericField = nullptr;
  421. if(si != nullptr)
  422. curGenericField = si->findField(fieldId);
  423. if(curGenericField != nullptr)
  424. {
  425. if(!hasDynamicSize && curGenericField->getTypeSize() != fieldSize)
  426. {
  427. BS_EXCEPT(InternalErrorException,
  428. "Data type mismatch. Type size stored in file and actual type size don't match. ("
  429. + toString(curGenericField->getTypeSize()) + " vs. " + toString(fieldSize) + ")");
  430. }
  431. if(curGenericField->mIsVectorType != isArray)
  432. {
  433. BS_EXCEPT(InternalErrorException,
  434. "Data type mismatch. One is array, other is a single type.");
  435. }
  436. if(curGenericField->mType != fieldType)
  437. {
  438. BS_EXCEPT(InternalErrorException,
  439. "Data type mismatch. Field types don't match. " + toString(UINT32(curGenericField->mType)) + " vs. " + toString(UINT32(fieldType)));
  440. }
  441. }
  442. int arrayNumElems = 1;
  443. if(isArray)
  444. {
  445. if((bytesRead + NUM_ELEM_FIELD_SIZE) > dataLength)
  446. {
  447. BS_EXCEPT(InternalErrorException,
  448. "Error decoding data.");
  449. }
  450. memcpy((void*)&arrayNumElems, data, NUM_ELEM_FIELD_SIZE);
  451. data += NUM_ELEM_FIELD_SIZE;
  452. bytesRead += NUM_ELEM_FIELD_SIZE;
  453. if(curGenericField != nullptr)
  454. curGenericField->setArraySize(object.get(), arrayNumElems);
  455. switch(fieldType)
  456. {
  457. case SerializableFT_ReflectablePtr:
  458. {
  459. RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
  460. for(int i = 0; i < arrayNumElems; i++)
  461. {
  462. if((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
  463. {
  464. BS_EXCEPT(InternalErrorException,
  465. "Error decoding data.");
  466. }
  467. int objectId = 0;
  468. memcpy(&objectId, data, COMPLEX_TYPE_FIELD_SIZE);
  469. data += COMPLEX_TYPE_FIELD_SIZE;
  470. bytesRead += COMPLEX_TYPE_FIELD_SIZE;
  471. if(curField != nullptr)
  472. {
  473. auto findObj = mObjectMap.find(objectId);
  474. if(findObj == mObjectMap.end())
  475. {
  476. if(objectId != 0)
  477. LOGWRN("When deserializing, object ID: " + toString(objectId) + " was found but no such object was contained in the file.");
  478. curField->setArrayValue(object.get(), i, nullptr);
  479. }
  480. else
  481. {
  482. ObjectToDecode& objToDecode = findObj->second;
  483. bool needsDecoding = (curField->getFlags() & RTTI_Flag_WeakRef) == 0 && !objToDecode.isDecoded;
  484. if(needsDecoding)
  485. {
  486. UINT32 objectBytesRead = objToDecode.locationInFile;
  487. decodeInternal(objToDecode.object, objToDecode.locationInBuffer, dataLength, objectBytesRead);
  488. objToDecode.isDecoded = true;
  489. }
  490. curField->setArrayValue(object.get(), i, objToDecode.object);
  491. }
  492. }
  493. }
  494. break;
  495. }
  496. case SerializableFT_Reflectable:
  497. {
  498. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  499. for(int i = 0; i < arrayNumElems; i++)
  500. {
  501. if((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
  502. {
  503. BS_EXCEPT(InternalErrorException,
  504. "Error decoding data.");
  505. }
  506. int complexTypeSize = 0;
  507. if(curField != nullptr)
  508. {
  509. std::shared_ptr<IReflectable> complexType = complexTypeFromBuffer(curField, data, &complexTypeSize);
  510. curField->setArrayValue(object.get(), i, *complexType);
  511. }
  512. else
  513. {
  514. memcpy(&complexTypeSize, data, COMPLEX_TYPE_FIELD_SIZE);
  515. complexTypeSize += COMPLEX_TYPE_FIELD_SIZE;
  516. }
  517. data += complexTypeSize;
  518. bytesRead += complexTypeSize;
  519. }
  520. break;
  521. }
  522. case SerializableFT_Plain:
  523. {
  524. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  525. for(int i = 0; i < arrayNumElems; i++)
  526. {
  527. UINT32 typeSize = fieldSize;
  528. if(hasDynamicSize)
  529. memcpy(&typeSize, data, sizeof(UINT32));
  530. if(curField != nullptr)
  531. curField->arrayElemFromBuffer(object.get(), i, data);
  532. data += typeSize;
  533. bytesRead += typeSize;
  534. }
  535. break;
  536. }
  537. default:
  538. BS_EXCEPT(InternalErrorException,
  539. "Error decoding data. Encountered a type I don't know how to decode. Type: " + toString(UINT32(fieldType)) +
  540. ", Is array: " + toString(isArray));
  541. }
  542. }
  543. else
  544. {
  545. switch(fieldType)
  546. {
  547. case SerializableFT_ReflectablePtr:
  548. {
  549. RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
  550. if((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
  551. {
  552. BS_EXCEPT(InternalErrorException,
  553. "Error decoding data.");
  554. }
  555. int objectId = 0;
  556. memcpy(&objectId, data, COMPLEX_TYPE_FIELD_SIZE);
  557. data += COMPLEX_TYPE_FIELD_SIZE;
  558. bytesRead += COMPLEX_TYPE_FIELD_SIZE;
  559. if(curField != nullptr)
  560. {
  561. auto findObj = mObjectMap.find(objectId);
  562. if(findObj == mObjectMap.end())
  563. {
  564. if(objectId != 0)
  565. LOGWRN("When deserializing, object ID: " + toString(objectId) + " was found but no such object was contained in the file.");
  566. curField->setValue(object.get(), nullptr);
  567. }
  568. else
  569. {
  570. ObjectToDecode& objToDecode = findObj->second;
  571. bool needsDecoding = (curField->getFlags() & RTTI_Flag_WeakRef) == 0 && !objToDecode.isDecoded;
  572. if(needsDecoding)
  573. {
  574. UINT32 objectBytesRead = objToDecode.locationInFile;
  575. decodeInternal(objToDecode.object, objToDecode.locationInBuffer, dataLength, objectBytesRead);
  576. objToDecode.isDecoded = true;
  577. }
  578. curField->setValue(object.get(), objToDecode.object);
  579. }
  580. }
  581. break;
  582. }
  583. case SerializableFT_Reflectable:
  584. {
  585. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  586. if((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
  587. {
  588. BS_EXCEPT(InternalErrorException,
  589. "Error decoding data.");
  590. }
  591. int complexTypeSize = 0;
  592. if(curField != nullptr)
  593. {
  594. std::shared_ptr<IReflectable> complexType = complexTypeFromBuffer(curField, data, &complexTypeSize);
  595. curField->setValue(object.get(), *complexType);
  596. }
  597. else
  598. {
  599. memcpy(&complexTypeSize, data, COMPLEX_TYPE_FIELD_SIZE);
  600. complexTypeSize += COMPLEX_TYPE_FIELD_SIZE;
  601. }
  602. data += complexTypeSize;
  603. bytesRead += complexTypeSize;
  604. break;
  605. }
  606. case SerializableFT_Plain:
  607. {
  608. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  609. UINT32 typeSize = fieldSize;
  610. if(hasDynamicSize)
  611. memcpy(&typeSize, data, sizeof(UINT32));
  612. if(curField != nullptr)
  613. curField->fromBuffer(object.get(), data);
  614. data += typeSize;
  615. bytesRead += typeSize;
  616. break;
  617. }
  618. case SerializableFT_DataBlock:
  619. {
  620. RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
  621. if((bytesRead + DATA_BLOCK_TYPE_FIELD_SIZE) > dataLength)
  622. {
  623. BS_EXCEPT(InternalErrorException,
  624. "Error decoding data.");
  625. }
  626. // Data block size
  627. UINT32 dataBlockSize = 0;
  628. memcpy(&dataBlockSize, data, DATA_BLOCK_TYPE_FIELD_SIZE);
  629. data += DATA_BLOCK_TYPE_FIELD_SIZE;
  630. bytesRead += DATA_BLOCK_TYPE_FIELD_SIZE;
  631. if((bytesRead + dataBlockSize) > dataLength)
  632. {
  633. BS_EXCEPT(InternalErrorException,
  634. "Error decoding data.");
  635. }
  636. // Data block data
  637. if(curField != nullptr)
  638. {
  639. UINT8* dataCopy = curField->allocate(object.get(), dataBlockSize); // TODO - Low priority. I need to read files better, so I
  640. memcpy(dataCopy, data, dataBlockSize); // can just pass the buffer pointer directly without copying (possibly large amounts of data)
  641. ManagedDataBlock value(dataCopy, dataBlockSize); // Not managed because I assume the owner class will decide whether to delete the data or keep it
  642. curField->setValue(object.get(), value);
  643. }
  644. data += dataBlockSize;
  645. bytesRead += dataBlockSize;
  646. break;
  647. }
  648. default:
  649. BS_EXCEPT(InternalErrorException,
  650. "Error decoding data. Encountered a type I don't know how to decode. Type: " + toString(UINT32(fieldType)) +
  651. ", Is array: " + toString(isArray));
  652. }
  653. }
  654. }
  655. moreObjectsToProcess = false;
  656. exit:
  657. // Finish serialization (in reverse order then it was started)
  658. if(object != nullptr)
  659. {
  660. Stack<RTTITypeBase*> typesToProcess;
  661. RTTITypeBase* currentType = object->getRTTI();
  662. while(currentType != nullptr)
  663. {
  664. typesToProcess.push(currentType);
  665. currentType = currentType->getBaseClass();
  666. }
  667. while(!typesToProcess.empty())
  668. {
  669. currentType = typesToProcess.top();
  670. typesToProcess.pop();
  671. currentType->onDeserializationEnded(object.get());
  672. }
  673. }
  674. return moreObjectsToProcess;
  675. }
  676. // TODO - This needs serious fixing, it doesn't account for all properties
  677. UINT32 BinarySerializer::getObjectSize(IReflectable* object)
  678. {
  679. if(object == nullptr)
  680. return 0;
  681. UINT32 objectSize = 0;
  682. RTTITypeBase* si = object->getRTTI();
  683. do
  684. {
  685. // Object ID + type data
  686. objectSize += sizeof(ObjectMetaData);
  687. int numFields = si->getNumFields();
  688. for(int i = 0; i < numFields; i++)
  689. {
  690. RTTIField* curGenericField = si->getField(i);
  691. // Field meta data
  692. objectSize += sizeof(UINT32);
  693. if(curGenericField->mIsVectorType)
  694. {
  695. UINT32 arrayNumElems = curGenericField->getArraySize(object);
  696. // Num array elems
  697. objectSize += sizeof(UINT32);
  698. switch(curGenericField->mType)
  699. {
  700. case SerializableFT_ReflectablePtr:
  701. {
  702. objectSize += sizeof(UINT32) * arrayNumElems;
  703. break;
  704. }
  705. case SerializableFT_Reflectable:
  706. {
  707. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  708. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  709. {
  710. IReflectable& childObject = curField->getArrayValue(object, arrIdx);
  711. objectSize += sizeof(UINT32); // Complex type size
  712. objectSize += getObjectSize(&childObject);
  713. }
  714. break;
  715. }
  716. case SerializableFT_Plain:
  717. {
  718. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  719. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  720. {
  721. UINT32 typeSize = 0;
  722. if(curField->hasDynamicSize())
  723. typeSize = curField->getArrayElemDynamicSize(object, arrIdx);
  724. else
  725. typeSize = curField->getTypeSize();
  726. objectSize += typeSize;
  727. }
  728. break;
  729. }
  730. default:
  731. BS_EXCEPT(InternalErrorException,
  732. "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
  733. ", Is array: " + toString(curGenericField->mIsVectorType));
  734. }
  735. }
  736. else
  737. {
  738. switch(curGenericField->mType)
  739. {
  740. case SerializableFT_ReflectablePtr:
  741. {
  742. objectSize += sizeof(UINT32);
  743. break;
  744. }
  745. case SerializableFT_Reflectable:
  746. {
  747. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  748. IReflectable& childObject = curField->getValue(object);
  749. objectSize += sizeof(UINT32); // Complex type size
  750. objectSize += getObjectSize(&childObject);
  751. break;
  752. }
  753. case SerializableFT_Plain:
  754. {
  755. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  756. UINT32 typeSize = 0;
  757. if(curField->hasDynamicSize())
  758. typeSize = curField->getDynamicSize(object);
  759. else
  760. typeSize = curField->getTypeSize();
  761. objectSize += typeSize;
  762. break;
  763. }
  764. case SerializableFT_DataBlock:
  765. {
  766. RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
  767. ManagedDataBlock value = curField->getValue(object);
  768. // Data block size
  769. UINT32 dataBlockSize = value.getSize();
  770. objectSize += sizeof(UINT32) + dataBlockSize;
  771. break;
  772. }
  773. default:
  774. BS_EXCEPT(InternalErrorException,
  775. "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
  776. ", Is array: " + toString(curGenericField->mIsVectorType));
  777. }
  778. }
  779. }
  780. si = si->getBaseClass();
  781. } while (si != nullptr);
  782. return objectSize;
  783. }
  784. UINT32 BinarySerializer::encodeFieldMetaData(UINT16 id, UINT8 size, bool array, SerializableFieldType type, bool hasDynamicSize)
  785. {
  786. // If O == 0 - Meta contains field information (Encoded using this method)
  787. //// Encoding: IIII IIII IIII IIII SSSS SSSS xxYP DCAO
  788. //// I - Id
  789. //// S - Size
  790. //// C - Complex
  791. //// A - Array
  792. //// D - Data block
  793. //// P - Complex ptr
  794. //// O - Object descriptor
  795. //// Y - Plain field has dynamic size
  796. return (id << 16 | size << 8 |
  797. (array ? 0x02 : 0) |
  798. ((type == SerializableFT_DataBlock) ? 0x04 : 0) |
  799. ((type == SerializableFT_Reflectable) ? 0x08 : 0) |
  800. ((type == SerializableFT_ReflectablePtr) ? 0x10 : 0) |
  801. (hasDynamicSize ? 0x20 : 0)); // TODO - Low priority. Technically I could encode this much more tightly, and use var-ints for ID
  802. }
  803. void BinarySerializer::decodeFieldMetaData(UINT32 encodedData, UINT16& id, UINT8& size, bool& array, SerializableFieldType& type, bool& hasDynamicSize)
  804. {
  805. if(isObjectMetaData(encodedData))
  806. {
  807. BS_EXCEPT(InternalErrorException,
  808. "Meta data represents an object description but is trying to be decoded as a field descriptor.");
  809. }
  810. hasDynamicSize = (encodedData & 0x20) != 0;
  811. if((encodedData & 0x10) != 0)
  812. type = SerializableFT_ReflectablePtr;
  813. else if((encodedData & 0x08) != 0)
  814. type = SerializableFT_Reflectable;
  815. else if((encodedData & 0x04) != 0)
  816. type = SerializableFT_DataBlock;
  817. else
  818. type = SerializableFT_Plain;
  819. array = (encodedData & 0x02) != 0;
  820. size = (UINT8)((encodedData >> 8) & 0xFF);
  821. id = (UINT16)((encodedData >> 16) & 0xFFFF);
  822. }
  823. BinarySerializer::ObjectMetaData BinarySerializer::encodeObjectMetaData(UINT32 objId, UINT32 objTypeId, bool isBaseClass)
  824. {
  825. // If O == 1 - Meta contains object instance information (Encoded using encodeObjectMetaData)
  826. //// Encoding: SSSS SSSS SSSS SSSS xxxx xxxx xxxx xxBO
  827. //// S - Size of the object identifier
  828. //// O - Object descriptor
  829. //// B - Base class indicator
  830. if(objId > 1073741823)
  831. {
  832. BS_EXCEPT(InvalidParametersException, "Object ID is larger than we can store (max 30 bits): " + toString(objId));
  833. }
  834. ObjectMetaData metaData;
  835. metaData.objectMeta = (objId << 2) | (isBaseClass ? 0x02 : 0) | 0x01;
  836. metaData.typeId = objTypeId;
  837. return metaData;
  838. }
  839. void BinarySerializer::decodeObjectMetaData(BinarySerializer::ObjectMetaData encodedData, UINT32& objId, UINT32& objTypeId, bool& isBaseClass)
  840. {
  841. if(!isObjectMetaData(encodedData.objectMeta))
  842. {
  843. BS_EXCEPT(InternalErrorException,
  844. "Meta data represents a field description but is trying to be decoded as an object descriptor.");
  845. }
  846. objId = (encodedData.objectMeta >> 2) & 0x3FFFFFFF;
  847. isBaseClass = (encodedData.objectMeta & 0x02) != 0;
  848. objTypeId = encodedData.typeId;
  849. }
  850. bool BinarySerializer::isObjectMetaData(UINT32 encodedData)
  851. {
  852. return ((encodedData & 0x01) != 0);
  853. }
  854. UINT8* BinarySerializer::complexTypeToBuffer(IReflectable* object, UINT8* buffer, UINT32& bufferLength,
  855. int* bytesWritten, std::function<UINT8*(UINT8*, int, UINT32&)> flushBufferCallback)
  856. {
  857. static const UINT32 COMPLEX_TYPE_FIELD_SIZE = 4; // Size of the field storing the size of a child complex type
  858. int complexTypeSize = 0;
  859. if(object != nullptr)
  860. complexTypeSize = getObjectSize(object);
  861. COPY_TO_BUFFER(&complexTypeSize, COMPLEX_TYPE_FIELD_SIZE)
  862. if(object != nullptr)
  863. return encodeInternal(object, 0, buffer, bufferLength, bytesWritten, flushBufferCallback);
  864. return buffer;
  865. }
  866. std::shared_ptr<IReflectable> BinarySerializer::complexTypeFromBuffer(RTTIReflectableFieldBase* field, UINT8* data, int* complexTypeSize)
  867. {
  868. static const int COMPLEX_TYPE_FIELD_SIZE = 4; // Size of the field storing the size of a child complex type
  869. memcpy(complexTypeSize, data, COMPLEX_TYPE_FIELD_SIZE);
  870. data += COMPLEX_TYPE_FIELD_SIZE;
  871. std::shared_ptr<IReflectable> emptyObject = nullptr;
  872. if(*complexTypeSize > 0)
  873. {
  874. emptyObject = field->newObject();
  875. UINT32 dummy = 0;
  876. decodeInternal(emptyObject, data, *complexTypeSize, dummy);
  877. }
  878. *complexTypeSize += COMPLEX_TYPE_FIELD_SIZE;
  879. return emptyObject;
  880. }
  881. UINT32 BinarySerializer::findOrCreatePersistentId(IReflectable* object)
  882. {
  883. void* ptrAddress = (void*)object;
  884. auto findIter = mObjectAddrToId.find(ptrAddress);
  885. if(findIter != mObjectAddrToId.end())
  886. return findIter->second;
  887. UINT32 objId = mLastUsedObjectId++;
  888. mObjectAddrToId.insert(std::make_pair(ptrAddress, objId));
  889. return objId;
  890. }
  891. UINT32 BinarySerializer::registerObjectPtr(std::shared_ptr<IReflectable> object)
  892. {
  893. if(object == nullptr)
  894. return 0;
  895. void* ptrAddress = (void*)object.get();
  896. auto iterFind = mObjectAddrToId.find(ptrAddress);
  897. if(iterFind == mObjectAddrToId.end())
  898. {
  899. UINT32 objId = findOrCreatePersistentId(object.get());
  900. mObjectsToEncode.push_back(ObjectToEncode(objId, object));
  901. mObjectAddrToId.insert(std::make_pair(ptrAddress, objId));
  902. return objId;
  903. }
  904. return iterFind->second;
  905. }
  906. }
  907. #undef COPY_TO_BUFFER