X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Fpublic-api%2Fcommon%2Fdali-vector.cpp;h=ea36bcdc2af947aca51de4416fb9467ac3afc9b3;hb=refs%2Fchanges%2F54%2F268354%2F2;hp=084515e3ad3efce1a5b50cc974418998ebd96a1c;hpb=7882128f66bc91dbca9573caddd312115be440c4;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/public-api/common/dali-vector.cpp b/dali/public-api/common/dali-vector.cpp index 084515e..ea36bcd 100644 --- a/dali/public-api/common/dali-vector.cpp +++ b/dali/public-api/common/dali-vector.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,125 +23,142 @@ namespace Dali { - VectorBase::VectorBase() - : mData( NULL ) +: mData(nullptr) { } -VectorBase::~VectorBase() -{ -} +VectorBase::~VectorBase() = default; VectorBase::SizeType VectorBase::Capacity() const { SizeType capacity = 0u; - if( mData ) + if(mData) { - SizeType* metadata = reinterpret_cast< SizeType* >( mData ); - capacity = *(metadata - 2u); + SizeType* metadata = reinterpret_cast(mData); + capacity = *(metadata - 2u); } return capacity; } - void VectorBase::Release() { - if( mData ) + if(mData) { // adjust pointer to real beginning - SizeType* metadata = reinterpret_cast< SizeType* >( mData ); - // TODO would be nice to memset to a bitpattern to catch illegal use of container after release - // but that would require knowledge of the itemsize - free( metadata - 2u ); - mData = 0u; + SizeType* metadata = reinterpret_cast(mData); + + delete[](metadata - 2u); + mData = nullptr; } } -void VectorBase::SetCount( SizeType count ) +void VectorBase::Replace(void* newData) +{ + if(mData) + { + // adjust pointer to real beginning + SizeType* metadata = reinterpret_cast(mData); + + // Cause timming issue, we set new data before metadata delete. + mData = newData; + + // delete metadata address after mData setup safety. + delete[](metadata - 2u); + } + else + { + // mData was nullptr. Just copy data address + mData = newData; + } +} + +void VectorBase::SetCount(SizeType count) { // someone can call Resize( 0u ) before ever populating the vector - if( mData ) + if(mData) { - SizeType* metadata = reinterpret_cast< SizeType* >( mData ); - *(metadata - 1u) = count; + SizeType* metadata = reinterpret_cast(mData); + *(metadata - 1u) = count; } } -void VectorBase::Reserve( SizeType capacity, SizeType elementSize ) +void VectorBase::Reserve(SizeType capacity, SizeType elementSize) { SizeType oldCapacity = Capacity(); - SizeType oldCount = Count(); - if( capacity > oldCapacity ) + SizeType oldCount = Count(); + if(capacity > oldCapacity) { const SizeType wholeAllocation = sizeof(SizeType) * 2u + capacity * elementSize; - void* wholeData = (void*)malloc( wholeAllocation ); - DALI_ASSERT_ALWAYS( wholeData && "VectorBase::Reserve - Memory allocation failed" ); + void* wholeData = reinterpret_cast(new uint8_t[wholeAllocation]); + DALI_ASSERT_ALWAYS(wholeData && "VectorBase::Reserve - Memory allocation failed"); -#if defined( DEBUG_ENABLED ) +#if defined(DEBUG_ENABLED) // in debug build this will help identify a vector of uninitialized data - memset( wholeData, 0xaa, wholeAllocation ); + memset(wholeData, 0xaa, wholeAllocation); #endif - SizeType* metaData = reinterpret_cast< SizeType* >( wholeData ); - *metaData++ = capacity; - *metaData++ = oldCount; - if( mData ) + SizeType* metaData = reinterpret_cast(wholeData); + *metaData++ = capacity; + *metaData++ = oldCount; + if(mData) { // copy over the old data - memcpy( metaData, mData, oldCount * elementSize ); - // release old buffer - Release(); + memcpy(metaData, mData, oldCount * elementSize); } - mData = metaData; + // release old buffer and set new data as mData + Replace(reinterpret_cast(metaData)); } } -void VectorBase::Copy( const VectorBase& vector, SizeType elementSize ) +void VectorBase::Copy(const VectorBase& vector, SizeType elementSize) { - // release old data - Release(); // reserve space based on source capacity - const SizeType capacity = vector.Capacity(); - Reserve( capacity, elementSize ); - // copy over whole data + const SizeType capacity = vector.Capacity(); const SizeType wholeAllocation = sizeof(SizeType) * 2u + capacity * elementSize; - SizeType* srcData = reinterpret_cast< SizeType* >( vector.mData ); - SizeType* dstData = reinterpret_cast< SizeType* >( mData ); - memcpy( dstData - 2u, srcData - 2u, wholeAllocation ); + void* wholeData = reinterpret_cast(new uint8_t[wholeAllocation]); + DALI_ASSERT_ALWAYS(wholeData && "VectorBase::Copy - Memory allocation failed"); + + // copy over whole data + SizeType* srcData = reinterpret_cast(vector.mData); + SizeType* dstData = reinterpret_cast(wholeData) + 2u; + memcpy(dstData - 2u, srcData - 2u, wholeAllocation); + + // release old buffer and set new data as mData + Replace(reinterpret_cast(dstData)); } -void VectorBase::Swap( VectorBase& vector ) +void VectorBase::Swap(VectorBase& vector) { // just swap the data pointers, metadata will swap as side effect - std::swap( mData, vector.mData ); + std::swap(mData, vector.mData); } -void VectorBase::Erase( char* address, SizeType elementSize ) +void VectorBase::Erase(char* address, SizeType elementSize) { // erase can be called on an unallocated vector - if( mData ) + if(mData) { - char* startAddress = address + elementSize; - const char* endAddress = reinterpret_cast< char* >( mData ) + Count() * elementSize; - SizeType numberOfBytes = endAddress - startAddress; + uint8_t* startAddress = reinterpret_cast(address) + elementSize; + const uint8_t* endAddress = reinterpret_cast(mData) + Count() * elementSize; + SizeType numberOfBytes = endAddress - startAddress; // addresses overlap so use memmove - memmove( address, startAddress, numberOfBytes ); - SetCount( Count() - 1u ); + memmove(address, startAddress, numberOfBytes); + SetCount(Count() - 1u); } } -char* VectorBase::Erase( char* first, char* last, SizeType elementSize ) +char* VectorBase::Erase(char* first, char* last, SizeType elementSize) { - char* next = NULL; + char* next = nullptr; - if( mData ) + if(mData) { - char* startAddress = last; - const char* endAddress = reinterpret_cast< char* >( mData ) + Count() * elementSize; - SizeType numberOfBytes = endAddress - startAddress; + uint8_t* startAddress = reinterpret_cast(last); + const uint8_t* endAddress = reinterpret_cast(mData) + Count() * elementSize; + SizeType numberOfBytes = endAddress - startAddress; // addresses overlap so use memmove - memmove( first, startAddress, numberOfBytes ); - SetCount( Count() - ( last - first ) / elementSize ); + memmove(first, startAddress, numberOfBytes); + SetCount(Count() - (last - first) / elementSize); next = first; } @@ -149,20 +166,19 @@ char* VectorBase::Erase( char* first, char* last, SizeType elementSize ) return next; } -void VectorBase::CopyMemory( char* destination, const char* source, size_t numberOfBytes ) +void VectorBase::CopyMemory(char* destination, const char* source, size_t numberOfBytes) { - if( ( ( source < destination ) && ( source + numberOfBytes > destination ) ) || - ( ( destination < source ) && ( destination + numberOfBytes > source ) ) ) + if(((source < destination) && (source + numberOfBytes > destination)) || + ((destination < source) && (destination + numberOfBytes > source))) { // If there is overlap, use memmove. - memmove( destination, source, numberOfBytes ); + memmove(destination, source, numberOfBytes); } else { // It's safe to use memcpy if there isn't overlap. - memcpy( destination, source, numberOfBytes ); + memcpy(destination, source, numberOfBytes); } } } // namespace Dali -