CmBinarySerializer.cpp 33 KB

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