CmBinarySerializer.cpp 33 KB

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