CmBinarySerializer.cpp 31 KB

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