CmBinarySerializer.cpp 34 KB

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