19 #ifndef PACKED_MEMORY_BUILDER_HXX
20 #define PACKED_MEMORY_BUILDER_HXX
26 #include <base_utils/base_utils_errors.h>
28 #include <base_utils/Mem.h>
33 namespace PackedMemory
46 const struct {
char c;
char *ptr; } *pAlignment= 0;
47 const size_t alignment= size_t(&pAlignment->ptr);
49 return (datasize + alignment - 1) / alignment * alignment;
63 return MEM_alloc((
int)size);
70 size_t dataToPackCount,
71 MEM_data_to_pack_p_t pDataToPack,
76 return MEM_alloc_packed(dataToPackCount, pDataToPack, allowOverride);
269 template <
class T,
typename Alloc = DefaultAllocator>
281 explicit Builder(
size_t elements= 1);
293 explicit Builder(
const char *pSrcString,
size_t maxLength= ~0);
332 template <
typename K>
333 inline K
addString(K &pDestPtr,
const char *pSrcString);
346 template <
typename K>
347 K
addData(K &pDestPtr,
size_t elements= 1,
const void *pSourceData= NULL);
360 template <
typename K,
typename J>
467 bool getMappedObject(
const void *pBaseAddress,
void *&pMappedObject,
bool bBaseOnly=
false)
const;
497 template <
class T,
typename Alloc>
499 m_pObjectData(NULL), m_lookupStringData(false)
508 buffer.resize(datasize);
514 m_pObjectData= datasize ?
reinterpret_cast<T *
>(&buffer[0]) : NULL;
517 template <
class T,
typename Alloc>
519 m_pObjectData(NULL), m_lookupStringData(false)
522 const size_t stringSize= pSrcString ? strlen(pSrcString) + 1 : 0;
523 const size_t datasize= stringSize < maxLength ? stringSize : maxLength;
529 buffer.resize(datasize);
535 m_pObjectData= datasize ?
reinterpret_cast<T *
>(&buffer[0]) : NULL;
538 if (pSrcString && datasize)
540 strncpy(&buffer[0], pSrcString, datasize);
541 buffer[datasize - 1] =
'\0';
545 template <
class T,
typename Alloc>
template <
typename K>
549 const size_t datasize= pSrcString ? strlen(pSrcString) + 1 : 0;
552 if (datasize && m_lookupStringData)
555 typename StringDataSet::iterator searchIter = m_addedStringData.find(
StringData(pSrcString, datasize));
557 if (searchIter != m_addedStringData.end())
560 K pReferenceData =
reinterpret_cast<K
>(
const_cast<char *
>(searchIter->m_pString));
562 return addReference(pDestPtr, pReferenceData);
567 K pAddedData = addData(pDestPtr, datasize, pSrcString);
569 m_addedStringData.insert(
StringData(pAddedData, datasize));
578 return addData(pDestPtr, datasize, pSrcString);
581 template <
class T,
typename Alloc>
template <
typename K>
585 const size_t datasize=
getAlignedSize(
sizeof(*pDestPtr) * elements);
588 void *pParameterAddess= (
void *)&pDestPtr;
592 void *pBaseObject= NULL;
593 if (!getMappedObject(pParameterAddess, pBaseObject))
595 throw IFail( BASE_UTILS_invalid_reference );
599 ObjectDataMap::const_iterator searchIter= m_objectDataMap.find(pParameterAddess);
600 if (searchIter != m_objectDataMap.end())
602 throw IFail( BASE_UTILS_already_initialized,
"m_objectDataMap" );
606 m_referencedObjects[pBaseObject].push_back(pParameterAddess);
609 Buffer &buffer= m_objectDataMap[pParameterAddess];
610 buffer.resize(datasize);
613 m_objectBackRefDataMap[&buffer[0]]=
BackRefData(pParameterAddess, datasize);
616 if (pSourceData && datasize)
619 memcpy(&buffer[0], pSourceData, datasize);
623 pDestPtr= datasize ?
reinterpret_cast<K
>(&buffer[0]) : NULL;
629 template <
class T,
typename Alloc>
template <
typename K,
typename J>
633 void *pParameterAddess= (
void *)&pDestPtr;
637 void *pBaseObject= NULL;
638 if (!getMappedObject(pParameterAddess, pBaseObject))
640 throw IFail( BASE_UTILS_invalid_reference );
644 ObjectDataMap::const_iterator searchIter= m_objectDataMap.find(pParameterAddess);
645 if (searchIter != m_objectDataMap.end())
647 throw IFail( BASE_UTILS_already_initialized,
"m_objectDataMap" );
652 void *pRefBaseObject= NULL;
653 if (!getMappedObject(pReferenceData, pRefBaseObject,
true))
655 throw IFail( BASE_UTILS_invalid_reference );
659 m_referencedObjects[pBaseObject].push_back(pParameterAddess);
662 m_backReferencedObjects[pParameterAddess]= pRefBaseObject;
666 Buffer &buffer= m_objectDataMap[pParameterAddess];
670 m_objectBackRefDataMap[&buffer[0]] =
BackRefData(pParameterAddess, 0);
673 pDestPtr= pReferenceData;
679 template <
class T,
typename Alloc>
689 createOutputBuffer(destinationMap, pDestination);
694 createOutputBufferUsingSMPack(destinationMap, pDestination, createMode ==
AllowOverride);
698 ReferencedObjectsMap::const_iterator referencedIter= m_referencedObjects.begin();
699 for ( ; referencedIter != m_referencedObjects.end(); ++referencedIter)
702 ObjectDataMap::const_iterator objectDataIter= m_objectDataMap.find(referencedIter->first);
703 if (objectDataIter == m_objectDataMap.end())
705 throw IFail( BASE_UTILS_expected_data_missing,
"m_objectDataMap" );
709 ObjectPointerMap::iterator destinationObject= destinationMap.find(referencedIter->first);
710 if (destinationObject == destinationMap.end())
712 throw IFail( BASE_UTILS_expected_data_missing,
"destinationMap" );
716 ReferencedObjectsList::const_iterator childIter= referencedIter->second.begin();
717 for ( ; childIter != referencedIter->second.end(); ++childIter)
720 ObjectPointerMap::iterator referencedDestinationObject= destinationMap.find(*childIter);
721 if (referencedDestinationObject == destinationMap.end())
723 throw IFail( BASE_UTILS_expected_data_missing,
"destinationMap" );
727 size_t offset= size_t(*childIter) - size_t(&objectDataIter->second[0]);
730 *
reinterpret_cast<void **
>(size_t(destinationObject->second) + offset) = referencedDestinationObject->second;
736 template <
class T,
typename Alloc>
740 if (pBaseAddress != NULL && !m_objectBackRefDataMap.empty())
743 typename ObjectBackRefDataMap::const_iterator searchIter = m_objectBackRefDataMap.upper_bound(pBaseAddress);
745 if (searchIter != m_objectBackRefDataMap.begin()) { --searchIter; }
748 const void *pObjectEnd =
reinterpret_cast<const char *
>(searchIter->first) + searchIter->second.datasize;
751 if ((bBaseOnly && pBaseAddress == searchIter->first) || (searchIter->first <= pBaseAddress && pBaseAddress < pObjectEnd))
754 pMappedObject = searchIter->second.pData;
760 pMappedObject = NULL;
764 template <
class T,
typename Alloc>
770 throw IFail( BASE_UTILS_invalid_parameter );
777 ObjectDataMap::const_iterator objectDataIter= m_objectDataMap.begin();
778 for ( ; objectDataIter != m_objectDataMap.end(); ++objectDataIter)
780 totalSize+= objectDataIter->second.size();
784 char *pOutputBuffer= totalSize ?
reinterpret_cast<char *
>(allocator().alloc(totalSize)) : NULL;
786 if (totalSize && !pOutputBuffer)
788 throw IFail( BASE_UTILS_no_memory );
793 *pDestination= totalSize ?
reinterpret_cast<T *
>(pOutputBuffer) : NULL;
797 char *pOutputBufferEnd= pOutputBuffer + totalSize;
800 objectDataIter= m_objectDataMap.begin();
801 for ( ; objectDataIter != m_objectDataMap.end(); ++objectDataIter)
804 if (objectDataIter->second.empty())
807 destinationMap[objectDataIter->first]= NULL;
812 memcpy(pOutputBuffer, &objectDataIter->second[0], objectDataIter->second.size());
813 destinationMap[objectDataIter->first]= pOutputBuffer;
814 pOutputBuffer+= objectDataIter->second.size();
820 ObjectPointerMap::const_iterator backRefIter= m_backReferencedObjects.begin();
821 for ( ; backRefIter != m_backReferencedObjects.end(); ++backRefIter)
824 ObjectPointerMap::iterator backRefDataIter= destinationMap.find(backRefIter->first);
825 if (backRefDataIter == destinationMap.end() || backRefDataIter->second != NULL)
827 throw IFail( BASE_UTILS_internal_error );
831 ObjectPointerMap::const_iterator searchIter= destinationMap.find(backRefIter->second);
832 if (searchIter == destinationMap.end() || searchIter->second == NULL)
834 throw IFail( BASE_UTILS_internal_error );
838 backRefDataIter->second= searchIter->second;
843 if (pOutputBuffer != pOutputBufferEnd || destinationMap[NULL] != *pDestination)
845 throw IFail( BASE_UTILS_internal_error );
849 template <
class T,
typename Alloc>
855 throw IFail(BASE_UTILS_invalid_parameter);
859 std::vector<MEM_data_to_pack_t> dataToPack;
860 dataToPack.reserve(m_objectDataMap.size());
863 ObjectDataMap::const_iterator objectDataIter = m_objectDataMap.begin();
864 for (; objectDataIter != m_objectDataMap.end(); ++objectDataIter)
866 MEM_data_to_pack_t data;
867 data.data = !objectDataIter->second.empty() ? objectDataIter->second.data() : NULL;
868 data.data_size = objectDataIter->second.size();
870 dataToPack.push_back(data);
875 *pDestination =
reinterpret_cast<T *
>(allocator().alloc_packed(dataToPack.size(), &dataToPack[0], allowOverride));
877 if (dataToPack.front().data_size && !*pDestination)
879 throw IFail(BASE_UTILS_no_memory);
883 objectDataIter = m_objectDataMap.begin();
884 for (
size_t i = 0; objectDataIter != m_objectDataMap.end(); ++i, ++objectDataIter)
886 destinationMap[objectDataIter->first] = (
void *)dataToPack[i].data;
890 ObjectPointerMap::const_iterator backRefIter = m_backReferencedObjects.begin();
891 for (; backRefIter != m_backReferencedObjects.end(); ++backRefIter)
894 ObjectPointerMap::iterator backRefDataIter = destinationMap.find(backRefIter->first);
895 if (backRefDataIter == destinationMap.end() || backRefDataIter->second != NULL)
897 throw IFail(BASE_UTILS_internal_error);
901 ObjectPointerMap::const_iterator searchIter = destinationMap.find(backRefIter->second);
902 if (searchIter == destinationMap.end() || searchIter->second == NULL)
904 throw IFail(BASE_UTILS_internal_error);
908 backRefDataIter->second = searchIter->second;
915 #endif // PACKED_MEMORY_BUILDER_HXX