CmBinarySerializer.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095
  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. std::unordered_set<UINT32> 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, boost::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. LOGWRN("When deserializing, object ID: " + toString(objectId) + " was found but no such object was contained in the file.");
  474. curField->setArrayValue(object.get(), i, nullptr);
  475. }
  476. else
  477. {
  478. ObjectToDecode& objToDecode = findObj->second;
  479. bool needsDecoding = (curField->getFlags() & RTTI_Flag_WeakRef) == 0 && !objToDecode.isDecoded;
  480. if(needsDecoding)
  481. {
  482. UINT32 objectBytesRead = objToDecode.locationInFile;
  483. decodeInternal(objToDecode.object, objToDecode.locationInBuffer, dataLength, objectBytesRead);
  484. objToDecode.isDecoded = true;
  485. }
  486. curField->setArrayValue(object.get(), i, objToDecode.object);
  487. }
  488. }
  489. }
  490. break;
  491. }
  492. case SerializableFT_Reflectable:
  493. {
  494. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  495. for(int i = 0; i < arrayNumElems; i++)
  496. {
  497. if((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
  498. {
  499. CM_EXCEPT(InternalErrorException,
  500. "Error decoding data.");
  501. }
  502. int complexTypeSize = 0;
  503. if(curField != nullptr)
  504. {
  505. std::shared_ptr<IReflectable> complexType = complexTypeFromBuffer(curField, data, &complexTypeSize);
  506. curField->setArrayValue(object.get(), i, *complexType);
  507. }
  508. else
  509. {
  510. memcpy(&complexTypeSize, data, COMPLEX_TYPE_FIELD_SIZE);
  511. complexTypeSize += COMPLEX_TYPE_FIELD_SIZE;
  512. }
  513. data += complexTypeSize;
  514. bytesRead += complexTypeSize;
  515. }
  516. break;
  517. }
  518. case SerializableFT_Plain:
  519. {
  520. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  521. for(int i = 0; i < arrayNumElems; i++)
  522. {
  523. UINT32 typeSize = fieldSize;
  524. if(hasDynamicSize)
  525. memcpy(&typeSize, data, sizeof(UINT32));
  526. if(curField != nullptr)
  527. curField->arrayElemFromBuffer(object.get(), i, data);
  528. data += typeSize;
  529. bytesRead += typeSize;
  530. }
  531. break;
  532. }
  533. default:
  534. CM_EXCEPT(InternalErrorException,
  535. "Error decoding data. Encountered a type I don't know how to decode. Type: " + toString(UINT32(fieldType)) +
  536. ", Is array: " + toString(isArray));
  537. }
  538. }
  539. else
  540. {
  541. switch(fieldType)
  542. {
  543. case SerializableFT_ReflectablePtr:
  544. {
  545. RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
  546. if((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
  547. {
  548. CM_EXCEPT(InternalErrorException,
  549. "Error decoding data.");
  550. }
  551. int objectId = 0;
  552. memcpy(&objectId, data, COMPLEX_TYPE_FIELD_SIZE);
  553. data += COMPLEX_TYPE_FIELD_SIZE;
  554. bytesRead += COMPLEX_TYPE_FIELD_SIZE;
  555. if(curField != nullptr)
  556. {
  557. auto findObj = mObjectMap.find(objectId);
  558. if(findObj == mObjectMap.end())
  559. {
  560. LOGWRN("When deserializing, object ID: " + toString(objectId) + " was found but no such object was contained in the file.");
  561. curField->setValue(object.get(), nullptr);
  562. }
  563. else
  564. {
  565. ObjectToDecode& objToDecode = findObj->second;
  566. bool needsDecoding = (curField->getFlags() & RTTI_Flag_WeakRef) == 0 && !objToDecode.isDecoded;
  567. if(needsDecoding)
  568. {
  569. UINT32 objectBytesRead = objToDecode.locationInFile;
  570. decodeInternal(objToDecode.object, objToDecode.locationInBuffer, dataLength, objectBytesRead);
  571. objToDecode.isDecoded = true;
  572. }
  573. curField->setValue(object.get(), objToDecode.object);
  574. }
  575. }
  576. break;
  577. }
  578. case SerializableFT_Reflectable:
  579. {
  580. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  581. if((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
  582. {
  583. CM_EXCEPT(InternalErrorException,
  584. "Error decoding data.");
  585. }
  586. int complexTypeSize = 0;
  587. if(curField != nullptr)
  588. {
  589. std::shared_ptr<IReflectable> complexType = complexTypeFromBuffer(curField, data, &complexTypeSize);
  590. curField->setValue(object.get(), *complexType);
  591. }
  592. else
  593. {
  594. memcpy(&complexTypeSize, data, COMPLEX_TYPE_FIELD_SIZE);
  595. complexTypeSize += COMPLEX_TYPE_FIELD_SIZE;
  596. }
  597. data += complexTypeSize;
  598. bytesRead += complexTypeSize;
  599. break;
  600. }
  601. case SerializableFT_Plain:
  602. {
  603. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  604. UINT32 typeSize = fieldSize;
  605. if(hasDynamicSize)
  606. memcpy(&typeSize, data, sizeof(UINT32));
  607. if(curField != nullptr)
  608. curField->fromBuffer(object.get(), data);
  609. data += typeSize;
  610. bytesRead += typeSize;
  611. break;
  612. }
  613. case SerializableFT_DataBlock:
  614. {
  615. RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
  616. if((bytesRead + DATA_BLOCK_TYPE_FIELD_SIZE) > dataLength)
  617. {
  618. CM_EXCEPT(InternalErrorException,
  619. "Error decoding data.");
  620. }
  621. // Data block size
  622. UINT32 dataBlockSize = 0;
  623. memcpy(&dataBlockSize, data, DATA_BLOCK_TYPE_FIELD_SIZE);
  624. data += DATA_BLOCK_TYPE_FIELD_SIZE;
  625. bytesRead += DATA_BLOCK_TYPE_FIELD_SIZE;
  626. if((bytesRead + dataBlockSize) > dataLength)
  627. {
  628. CM_EXCEPT(InternalErrorException,
  629. "Error decoding data.");
  630. }
  631. // Data block data
  632. if(curField != nullptr)
  633. {
  634. UINT8* dataCopy = curField->allocate(object.get(), dataBlockSize); // TODO - Low priority. I need to read files better, so I
  635. memcpy(dataCopy, data, dataBlockSize); // can just pass the buffer pointer directly without copying (possibly large amounts of data)
  636. ManagedDataBlock value(dataCopy, dataBlockSize); // Not managed because I assume the owner class will decide whether to delete the data or keep it
  637. curField->setValue(object.get(), value);
  638. }
  639. data += dataBlockSize;
  640. bytesRead += dataBlockSize;
  641. break;
  642. }
  643. default:
  644. CM_EXCEPT(InternalErrorException,
  645. "Error decoding data. Encountered a type I don't know how to decode. Type: " + toString(UINT32(fieldType)) +
  646. ", Is array: " + toString(isArray));
  647. }
  648. }
  649. }
  650. moreObjectsToProcess = false;
  651. exit:
  652. // Finish serialization (in reverse order then it was started)
  653. if(object != nullptr)
  654. {
  655. stack<RTTITypeBase*>::type typesToProcess;
  656. RTTITypeBase* currentType = object->getRTTI();
  657. while(currentType != nullptr)
  658. {
  659. typesToProcess.push(currentType);
  660. currentType = currentType->getBaseClass();
  661. }
  662. while(!typesToProcess.empty())
  663. {
  664. currentType = typesToProcess.top();
  665. typesToProcess.pop();
  666. currentType->onDeserializationEnded(object.get());
  667. }
  668. }
  669. return moreObjectsToProcess;
  670. }
  671. // TODO - This needs serious fixing, it doesn't account for all properties
  672. UINT32 BinarySerializer::getObjectSize(IReflectable* object)
  673. {
  674. if(object == nullptr)
  675. return 0;
  676. UINT32 objectSize = 0;
  677. RTTITypeBase* si = object->getRTTI();
  678. do
  679. {
  680. // Object ID + type data
  681. objectSize += sizeof(ObjectMetaData);
  682. int numFields = si->getNumFields();
  683. for(int i = 0; i < numFields; i++)
  684. {
  685. RTTIField* curGenericField = si->getField(i);
  686. // Field meta data
  687. objectSize += sizeof(UINT32);
  688. if(curGenericField->mIsVectorType)
  689. {
  690. UINT32 arrayNumElems = curGenericField->getArraySize(object);
  691. // Num array elems
  692. objectSize += sizeof(UINT32);
  693. switch(curGenericField->mType)
  694. {
  695. case SerializableFT_ReflectablePtr:
  696. {
  697. objectSize += sizeof(UINT32) * arrayNumElems;
  698. break;
  699. }
  700. case SerializableFT_Reflectable:
  701. {
  702. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  703. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  704. {
  705. IReflectable& childObject = curField->getArrayValue(object, arrIdx);
  706. objectSize += sizeof(UINT32); // Complex type size
  707. objectSize += getObjectSize(&childObject);
  708. }
  709. break;
  710. }
  711. case SerializableFT_Plain:
  712. {
  713. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  714. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  715. {
  716. UINT32 typeSize = 0;
  717. if(curField->hasDynamicSize())
  718. typeSize = curField->getArrayElemDynamicSize(object, arrIdx);
  719. else
  720. typeSize = curField->getTypeSize();
  721. objectSize += typeSize;
  722. }
  723. break;
  724. }
  725. default:
  726. CM_EXCEPT(InternalErrorException,
  727. "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
  728. ", Is array: " + toString(curGenericField->mIsVectorType));
  729. }
  730. }
  731. else
  732. {
  733. switch(curGenericField->mType)
  734. {
  735. case SerializableFT_ReflectablePtr:
  736. {
  737. objectSize += sizeof(UINT32);
  738. break;
  739. }
  740. case SerializableFT_Reflectable:
  741. {
  742. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  743. IReflectable& childObject = curField->getValue(object);
  744. objectSize += sizeof(UINT32); // Complex type size
  745. objectSize += getObjectSize(&childObject);
  746. break;
  747. }
  748. case SerializableFT_Plain:
  749. {
  750. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  751. UINT32 typeSize = 0;
  752. if(curField->hasDynamicSize())
  753. typeSize = curField->getDynamicSize(object);
  754. else
  755. typeSize = curField->getTypeSize();
  756. objectSize += typeSize;
  757. break;
  758. }
  759. case SerializableFT_DataBlock:
  760. {
  761. RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
  762. ManagedDataBlock value = curField->getValue(object);
  763. // Data block size
  764. UINT32 dataBlockSize = value.getSize();
  765. objectSize += sizeof(UINT32) + dataBlockSize;
  766. break;
  767. }
  768. default:
  769. CM_EXCEPT(InternalErrorException,
  770. "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
  771. ", Is array: " + toString(curGenericField->mIsVectorType));
  772. }
  773. }
  774. }
  775. si = si->getBaseClass();
  776. } while (si != nullptr);
  777. return objectSize;
  778. }
  779. UINT32 BinarySerializer::encodeFieldMetaData(UINT16 id, UINT8 size, bool array, SerializableFieldType type, bool hasDynamicSize)
  780. {
  781. // If O == 0 - Meta contains field information (Encoded using this method)
  782. //// Encoding: IIII IIII IIII IIII SSSS SSSS xxYP DCAO
  783. //// I - Id
  784. //// S - Size
  785. //// C - Complex
  786. //// A - Array
  787. //// D - Data block
  788. //// P - Complex ptr
  789. //// O - Object descriptor
  790. //// Y - Plain field has dynamic size
  791. return (id << 16 | size << 8 |
  792. (array ? 0x02 : 0) |
  793. ((type == SerializableFT_DataBlock) ? 0x04 : 0) |
  794. ((type == SerializableFT_Reflectable) ? 0x08 : 0) |
  795. ((type == SerializableFT_ReflectablePtr) ? 0x10 : 0) |
  796. (hasDynamicSize ? 0x20 : 0)); // TODO - Low priority. Technically I could encode this much more tightly, and use var-ints for ID
  797. }
  798. void BinarySerializer::decodeFieldMetaData(UINT32 encodedData, UINT16& id, UINT8& size, bool& array, SerializableFieldType& type, bool& hasDynamicSize)
  799. {
  800. if(isObjectMetaData(encodedData))
  801. {
  802. CM_EXCEPT(InternalErrorException,
  803. "Meta data represents an object description but is trying to be decoded as a field descriptor.");
  804. }
  805. hasDynamicSize = (encodedData & 0x20) != 0;
  806. if((encodedData & 0x10) != 0)
  807. type = SerializableFT_ReflectablePtr;
  808. else if((encodedData & 0x08) != 0)
  809. type = SerializableFT_Reflectable;
  810. else if((encodedData & 0x04) != 0)
  811. type = SerializableFT_DataBlock;
  812. else
  813. type = SerializableFT_Plain;
  814. array = (encodedData & 0x02) != 0;
  815. size = (UINT8)((encodedData >> 8) & 0xFF);
  816. id = (UINT16)((encodedData >> 16) & 0xFFFF);
  817. }
  818. BinarySerializer::ObjectMetaData BinarySerializer::encodeObjectMetaData(UINT32 objId, UINT32 objTypeId, bool isBaseClass)
  819. {
  820. // If O == 1 - Meta contains object instance information (Encoded using encodeObjectMetaData)
  821. //// Encoding: SSSS SSSS SSSS SSSS xxxx xxxx xxxx xxBO
  822. //// S - Size of the object identifier
  823. //// O - Object descriptor
  824. //// B - Base class indicator
  825. if(objId > 1073741823)
  826. {
  827. CM_EXCEPT(InvalidParametersException, "Object ID is larger than we can store (max 30 bits): " + toString(objId));
  828. }
  829. ObjectMetaData metaData;
  830. metaData.objectMeta = (objId << 2) | (isBaseClass ? 0x02 : 0) | 0x01;
  831. metaData.typeId = objTypeId;
  832. return metaData;
  833. }
  834. void BinarySerializer::decodeObjectMetaData(BinarySerializer::ObjectMetaData encodedData, UINT32& objId, UINT32& objTypeId, bool& isBaseClass)
  835. {
  836. if(!isObjectMetaData(encodedData.objectMeta))
  837. {
  838. CM_EXCEPT(InternalErrorException,
  839. "Meta data represents a field description but is trying to be decoded as an object descriptor.");
  840. }
  841. objId = (encodedData.objectMeta >> 2) & 0x3FFFFFFF;
  842. isBaseClass = (encodedData.objectMeta & 0x02) != 0;
  843. objTypeId = encodedData.typeId;
  844. }
  845. bool BinarySerializer::isObjectMetaData(UINT32 encodedData)
  846. {
  847. return ((encodedData & 0x01) != 0);
  848. }
  849. UINT8* BinarySerializer::complexTypeToBuffer(IReflectable* object, UINT8* buffer, UINT32& bufferLength,
  850. int* bytesWritten, boost::function<UINT8*(UINT8*, int, UINT32&)> flushBufferCallback)
  851. {
  852. static const UINT32 COMPLEX_TYPE_FIELD_SIZE = 4; // Size of the field storing the size of a child complex type
  853. int complexTypeSize = 0;
  854. if(object != nullptr)
  855. complexTypeSize = getObjectSize(object);
  856. COPY_TO_BUFFER(&complexTypeSize, COMPLEX_TYPE_FIELD_SIZE)
  857. if(object != nullptr)
  858. return encodeInternal(object, 0, buffer, bufferLength, bytesWritten, flushBufferCallback);
  859. return buffer;
  860. }
  861. std::shared_ptr<IReflectable> BinarySerializer::complexTypeFromBuffer(RTTIReflectableFieldBase* field, UINT8* data, int* complexTypeSize)
  862. {
  863. static const int COMPLEX_TYPE_FIELD_SIZE = 4; // Size of the field storing the size of a child complex type
  864. memcpy(complexTypeSize, data, COMPLEX_TYPE_FIELD_SIZE);
  865. data += COMPLEX_TYPE_FIELD_SIZE;
  866. std::shared_ptr<IReflectable> emptyObject = nullptr;
  867. if(*complexTypeSize > 0)
  868. {
  869. emptyObject = field->newObject();
  870. UINT32 dummy = 0;
  871. decodeInternal(emptyObject, data, *complexTypeSize, dummy);
  872. }
  873. *complexTypeSize += COMPLEX_TYPE_FIELD_SIZE;
  874. return emptyObject;
  875. }
  876. UINT32 BinarySerializer::findOrCreatePersistentId(IReflectable* object)
  877. {
  878. void* ptrAddress = (void*)object;
  879. auto findIter = mObjectAddrToId.find(ptrAddress);
  880. if(findIter != mObjectAddrToId.end())
  881. return findIter->second;
  882. UINT32 objId = mLastUsedObjectId++;
  883. mObjectAddrToId.insert(std::make_pair(ptrAddress, objId));
  884. return objId;
  885. }
  886. UINT32 BinarySerializer::registerObjectPtr(std::shared_ptr<IReflectable> object)
  887. {
  888. if(object == nullptr)
  889. return 0;
  890. void* ptrAddress = (void*)object.get();
  891. auto iterFind = mObjectAddrToId.find(ptrAddress);
  892. if(iterFind == mObjectAddrToId.end())
  893. {
  894. UINT32 objId = findOrCreatePersistentId(object.get());
  895. mObjectsToEncode.push_back(ObjectToEncode(objId, object));
  896. mObjectAddrToId.insert(std::make_pair(ptrAddress, objId));
  897. return objId;
  898. }
  899. return iterFind->second;
  900. }
  901. }
  902. #undef COPY_TO_BUFFER