| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390 |
- #include "BsBinarySerializer.h"
- #include "BsException.h"
- #include "BsDebug.h"
- #include "BsIReflectable.h"
- #include "BsRTTIType.h"
- #include "BsRTTIField.h"
- #include "BsRTTIPlainField.h"
- #include "BsRTTIReflectableField.h"
- #include "BsRTTIReflectablePtrField.h"
- #include "BsRTTIManagedDataBlockField.h"
- #include "BsMemorySerializer.h"
- #include <unordered_set>
- /**
- * @brief A macro that represents a block of code that gets used a lot inside
- * encodeInternal. It checks if the buffer has enough space, and if it does
- * it copies the data from the specified location and increments the needed
- * pointers and counters. If there is not enough space the buffer is flushed
- * (hopefully to make some space). If there is still not enough space the entire
- * encoding process ends.
- *
- * @param dataPtr Pointer to data which to copy.
- * @param size Size of the data to copy
- */
- #define COPY_TO_BUFFER(dataIter, size) \
- if((*bytesWritten + size##) > bufferLength) \
- { \
- mTotalBytesWritten += *bytesWritten; \
- buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength); \
- if(buffer == nullptr || bufferLength < size##) return nullptr; \
- *bytesWritten = 0; \
- } \
- \
- memcpy(buffer, dataIter##, size##); \
- buffer += size##; \
- *bytesWritten += size##;
- namespace BansheeEngine
- {
- BinarySerializer::BinarySerializer()
- :mLastUsedObjectId(1)
- {
- }
- void BinarySerializer::encode(IReflectable* object, UINT8* buffer, UINT32 bufferLength,
- UINT32* bytesWritten, std::function<UINT8*(UINT8*, UINT32, UINT32&)> flushBufferCallback, bool shallow)
- {
- mObjectsToEncode.clear();
- mObjectAddrToId.clear();
- mLastUsedObjectId = 1;
- *bytesWritten = 0;
- mTotalBytesWritten = 0;
- UINT8* bufferStart = buffer;
- Vector<std::shared_ptr<IReflectable>> encodedObjects;
- UINT32 objectId = findOrCreatePersistentId(object);
-
- // Encode primary object and its value types
- buffer = encodeInternal(object, objectId, buffer, bufferLength, bytesWritten, flushBufferCallback, shallow);
- if(buffer == nullptr)
- {
- BS_EXCEPT(InternalErrorException,
- "Destination buffer is null or not large enough.");
- }
- // Encode pointed to objects and their value types
- UnorderedSet<UINT32> serializedObjects;
- while(true)
- {
- auto iter = mObjectsToEncode.begin();
- bool foundObjectToProcess = false;
- for(iter; iter != mObjectsToEncode.end(); ++iter)
- {
- auto foundExisting = serializedObjects.find(iter->objectId);
- if(foundExisting != serializedObjects.end())
- continue; // Already processed
- std::shared_ptr<IReflectable> curObject = iter->object;
- UINT32 curObjectid = iter->objectId;
- serializedObjects.insert(curObjectid);
- mObjectsToEncode.erase(iter);
- buffer = encodeInternal(curObject.get(), curObjectid, buffer,
- bufferLength, bytesWritten, flushBufferCallback, shallow);
- if(buffer == nullptr)
- {
- BS_EXCEPT(InternalErrorException,
- "Destination buffer is null or not large enough.");
- }
- foundObjectToProcess = true;
- // Ensure we keep a reference to the object so it isn't released.
- // The system assigns unique IDs to IReflectable objects based on pointer
- // addresses but if objects get released then same address could be assigned twice.
- // Note: To get around this I could assign unique IDs to IReflectable objects
- encodedObjects.push_back(curObject);
- break; // Need to start over as mObjectsToSerialize was possibly modified
- }
- if(!foundObjectToProcess) // We're done
- break;
- }
- // Final flush
- if(*bytesWritten > 0)
- {
- mTotalBytesWritten += *bytesWritten;
- buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength);
- }
- *bytesWritten = mTotalBytesWritten;
- encodedObjects.clear();
- mObjectsToEncode.clear();
- mObjectAddrToId.clear();
- }
- std::shared_ptr<IReflectable> BinarySerializer::decode(UINT8* data, UINT32 dataLength)
- {
- SPtr<SerializedObject> intermediateObject = _decodeIntermediate(data, dataLength);
- if (intermediateObject == nullptr)
- return nullptr;
- return _decodeIntermediate(intermediateObject);
- }
- SPtr<IReflectable> BinarySerializer::_decodeIntermediate(const SPtr<SerializedObject>& serializedObject)
- {
- mObjectMap.clear();
- SPtr<IReflectable> output;
- RTTITypeBase* type = IReflectable::_getRTTIfromTypeId(serializedObject->getRootTypeId());
- if (type != nullptr)
- {
- output = type->newRTTIObject();
- auto iterNewObj = mObjectMap.insert(std::make_pair(serializedObject, ObjectToDecode(output, serializedObject)));
- decodeInternal(output, serializedObject);
- iterNewObj.first->second.isDecoded = true;
- }
- // Go through the remaining objects (should be only ones with weak refs)
- for (auto iter = mObjectMap.begin(); iter != mObjectMap.end(); ++iter)
- {
- ObjectToDecode& objToDecode = iter->second;
- if (objToDecode.isDecoded)
- continue;
- decodeInternal(objToDecode.object, objToDecode.serializedObject);
- objToDecode.isDecoded = true;
- }
- mObjectMap.clear();
- return output;
- }
- UINT8* BinarySerializer::encodeInternal(IReflectable* object, UINT32 objectId, UINT8* buffer, UINT32& bufferLength,
- UINT32* bytesWritten, std::function<UINT8*(UINT8*, UINT32, UINT32&)> flushBufferCallback, bool shallow)
- {
- RTTITypeBase* si = object->getRTTI();
- bool isBaseClass = false;
- // If an object has base classes, we need to iterate through all of them
- do
- {
- si->onSerializationStarted(object);
- // Encode object ID & type
- ObjectMetaData objectMetaData = encodeObjectMetaData(objectId, si->getRTTIId(), isBaseClass);
- COPY_TO_BUFFER(&objectMetaData, sizeof(ObjectMetaData))
- int numFields = si->getNumFields();
- for(int i = 0; i < numFields; i++)
- {
- RTTIField* curGenericField = si->getField(i);
- // Copy field ID & other meta-data like field size and type
- int metaData = encodeFieldMetaData(curGenericField->mUniqueId, curGenericField->getTypeSize(),
- curGenericField->mIsVectorType, curGenericField->mType, curGenericField->hasDynamicSize());
- COPY_TO_BUFFER(&metaData, META_SIZE)
- if(curGenericField->mIsVectorType)
- {
- UINT32 arrayNumElems = curGenericField->getArraySize(object);
- // Copy num vector elements
- COPY_TO_BUFFER(&arrayNumElems, NUM_ELEM_FIELD_SIZE)
- switch(curGenericField->mType)
- {
- case SerializableFT_ReflectablePtr:
- {
- RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
- for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
- {
- std::shared_ptr<IReflectable> childObject;
-
- if (!shallow)
- childObject = curField->getArrayValue(object, arrIdx);
- UINT32 objId = registerObjectPtr(childObject);
- COPY_TO_BUFFER(&objId, sizeof(UINT32))
- }
- break;
- }
- case SerializableFT_Reflectable:
- {
- RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
- for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
- {
- IReflectable& childObject = curField->getArrayValue(object, arrIdx);
- buffer = complexTypeToBuffer(&childObject, buffer, bufferLength,
- bytesWritten, flushBufferCallback, shallow);
- if(buffer == nullptr)
- {
- si->onSerializationEnded(object);
- return nullptr;
- }
- }
- break;
- }
- case SerializableFT_Plain:
- {
- RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
- for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
- {
- UINT32 typeSize = 0;
- if(curField->hasDynamicSize())
- typeSize = curField->getArrayElemDynamicSize(object, arrIdx);
- else
- typeSize = curField->getTypeSize();
- if ((*bytesWritten + typeSize) > bufferLength)
- {
- UINT8* tempBuffer = (UINT8*)stackAlloc(typeSize);
- curField->arrayElemToBuffer(object, arrIdx, tempBuffer);
- buffer = dataBlockToBuffer(tempBuffer, typeSize, buffer, bufferLength, bytesWritten, flushBufferCallback);
- if (buffer == nullptr || bufferLength == 0)
- {
- stackDeallocLast(tempBuffer);
- si->onSerializationEnded(object);
- return nullptr;
- }
- stackDeallocLast(tempBuffer);
- }
- else
- {
- curField->arrayElemToBuffer(object, arrIdx, buffer);
- buffer += typeSize;
- *bytesWritten += typeSize;
- }
- }
- break;
- }
- default:
- BS_EXCEPT(InternalErrorException,
- "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
- ", Is array: " + toString(curGenericField->mIsVectorType));
- }
- }
- else
- {
- switch(curGenericField->mType)
- {
- case SerializableFT_ReflectablePtr:
- {
- RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
- std::shared_ptr<IReflectable> childObject;
-
- if (!shallow)
- childObject = curField->getValue(object);
- UINT32 objId = registerObjectPtr(childObject);
- COPY_TO_BUFFER(&objId, sizeof(UINT32))
- break;
- }
- case SerializableFT_Reflectable:
- {
- RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
- IReflectable& childObject = curField->getValue(object);
- buffer = complexTypeToBuffer(&childObject, buffer, bufferLength,
- bytesWritten, flushBufferCallback, shallow);
- if(buffer == nullptr)
- {
- si->onSerializationEnded(object);
- return nullptr;
- }
- break;
- }
- case SerializableFT_Plain:
- {
- RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
- UINT32 typeSize = 0;
- if(curField->hasDynamicSize())
- typeSize = curField->getDynamicSize(object);
- else
- typeSize = curField->getTypeSize();
- if ((*bytesWritten + typeSize) > bufferLength)
- {
- UINT8* tempBuffer = (UINT8*)stackAlloc(typeSize);
- curField->toBuffer(object, tempBuffer);
-
- buffer = dataBlockToBuffer(tempBuffer, typeSize, buffer, bufferLength, bytesWritten, flushBufferCallback);
- if (buffer == nullptr || bufferLength == 0)
- {
- stackDeallocLast(tempBuffer);
- si->onSerializationEnded(object);
- return nullptr;
- }
- stackDeallocLast(tempBuffer);
- }
- else
- {
- curField->toBuffer(object, buffer);
- buffer += typeSize;
- *bytesWritten += typeSize;
- }
- break;
- }
- case SerializableFT_DataBlock:
- {
- RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
- ManagedDataBlock value = curField->getValue(object);
- // Data block size
- UINT32 dataBlockSize = value.getSize();
- COPY_TO_BUFFER(&dataBlockSize, sizeof(UINT32))
- // Data block data
- UINT8* dataToStore = value.getData();
- buffer = dataBlockToBuffer(dataToStore, dataBlockSize, buffer, bufferLength, bytesWritten, flushBufferCallback);
- if (buffer == nullptr || bufferLength == 0)
- {
- si->onSerializationEnded(object);
- return nullptr;
- }
- break;
- }
- default:
- BS_EXCEPT(InternalErrorException,
- "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
- ", Is array: " + toString(curGenericField->mIsVectorType));
- }
- }
- }
- si->onSerializationEnded(object);
- si = si->getBaseClass();
- isBaseClass = true;
- } while(si != nullptr); // Repeat until we reach the top of the inheritance hierarchy
- return buffer;
- }
- SPtr<SerializedObject> BinarySerializer::_encodeIntermediate(IReflectable* object, bool shallow)
- {
- // TODO: This is a hacky way of generating an intermediate format to save development time and complexity.
- // It is hacky because it requires a full on encode to binary and then decode into intermediate. It should
- // be better to modify encoding process so it outputs the intermediate format directly (similar to how decoding works).
- // This also means that once you have an intermediate format you cannot use it to encode to binary.
- MemorySerializer ms;
- UINT32 dataLength = 0;
- UINT8* data = ms.encode(object, dataLength, &bs_alloc, shallow);
- BinarySerializer bs;
- SPtr<SerializedObject> obj = bs._decodeIntermediate(data, dataLength, true);
- bs_free(data);
- return obj;
- }
- SPtr<SerializedObject> BinarySerializer::_decodeIntermediate(UINT8* data, UINT32 dataLength, bool copyData)
- {
- UINT32 bytesRead = 0;
- mInterimObjectMap.clear();
- SPtr<SerializedObject> rootObj;
- bool hasMore = decodeIntermediateInternal(data, dataLength, bytesRead, rootObj, copyData);
- while (hasMore)
- {
- UINT8* dataPtr = data + bytesRead;
- SPtr<SerializedObject> dummyObj;
- hasMore = decodeIntermediateInternal(dataPtr, dataLength, bytesRead, dummyObj, copyData);
- }
- return rootObj;
- }
- bool BinarySerializer::decodeIntermediateInternal(UINT8* data, UINT32 dataLength, UINT32& bytesRead, SPtr<SerializedObject>& output, bool copyData)
- {
- if ((bytesRead + sizeof(ObjectMetaData)) > dataLength)
- {
- BS_EXCEPT(InternalErrorException,
- "Error decoding data.");
- }
- ObjectMetaData objectMetaData;
- objectMetaData.objectMeta = 0;
- objectMetaData.typeId = 0;
- memcpy(&objectMetaData, data, sizeof(ObjectMetaData));
- data += sizeof(ObjectMetaData);
- bytesRead += sizeof(ObjectMetaData);
- UINT32 objectId = 0;
- UINT32 objectTypeId = 0;
- bool objectIsBaseClass = false;
- decodeObjectMetaData(objectMetaData, objectId, objectTypeId, objectIsBaseClass);
- if (objectIsBaseClass)
- {
- BS_EXCEPT(InternalErrorException, "Encountered a base-class object while looking for a new object. " \
- "Base class objects are only supposed to be parts of a larger object.");
- }
- RTTITypeBase* rtti = IReflectable::_getRTTIfromTypeId(objectTypeId);
- SerializedSubObject* serializedSubObject = nullptr;
-
- if (rtti != nullptr)
- {
- if (objectId > 0)
- {
- auto iterFind = mInterimObjectMap.find(objectId);
- if (iterFind == mInterimObjectMap.end())
- {
- output = bs_shared_ptr<SerializedObject>();
- mInterimObjectMap.insert(std::make_pair(objectId, output));
- }
- else
- output = iterFind->second;
- }
- else // Not a reflectable ptr referenced object
- output = bs_shared_ptr<SerializedObject>();
- output->subObjects.push_back(SerializedSubObject());
- serializedSubObject = &output->subObjects.back();
- serializedSubObject->typeId = objectTypeId;
- }
- while (bytesRead < dataLength)
- {
- int metaData = -1;
- if ((bytesRead + META_SIZE) > dataLength)
- {
- BS_EXCEPT(InternalErrorException,
- "Error decoding data.");
- }
- memcpy((void*)&metaData, data, META_SIZE);
- if (isObjectMetaData(metaData)) // We've reached a new object
- {
- if ((bytesRead + sizeof(ObjectMetaData)) > dataLength)
- {
- BS_EXCEPT(InternalErrorException,
- "Error decoding data.");
- }
- ObjectMetaData objMetaData;
- objMetaData.objectMeta = 0;
- objMetaData.typeId = 0;
- memcpy(&objMetaData, data, sizeof(ObjectMetaData));
- UINT32 objId = 0;
- UINT32 objTypeId = 0;
- bool objIsBaseClass = false;
- decodeObjectMetaData(objMetaData, objId, objTypeId, objIsBaseClass);
- // If it's a base class, get base class RTTI and handle that
- if (objIsBaseClass)
- {
- if (rtti != nullptr)
- rtti = rtti->getBaseClass();
- // Saved and current base classes don't match, so just skip over all that data
- if (rtti == nullptr || rtti->getRTTIId() != objTypeId)
- {
- rtti = nullptr;
- }
- if (rtti != nullptr)
- {
- output->subObjects.push_back(SerializedSubObject());
- serializedSubObject = &output->subObjects.back();
- serializedSubObject->typeId = objTypeId;
- }
- data += sizeof(ObjectMetaData);
- bytesRead += sizeof(ObjectMetaData);
- continue;
- }
- else
- {
- if (objId != 0)
- return true;
- // Objects with ID == 0 represent complex types serialized by value, but they should only get serialized
- // if we encounter a field with one, not by just iterating through the file.
- BS_EXCEPT(InternalErrorException, "Object with ID 0 encountered. Cannot proceed with serialization.");
- }
- }
- data += META_SIZE;
- bytesRead += META_SIZE;
- bool isArray;
- SerializableFieldType fieldType;
- UINT16 fieldId;
- UINT8 fieldSize;
- bool hasDynamicSize;
- decodeFieldMetaData(metaData, fieldId, fieldSize, isArray, fieldType, hasDynamicSize);
- RTTIField* curGenericField = nullptr;
- if (rtti != nullptr)
- curGenericField = rtti->findField(fieldId);
- if (curGenericField != nullptr)
- {
- if (!hasDynamicSize && curGenericField->getTypeSize() != fieldSize)
- {
- BS_EXCEPT(InternalErrorException,
- "Data type mismatch. Type size stored in file and actual type size don't match. ("
- + toString(curGenericField->getTypeSize()) + " vs. " + toString(fieldSize) + ")");
- }
- if (curGenericField->mIsVectorType != isArray)
- {
- BS_EXCEPT(InternalErrorException,
- "Data type mismatch. One is array, other is a single type.");
- }
- if (curGenericField->mType != fieldType)
- {
- BS_EXCEPT(InternalErrorException,
- "Data type mismatch. Field types don't match. " + toString(UINT32(curGenericField->mType)) + " vs. " + toString(UINT32(fieldType)));
- }
- }
- SPtr<SerializedInstance> serializedEntry;
- bool hasModification = false;
- int arrayNumElems = 1;
- if (isArray)
- {
- if ((bytesRead + NUM_ELEM_FIELD_SIZE) > dataLength)
- {
- BS_EXCEPT(InternalErrorException,
- "Error decoding data.");
- }
- memcpy((void*)&arrayNumElems, data, NUM_ELEM_FIELD_SIZE);
- data += NUM_ELEM_FIELD_SIZE;
- bytesRead += NUM_ELEM_FIELD_SIZE;
- SPtr<SerializedArray> serializedArray;
- if (curGenericField != nullptr)
- {
- serializedArray = bs_shared_ptr<SerializedArray>();
- serializedArray->numElements = arrayNumElems;
- serializedEntry = serializedArray;
- hasModification = true;
- }
- switch (fieldType)
- {
- case SerializableFT_ReflectablePtr:
- {
- RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
- for (int i = 0; i < arrayNumElems; i++)
- {
- if ((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
- {
- BS_EXCEPT(InternalErrorException,
- "Error decoding data.");
- }
- int childObjectId = 0;
- memcpy(&childObjectId, data, COMPLEX_TYPE_FIELD_SIZE);
- data += COMPLEX_TYPE_FIELD_SIZE;
- bytesRead += COMPLEX_TYPE_FIELD_SIZE;
- if (curField != nullptr)
- {
- SPtr<SerializedObject> serializedArrayEntry = nullptr;
-
- if (childObjectId > 0)
- {
- auto findObj = mInterimObjectMap.find(childObjectId);
- if (findObj == mInterimObjectMap.end())
- {
- serializedArrayEntry = bs_shared_ptr<SerializedObject>();
- mInterimObjectMap.insert(std::make_pair(childObjectId, serializedArrayEntry));
- }
- else
- serializedArrayEntry = findObj->second;
- }
- SerializedArrayEntry arrayEntry;
- arrayEntry.serialized = serializedArrayEntry;
- arrayEntry.index = i;
- serializedArray->entries[i] = arrayEntry;
- }
- }
- break;
- }
- case SerializableFT_Reflectable:
- {
- RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
- for (int i = 0; i < arrayNumElems; i++)
- {
- if ((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
- {
- BS_EXCEPT(InternalErrorException,
- "Error decoding data.");
- }
- UINT32 complexTypeSize = 0;
- memcpy(&complexTypeSize, data, COMPLEX_TYPE_FIELD_SIZE);
- data += COMPLEX_TYPE_FIELD_SIZE;
- bytesRead += COMPLEX_TYPE_FIELD_SIZE;
- if (curField != nullptr && complexTypeSize > 0)
- {
- UINT32 dummy = 0;
- SPtr<SerializedObject> serializedArrayEntry;
- decodeIntermediateInternal(data, complexTypeSize, dummy, serializedArrayEntry, copyData);
- SerializedArrayEntry arrayEntry;
- arrayEntry.serialized = serializedArrayEntry;
- arrayEntry.index = i;
- serializedArray->entries[i] = arrayEntry;
- }
- data += complexTypeSize;
- bytesRead += complexTypeSize;
- }
- break;
- }
- case SerializableFT_Plain:
- {
- RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
- for (int i = 0; i < arrayNumElems; i++)
- {
- UINT32 typeSize = fieldSize;
- if (hasDynamicSize)
- memcpy(&typeSize, data, sizeof(UINT32));
- if (curField != nullptr)
- {
- SPtr<SerializedField> serializedField = bs_shared_ptr<SerializedField>();
- if (copyData)
- {
- serializedField->value = (UINT8*)bs_alloc(typeSize);
- memcpy(serializedField->value, data, typeSize);
- serializedField->ownsMemory = true;
- }
- else
- serializedField->value = data;
- serializedField->size = typeSize;
- SerializedArrayEntry arrayEntry;
- arrayEntry.serialized = serializedField;
- arrayEntry.index = i;
- serializedArray->entries[i] = arrayEntry;
- }
- data += typeSize;
- bytesRead += typeSize;
- }
- break;
- }
- default:
- BS_EXCEPT(InternalErrorException,
- "Error decoding data. Encountered a type I don't know how to decode. Type: " + toString(UINT32(fieldType)) +
- ", Is array: " + toString(isArray));
- }
- }
- else
- {
- switch (fieldType)
- {
- case SerializableFT_ReflectablePtr:
- {
- RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
- if ((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
- {
- BS_EXCEPT(InternalErrorException,
- "Error decoding data.");
- }
- int childObjectId = 0;
- memcpy(&childObjectId, data, COMPLEX_TYPE_FIELD_SIZE);
- data += COMPLEX_TYPE_FIELD_SIZE;
- bytesRead += COMPLEX_TYPE_FIELD_SIZE;
- if (curField != nullptr)
- {
- SPtr<SerializedObject> serializedField = nullptr;
- if (childObjectId > 0)
- {
- auto findObj = mInterimObjectMap.find(childObjectId);
- if (findObj == mInterimObjectMap.end())
- {
- serializedField = bs_shared_ptr<SerializedObject>();
- mInterimObjectMap.insert(std::make_pair(childObjectId, serializedField));
- }
- else
- serializedField = findObj->second;
- }
- serializedEntry = serializedField;
- hasModification = true;
- }
- break;
- }
- case SerializableFT_Reflectable:
- {
- RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
- if ((bytesRead + COMPLEX_TYPE_FIELD_SIZE) > dataLength)
- {
- BS_EXCEPT(InternalErrorException,
- "Error decoding data.");
- }
- UINT32 complexTypeSize = 0;
- memcpy(&complexTypeSize, data, COMPLEX_TYPE_FIELD_SIZE);
- data += COMPLEX_TYPE_FIELD_SIZE;
- bytesRead += COMPLEX_TYPE_FIELD_SIZE;
- if (curField != nullptr && complexTypeSize > 0)
- {
- UINT32 dummy = 0;
- SPtr<SerializedObject> serializedChildObj;
- decodeIntermediateInternal(data, complexTypeSize, dummy, serializedChildObj, copyData);
- serializedEntry = serializedChildObj;
- hasModification = true;
- }
- data += complexTypeSize;
- bytesRead += complexTypeSize;
- break;
- }
- case SerializableFT_Plain:
- {
- RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
- UINT32 typeSize = fieldSize;
- if (hasDynamicSize)
- memcpy(&typeSize, data, sizeof(UINT32));
- if (curField != nullptr)
- {
- SPtr<SerializedField> serializedField = bs_shared_ptr<SerializedField>();
- if (copyData)
- {
- serializedField->value = (UINT8*)bs_alloc(typeSize);
- memcpy(serializedField->value, data, typeSize);
- serializedField->ownsMemory = true;
- }
- else
- serializedField->value = data;
- serializedField->size = typeSize;
- serializedEntry = serializedField;
- hasModification = true;
- }
- data += typeSize;
- bytesRead += typeSize;
- break;
- }
- case SerializableFT_DataBlock:
- {
- RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
- if ((bytesRead + DATA_BLOCK_TYPE_FIELD_SIZE) > dataLength)
- {
- BS_EXCEPT(InternalErrorException,
- "Error decoding data.");
- }
- // Data block size
- UINT32 dataBlockSize = 0;
- memcpy(&dataBlockSize, data, DATA_BLOCK_TYPE_FIELD_SIZE);
- data += DATA_BLOCK_TYPE_FIELD_SIZE;
- bytesRead += DATA_BLOCK_TYPE_FIELD_SIZE;
- if ((bytesRead + dataBlockSize) > dataLength)
- {
- BS_EXCEPT(InternalErrorException,
- "Error decoding data.");
- }
- // Data block data
- if (curField != nullptr)
- {
- SPtr<SerializedField> serializedField = bs_shared_ptr<SerializedField>();
- if (copyData)
- {
- serializedField->value = (UINT8*)bs_alloc(dataBlockSize);
- memcpy(serializedField->value, data, dataBlockSize);
- serializedField->ownsMemory = true;
- }
- else
- serializedField->value = data;
- serializedField->size = dataBlockSize;
- serializedEntry = serializedField;
- hasModification = true;
- }
- data += dataBlockSize;
- bytesRead += dataBlockSize;
- break;
- }
- default:
- BS_EXCEPT(InternalErrorException,
- "Error decoding data. Encountered a type I don't know how to decode. Type: " + toString(UINT32(fieldType)) +
- ", Is array: " + toString(isArray));
- }
- }
- if (hasModification)
- {
- SerializedEntry entry;
- entry.fieldId = curGenericField->mUniqueId;
- entry.serialized = serializedEntry;
- serializedSubObject->entries.insert(std::make_pair(curGenericField->mUniqueId, entry));
- }
- }
- return false;
- }
- void BinarySerializer::decodeInternal(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& serializableObject)
- {
- UINT32 numSubObjects = (UINT32)serializableObject->subObjects.size();
- Vector<RTTITypeBase*> rttiTypes;
- for (UINT32 subObjectIdx = 0; subObjectIdx < numSubObjects; subObjectIdx++)
- {
- const SerializedSubObject& subObject = serializableObject->subObjects[subObjectIdx];
- RTTITypeBase* rtti = IReflectable::_getRTTIfromTypeId(subObject.typeId);
- if (rtti == nullptr)
- continue;
- rtti->onDeserializationStarted(object.get());
- rttiTypes.push_back(rtti);
- UINT32 numFields = rtti->getNumFields();
- for (UINT32 fieldIdx = 0; fieldIdx < numFields; fieldIdx++)
- {
- RTTIField* curGenericField = rtti->getField(fieldIdx);
- auto iterFindFieldData = subObject.entries.find(curGenericField->mUniqueId);
- if (iterFindFieldData == subObject.entries.end())
- continue;
- SPtr<SerializedInstance> entryData = iterFindFieldData->second.serialized;
- if (curGenericField->isArray())
- {
- SPtr<SerializedArray> arrayData = std::static_pointer_cast<SerializedArray>(entryData);
- UINT32 arrayNumElems = (UINT32)arrayData->numElements;
- curGenericField->setArraySize(object.get(), arrayNumElems);
- switch (curGenericField->mType)
- {
- case SerializableFT_ReflectablePtr:
- {
- RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
- for (auto& arrayElem : arrayData->entries)
- {
- SPtr<SerializedObject> arrayElemData = std::static_pointer_cast<SerializedObject>(arrayElem.second.serialized);
- RTTITypeBase* childRtti = nullptr;
-
- if (arrayElemData != nullptr)
- childRtti = IReflectable::_getRTTIfromTypeId(arrayElemData->getRootTypeId());
- if (childRtti != nullptr)
- {
- auto findObj = mObjectMap.find(arrayElemData);
- if (findObj == mObjectMap.end())
- {
- SPtr<IReflectable> newObject = childRtti->newRTTIObject();
- findObj = mObjectMap.insert(std::make_pair(arrayElemData, ObjectToDecode(newObject, arrayElemData))).first;
- }
- ObjectToDecode& objToDecode = findObj->second;
- bool needsDecoding = (curField->getFlags() & RTTI_Flag_WeakRef) == 0 && !objToDecode.isDecoded;
- if (needsDecoding)
- {
- decodeInternal(objToDecode.object, objToDecode.serializedObject);
- objToDecode.isDecoded = true;
- }
- curField->setArrayValue(object.get(), arrayElem.first, objToDecode.object);
- }
- else
- {
- curField->setArrayValue(object.get(), arrayElem.first, nullptr);
- }
- }
- }
- break;
- case SerializableFT_Reflectable:
- {
- RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
- for (auto& arrayElem : arrayData->entries)
- {
- SPtr<SerializedObject> arrayElemData = std::static_pointer_cast<SerializedObject>(arrayElem.second.serialized);
- RTTITypeBase* childRtti = nullptr;
- if (arrayElemData != nullptr)
- childRtti = IReflectable::_getRTTIfromTypeId(arrayElemData->getRootTypeId());
- if (childRtti != nullptr)
- {
- SPtr<IReflectable> newObject = childRtti->newRTTIObject();
- decodeInternal(newObject, arrayElemData);
- curField->setArrayValue(object.get(), arrayElem.first, *newObject);
- }
- }
- break;
- }
- case SerializableFT_Plain:
- {
- RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
- for (auto& arrayElem : arrayData->entries)
- {
- SPtr<SerializedField> fieldData = std::static_pointer_cast<SerializedField>(arrayElem.second.serialized);
- if (fieldData != nullptr)
- {
- curField->arrayElemFromBuffer(object.get(), arrayElem.first, fieldData->value);
- }
- }
- }
- break;
- }
- }
- else
- {
- switch (curGenericField->mType)
- {
- case SerializableFT_ReflectablePtr:
- {
- RTTIReflectablePtrFieldBase* curField = static_cast<RTTIReflectablePtrFieldBase*>(curGenericField);
- SPtr<SerializedObject> fieldObjectData = std::static_pointer_cast<SerializedObject>(entryData);
- RTTITypeBase* childRtti = nullptr;
- if (fieldObjectData != nullptr)
- childRtti = IReflectable::_getRTTIfromTypeId(fieldObjectData->getRootTypeId());
- if (childRtti != nullptr)
- {
- auto findObj = mObjectMap.find(fieldObjectData);
- if (findObj == mObjectMap.end())
- {
- SPtr<IReflectable> newObject = childRtti->newRTTIObject();
- findObj = mObjectMap.insert(std::make_pair(fieldObjectData, ObjectToDecode(newObject, fieldObjectData))).first;
- }
- ObjectToDecode& objToDecode = findObj->second;
- bool needsDecoding = (curField->getFlags() & RTTI_Flag_WeakRef) == 0 && !objToDecode.isDecoded;
- if (needsDecoding)
- {
- decodeInternal(objToDecode.object, objToDecode.serializedObject);
- objToDecode.isDecoded = true;
- }
- curField->setValue(object.get(), objToDecode.object);
- }
- else
- {
- curField->setValue(object.get(), nullptr);
- }
- }
- break;
- case SerializableFT_Reflectable:
- {
- RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
- SPtr<SerializedObject> fieldObjectData = std::static_pointer_cast<SerializedObject>(entryData);
- RTTITypeBase* childRtti = nullptr;
- if (fieldObjectData != nullptr)
- childRtti = IReflectable::_getRTTIfromTypeId(fieldObjectData->getRootTypeId());
- if (childRtti != nullptr)
- {
- SPtr<IReflectable> newObject = childRtti->newRTTIObject();
- decodeInternal(newObject, fieldObjectData);
- curField->setValue(object.get(), *newObject);
- }
- break;
- }
- case SerializableFT_Plain:
- {
- RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
- SPtr<SerializedField> fieldData = std::static_pointer_cast<SerializedField>(entryData);
- if (fieldData != nullptr)
- {
- curField->fromBuffer(object.get(), fieldData->value);
- }
- }
- break;
- case SerializableFT_DataBlock:
- {
- RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
- SPtr<SerializedField> fieldData = std::static_pointer_cast<SerializedField>(entryData);
- if (fieldData != nullptr)
- {
- UINT8* dataCopy = curField->allocate(object.get(), fieldData->size); // TODO - Low priority. I need to read files better, so I
- memcpy(dataCopy, fieldData->value, fieldData->size); // can just pass the buffer pointer directly without copying (possibly large amounts of data)
- ManagedDataBlock value(dataCopy, fieldData->size); // Not managed because I assume the owner class will decide whether to delete the data or keep it
- curField->setValue(object.get(), value);
- }
- break;
- }
- }
- }
- }
- }
- for (auto iterFind = rttiTypes.rbegin(); iterFind != rttiTypes.rend(); ++iterFind)
- {
- (*iterFind)->onDeserializationEnded(object.get());
- }
- }
- // TODO - This needs serious fixing, it doesn't account for all properties
- UINT32 BinarySerializer::getObjectSize(IReflectable* object)
- {
- if(object == nullptr)
- return 0;
- UINT32 objectSize = 0;
- RTTITypeBase* si = object->getRTTI();
- do
- {
- // Object ID + type data
- objectSize += sizeof(ObjectMetaData);
- int numFields = si->getNumFields();
- for(int i = 0; i < numFields; i++)
- {
- RTTIField* curGenericField = si->getField(i);
- // Field meta data
- objectSize += sizeof(UINT32);
- if(curGenericField->mIsVectorType)
- {
- UINT32 arrayNumElems = curGenericField->getArraySize(object);
- // Num array elems
- objectSize += sizeof(UINT32);
- switch(curGenericField->mType)
- {
- case SerializableFT_ReflectablePtr:
- {
- objectSize += sizeof(UINT32) * arrayNumElems;
- break;
- }
- case SerializableFT_Reflectable:
- {
- RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
- for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
- {
- IReflectable& childObject = curField->getArrayValue(object, arrIdx);
- objectSize += sizeof(UINT32); // Complex type size
- objectSize += getObjectSize(&childObject);
- }
- break;
- }
- case SerializableFT_Plain:
- {
- RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
- for(UINT32 arrIdx = 0; arrIdx < arrayNumElems; arrIdx++)
- {
- UINT32 typeSize = 0;
- if(curField->hasDynamicSize())
- typeSize = curField->getArrayElemDynamicSize(object, arrIdx);
- else
- typeSize = curField->getTypeSize();
- objectSize += typeSize;
- }
- break;
- }
- default:
- BS_EXCEPT(InternalErrorException,
- "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
- ", Is array: " + toString(curGenericField->mIsVectorType));
- }
- }
- else
- {
- switch(curGenericField->mType)
- {
- case SerializableFT_ReflectablePtr:
- {
- objectSize += sizeof(UINT32);
- break;
- }
- case SerializableFT_Reflectable:
- {
- RTTIReflectableFieldBase* curField = static_cast<RTTIReflectableFieldBase*>(curGenericField);
- IReflectable& childObject = curField->getValue(object);
- objectSize += sizeof(UINT32); // Complex type size
- objectSize += getObjectSize(&childObject);
- break;
- }
- case SerializableFT_Plain:
- {
- RTTIPlainFieldBase* curField = static_cast<RTTIPlainFieldBase*>(curGenericField);
- UINT32 typeSize = 0;
- if(curField->hasDynamicSize())
- typeSize = curField->getDynamicSize(object);
- else
- typeSize = curField->getTypeSize();
- objectSize += typeSize;
- break;
- }
- case SerializableFT_DataBlock:
- {
- RTTIManagedDataBlockFieldBase* curField = static_cast<RTTIManagedDataBlockFieldBase*>(curGenericField);
- ManagedDataBlock value = curField->getValue(object);
- // Data block size
- UINT32 dataBlockSize = value.getSize();
- objectSize += sizeof(UINT32) + dataBlockSize;
- break;
- }
- default:
- BS_EXCEPT(InternalErrorException,
- "Error encoding data. Encountered a type I don't know how to encode. Type: " + toString(UINT32(curGenericField->mType)) +
- ", Is array: " + toString(curGenericField->mIsVectorType));
- }
- }
- }
- si = si->getBaseClass();
- } while (si != nullptr);
- return objectSize;
- }
- UINT32 BinarySerializer::encodeFieldMetaData(UINT16 id, UINT8 size, bool array, SerializableFieldType type, bool hasDynamicSize)
- {
- // If O == 0 - Meta contains field information (Encoded using this method)
- //// Encoding: IIII IIII IIII IIII SSSS SSSS xxYP DCAO
- //// I - Id
- //// S - Size
- //// C - Complex
- //// A - Array
- //// D - Data block
- //// P - Complex ptr
- //// O - Object descriptor
- //// Y - Plain field has dynamic size
- return (id << 16 | size << 8 |
- (array ? 0x02 : 0) |
- ((type == SerializableFT_DataBlock) ? 0x04 : 0) |
- ((type == SerializableFT_Reflectable) ? 0x08 : 0) |
- ((type == SerializableFT_ReflectablePtr) ? 0x10 : 0) |
- (hasDynamicSize ? 0x20 : 0)); // TODO - Low priority. Technically I could encode this much more tightly, and use var-ints for ID
- }
- void BinarySerializer::decodeFieldMetaData(UINT32 encodedData, UINT16& id, UINT8& size, bool& array, SerializableFieldType& type, bool& hasDynamicSize)
- {
- if(isObjectMetaData(encodedData))
- {
- BS_EXCEPT(InternalErrorException,
- "Meta data represents an object description but is trying to be decoded as a field descriptor.");
- }
- hasDynamicSize = (encodedData & 0x20) != 0;
- if((encodedData & 0x10) != 0)
- type = SerializableFT_ReflectablePtr;
- else if((encodedData & 0x08) != 0)
- type = SerializableFT_Reflectable;
- else if((encodedData & 0x04) != 0)
- type = SerializableFT_DataBlock;
- else
- type = SerializableFT_Plain;
- array = (encodedData & 0x02) != 0;
- size = (UINT8)((encodedData >> 8) & 0xFF);
- id = (UINT16)((encodedData >> 16) & 0xFFFF);
- }
- BinarySerializer::ObjectMetaData BinarySerializer::encodeObjectMetaData(UINT32 objId, UINT32 objTypeId, bool isBaseClass)
- {
- // If O == 1 - Meta contains object instance information (Encoded using encodeObjectMetaData)
- //// Encoding: SSSS SSSS SSSS SSSS xxxx xxxx xxxx xxBO
- //// S - Size of the object identifier
- //// O - Object descriptor
- //// B - Base class indicator
-
- if(objId > 1073741823)
- {
- BS_EXCEPT(InvalidParametersException, "Object ID is larger than we can store (max 30 bits): " + toString(objId));
- }
- ObjectMetaData metaData;
- metaData.objectMeta = (objId << 2) | (isBaseClass ? 0x02 : 0) | 0x01;
- metaData.typeId = objTypeId;
- return metaData;
- }
- void BinarySerializer::decodeObjectMetaData(BinarySerializer::ObjectMetaData encodedData, UINT32& objId, UINT32& objTypeId, bool& isBaseClass)
- {
- if(!isObjectMetaData(encodedData.objectMeta))
- {
- BS_EXCEPT(InternalErrorException,
- "Meta data represents a field description but is trying to be decoded as an object descriptor.");
- }
- objId = (encodedData.objectMeta >> 2) & 0x3FFFFFFF;
- isBaseClass = (encodedData.objectMeta & 0x02) != 0;
- objTypeId = encodedData.typeId;
- }
- bool BinarySerializer::isObjectMetaData(UINT32 encodedData)
- {
- return ((encodedData & 0x01) != 0);
- }
- UINT8* BinarySerializer::complexTypeToBuffer(IReflectable* object, UINT8* buffer, UINT32& bufferLength,
- UINT32* bytesWritten, std::function<UINT8*(UINT8*, UINT32, UINT32&)> flushBufferCallback, bool shallow)
- {
- int complexTypeSize = 0;
- if(object != nullptr)
- complexTypeSize = getObjectSize(object);
- COPY_TO_BUFFER(&complexTypeSize, COMPLEX_TYPE_FIELD_SIZE)
- if(object != nullptr)
- return encodeInternal(object, 0, buffer, bufferLength, bytesWritten, flushBufferCallback, shallow);
- return buffer;
- }
- UINT8* BinarySerializer::dataBlockToBuffer(UINT8* data, UINT32 size, UINT8* buffer, UINT32& bufferLength, UINT32* bytesWritten,
- std::function<UINT8*(UINT8* buffer, UINT32 bytesWritten, UINT32& newBufferSize)> flushBufferCallback)
- {
- UINT32 remainingSize = size;
- while (remainingSize > 0)
- {
- UINT32 remainingSpaceInBuffer = bufferLength - *bytesWritten;
- if (remainingSize <= remainingSpaceInBuffer)
- {
- COPY_TO_BUFFER(data, remainingSize);
- remainingSize = 0;
- }
- else
- {
- memcpy(buffer, data, remainingSpaceInBuffer);
- buffer += remainingSpaceInBuffer;
- *bytesWritten += remainingSpaceInBuffer;
- data += remainingSpaceInBuffer;
- remainingSize -= remainingSpaceInBuffer;
- mTotalBytesWritten += *bytesWritten;
- buffer = flushBufferCallback(buffer - *bytesWritten, *bytesWritten, bufferLength);
- if (buffer == nullptr || bufferLength == 0)
- return nullptr;
- *bytesWritten = 0;
- }
- }
- return buffer;
- }
- UINT32 BinarySerializer::findOrCreatePersistentId(IReflectable* object)
- {
- void* ptrAddress = (void*)object;
- auto findIter = mObjectAddrToId.find(ptrAddress);
- if(findIter != mObjectAddrToId.end())
- return findIter->second;
- UINT32 objId = mLastUsedObjectId++;
- mObjectAddrToId.insert(std::make_pair(ptrAddress, objId));
- return objId;
- }
- UINT32 BinarySerializer::registerObjectPtr(std::shared_ptr<IReflectable> object)
- {
- if(object == nullptr)
- return 0;
- void* ptrAddress = (void*)object.get();
- auto iterFind = mObjectAddrToId.find(ptrAddress);
- if(iterFind == mObjectAddrToId.end())
- {
- UINT32 objId = findOrCreatePersistentId(object.get());
- mObjectsToEncode.push_back(ObjectToEncode(objId, object));
- mObjectAddrToId.insert(std::make_pair(ptrAddress, objId));
- return objId;
- }
- return iterFind->second;
- }
- }
- #undef COPY_TO_BUFFER
|