23 #ifndef ODARRAYMEMALLOC_H_INCLUDED
24 #define ODARRAYMEMALLOC_H_INCLUDED
40 static void*
Realloc(
void* pMemBlock,
size_t newSize,
size_t oldSize)
45 template <
class T,
class A = OdObjectsAllocator<T>,
class Mm = OdrxMemoryManager>
class OdArrayMemAlloc;
73 T*
data()
const {
return (T*)(
this+1); }
75 static Buffer* allocate(
size_type nLength2Allocate,
int nGrowBy)
77 size_type nBytes2Allocate =
sizeof(Buffer) + nLength2Allocate *
sizeof(T);
78 ODA_ASSERT(nBytes2Allocate > nLength2Allocate);
79 if(nBytes2Allocate > nLength2Allocate)
81 Buffer* pBuffer = (Buffer*)Mm::Alloc(nBytes2Allocate);
84 pBuffer->m_nRefCounter = 1;
85 pBuffer->m_nGrowBy = nGrowBy;
86 pBuffer->m_nAllocated = nLength2Allocate;
87 pBuffer->m_nLength = 0;
93 static Buffer* _default()
95 return (Buffer*)&g_empty_array_buffer;
100 if((--m_nRefCounter)==0 &&
this != _default())
102 A::destroy(
data(), m_nLength);
106 void addref()
const { ++m_nRefCounter; }
110 bool _may_use_realloc;
113 inline reallocator(
bool may_use_realloc =
false ) : _may_use_realloc(may_use_realloc) , m_pBuffer(
NULL)
115 if ( !_may_use_realloc )
117 m_pBuffer = Buffer::_default();
123 if(!pArray->referenced())
127 if ( !_may_use_realloc )
129 m_pBuffer->release();
130 m_pBuffer = pArray->buffer();
133 pArray->copy_buffer(nNewLen, _may_use_realloc);
138 pArray->copy_buffer(nNewLen);
143 if ( !_may_use_realloc ) m_pBuffer->release();
151 void copy_before_write(
size_type len,
bool may_use_realloc =
false )
156 copy_buffer( len, may_use_realloc );
158 void copy_if_referenced() {
if(referenced()) { copy_buffer(
physicalLength()); } }
159 void copy_buffer(
size_type len,
bool may_use_realloc =
false,
bool force_size =
false )
161 Buffer* pOldBuffer =
buffer();
162 int nGrowBy = pOldBuffer->m_nGrowBy;
169 len2 = ((len2 - 1) / nGrowBy) * nGrowBy;
173 len2 = pOldBuffer->m_nLength;
174 len2 = len2 + -nGrowBy * len2 / 100;
181 if ( may_use_realloc && A::useRealloc() && !
empty() )
183 Buffer* pNewBuffer =
reinterpret_cast<Buffer*
>( Mm::Realloc(
184 pOldBuffer, len2 *
sizeof(T) +
sizeof(Buffer), pOldBuffer->m_nAllocated *
sizeof(T) +
sizeof(Buffer) ) );
185 pNewBuffer->m_nAllocated = len2;
186 pNewBuffer->m_nLength =
odmin(pNewBuffer->m_nLength, len);
187 m_pData = pNewBuffer->data();
191 Buffer* pNewBuffer = Buffer::allocate(len2, nGrowBy);
192 len =
odmin(pOldBuffer->m_nLength, len);
193 A::constructn(pNewBuffer->data(), pOldBuffer->data(), len);
194 pNewBuffer->m_nLength = len;
195 m_pData = pNewBuffer->data();
196 pOldBuffer->release();
241 if(afterLast >
first)
245 r.reallocate(
this, len + num2copy);
246 A::constructn(m_pData + len,
first, num2copy);
247 buffer()->m_nLength = len + num2copy;
248 T* pDestination = m_pData +
index;
251 A::move(pDestination + num2copy, pDestination, len -
index);
258 rise_error(eInvalidInput);
276 A::constructn(m_pData + len, d,
value);
304 copy_before_write( len + d,
true );
305 A::constructn(m_pData + len, d);
359 {
erase(begin_non_const(), end_non_const());
insert(begin_non_const(),
first, afterLast); }
372 if(
first != afterLast)
376 return begin_non_const()+i;
389 return begin_non_const()+i;
420 r.reallocate(
this, len + numElements);
421 A::constructn(m_pData + len, numElements,
value);
422 buffer()->m_nLength = len + numElements;
427 A::move(pData + numElements, pData, len -
index);
431 pData[numElements] =
value;
433 return begin_non_const()+
index;
447 const T&
value = T())
451 return (begin_non_const() +
index);
522 size_type arrayIndex) { assertValid(arrayIndex); copy_if_referenced();
return *(
data() + arrayIndex); }
527 const T&
at(
size_type arrayIndex)
const { assertValid(arrayIndex);
return *(
data() + arrayIndex); }
537 { assertValid(arrayIndex); copy_if_referenced(); m_pData[arrayIndex] =
value;
return *
this; }
544 size_type arrayIndex)
const { assertValid(arrayIndex);
return *(
data() + arrayIndex); }
600 copy_if_referenced();
637 source.buffer()->addref();
651 if(
at(i) != array[i])
668 copy_if_referenced();
710 if( arrayIndex == len )
714 else if ( arrayIndex < len )
717 r.reallocate(
this, len+1 );
718 A::construct( m_pData + len );
720 A::move(m_pData + arrayIndex + 1, m_pData + arrayIndex, len - arrayIndex);
721 m_pData[arrayIndex] =
value;
725 rise_error(eInvalidIndex);
745 assertValid(arrayIndex);
747 if(arrayIndex < --len)
749 copy_if_referenced();
751 A::move(pData + arrayIndex, pData + arrayIndex + 1, len - arrayIndex);
772 if(!isValid(startIndex) || startIndex > endIndex)
774 rise_error(eInvalidIndex);
777 copy_if_referenced();
780 size_type n2remove = endIndex - startIndex;
781 A::move(pData + startIndex, pData + endIndex, len - endIndex);
782 A::destroy(pData + len - n2remove, n2remove);
783 buffer()->m_nLength -= n2remove;
806 const T* pData =
data();
809 if(pData[i] ==
value)
847 copy_buffer(physLength,
true,
true);
859 copy_if_referenced();
886 if(!isValid(firstIndex) || !isValid(secondIndex))
888 rise_error(eInvalidIndex);
890 if(firstIndex != secondIndex)
892 const T tmp =
at(firstIndex);
893 at(firstIndex) =
at(secondIndex);
894 at(secondIndex) = tmp;
927 T*
data() {
return (
length() ? m_pData : 0); }
929 const T*
data()
const {
return m_pData; }
933 return (
reinterpret_cast<Buffer*
>(
const_cast<OdArrayMemAlloc*
>(
this)->m_pData) - 1);
935 bool referenced()
const
937 return (
buffer()->m_nRefCounter>1);
943 #endif // ODARRAYMEMALLOC_H_INCLUDED