CmBinarySerializer.cpp 29 KB

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