CmBinarySerializer.cpp 34 KB

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