24#ifndef ODARRAYMEMALLOC_H_INCLUDED
25#define ODARRAYMEMALLOC_H_INCLUDED
40 static void*
Alloc(
size_t nBytes) { return ::odrxAlloc(nBytes); }
42 static void*
Realloc(
void* pMemBlock,
size_t newSize,
size_t oldSize)
44 return ::odrxRealloc(pMemBlock, newSize, oldSize);
47template <
class T,
class A = OdObjectsAllocator<T>,
class Mm = OdrxMemoryManager>
class OdArrayMemAlloc;
75 T*
data()
const {
return (T*)(
this+1); }
77 static Buffer* allocate(
size_type nLength2Allocate,
int nGrowBy)
79 size_type nBytes2Allocate =
sizeof(Buffer) + nLength2Allocate *
sizeof(T);
80 ODA_ASSERT(nBytes2Allocate > nLength2Allocate);
81 if(nBytes2Allocate > nLength2Allocate)
83 Buffer* pBuffer = (Buffer*)Mm::Alloc(nBytes2Allocate);
86 pBuffer->m_nRefCounter = 1;
87 pBuffer->m_nGrowBy = nGrowBy;
88 pBuffer->m_nAllocated = nLength2Allocate;
89 pBuffer->m_nLength = 0;
95 static Buffer* _default()
112 bool _may_use_realloc;
115 inline reallocator(
bool may_use_realloc =
false ) : _may_use_realloc(may_use_realloc) , m_pBuffer(NULL)
117 if ( !_may_use_realloc )
119 m_pBuffer = Buffer::_default();
125 if(!pArray->referenced())
129 if ( !_may_use_realloc )
131 m_pBuffer->release();
132 m_pBuffer = pArray->buffer();
135 pArray->copy_buffer(nNewLen, _may_use_realloc);
140 pArray->copy_buffer(nNewLen);
143 inline ~reallocator()
145 if ( !_may_use_realloc ) m_pBuffer->release();
153 void copy_before_write(
size_type len,
bool may_use_realloc =
false )
158 copy_buffer( len, may_use_realloc );
160 void copy_if_referenced() {
if(referenced()) { copy_buffer(
physicalLength()); } }
161 void copy_buffer(
size_type len,
bool may_use_realloc =
false,
bool force_size =
false )
163 Buffer* pOldBuffer =
buffer();
164 int nGrowBy = pOldBuffer->m_nGrowBy;
171 len2 = ((len2 - 1) / nGrowBy) * nGrowBy;
175 len2 = pOldBuffer->m_nLength;
176 len2 = len2 + -nGrowBy * len2 / 100;
183 if ( may_use_realloc && A::useRealloc() && !
empty() )
185 Buffer* pNewBuffer =
reinterpret_cast<Buffer*
>( Mm::Realloc(
186 pOldBuffer, len2 *
sizeof(T) +
sizeof(Buffer), pOldBuffer->m_nAllocated *
sizeof(T) +
sizeof(Buffer) ) );
187 pNewBuffer->m_nAllocated = len2;
188 pNewBuffer->m_nLength =
odmin(pNewBuffer->m_nLength, len);
189 m_pData = pNewBuffer->data();
193 Buffer* pNewBuffer = Buffer::allocate(len2, nGrowBy);
194 len =
odmin(pOldBuffer->m_nLength, len);
195 A::copyConstructRange(pNewBuffer->data(), pOldBuffer->data(), len);
196 pNewBuffer->m_nLength = len;
197 m_pData = pNewBuffer->data();
198 pOldBuffer->release();
241 if(index <= len && afterLast>=
first)
243 if(afterLast >
first)
247 r.reallocate(
this, len + num2copy);
248 A::defaultConstructFill(m_pData + len, num2copy);
249 buffer()->m_nLength = len + num2copy;
250 T* pDestination = m_pData +
index;
253 A::moveAssignRange(pDestination + num2copy, pDestination, len -
index);
260 rise_error(eInvalidInput);
278 A::copyConstructFill(m_pData + len, d,
value);
306 copy_before_write( len + d,
true );
307 A::defaultConstructFill(m_pData + len, d);
361 {
erase(begin_non_const(), end_non_const());
insert(begin_non_const(),
first, afterLast); }
374 if(
first != afterLast)
378 return begin_non_const()+i;
391 return begin_non_const()+i;
422 r.reallocate(
this, len + numElements);
423 A::defaultConstructFill(m_pData + len, numElements,
value);
424 buffer()->m_nLength = len + numElements;
429 A::moveAssignRange(pData + numElements, pData, len -
index);
433 pData[numElements] =
value;
435 return begin_non_const()+
index;
449 const T&
value = T())
453 return (begin_non_const() +
index);
524 size_type arrayIndex) { assertValid(arrayIndex); copy_if_referenced();
return *(
data() + arrayIndex); }
529 const T&
at(
size_type arrayIndex)
const { assertValid(arrayIndex);
return *(
data() + arrayIndex); }
539 { assertValid(arrayIndex); copy_if_referenced(); m_pData[arrayIndex] =
value;
return *
this; }
546 size_type arrayIndex)
const { assertValid(arrayIndex);
return *(
data() + arrayIndex); }
602 copy_if_referenced();
639 source.buffer()->addref();
653 if(
at(i) != array[i])
670 copy_if_referenced();
712 if( arrayIndex == len )
716 else if ( arrayIndex < len )
719 r.reallocate(
this, len+1 );
720 A::defaultConstruct( m_pData + len );
722 A::moveAssignRange(m_pData + arrayIndex + 1, m_pData + arrayIndex, len - arrayIndex);
723 m_pData[arrayIndex] =
value;
727 rise_error(eInvalidIndex);
747 assertValid(arrayIndex);
749 if(arrayIndex < --len)
751 copy_if_referenced();
753 A::moveAssignRange(pData + arrayIndex, pData + arrayIndex + 1, len - arrayIndex);
774 if(!isValid(startIndex) || startIndex > endIndex)
776 rise_error(eInvalidIndex);
779 copy_if_referenced();
782 size_type n2remove = endIndex - startIndex;
783 A::moveAssignRange(pData + startIndex, pData + endIndex, len - endIndex);
784 A::destroyRange(pData + len - n2remove, n2remove);
785 buffer()->m_nLength -= n2remove;
808 const T* pData =
data();
811 if(pData[i] ==
value)
849 copy_buffer(physLength,
true,
true);
861 copy_if_referenced();
888 if(!isValid(firstIndex) || !isValid(secondIndex))
890 rise_error(eInvalidIndex);
892 if(firstIndex != secondIndex)
894 T tmp = std::move(
at(firstIndex));
895 at(firstIndex) = std::move(
at(secondIndex));
896 at(secondIndex) = std::move(tmp);
929 T*
data() {
return (
length() ? m_pData : 0); }
931 const T*
data()
const {
return m_pData; }
935 return (
reinterpret_cast<Buffer*
>(
const_cast<OdArrayMemAlloc*
>(
this)->m_pData) - 1);
937 bool referenced()
const
939 return (
buffer()->m_nRefCounter>1);
ALLOCDLL_EXPORT void odrxFree(void *pMemBlock)
OdArrayMemAlloc & reverse()
OdArrayMemAlloc & setLogicalLength(size_type logLength)
bool contains(const T &value, size_type start=0) const
const T & at(size_type arrayIndex) const
bool remove(const T &value, size_type start=0)
OdArrayMemAlloc & setAll(const T &value)
OdArrayMemAlloc & setAt(size_type arrayIndex, const T &value)
iterator insert(iterator before, size_type numElements, const T &value)
OdArrayMemAlloc & append(const OdArrayMemAlloc &otherArray)
void reserve(size_type reserveLength)
OdArrayMemAlloc & removeSubArray(size_type startIndex, size_type endIndex)
void insert(iterator before, const_iterator first, const_iterator afterLast)
const_iterator end() const
bool find(const T &value, size_type &findIndex, size_type start=0) const
size_type append(const T &value)
const_iterator begin() const
OdArrayMemAlloc(const OdArrayMemAlloc &source)
iterator insert(iterator before, const T &value=T())
OdArrayMemAlloc & operator=(const OdArrayMemAlloc &source)
void push_back(const T &value)
OdArrayMemAlloc & swap(size_type firstIndex, size_type secondIndex)
T & at(size_type arrayIndex)
const T & getAt(size_type arrayIndex) const
const T & operator[](size_type index) const
iterator erase(iterator where)
const T * asArrayPtr() const
bool operator==(const OdArrayMemAlloc &array) const
size_type logicalLength() const
OdArrayMemAlloc(size_type physicalLength, int growLength=8)
void resize(size_type logicalLength)
OdArrayMemAlloc & removeLast()
size_type physicalLength() const
OdArrayMemAlloc & removeAt(size_type arrayIndex)
OdArrayMemAlloc & setGrowLength(int growLength)
OdArrayMemAlloc & removeFirst()
void assign(const_iterator first, const_iterator afterLast)
OdArrayMemAlloc & setPhysicalLength(size_type physLength)
size_type capacity() const
iterator erase(iterator first, iterator afterLast)
OdArrayMemAlloc & insertAt(size_type arrayIndex, const T &value)
void resize(size_type logicalLength, const T &value)
static void * Realloc(void *pMemBlock, size_t newSize, size_t oldSize)
static void * Alloc(size_t nBytes)
static void Free(void *pMemBlock)
GLint GLenum GLsizei GLsizei GLint GLsizei const void * data
GLsizei GLsizei GLchar * source
GLsizei const GLfloat * value
static FIRSTDLL_EXPORT_STATIC OdArrayBuffer g_empty_array_buffer
OdRefCounter m_nRefCounter