CmBinarySerializer.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  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(dataPtr, 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, dataPtr##, 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. buffer = encodeInternal(curObject.get(), iter->objectId, buffer, bufferLength, bytesWritten, flushBufferCallback);
  69. if(buffer == nullptr)
  70. {
  71. CM_EXCEPT(InternalErrorException,
  72. "Destination buffer is null or not large enough.");
  73. }
  74. serializedObjects.insert(iter->objectId);
  75. mObjectsToEncode.erase(iter);
  76. foundObjectToProcess = true;
  77. break; // Need to start over as mObjectsToSerialize was possibly modified
  78. }
  79. if(!foundObjectToProcess) // We're done
  80. break;
  81. }
  82. // Final flush
  83. if(*bytesWritten > 0)
  84. {
  85. mTotalBytesWritten += *bytesWritten;
  86. buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength);
  87. }
  88. *bytesWritten = mTotalBytesWritten;
  89. }
  90. std::shared_ptr<IReflectable> BinarySerializer::decode(UINT8* data, UINT32 dataLength)
  91. {
  92. mPtrsToResolve.clear();
  93. mDecodedObjects.clear();
  94. // Find and instantiate root object
  95. if(sizeof(UINT32) > dataLength)
  96. {
  97. CM_EXCEPT(InternalErrorException,
  98. "Error decoding data.");
  99. }
  100. ObjectMetaData objectMetaData;
  101. objectMetaData.objectMeta = 0;
  102. objectMetaData.typeId = 0;
  103. memcpy(&objectMetaData, data, sizeof(ObjectMetaData));
  104. UINT32 objectId = 0;
  105. UINT32 objectTypeId = 0;
  106. decodeObjectMetaData(objectMetaData, objectId, objectTypeId);
  107. std::shared_ptr<IReflectable> object = IReflectable::createInstanceFromTypeId(objectTypeId);
  108. std::shared_ptr<IReflectable> rootObject = object;
  109. // Create initial object + all other objects that are being referenced.
  110. // Use fields to find the type of referenced object.
  111. UINT32 bytesRead = 0;
  112. while(decodeInternal(object, data, dataLength, bytesRead))
  113. {
  114. data += bytesRead;
  115. if((bytesRead + sizeof(UINT32)) > dataLength)
  116. {
  117. CM_EXCEPT(InternalErrorException,
  118. "Error decoding data.");
  119. }
  120. objectMetaData.objectMeta = 0;
  121. objectMetaData.typeId = 0;
  122. memcpy(&objectMetaData, data, sizeof(ObjectMetaData));
  123. objectId = 0;
  124. objectTypeId = 0;
  125. decodeObjectMetaData(objectMetaData, objectId, objectTypeId);
  126. object = nullptr;
  127. if(objectId != 0)
  128. {
  129. auto iterFind = std::find_if(mPtrsToResolve.begin(), mPtrsToResolve.end(), [objectId](PtrToResolve x) { return x.id == objectId; });
  130. if(iterFind != mPtrsToResolve.end())
  131. {
  132. object = IReflectable::createInstanceFromTypeId(objectTypeId);
  133. }
  134. }
  135. }
  136. for(auto iter = mPtrsToResolve.begin(); iter != mPtrsToResolve.end(); ++iter)
  137. {
  138. std::shared_ptr<IReflectable> resolvedObject = nullptr;
  139. PtrToResolve curPtr = *iter;
  140. if(curPtr.id != 0)
  141. {
  142. auto iterFind = mDecodedObjects.find(curPtr.id);
  143. if(iterFind != mDecodedObjects.end())
  144. resolvedObject = iterFind->second;
  145. }
  146. if(curPtr.field->mIsVectorType)
  147. curPtr.field->setArrayValue(curPtr.object.get(), curPtr.arrIdx, resolvedObject);
  148. else
  149. curPtr.field->setValue(curPtr.object.get(), resolvedObject);
  150. }
  151. return rootObject;
  152. }
  153. UINT8* BinarySerializer::encodeInternal(IReflectable* object, UINT32 objectId, UINT8* buffer, UINT32& bufferLength,
  154. int* bytesWritten, boost::function<UINT8*(UINT8*, int, UINT32&)> flushBufferCallback)
  155. {
  156. static const UINT32 META_SIZE = 4; // Meta field size
  157. static const UINT32 NUM_ELEM_FIELD_SIZE = 4; // Size of the field storing number of array elements
  158. static const UINT32 COMPLEX_TYPE_SIZE = 4; // Size of the field storing the size of a child complex type
  159. RTTITypeBase* si = object->getRTTI();
  160. // Encode object ID & type
  161. ObjectMetaData objectMetaData = encodeObjectMetaData(objectId, si->getRTTIId());
  162. COPY_TO_BUFFER(&objectMetaData, sizeof(ObjectMetaData))
  163. int numFields = si->getNumFields();
  164. for(int i = 0; i < numFields; i++)
  165. {
  166. RTTIField* curGenericField = si->getField(i);
  167. // Copy field ID & other meta-data like field size and type
  168. int metaData = encodeFieldMetaData(curGenericField->mUniqueId, curGenericField->getTypeSize(),
  169. curGenericField->mIsVectorType, curGenericField->mType, curGenericField->hasDynamicSize());
  170. COPY_TO_BUFFER(&metaData, META_SIZE)
  171. if(curGenericField->mIsVectorType)
  172. {
  173. UINT32 arrayNumElems = curGenericField->getArraySize(object);
  174. // Copy num vector elements
  175. COPY_TO_BUFFER(&arrayNumElems, NUM_ELEM_FIELD_SIZE)
  176. switch(curGenericField->mType)
  177. {
  178. case SerializableFT_ReflectablePtr:
  179. {
  180. RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
  181. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  182. {
  183. std::shared_ptr<IReflectable> childObject = curField->getArrayValue(object, arrIdx);
  184. UINT32 objId = registerObjectPtr(childObject);
  185. COPY_TO_BUFFER(&objId, sizeof(UINT32))
  186. }
  187. break;
  188. }
  189. case SerializableFT_Reflectable:
  190. {
  191. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  192. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  193. {
  194. IReflectable& childObject = curField->getArrayValue(object, arrIdx);
  195. buffer = complexTypeToBuffer(&childObject, buffer, bufferLength, bytesWritten, flushBufferCallback);
  196. if(buffer == nullptr)
  197. return nullptr;
  198. }
  199. break;
  200. }
  201. case SerializableFT_Plain:
  202. {
  203. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  204. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  205. {
  206. UINT32 typeSize = 0;
  207. if(curField->hasDynamicSize())
  208. typeSize = curField->getArrayElemDynamicSize(object, arrIdx);
  209. else
  210. typeSize = curField->getTypeSize();
  211. if((*bytesWritten + typeSize) > bufferLength)
  212. {
  213. mTotalBytesWritten += *bytesWritten;
  214. buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength);
  215. if(buffer == nullptr || bufferLength < typeSize) return nullptr;
  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. return nullptr;
  249. break;
  250. }
  251. case SerializableFT_Plain:
  252. {
  253. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  254. UINT32 typeSize = 0;
  255. if(curField->hasDynamicSize())
  256. typeSize = curField->getDynamicSize(object);
  257. else
  258. typeSize = curField->getTypeSize();
  259. if((*bytesWritten + typeSize) > bufferLength)
  260. {
  261. mTotalBytesWritten += *bytesWritten;
  262. buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength);
  263. if(buffer == nullptr || bufferLength < typeSize) return nullptr;
  264. *bytesWritten = 0;
  265. }
  266. curField->toBuffer(object, buffer);
  267. buffer += typeSize;
  268. *bytesWritten += typeSize;
  269. break;
  270. }
  271. case SerializableFT_DataBlock:
  272. {
  273. RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
  274. ManagedDataBlock value = curField->getValue(object);
  275. // Data block size
  276. UINT32 dataBlockSize = value.getSize();
  277. COPY_TO_BUFFER(&dataBlockSize, sizeof(UINT32))
  278. // Data block data
  279. UINT8* dataToStore = value.getData();
  280. UINT32 remainingSize = dataBlockSize;
  281. while(remainingSize > 0)
  282. {
  283. UINT32 remainingSpaceInBuffer = bufferLength - *bytesWritten;
  284. if(remainingSize <= remainingSpaceInBuffer)
  285. {
  286. COPY_TO_BUFFER(dataToStore, remainingSize);
  287. remainingSize = 0;
  288. }
  289. else
  290. {
  291. memcpy(buffer, dataToStore, remainingSpaceInBuffer);
  292. buffer += remainingSpaceInBuffer;
  293. *bytesWritten += remainingSpaceInBuffer;
  294. dataToStore += remainingSpaceInBuffer;
  295. remainingSize -= remainingSpaceInBuffer;
  296. mTotalBytesWritten += *bytesWritten;
  297. buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength);
  298. if(buffer == nullptr || bufferLength == 0) return nullptr;
  299. *bytesWritten = 0;
  300. }
  301. }
  302. break;
  303. }
  304. default:
  305. CM_EXCEPT(InternalErrorException,
  306. "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
  307. ", Is array: " + toString(curGenericField->mIsVectorType));
  308. }
  309. }
  310. }
  311. return buffer;
  312. }
  313. bool BinarySerializer::decodeInternal(std::shared_ptr<IReflectable> object, UINT8* data, UINT32 dataLength, UINT32& bytesRead)
  314. {
  315. static const int META_SIZE = 4; // Meta field size
  316. static const int NUM_ELEM_FIELD_SIZE = 4; // Size of the field storing number of array elements
  317. static const int COMPLEX_TYPE_FIELD_SIZE = 4; // Size of the field storing the size of a child complex type
  318. static const int DATA_BLOCK_TYPE_FIELD_SIZE = 4;
  319. RTTITypeBase* si = nullptr;
  320. if(object != nullptr)
  321. si = object->getRTTI();
  322. if((bytesRead + sizeof(ObjectMetaData)) > dataLength)
  323. {
  324. CM_EXCEPT(InternalErrorException,
  325. "Error decoding data.");
  326. }
  327. ObjectMetaData objectMetaData;
  328. objectMetaData.objectMeta = 0;
  329. objectMetaData.typeId = 0;
  330. memcpy(&objectMetaData, data, sizeof(ObjectMetaData));
  331. data += sizeof(ObjectMetaData);
  332. bytesRead += sizeof(ObjectMetaData);
  333. UINT32 objectId = 0;
  334. UINT32 objectTypeId = 0;
  335. decodeObjectMetaData(objectMetaData, objectId, objectTypeId);
  336. if(object != nullptr && objectId != 0)
  337. mDecodedObjects.insert(std::make_pair(objectId, object));
  338. while(bytesRead < dataLength)
  339. {
  340. int metaData = -1;
  341. if((bytesRead + META_SIZE) > dataLength)
  342. {
  343. CM_EXCEPT(InternalErrorException,
  344. "Error decoding data.");
  345. }
  346. memcpy((void*)&metaData, data, META_SIZE);
  347. if(isObjectMetaData(metaData)) // We've reached a new object
  348. {
  349. if((bytesRead + sizeof(ObjectMetaData)) > dataLength)
  350. {
  351. CM_EXCEPT(InternalErrorException,
  352. "Error decoding data.");
  353. }
  354. ObjectMetaData objMetaData;
  355. objMetaData.objectMeta = 0;
  356. objMetaData.typeId = 0;
  357. memcpy(&objMetaData, data, sizeof(ObjectMetaData));
  358. UINT32 objId = 0;
  359. UINT32 objTypeId = 0;
  360. decodeObjectMetaData(objMetaData, objId, objTypeId);
  361. if(objId != 0)
  362. return true; // Pointers we decode later, only if they're being referenced by something
  363. // Objects with ID == 0 represent complex types serialized by value, but they should only get serialized
  364. // if we encounter a field with one, not by just iterating through the file.
  365. CM_EXCEPT(InternalErrorException, "Object with ID 0 encountered. Cannot proceed with serialization.");
  366. }
  367. data += META_SIZE;
  368. bytesRead += META_SIZE;
  369. bool isArray;
  370. SerializableFieldType fieldType;
  371. UINT16 fieldId;
  372. UINT8 fieldSize;
  373. bool hasDynamicSize;
  374. decodeFieldMetaData(metaData, fieldId, fieldSize, isArray, fieldType, hasDynamicSize);
  375. RTTIField* curGenericField = nullptr;
  376. if(si != nullptr)
  377. curGenericField = si->findField(fieldId);
  378. if(curGenericField != nullptr)
  379. {
  380. if(curGenericField->getTypeSize() != fieldSize)
  381. {
  382. CM_EXCEPT(InternalErrorException,
  383. "Data type mismatch. Type size stored in file and actual type size don't match. ("
  384. + toString(curGenericField->getTypeSize()) + " vs. " + toString(fieldSize) + ")");
  385. }
  386. if(curGenericField->mIsVectorType != isArray)
  387. {
  388. CM_EXCEPT(InternalErrorException,
  389. "Data type mismatch. One is array, other is a single type.");
  390. }
  391. if(curGenericField->mType != fieldType)
  392. {
  393. CM_EXCEPT(InternalErrorException,
  394. "Data type mismatch. Field types don't match. " + toString(UINT32(curGenericField->mType)) + " vs. " + toString(UINT32(fieldType)));
  395. }
  396. }
  397. int arrayNumElems = 1;
  398. if(isArray)
  399. {
  400. if((bytesRead + NUM_ELEM_FIELD_SIZE) > dataLength)
  401. {
  402. CM_EXCEPT(InternalErrorException,
  403. "Error decoding data.");
  404. }
  405. memcpy((void*)&arrayNumElems, data, NUM_ELEM_FIELD_SIZE);
  406. data += NUM_ELEM_FIELD_SIZE;
  407. bytesRead += NUM_ELEM_FIELD_SIZE;
  408. if(curGenericField != nullptr)
  409. curGenericField->setArraySize(object.get(), arrayNumElems);
  410. switch(fieldType)
  411. {
  412. case SerializableFT_ReflectablePtr:
  413. {
  414. RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
  415. for(int i = 0; i < arrayNumElems; i++)
  416. {
  417. if((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
  418. {
  419. CM_EXCEPT(InternalErrorException,
  420. "Error decoding data.");
  421. }
  422. int objectId = 0;
  423. memcpy(&objectId, data, COMPLEX_TYPE_FIELD_SIZE);
  424. data += COMPLEX_TYPE_FIELD_SIZE;
  425. bytesRead += COMPLEX_TYPE_FIELD_SIZE;
  426. if(curField != nullptr)
  427. mPtrsToResolve.push_back(PtrToResolve(curField, object, objectId, i));
  428. }
  429. break;
  430. }
  431. case SerializableFT_Reflectable:
  432. {
  433. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  434. for(int i = 0; i < arrayNumElems; i++)
  435. {
  436. if((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
  437. {
  438. CM_EXCEPT(InternalErrorException,
  439. "Error decoding data.");
  440. }
  441. int complexTypeSize = COMPLEX_TYPE_FIELD_SIZE;
  442. if(curField != nullptr)
  443. {
  444. std::shared_ptr<IReflectable> complexType = complexTypeFromBuffer(curField, data, &complexTypeSize);
  445. curField->setArrayValue(object.get(), i, *complexType);
  446. }
  447. data += complexTypeSize;
  448. bytesRead += complexTypeSize;
  449. }
  450. break;
  451. }
  452. case SerializableFT_Plain:
  453. {
  454. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  455. for(int i = 0; i < arrayNumElems; i++)
  456. {
  457. UINT32 typeSize = fieldSize;
  458. if(hasDynamicSize)
  459. memcpy(&typeSize, data, sizeof(UINT32));
  460. if(curField != nullptr)
  461. curField->arrayElemFromBuffer(object.get(), i, data);
  462. data += typeSize;
  463. bytesRead += typeSize;
  464. }
  465. break;
  466. }
  467. default:
  468. CM_EXCEPT(InternalErrorException,
  469. "Error decoding data. Encountered a type I don't know how to decode. Type: " + toString(UINT32(fieldType)) +
  470. ", Is array: " + toString(isArray));
  471. }
  472. }
  473. else
  474. {
  475. switch(fieldType)
  476. {
  477. case SerializableFT_ReflectablePtr:
  478. {
  479. RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
  480. if((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
  481. {
  482. CM_EXCEPT(InternalErrorException,
  483. "Error decoding data.");
  484. }
  485. int objectId = 0;
  486. memcpy(&objectId, data, COMPLEX_TYPE_FIELD_SIZE);
  487. data += COMPLEX_TYPE_FIELD_SIZE;
  488. bytesRead += COMPLEX_TYPE_FIELD_SIZE;
  489. if(curField != nullptr)
  490. mPtrsToResolve.push_back(PtrToResolve(curField, object, objectId));
  491. break;
  492. }
  493. case SerializableFT_Reflectable:
  494. {
  495. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  496. if((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
  497. {
  498. CM_EXCEPT(InternalErrorException,
  499. "Error decoding data.");
  500. }
  501. int complexTypeSize = COMPLEX_TYPE_FIELD_SIZE;
  502. if(curField != nullptr)
  503. {
  504. std::shared_ptr<IReflectable> complexType = complexTypeFromBuffer(curField, data, &complexTypeSize);
  505. curField->setValue(object.get(), *complexType);
  506. }
  507. data += complexTypeSize;
  508. bytesRead += complexTypeSize;
  509. break;
  510. }
  511. case SerializableFT_Plain:
  512. {
  513. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  514. UINT32 typeSize = fieldSize;
  515. if(hasDynamicSize)
  516. memcpy(&typeSize, data, sizeof(UINT32));
  517. if(curField != nullptr)
  518. curField->fromBuffer(object.get(), data);
  519. data += typeSize;
  520. bytesRead += typeSize;
  521. break;
  522. }
  523. case SerializableFT_DataBlock:
  524. {
  525. RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
  526. if((bytesRead + DATA_BLOCK_TYPE_FIELD_SIZE) > dataLength)
  527. {
  528. CM_EXCEPT(InternalErrorException,
  529. "Error decoding data.");
  530. }
  531. // Data block size
  532. UINT32 dataBlockSize = 0;
  533. memcpy(&dataBlockSize, data, DATA_BLOCK_TYPE_FIELD_SIZE);
  534. data += DATA_BLOCK_TYPE_FIELD_SIZE;
  535. bytesRead += DATA_BLOCK_TYPE_FIELD_SIZE;
  536. if((bytesRead + dataBlockSize) > dataLength)
  537. {
  538. CM_EXCEPT(InternalErrorException,
  539. "Error decoding data.");
  540. }
  541. // Data block data
  542. if(curField != nullptr)
  543. {
  544. UINT8* dataCopy = new UINT8[dataBlockSize]; // TODO - Low priority. I need to read files better, so I
  545. memcpy(dataCopy, data, dataBlockSize); // can just pass the buffer pointer directly without copying (possibly large amounts of data)
  546. ManagedDataBlock value(dataCopy, dataBlockSize, false); // Not managed because I assume the owner class will decide whether to delete the data or keep it
  547. curField->setValue(object.get(), value);
  548. }
  549. data += dataBlockSize;
  550. bytesRead += dataBlockSize;
  551. break;
  552. }
  553. default:
  554. CM_EXCEPT(InternalErrorException,
  555. "Error decoding data. Encountered a type I don't know how to decode. Type: " + toString(UINT32(fieldType)) +
  556. ", Is array: " + toString(isArray));
  557. }
  558. }
  559. }
  560. return false;
  561. }
  562. UINT32 BinarySerializer::getObjectSize(IReflectable* object)
  563. {
  564. if(object == nullptr)
  565. return 0;
  566. UINT32 objectSize = 0;
  567. RTTITypeBase* si = object->getRTTI();
  568. // Object ID
  569. objectSize += sizeof(UINT32);
  570. int numFields = si->getNumFields();
  571. for(int i = 0; i < numFields; i++)
  572. {
  573. RTTIField* curGenericField = si->getField(i);
  574. // Field meta data
  575. objectSize += sizeof(UINT32);
  576. if(curGenericField->mIsVectorType)
  577. {
  578. UINT32 arrayNumElems = curGenericField->getArraySize(object);
  579. // Num array elems
  580. objectSize += sizeof(UINT32);
  581. switch(curGenericField->mType)
  582. {
  583. case SerializableFT_ReflectablePtr:
  584. {
  585. objectSize += sizeof(UINT32) * arrayNumElems;
  586. break;
  587. }
  588. case SerializableFT_Reflectable:
  589. {
  590. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  591. for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
  592. {
  593. IReflectable& childObject = curField->getArrayValue(object, arrIdx);
  594. objectSize += getObjectSize(&childObject);
  595. }
  596. break;
  597. }
  598. case SerializableFT_Plain:
  599. {
  600. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  601. objectSize += arrayNumElems * curField->getTypeSize();
  602. break;
  603. }
  604. default:
  605. CM_EXCEPT(InternalErrorException,
  606. "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
  607. ", Is array: " + toString(curGenericField->mIsVectorType));
  608. }
  609. }
  610. else
  611. {
  612. switch(curGenericField->mType)
  613. {
  614. case SerializableFT_ReflectablePtr:
  615. {
  616. objectSize += sizeof(UINT32);
  617. break;
  618. }
  619. case SerializableFT_Reflectable:
  620. {
  621. RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
  622. IReflectable& childObject = curField->getValue(object);
  623. objectSize += getObjectSize(&childObject);
  624. break;
  625. }
  626. case SerializableFT_Plain:
  627. {
  628. RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
  629. objectSize += curField->getTypeSize();
  630. break;
  631. }
  632. case SerializableFT_DataBlock:
  633. {
  634. RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
  635. ManagedDataBlock value = curField->getValue(object);
  636. // Data block size
  637. UINT32 dataBlockSize = value.getSize();
  638. objectSize += sizeof(UINT32) + dataBlockSize;
  639. break;
  640. }
  641. default:
  642. CM_EXCEPT(InternalErrorException,
  643. "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
  644. ", Is array: " + toString(curGenericField->mIsVectorType));
  645. }
  646. }
  647. }
  648. return objectSize;
  649. }
  650. UINT32 BinarySerializer::encodeFieldMetaData(UINT16 id, UINT8 size, bool array, SerializableFieldType type, bool hasDynamicSize)
  651. {
  652. // If O == 0 - Meta contains field information (Encoded using this method)
  653. //// Encoding: IIII IIII IIII IIII SSSS SSSS xxYP DCAO
  654. //// I - Id
  655. //// S - Size
  656. //// C - Complex
  657. //// A - Array
  658. //// D - Data block
  659. //// P - Complex ptr
  660. //// O - Object descriptor
  661. //// Y - Simple field has dynamic size
  662. return (id << 16 | size << 8 |
  663. (array ? 0x02 : 0) |
  664. ((type == SerializableFT_DataBlock) ? 0x04 : 0) |
  665. ((type == SerializableFT_Reflectable) ? 0x08 : 0) |
  666. ((type == SerializableFT_ReflectablePtr) ? 0x10 : 0) |
  667. (hasDynamicSize ? 0x20 : 0)); // TODO - Low priority. Technically I could encode this much more tightly, and use var-ints for ID
  668. }
  669. void BinarySerializer::decodeFieldMetaData(UINT32 encodedData, UINT16& id, UINT8& size, bool& array, SerializableFieldType& type, bool& hasDynamicSize)
  670. {
  671. if(isObjectMetaData(encodedData))
  672. {
  673. CM_EXCEPT(InternalErrorException,
  674. "Meta data represents an object description but is trying to be decoded as a field descriptor.");
  675. }
  676. hasDynamicSize = (encodedData & 0x20) != 0;
  677. if((encodedData & 0x10) != 0)
  678. type = SerializableFT_ReflectablePtr;
  679. else if((encodedData & 0x08) != 0)
  680. type = SerializableFT_Reflectable;
  681. else if((encodedData & 0x04) != 0)
  682. type = SerializableFT_DataBlock;
  683. else
  684. type = SerializableFT_Plain;
  685. array = (encodedData & 0x02) != 0;
  686. size = (UINT8)((encodedData >> 8) & 0xFF);
  687. id = (UINT16)((encodedData >> 16) & 0xFFFF);
  688. }
  689. BinarySerializer::ObjectMetaData BinarySerializer::encodeObjectMetaData(UINT32 objId, UINT32 objTypeId)
  690. {
  691. // If O == 1 - Meta contains object instance information (Encoded using encodeObjectMetaData)
  692. //// Encoding: SSSS SSSS SSSS SSSS xxxx xxxx xxxx xxxO
  693. //// S - Size of the object identifier
  694. //// O - Object descriptor
  695. ObjectMetaData metaData;
  696. metaData.objectMeta = (objId << 1) | 0x01;
  697. metaData.typeId = objTypeId;
  698. return metaData;
  699. }
  700. void BinarySerializer::decodeObjectMetaData(BinarySerializer::ObjectMetaData encodedData, UINT32& objId, UINT32& objTypeId)
  701. {
  702. if(!isObjectMetaData(encodedData.objectMeta))
  703. {
  704. CM_EXCEPT(InternalErrorException,
  705. "Meta data represents a field description but is trying to be decoded as an object descriptor.");
  706. }
  707. objId = (encodedData.objectMeta >> 1) & 0x7FFFFFFF;
  708. objTypeId = encodedData.typeId;
  709. }
  710. bool BinarySerializer::isObjectMetaData(UINT32 encodedData)
  711. {
  712. return ((encodedData & 0x01) != 0);
  713. }
  714. UINT8* BinarySerializer::complexTypeToBuffer(IReflectable* object, UINT8* buffer, UINT32& bufferLength,
  715. int* bytesWritten, boost::function<UINT8*(UINT8*, int, UINT32&)> flushBufferCallback)
  716. {
  717. static const UINT32 COMPLEX_TYPE_FIELD_SIZE = 4; // Size of the field storing the size of a child complex type
  718. int complexTypeSize = 0;
  719. if(object != nullptr)
  720. complexTypeSize = getObjectSize(object);
  721. COPY_TO_BUFFER(&complexTypeSize, COMPLEX_TYPE_FIELD_SIZE)
  722. if(object != nullptr)
  723. return encodeInternal(object, 0, buffer, bufferLength, bytesWritten, flushBufferCallback);
  724. return buffer;
  725. }
  726. std::shared_ptr<IReflectable> BinarySerializer::complexTypeFromBuffer(RTTIReflectableFieldBase* field, UINT8* data, int* complexTypeSize)
  727. {
  728. static const int COMPLEX_TYPE_FIELD_SIZE = 4; // Size of the field storing the size of a child complex type
  729. memcpy(complexTypeSize, data, COMPLEX_TYPE_FIELD_SIZE);
  730. data += COMPLEX_TYPE_FIELD_SIZE;
  731. std::shared_ptr<IReflectable> emptyObject = nullptr;
  732. if(*complexTypeSize > 0)
  733. {
  734. emptyObject = field->newObject();
  735. UINT32 dummy = 0;
  736. decodeInternal(emptyObject, data, *complexTypeSize, dummy);
  737. }
  738. *complexTypeSize += COMPLEX_TYPE_FIELD_SIZE;
  739. return emptyObject;
  740. }
  741. UINT32 BinarySerializer::findOrCreatePersistentId(IReflectable* object)
  742. {
  743. UINT32 ptrAddress = (UINT32)object;
  744. auto findIter = mObjectAddrToId.find(ptrAddress);
  745. if(findIter != mObjectAddrToId.end())
  746. return findIter->second;
  747. UINT32 objId = mLastUsedObjectId++;
  748. mObjectAddrToId.insert(std::make_pair(ptrAddress, objId));
  749. return objId;
  750. }
  751. UINT32 BinarySerializer::registerObjectPtr(std::shared_ptr<IReflectable> object)
  752. {
  753. if(object == nullptr)
  754. return 0;
  755. UINT32 ptrAddress = (UINT32)object.get();
  756. auto iterFind = mObjectAddrToId.find(ptrAddress);
  757. if(iterFind == mObjectAddrToId.end())
  758. {
  759. UINT32 objId = findOrCreatePersistentId(object.get());
  760. mObjectsToEncode.push_back(ObjectToEncode(objId, object));
  761. mObjectAddrToId.insert(std::make_pair(ptrAddress, objId));
  762. return objId;
  763. }
  764. return iterFind->second;
  765. }
  766. }
  767. #undef COPY_TO_BUFFER