28#ifndef ODARRAY_H_INCLUDED
29#define ODARRAY_H_INCLUDED
48 static const bool value =
false;
51template <
class First,
class Second>
54 static const bool value = std::is_trivially_copyable<First>::value && std::is_trivially_copyable<Second>::value;
58template<
typename T,
bool >
109 #if defined (_MSC_VER) && defined(_DEBUG)
113 memcpy(pDestination, pSource, numElements *
sizeof(T));
133 #if defined (_MSC_VER) && defined(_DEBUG)
137 memmove(pDestination, pSource, numElements *
sizeof(T));
156 #if defined (_MSC_VER) && defined(_DEBUG)
160 memmove(pDestination, pSource, numElements *
sizeof(T));
192 #if defined (_MSC_VER) && defined(_DEBUG)
195#if defined(__GNUC__) && (__GNUC__ > 4)
197#pragma GCC diagnostic push
198#pragma GCC diagnostic ignored "-Warray-bounds"
199#pragma GCC diagnostic ignored "-Wstringop-overflow"
204#if defined(__GNUC__) && (__GNUC__ > 4)
205#pragma GCC diagnostic pop
221 #if defined (_MSC_VER) && defined(_DEBUG)
241 #if defined (_MSC_VER) && defined(_DEBUG)
248 memcpy(pDestination + numElements, &
value,
sizeof(
value));
393 #if defined (_MSC_VER) && defined(_DEBUG)
398 memset(pDestination, 0, numElements *
sizeof(T));
438 *pDestination = *pSource;
460 if (pDestination <= pSource || pDestination >= pSource + numElements)
468 pDestination[numElements] = pSource[numElements];
488 if (pDestination <= pSource || pDestination >= pSource + numElements)
492 *pDestination = std::move(*pSource);
501 pDestination[numElements] = std::move(pSource[numElements]);
537 ::new (pElement) T(
value);
553 ::new (pElement) T(std::move(
value));
711 #if defined (_MSC_VER) && defined(_DEBUG)
716 memcpy(pDestination, pSource, numElements *
sizeof(T));
736 #if defined (_MSC_VER) && defined(_DEBUG)
741 memmove(pDestination, pSource, numElements *
sizeof(T));
760 #if defined (_MSC_VER) && defined(_DEBUG)
765 memmove(pDestination, pSource, numElements *
sizeof(T));
837 using ConstForPtrT =
typename std::conditional<std::is_pointer<T>::value,
838 typename std::add_const<typename std::remove_pointer<T>::type>
::type*, T>
::type;
842 T*
data()
const {
return (T*)(
this+1); }
844 static Buffer* allocate(
size_type nLength2Allocate,
int nGrowBy)
846 OdUInt64 nBytes2Allocate = (
OdUInt64)
sizeof(Buffer) + nLength2Allocate *
sizeof(T);
847 ODA_ASSERT(nBytes2Allocate > nLength2Allocate);
848 size_t nBytes2AllocateSize_t = (size_t)nBytes2Allocate;
849 if(nBytes2Allocate > nLength2Allocate && (
OdUInt64)nBytes2AllocateSize_t == nBytes2Allocate)
851 Buffer* pBuffer = (Buffer*)
::odrxAlloc(nBytes2AllocateSize_t);
854 pBuffer->m_nRefCounter = 1;
855 pBuffer->m_nGrowBy = nGrowBy;
856 pBuffer->m_nAllocated = nLength2Allocate;
857 pBuffer->m_nLength = 0;
863 static Buffer* _default()
879#pragma warning(disable : 4127)
884 bool _may_use_realloc;
887 inline reallocator(
bool may_use_realloc =
false ) : _may_use_realloc(may_use_realloc), m_pBuffer(NULL) {}
890 if(!pArray->referenced())
894 if ( !_may_use_realloc )
897 m_pBuffer->release();
898 if (!std::is_copy_constructible<T>::value)
900 m_pBuffer = pArray->buffer();
903 pArray->copy_buffer(nNewLen, _may_use_realloc);
908 pArray->copy_buffer(nNewLen);
911 inline ~reallocator()
914 m_pBuffer->release();
925 void copy_before_write(
size_type len,
bool may_use_realloc =
false )
930 copy_buffer( len, may_use_realloc );
932 void copy_if_referenced() {
if(referenced()) { copy_buffer(
physicalLength()); } }
934#if !defined(SWIG) || defined(SWIGBUILD)
936 template<
typename U = T,
937 typename std::enable_if<std::is_same<U, T>::value && std::is_copy_constructible<U>::value,
bool>
::type =
true>
938 inline void copyConstructRangeChecked(T* dest, T*
source,
size_type len)
940 A::copyConstructRange(dest,
source, len);
942 template<
typename U = T,
943 typename std::enable_if<std::is_same<U, T>::value && !std::is_copy_constructible<U>::value,
bool>
::type =
true>
944 inline void copyConstructRangeChecked(T* dest, T*
source,
size_type len)
950 void copy_buffer(
size_type len,
bool may_use_realloc =
false,
bool force_size =
false,
bool releaseOldBufAfterCopy =
true)
952 Buffer* pOldBuffer =
buffer();
953 int nGrowBy = pOldBuffer->m_nGrowBy;
960 len2 = ((len2 - 1) / nGrowBy) * nGrowBy;
964 len2 = pOldBuffer->m_nLength;
965 len2 = len2 + -nGrowBy * len2 / 100;
972 if (may_use_realloc && A::useRealloc() && !
empty())
974 Buffer* pNewBuffer =
reinterpret_cast<Buffer*
>(
::odrxRealloc(
975 pOldBuffer, len2 *
sizeof(T) +
sizeof(Buffer), pOldBuffer->m_nAllocated *
sizeof(T) +
sizeof(Buffer)));
978 pNewBuffer->m_nAllocated = len2;
979 pNewBuffer->m_nLength =
odmin(pNewBuffer->m_nLength, len);
980 m_pData = pNewBuffer->data();
984 Buffer* pNewBuffer = Buffer::allocate(len2, nGrowBy);
987 len =
odmin(pOldBuffer->m_nLength, len);
989 A::moveConstructRange(pNewBuffer->data(), pOldBuffer->data(), len);
991 copyConstructRangeChecked(pNewBuffer->data(), pOldBuffer->data(), len);
992 pNewBuffer->m_nLength = len;
993 m_pData = pNewBuffer->data();
994 if (releaseOldBufAfterCopy)
995 pOldBuffer->release();
1006 static inline void rise_error(
OdResult e)
1021 copy_if_referenced();
1045 copy_if_referenced();
1067 return std::reverse_iterator<iterator>(
end());
1072 std::reverse_iterator<const_iterator>
rbegin()
const
1074 return std::reverse_iterator<const_iterator>(
end());
1080 std::reverse_iterator<iterator>
rend()
1082 return std::reverse_iterator<iterator>(
begin());
1087 std::reverse_iterator<const_iterator>
rend()
const
1089 return std::reverse_iterator<const_iterator>(
begin());
1106#ifdef ODA_DIAGNOSTICS
1107 if (
first >= begin_const() &&
first < end_const() && before < afterLast)
1108 throw OdError(L
"Inserted iterator range will become invalid while inserting.");
1112 if(index <= len && afterLast>=
first)
1114 if(afterLast >
first)
1118 r.reallocate(
this, len + num2copy);
1119 A::defaultConstructFill(m_pData + len, num2copy);
1120 buffer()->m_nLength = len + num2copy;
1121 T* pDestination = m_pData +
index;
1124 A::moveAssignRange(pDestination + num2copy, pDestination, len -
index);
1131 rise_error(eInvalidInput);
1149#ifdef ODA_DIAGNOSTICS
1150 if (
first >= begin_const() &&
first < end_const() && before < afterLast)
1151 throw OdError(L
"Inserted iterator range will become invalid while inserting.");
1155 if (index <= len && afterLast >=
first)
1157 if (afterLast >
first)
1161 r.reallocate(
this, len + num2copy);
1162 A::defaultConstructFill(m_pData + len, num2copy);
1163 buffer()->m_nLength = len + num2copy;
1164 T* pDestination = m_pData +
index;
1167 A::moveAssignRange(pDestination + num2copy, pDestination, len -
index);
1174 rise_error(eInvalidInput);
1229 if ( !referenced() )
1249 return buffer()->m_nLength;
1270 return buffer()->m_nAllocated;
1303#ifdef ODA_DIAGNOSTICS
1311 if (
first < end_const() &&
first >= begin_const())
1313 throw OdError(L
"Assignment of a subrange from self is not allowed.");
1316 if (afterLast <
first)
1318 rise_error(eInvalidInput);
1320 if (afterLast >
first)
1323 copy_buffer(num2copy,
true);
1324 buffer()->m_nLength = num2copy;
1342#ifdef ODA_DIAGNOSTICS
1350 if (
first < end_const() &&
first >= begin_const())
1352 throw OdError(L
"Assignment of a subrange from self is not allowed.");
1355 if (afterLast <
first)
1357 rise_error(eInvalidInput);
1359 if (afterLast >
first)
1362 copy_buffer(num2move,
true);
1363 buffer()->m_nLength = num2move;
1379 if(
first != afterLast)
1383 return begin_non_const()+i;
1395 return begin_non_const()+i;
1402 copy_if_referenced();
1404 A::destroyRange(m_pData, len);
1405 buffer()->m_nLength -= len;
1416 bool ref = referenced();
1421 copy_buffer(newLen, !
ref);
1422 A::moveConstruct(m_pData + len, std::move(valueCopy));
1426 A::copyConstruct(m_pData + len,
value);
1428 buffer()->m_nLength = newLen;
1439 bool ref = referenced();
1443 T valueMoved(std::move(
value));
1444 copy_buffer(newLen, !
ref);
1445 A::moveConstruct(m_pData + len, std::move(valueMoved));
1449 A::moveConstruct(m_pData + len, std::move(
value));
1451 buffer()->m_nLength = newLen;
1466 if (numElements == 0)
1474 r.reallocate(
this, len + numElements);
1475 A::defaultConstructFill(m_pData + len, numElements);
1476 buffer()->m_nLength = len + numElements;
1481 A::moveAssignRange(pData + numElements, pData, len -
index);
1483 while (numElements-- > 1)
1485 pData[numElements] = tmpval;
1487 pData[0] = std::move(tmpval);
1488 return begin_non_const()+
index;
1497 const T&
value = T())
1501 return (begin_non_const() +
index);
1514 return (begin_non_const() +
index);
1539 return buffer()->m_nLength;
1571 return buffer()->m_nAllocated;
1582 return buffer()->m_nGrowBy;
1612 copy_if_referenced();
1623 return m_pData[
index];
1632 copy_if_referenced();
1633 return m_pData[
index];
1644 assertValid(arrayIndex);
1645 copy_if_referenced();
1646 return *(
data() + arrayIndex);
1657 assertValid(arrayIndex);
1658 return *(
data() + arrayIndex);
1672 assertValid(arrayIndex);
1673 copy_if_referenced();
1674 m_pData[arrayIndex] =
value;
1687 assertValid(arrayIndex);
1688 return *(
data() + arrayIndex);
1771 T tmp(std::move(
value));
1773 r.reallocate(
this, newLen);
1774 A::moveConstruct(m_pData + oldLen, std::move(tmp));
1776 if (
index != oldLen) {
1777 tmp = std::move(*(m_pData + oldLen));
1778 A::moveAssignRange(m_pData +
index + 1, m_pData +
index, oldLen -
index);
1779 *(m_pData +
index) = std::move(tmp);
1830 r.reallocate(
this, oldLen + nCount);
1831 A::copyConstructFill(m_pData + oldLen, nCount, tmp);
1832 (
buffer()->m_nLength) += nCount;
1844 template<
typename... Args>
1849 const auto count_elements =
sizeof...(Args);
1850 if (count_elements == 0)
1855 Buffer* oldBuf =
buffer();
1860 copy_buffer(oldLen + count_elements,
false,
false,
false);
1861 A::defaultConstructFill(m_pData + oldLen, count_elements);
1863 variadicAssignHelper(oldLen, args...);
1876 return begin_non_const() + i;
1911 copy_if_referenced();
1945 static_assert(std::is_copy_constructible<T>::value,
"Can not copy array with non-copyable argument");
1951 source.m_pData = Buffer::_default()->data();
1952 source.buffer()->addref();
1958 res.
assign(sourceArray, sourceArray + sourceLength);
1973 static_assert(std::is_copy_constructible<T>::value,
"Can not copy array with non-copyable argument");
1974 source.buffer()->addref();
1976 m_pData =
source.m_pData;
1984 std::swap( m_pData,
source.m_pData );
1996 if(
at(i) != array[i])
2021 copy_if_referenced();
2074 if( arrayIndex == len )
2078 else if ( arrayIndex < len )
2082 r.reallocate(
this, len+1 );
2083 A::defaultConstruct( m_pData + len );
2085 A::moveAssignRange(m_pData + arrayIndex + 1, m_pData + arrayIndex, len - arrayIndex);
2086 m_pData[arrayIndex] = std::move(tmpval);
2090 rise_error(eInvalidIndex);
2130 assertValid(arrayIndex);
2132 if(arrayIndex < --len)
2134 copy_if_referenced();
2136 A::moveAssignRange(pData + arrayIndex, pData + arrayIndex + 1, len - arrayIndex);
2155 if(!isValid(startIndex) || startIndex > endIndex)
2157 rise_error(eInvalidIndex);
2160 copy_if_referenced();
2163 size_type n2remove = endIndex - startIndex;
2164 A::moveAssignRange(pData + startIndex, pData + endIndex, len - endIndex);
2165 A::destroyRange(pData + len - n2remove, n2remove);
2166 buffer()->m_nLength -= n2remove;
2187 const T* pData =
data();
2190 if (pData[i] ==
value)
2232 copy_buffer(physLength, !referenced(),
true);
2246 copy_if_referenced();
2248 iterator iter1 = begin_non_const();
2251 while(iter1 < iter2)
2274 if(!isValid(firstIndex) || !isValid(secondIndex))
2276 rise_error(eInvalidIndex);
2278 if(firstIndex != secondIndex)
2280 T tmp = std::move(
at(firstIndex));
2281 at(firstIndex) = std::move(
at(secondIndex));
2282 at(secondIndex) = std::move(tmp);
2296 m_pData = other.m_pData;
2297 other.m_pData = temp;
2332 return (
length() ? m_pData : 0);
2335 const T*
data()
const
2342 return (
reinterpret_cast<Buffer*
>(
const_cast<OdArray*
>(
this)->m_pData) - 1);
2344 bool referenced()
const
2346 return (
buffer()->m_nRefCounter>1);
2350 OdArray& variadicAssignHelper(
2358 OdArray& variadicAssignHelper(
2368 template<
typename... Args>
2369 OdArray& variadicAssignHelper(
2376 return variadicAssignHelper(
index + 1, args...);
2380#if !defined(SWIG) || defined(SWIGBUILD)
2382 template<
typename U = T,
2383 typename std::enable_if<std::is_same<U, T>::value && !std::is_move_assignable<U>::value,
bool>
::type =
true>
2384 void increaseLogicalLength(
2390 throw OdError(eNotApplicable);
2393 template<
typename U = T,
2394 typename std::enable_if<std::is_same<U, T>::value && std::is_move_assignable<U>::value,
bool>
::type =
true>
2395 void increaseLogicalLength(
2403 A::copyConstructFill(m_pData + len, d,
value);
2406 template<
typename U = T,
2407 typename std::enable_if<std::is_same<U, T>::value && !std::is_default_constructible<U>::value,
bool>
::type =
true>
2408 void increaseLogicalLength(
2413 throw OdError(eNotApplicable);
2416 template<
typename U = T,
2417 typename std::enable_if<std::is_same<U, T>::value && std::is_default_constructible<U>::value,
bool>
::type =
true>
2418 void increaseLogicalLength(
2423 copy_before_write(len + d,
true);
2424 A::defaultConstructFill(m_pData + len, d);
#define ODA_ASSERT_ONCE(exp)
ALLOCDLL_EXPORT void * odrxRealloc(void *pMemBlock, size_t newSize, size_t oldSize)
ALLOCDLL_EXPORT void * odrxAlloc(size_t nBytes)
ALLOCDLL_EXPORT void odrxFree(void *pMemBlock)
#define FIRSTDLL_EXPORT_STATIC
const T * asArrayPtr() const
OdArray & appendMove(OdArray &otherArray)
OdArray & insertAtMove(size_type index, T &value)
size_type capacity() const
OdArray & swap(size_type firstIndex, size_type secondIndex)
const T & getAt(size_type arrayIndex) const
bool operator==(const OdArray &array) const
const T & operator[](size_type index) const
void swap(OdArray &other)
const_iterator end() const
void assign(const_iterator first, const_iterator afterLast)
size_type physicalLength() const
std::reverse_iterator< const_iterator > rbegin() const
iterator insert(iterator before, T &&value)
std::reverse_iterator< const_iterator > rend() const
OdArray & setAll(const T &value)
bool operator!=(const OdArray &array) const
OdArray(size_type physicalLength, int growLength=8)
void resize(size_type logicalLength)
void insertMove(iterator before, iterator first, iterator afterLast)
OdArray & operator=(const OdArray &source)
OdArray & append(const OdArray &otherArray)
void push_back(T &&value)
bool contains(const ConstForPtrT &value, size_type start=0) const
OdArray & setPhysicalLength(size_type physLength)
OdArray & setGrowLength(int growLength)
iterator erase(iterator where)
OdArray(const OdArray &source)
typename std::conditional< std::is_pointer< T >::value, typename std::add_const< typename std::remove_pointer< T >::type >::type *, T >::type ConstForPtrT
OdArray(OdArray &&source)
bool find(const ConstForPtrT &value, size_type &findIndex, size_type start=0) const
void push_back(const T &value)
OdArray & setAt(size_type arrayIndex, const T &value)
size_type logicalLength() const
const T & const_reference
size_type append(T &&value)
OdArray & appendList(const Args &... args)
OdArray & appendRep(const T &value, size_type nCount)
void reserve(size_type reserveLength)
void insert(iterator before, const_iterator first, const_iterator afterLast)
const T & at(size_type arrayIndex) const
std::reverse_iterator< iterator > rend()
OdArray & setLogicalLength(size_type logLength)
typename A::size_type size_type
OdArray & removeSubArray(size_type startIndex, size_type endIndex)
OdArray & append(OdArray &&otherArray)
iterator erase(iterator first, iterator afterLast)
iterator insert(iterator before, size_type numElements, const T &value)
T & at(size_type arrayIndex)
void assignMove(iterator first, iterator afterLast)
static OdArray< T, A > create(T *sourceArray, int sourceLength)
OdArray & insertAt(size_type index, T &&val)
OdArray & removeAt(size_type arrayIndex)
size_type appendMove(T &value)
OdArray & insertAt(size_type arrayIndex, const T &value)
void resize(size_type logicalLength, const T &value)
size_type append(const T &value)
iterator insert(iterator before, const T &value=T())
std::reverse_iterator< iterator > rbegin()
bool remove(const T &value, size_type start=0)
const_iterator begin() const
static void defaultConstructFill(T *pDestination, size_type numElements)
static void copyConstructFill(T *pDestination, size_type numElements, const T &value)
static void copyConstructRange(T *pDestination, const T *pSource, size_type numElements)
static void moveAssignRange(T *pDestination, T *pSource, size_type numElements)
static void defaultConstructFill(T *pDestination, size_type numElements)
static void defaultConstruct(T *pElement)
static void moveConstruct(T *pElement, T &&value)
static void copyConstruct(T *pElement, const T &value)
static void destroy(T *pObject)
static void copyAssignRangeDisjoint(T *pDestination, const T *pSource, size_type numElements)
static void copyConstructRange(T *pDestination, const T *pSource, size_type numElements)
static void copyConstructFill(T *pDestination, size_type numElements, const T &value)
static void copyAssignRange(T *pDestination, const T *pSource, size_type numElements)
static void moveConstructRange(T *pDestination, T *pSource, size_type numElements)
static void destroyRange(T *objects, size_type numObjects)
static void moveAssignRange(T *pDestination, T *pSource, size_type numElements)
static void copyConstructRange(T *pDestination, const T *pSource, size_type numElements)
static void defaultConstructFill(T *pDestination, size_type numElements)
static void copyConstructFill(T *pDestination, size_type numElements, const T &value)
static void moveConstructRange(T *pDestination, T *pSource, size_type numElements)
static void copyAssignRange(T *pDestination, const T *pSource, size_type numElements)
static void defaultConstruct(T *pElement)
static void destroyRange(T *objects, size_type numObjects)
static void destroy(T *pObject)
static void copyConstruct(T *pElement, const T &value)
static void moveConstruct(T *pElement, T &&value)
static void copyAssignRangeDisjoint(T *pDestination, const T *pSource, size_type numElements)
static void copyAssignRangeDisjoint(T *pDestination, const T *pSource, size_type numElements)
static void moveAssignRange(T *pDestination, T *pSource, size_type numElements)
static void copyAssignRange(T *pDestination, const T *pSource, size_type numElements)
GLint GLenum GLsizei GLsizei GLint GLsizei const void * data
GLsizei GLsizei GLchar * source
GLuint GLsizei GLsizei GLint GLenum * type
GLsizei const GLfloat * value
static FIRSTDLL_EXPORT_STATIC OdArrayBuffer g_empty_array_buffer
OdRefCounter m_nRefCounter
check_trivially_copyable()