CmBinarySerializer.cpp 33 KB

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