CFx SDK Documentation 2024 SP0
Loading...
Searching...
No Matches
OdArrayMemAlloc.h
Go to the documentation of this file.
1// FELIX_CHANGE_BEGIN file was take from ODA gitlab repository https://gitlab.opendesign.com/
3// Copyright (C) 2002-2022, Open Design Alliance (the "Alliance").
4// All rights reserved.
5//
6// This software and its documentation and related materials are owned by
7// the Alliance. The software may only be incorporated into application
8// programs owned by members of the Alliance, subject to a signed
9// Membership Agreement and Supplemental Software License Agreement with the
10// Alliance. The structure and organization of this software are the valuable
11// trade secrets of the Alliance and its suppliers. The software is also
12// protected by copyright law and international treaty provisions. Application
13// programs incorporating this software must include the following statement
14// with their copyright notices:
15//
16// This application incorporates Open Design Alliance software pursuant to a license
17// agreement with Open Design Alliance.
18// Open Design Alliance Copyright (C) 2002-2022 by Open Design Alliance.
19// All rights reserved.
20//
21// By use of this software, its documentation or related materials, you
22// acknowledge and accept the above terms.
24#ifndef ODARRAYMEMALLOC_H_INCLUDED
25#define ODARRAYMEMALLOC_H_INCLUDED
26
27#include <new>
28#include <utility>
29
30#include "TD_PackPush.h"
31
32#include "OdArray.h"
33#include "OdAlloc.h"
34
38{
39public:
40 static void* Alloc(size_t nBytes) { return ::odrxAlloc(nBytes); }
41 static void Free(void* pMemBlock) { ::odrxFree(pMemBlock); }
42 static void* Realloc(void* pMemBlock, size_t newSize, size_t oldSize)
43 {
44 return ::odrxRealloc(pMemBlock, newSize, oldSize);
45 }
46};
47template <class T, class A = OdObjectsAllocator<T>, class Mm = OdrxMemoryManager> class OdArrayMemAlloc;
48
66template <class T, class A, class Mm> class OdArrayMemAlloc
67{
68public:
69 typedef typename A::size_type size_type;
70 typedef T* iterator;
71 typedef const T* const_iterator;
72private:
73 struct Buffer : OdArrayBuffer
74 {
75 T* data() const { return (T*)(this+1); }
76
77 static Buffer* allocate(size_type nLength2Allocate, int nGrowBy)
78 {
79 size_type nBytes2Allocate = sizeof(Buffer) + nLength2Allocate * sizeof(T);
80 ODA_ASSERT(nBytes2Allocate > nLength2Allocate); // size_type overflow
81 if(nBytes2Allocate > nLength2Allocate)
82 {
83 Buffer* pBuffer = (Buffer*)Mm::Alloc(nBytes2Allocate);
84 if (pBuffer)
85 {
86 pBuffer->m_nRefCounter = 1;
87 pBuffer->m_nGrowBy = nGrowBy;
88 pBuffer->m_nAllocated = nLength2Allocate;
89 pBuffer->m_nLength = 0;
90 return pBuffer;
91 }
92 }
93 throw OdError(eOutOfMemory);
94 }
95 static Buffer* _default()
96 {
97 return (Buffer*)&g_empty_array_buffer;
98 }
99 void release()
100 {
102 if((--m_nRefCounter)==0 && this != _default())
103 {
104 A::destroyRange(data(), m_nLength);
105 Mm::Free(this);
106 }
107 }
108 void addref() const { ++m_nRefCounter; }
109 };
110 class reallocator
111 {
112 bool _may_use_realloc;
113 Buffer* m_pBuffer;
114 public:
115 inline reallocator( bool may_use_realloc = false ) : _may_use_realloc(may_use_realloc) , m_pBuffer(NULL)
116 {
117 if ( !_may_use_realloc )
118 {
119 m_pBuffer = Buffer::_default();
120 m_pBuffer->addref();
121 }
122 }
123 inline void reallocate(OdArrayMemAlloc* pArray, size_type nNewLen )
124 {
125 if(!pArray->referenced())
126 {
127 if(nNewLen > pArray->physicalLength())
128 {
129 if ( !_may_use_realloc )
130 {
131 m_pBuffer->release();
132 m_pBuffer = pArray->buffer();
133 m_pBuffer->addref(); // save buffer to ensure copy from itself would work (e.g insertAt)
134 }
135 pArray->copy_buffer(nNewLen, _may_use_realloc);
136 }
137 }
138 else
139 {
140 pArray->copy_buffer(nNewLen);
141 }
142 }
143 inline ~reallocator()
144 {
145 if ( !_may_use_realloc ) m_pBuffer->release();
146 }
147 };
148 friend class reallocator;
149 const_iterator begin_const() const { return begin(); }
150 iterator begin_non_const() { return begin(); }
151 const_iterator end_const() { return end(); }
152 iterator end_non_const() { return end(); }
153 void copy_before_write(size_type len, bool may_use_realloc = false )
154 {
155 if( referenced() )
156 copy_buffer(len);
157 else if ( len > physicalLength() )
158 copy_buffer( len, may_use_realloc );
159 }
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 )
162 {
163 Buffer* pOldBuffer = buffer();
164 int nGrowBy = pOldBuffer->m_nGrowBy;
165 size_type len2 = len;
166 if ( !force_size )
167 {
168 if(nGrowBy > 0)
169 {
170 len2 += nGrowBy;
171 len2 = ((len2 - 1) / nGrowBy) * nGrowBy;
172 }
173 else
174 {
175 len2 = pOldBuffer->m_nLength;
176 len2 = len2 + -nGrowBy * len2 / 100;
177 if(len2 < len)
178 {
179 len2 = len;
180 }
181 }
182 }
183 if ( may_use_realloc && A::useRealloc() && !empty() )
184 {
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();
190 }
191 else
192 {
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();
199 }
200 }
201 inline void assertValid(size_type index) const { if(!isValid(index)) { ODA_FAIL(); throw OdError_InvalidIndex(); } }
202 static inline void rise_error(OdResult e) { ODA_FAIL(); throw OdError(e); }
203public:
204 // STL-like interface
205
209 iterator begin() { if(!empty()) { copy_if_referenced(); return data(); } return 0; }
213 const_iterator begin() const { if(!empty()) { return data(); } return 0; }
214
218 iterator end() { if(!empty()) { copy_if_referenced(); return data() + length(); } return 0; }
222 const_iterator end() const { if(!empty()) { return data()+length(); } return 0; }
223
234 void insert(
235 iterator before,
237 const_iterator afterLast)
238 {
239 size_type len = length();
240 size_type index = (size_type)(before - begin_const());
241 if(index <= len && afterLast>=first)
242 {
243 if(afterLast > first)
244 {
245 size_type num2copy = (size_type)(afterLast - first);
246 reallocator r( first < begin() || first >= end() );
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;
251 if(index != len)
252 {
253 A::moveAssignRange(pDestination + num2copy, pDestination, len - index);
254 }
255 A::copyAssignRangeDisjoint(pDestination, first, (size_type)(afterLast - first));
256 }
257 }
258 else
259 {
260 rise_error(eInvalidInput);
261 }
262 }
268 void resize(
270 const T& value )
271 {
272 size_type len = length();
273 int d = logicalLength - len;
274 if ( d > 0 )
275 {
276 reallocator r( m_pData > &value || &value > (m_pData + len) );
277 r.reallocate(this, logicalLength);
278 A::copyConstructFill(m_pData + len, d, value);
279 }
280 else if ( d < 0 )
281 {
282 d=-d;
283 if(!referenced())
284 {
285 A::destroyRange(m_pData + logicalLength, d);
286 }
287 else
288 {
289 copy_buffer(logicalLength);
290 }
291 }
292 buffer()->m_nLength = logicalLength;
293 }
294
299 void resize(
301 {
302 size_type len = length();
303 int d = logicalLength - len;
304 if ( d > 0 )
305 {
306 copy_before_write( len + d, true );
307 A::defaultConstructFill(m_pData + len, d);
308 }
309 else if ( d < 0 )
310 {
311 d = -d;
312 if ( !referenced() )
313 {
314 A::destroyRange( m_pData + logicalLength, d );
315 }
316 else
317 {
318 copy_buffer(logicalLength);
319 }
320 }
321 buffer()->m_nLength = logicalLength;
322 }
323
327 size_type size() const { return buffer()->m_nLength; }
328
332 bool empty() const { return size() == 0; }
333
337 size_type capacity() const { return buffer()->m_nAllocated; }
338
346 size_type reserveLength) { if(physicalLength() < reserveLength) { setPhysicalLength(reserveLength); } }
347
358 void assign(
360 const_iterator afterLast)
361 { erase(begin_non_const(), end_non_const()); insert(begin_non_const(), first, afterLast); }
362
371 iterator afterLast)
372 {
373 size_type i = (size_type)(first - begin_const());
374 if(first != afterLast)
375 {
376 removeSubArray(i, (size_type)(afterLast-begin_const()-1));
377 }
378 return begin_non_const()+i;
379 }
380
387 iterator where)
388 {
389 size_type i = where - begin_const();
390 removeAt(i);
391 return begin_non_const()+i;
392 }
396 void clear() { erase(begin_non_const(), end_non_const()); }
397
402 const T& value) { insertAt(length(), value); }
403
415 iterator before,
416 size_type numElements,
417 const T& value)
418 {
419 size_type len = length();
420 size_type index = before - begin_const();
421 reallocator r( m_pData > &value || &value > (m_pData + len) );
422 r.reallocate(this, len + numElements);
423 A::defaultConstructFill(m_pData + len, numElements, value);
424 buffer()->m_nLength = len + numElements;
425 T* pData = data();
426 pData += index;
427 if(index != len)
428 {
429 A::moveAssignRange(pData + numElements, pData, len - index);
430 }
431 while(numElements--)
432 {
433 pData[numElements] = value;
434 }
435 return begin_non_const()+index;
436 }
437
448 iterator before,
449 const T& value = T())
450 {
451 size_type index = before - begin_const();
453 return (begin_non_const() + index);
454 }
455
456 // ARX-like interface
457
465 const T& value,
466 size_type start = 0) const
467 { size_type dummy; return find(value, dummy, start); }
468
469
473 size_type length() const { return buffer()->m_nLength; }
474
478 bool isEmpty() const { return length() == 0; }
479
483 size_type logicalLength() const { return length(); }
484
488 size_type physicalLength() const { return buffer()->m_nAllocated; }
489
493 int growLength() const { return buffer()->m_nGrowBy; }
494
498 const T* asArrayPtr() const { return data(); }
499
503 const T* getPtr() const { return data(); }
504
508 T* asArrayPtr() { copy_if_referenced(); return data(); }
509
513 const T& operator [](
514 size_type index) const { assertValid(index); return m_pData[index]; }
516 size_type index) { assertValid(index); copy_if_referenced(); return m_pData[index]; }
517
518
523 T& at(
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); }
530
537 size_type arrayIndex,
538 const T& value)
539 { assertValid(arrayIndex); copy_if_referenced(); m_pData[arrayIndex] = value; return *this; }
540
545 const T& getAt(
546 size_type arrayIndex) const { assertValid(arrayIndex); return *(data() + arrayIndex); }
547
551 T& first() { return *begin(); }
555 const T& first() const { return *begin(); }
556
560 T& last() { return at(length()-1); }
564 const T& last() const { return at(length()-1); }
565
575 const T& value) { insertAt(length(), value); return length()-1; }
576
581 iterator append() { size_type i = append(T()); return begin_non_const() + i; }
582
587
592
598 int growLength)
599 {
600 if(growLength != 0)
601 {
602 copy_if_referenced();
603 buffer()->m_nGrowBy = growLength;
604 }
605 else
606 {
607 ODA_FAIL();
608 }
609 return *this;
610 }
611
617 int growLength = 8) : m_pData(0)
618 {
619 if(growLength != 0)
620 {
621 m_pData = Buffer::allocate(physicalLength, growLength)->data();
622 }
623 else
624 {
625 ODA_FAIL();
626 *this = OdArrayMemAlloc<T,A>();
627 }
628 }
629
630 OdArrayMemAlloc() : m_pData(Buffer::_default()->data()) { buffer()->addref(); }
631
632 OdArrayMemAlloc(const OdArrayMemAlloc& source) : m_pData((T*)source.data()) { buffer()->addref(); }
633
634 ~OdArrayMemAlloc() { buffer()->release(); }
635
637 const OdArrayMemAlloc& source)
638 {
639 source.buffer()->addref();
640 if (m_pData != 0)
641 buffer()->release();
642 m_pData = source.m_pData;
643 return *this;
644 }
645
647 const OdArrayMemAlloc& array) const
648 {
649 if(length() == array.length())
650 {
651 for(size_type i = 0; i < length(); i++)
652 {
653 if(at(i) != array[i])
654 {
655 return false;
656 }
657 }
658 return true;
659 }
660 return false;
661 }
662
668 const T& value)
669 {
670 copy_if_referenced();
671 T* pData = data();
672 size_type n = length();
673 while(n)
674 {
675 pData[--n] = value;
676 }
677 return *this;
678 }
688 const OdArrayMemAlloc& otherArray)
689 {
690 insert(end_non_const(), otherArray.begin(), otherArray.end());
691 return *this;
692 }
693
708 size_type arrayIndex,
709 const T& value)
710 {
711 size_type len = length();
712 if( arrayIndex == len )
713 {
714 resize( len + 1, value );
715 }
716 else if ( arrayIndex < len )
717 {
718 reallocator r( m_pData > &value || &value > (m_pData + len) );
719 r.reallocate( this, len+1 );
720 A::defaultConstruct( m_pData + len );
721 ++(buffer()->m_nLength);
722 A::moveAssignRange(m_pData + arrayIndex + 1, m_pData + arrayIndex, len - arrayIndex);
723 m_pData[arrayIndex] = value;
724 }
725 else
726 {
727 rise_error(eInvalidIndex);
728 }
729 return *this;
730 }
731
745 size_type arrayIndex)
746 {
747 assertValid(arrayIndex);
748 size_type len = length();
749 if(arrayIndex < --len)
750 {
751 copy_if_referenced();
752 T* pData = data();
753 A::moveAssignRange(pData + arrayIndex, pData + arrayIndex + 1, len - arrayIndex);
754 }
755 resize(len);
756 return *this;
757 }
758
771 size_type startIndex,
772 size_type endIndex)
773 {
774 if(!isValid(startIndex) || startIndex > endIndex)
775 {
776 rise_error(eInvalidIndex);
777 }
778 size_type len = length();
779 copy_if_referenced();
780 T* pData = data();
781 ++endIndex;
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;
786 return *this;
787 }
788
799 bool find(
800 const T& value,
801 size_type& findIndex,
802 size_type start=0) const
803 {
804 if(!empty())
805 {
806 assertValid(start);
807 size_type len = length();
808 const T* pData = data();
809 for(size_type i = start; i<len; ++i)
810 {
811 if(pData[i] == value)
812 {
813 findIndex = i;
814 return true;
815 }
816 }
817 }
818 return false;
819 }
820
828 size_type logLength)
829 {
830 resize(logLength);
831 return *this;
832 }
833
841 size_type physLength)
842 {
843 if(physLength==0)
844 {
845 *this = OdArrayMemAlloc<T, A>();
846 }
847 else if(physLength != physicalLength())
848 {
849 copy_buffer(physLength,true,true);
850 }
851 return *this;
852 }
853
858 {
859 if(!empty())
860 {
861 copy_if_referenced();
862 T tmp;
863 iterator iter1 = begin_non_const();
864 iterator iter2 = end_non_const();
865 --iter2;
866 while(iter1 < iter2)
867 {
868 tmp = *iter1;
869 *iter1 = *iter2;
870 *iter2 = tmp;
871 ++iter1;
872 --iter2;
873 }
874 }
875 return *this;
876 }
877
878
885 size_type firstIndex,
886 size_type secondIndex)
887 {
888 if(!isValid(firstIndex) || !isValid(secondIndex))
889 {
890 rise_error(eInvalidIndex);
891 }
892 if(firstIndex != secondIndex)
893 {
894 T tmp = std::move(at(firstIndex));
895 at(firstIndex) = std::move(at(secondIndex));
896 at(secondIndex) = std::move(tmp);
897 }
898 return *this;
899 }
911 bool remove(
912 const T& value,
913 size_type start = 0)
914 {
915 size_type i = 0;
916 if(find(value, i, start))
917 {
918 removeAt(i);
919 return true;
920 }
921 return false;
922 }
923private:
924
925 T* m_pData;
926
927 bool isValid(size_type i) const { return (i < length()); }
928
929 T* data() { return (length() ? m_pData : 0); }
930
931 const T* data() const { return m_pData; }
932
933 Buffer* buffer() const
934 {
935 return (reinterpret_cast<Buffer*>(const_cast<OdArrayMemAlloc*>(this)->m_pData) - 1);
936 }
937 bool referenced() const
938 {
939 return (buffer()->m_nRefCounter>1);
940 }
941};
942
943#include "TD_PackPop.h"
944
945#endif // ODARRAYMEMALLOC_H_INCLUDED
946// FELIX_CHANGE_END file was take from ODA gitlab repository https://gitlab.opendesign.com/
#define ODA_ASSERT(exp)
Definition: DebugStuff.h:57
#define ODA_FAIL()
Definition: DebugStuff.h:88
ALLOCDLL_EXPORT void odrxFree(void *pMemBlock)
#define odmin(X, Y)
Definition: OdPlatform.h:34
OdResult
Definition: OdResult.h:29
OdArrayMemAlloc & reverse()
OdArrayMemAlloc & setLogicalLength(size_type logLength)
bool contains(const T &value, size_type start=0) const
const T & at(size_type arrayIndex) const
const T * getPtr() 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)
const T * const_iterator
void reserve(size_type reserveLength)
bool isEmpty() const
const T & last() const
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)
const T & first() const
OdArrayMemAlloc & swap(size_type firstIndex, size_type secondIndex)
T & at(size_type arrayIndex)
const T & getAt(size_type arrayIndex) const
A::size_type size_type
const T & operator[](size_type index) const
size_type size() const
iterator erase(iterator where)
const T * asArrayPtr() const
bool operator==(const OdArrayMemAlloc &array) const
size_type logicalLength() const
int growLength() 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)
friend class reallocator
size_type length() const
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)
bool empty() const
static void * Realloc(void *pMemBlock, size_t newSize, size_t oldSize)
static void * Alloc(size_t nBytes)
static void Free(void *pMemBlock)
GLuint buffer
Definition: gles2_ext.h:178
GLint GLenum GLsizei GLsizei GLint GLsizei const void * data
Definition: gles2_ext.h:110
GLuint index
Definition: gles2_ext.h:265
GLsizei GLsizei GLchar * source
Definition: gles2_ext.h:282
GLsizei const GLfloat * value
Definition: gles2_ext.h:302
static FIRSTDLL_EXPORT_STATIC OdArrayBuffer g_empty_array_buffer
Definition: OdArray.h:795
size_type m_nLength
Definition: OdArray.h:793
OdRefCounter m_nRefCounter
Definition: OdArray.h:790