File indexing completed on 2026-09-17 09:21:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef NCollection_DynamicArray_HeaderFile
0015 #define NCollection_DynamicArray_HeaderFile
0016
0017 #include <NCollection_Allocator.hxx>
0018 #include <NCollection_LinearVector.hxx>
0019 #include <Standard_DimensionMismatch.hxx>
0020 #include <Standard_OutOfMemory.hxx>
0021 #include <Standard_NotImplemented.hxx>
0022 #include <Standard_OutOfRange.hxx>
0023
0024 #include <NCollection_DefineAlloc.hxx>
0025 #include <NCollection_Iterator.hxx>
0026 #include <NCollection_OccAllocator.hxx>
0027 #include <StdFail_NotDone.hxx>
0028
0029 #include <cstring>
0030 #include <locale>
0031 #include <type_traits>
0032 #include <vector>
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 template <class TheItemType>
0055 class NCollection_DynamicArray
0056 {
0057 public:
0058
0059 DEFINE_STANDARD_ALLOC;
0060 DEFINE_NCOLLECTION_ALLOC;
0061
0062 public:
0063 typedef NCollection_OccAllocator<TheItemType> allocator_type;
0064 typedef NCollection_LinearVector<TheItemType*> vector;
0065
0066 public:
0067
0068 using value_type = TheItemType;
0069 using size_type = size_t;
0070 using difference_type = size_t;
0071 using pointer = TheItemType*;
0072 using const_pointer = const TheItemType*;
0073 using reference = TheItemType&;
0074 using const_reference = const TheItemType&;
0075
0076 public:
0077 template <bool IsConstant>
0078 class DynamicIterator
0079 {
0080 public:
0081 using iterator_category = std::random_access_iterator_tag;
0082 using value_type = TheItemType;
0083 using difference_type = ptrdiff_t;
0084 using pointer = typename std::conditional<IsConstant, const TheItemType*, TheItemType*>::type;
0085 using reference = typename std::conditional<IsConstant, const TheItemType&, TheItemType&>::type;
0086
0087 public:
0088 DynamicIterator() noexcept
0089 : myOwner(nullptr),
0090 myIndex(0),
0091 myUsedSize(0),
0092 myInternalSize(1),
0093 myBlockShift(0),
0094 myBlockMask(0),
0095 myBlockIndex(0),
0096 myCurrPtr(nullptr),
0097 myBlockEnd(nullptr)
0098 {
0099 }
0100
0101 DynamicIterator(const NCollection_DynamicArray& theArray) noexcept
0102 : DynamicIterator(0, theArray)
0103 {
0104 }
0105
0106 DynamicIterator(const size_t theIndex, const NCollection_DynamicArray& theArray) noexcept
0107 : myOwner(&theArray),
0108 myIndex(theIndex),
0109 myUsedSize(theArray.myUsedSize),
0110 myInternalSize(theArray.myInternalSize),
0111 myBlockShift(theArray.myBlockShift),
0112 myBlockMask(theArray.myBlockMask),
0113 myBlockIndex(0),
0114 myCurrPtr(nullptr),
0115 myBlockEnd(nullptr)
0116 {
0117 setIndex(theIndex);
0118 }
0119
0120 DynamicIterator(const DynamicIterator<false>& theOther) noexcept
0121 : myOwner(theOther.myOwner),
0122 myIndex(theOther.myIndex),
0123 myUsedSize(theOther.myUsedSize),
0124 myInternalSize(theOther.myInternalSize),
0125 myBlockShift(theOther.myBlockShift),
0126 myBlockMask(theOther.myBlockMask),
0127 myBlockIndex(theOther.myBlockIndex),
0128 myCurrPtr(theOther.myCurrPtr),
0129 myBlockEnd(theOther.myBlockEnd)
0130 {
0131 }
0132
0133 DynamicIterator& operator=(const DynamicIterator<false>& theOther) noexcept
0134 {
0135 myOwner = theOther.myOwner;
0136 myIndex = theOther.myIndex;
0137 myUsedSize = theOther.myUsedSize;
0138 myInternalSize = theOther.myInternalSize;
0139 myBlockShift = theOther.myBlockShift;
0140 myBlockMask = theOther.myBlockMask;
0141 myBlockIndex = theOther.myBlockIndex;
0142 myCurrPtr = theOther.myCurrPtr;
0143 myBlockEnd = theOther.myBlockEnd;
0144 return *this;
0145 }
0146
0147 public:
0148 bool operator==(const DynamicIterator& theOther) const noexcept
0149 {
0150 return myOwner == theOther.myOwner && myIndex == theOther.myIndex;
0151 }
0152
0153 template <bool theOtherIsConstant>
0154 bool operator==(const DynamicIterator<theOtherIsConstant>& theOther) const noexcept
0155 {
0156 return myOwner == theOther.myOwner && myIndex == theOther.myIndex;
0157 }
0158
0159 template <bool theOtherIsConstant>
0160 bool operator!=(const DynamicIterator<theOtherIsConstant>& theOther) const noexcept
0161 {
0162 return myOwner != theOther.myOwner || myIndex != theOther.myIndex;
0163 }
0164
0165 bool operator!=(const DynamicIterator& theOther) const noexcept { return !(*this == theOther); }
0166
0167 reference operator*() const noexcept { return *myCurrPtr; }
0168
0169 pointer operator->() const noexcept { return myCurrPtr; }
0170
0171 DynamicIterator& operator++() noexcept
0172 {
0173 ++myIndex;
0174 ++myCurrPtr;
0175 if (myIndex >= myUsedSize)
0176 {
0177 myCurrPtr = nullptr;
0178 myBlockEnd = nullptr;
0179 }
0180 else if (myCurrPtr == myBlockEnd)
0181 {
0182 ++myBlockIndex;
0183 myCurrPtr = blockStart(myBlockIndex);
0184 myBlockEnd = myCurrPtr + myInternalSize;
0185 }
0186 return *this;
0187 }
0188
0189 DynamicIterator operator++(int) noexcept
0190 {
0191 DynamicIterator theOld(*this);
0192 ++(*this);
0193 return theOld;
0194 }
0195
0196 DynamicIterator& operator--() noexcept
0197 {
0198 if (myIndex == myUsedSize)
0199 {
0200 setIndex(myUsedSize - 1);
0201 return *this;
0202 }
0203
0204 --myIndex;
0205 if (myCurrPtr > blockStart(myBlockIndex))
0206 {
0207 --myCurrPtr;
0208 }
0209 else
0210 {
0211 --myBlockIndex;
0212 myCurrPtr = blockStart(myBlockIndex) + (myInternalSize - 1);
0213 myBlockEnd = blockStart(myBlockIndex) + myInternalSize;
0214 }
0215 return *this;
0216 }
0217
0218 DynamicIterator operator--(int) noexcept
0219 {
0220 DynamicIterator theOld(*this);
0221 --(*this);
0222 return theOld;
0223 }
0224
0225 DynamicIterator& operator+=(const difference_type theOffset) noexcept
0226 {
0227 setIndex(static_cast<size_t>(static_cast<difference_type>(myIndex) + theOffset));
0228 return *this;
0229 }
0230
0231 DynamicIterator operator+(const difference_type theOffset) const noexcept
0232 {
0233 DynamicIterator aTemp(*this);
0234 aTemp += theOffset;
0235 return aTemp;
0236 }
0237
0238 DynamicIterator& operator-=(const difference_type theOffset) noexcept
0239 {
0240 return *this += -theOffset;
0241 }
0242
0243 DynamicIterator operator-(const difference_type theOffset) const noexcept
0244 {
0245 DynamicIterator aTemp(*this);
0246 aTemp += -theOffset;
0247 return aTemp;
0248 }
0249
0250 difference_type operator-(const DynamicIterator& theOther) const noexcept
0251 {
0252 return static_cast<difference_type>(myIndex) - static_cast<difference_type>(theOther.myIndex);
0253 }
0254
0255 reference operator[](const difference_type theOffset) const noexcept
0256 {
0257 return *(*this + theOffset);
0258 }
0259
0260 bool operator<(const DynamicIterator& theOther) const noexcept
0261 {
0262 return (*this - theOther) < 0;
0263 }
0264
0265 bool operator>(const DynamicIterator& theOther) const noexcept { return theOther < *this; }
0266
0267 bool operator<=(const DynamicIterator& theOther) const noexcept { return !(theOther < *this); }
0268
0269 bool operator>=(const DynamicIterator& theOther) const noexcept { return !(*this < theOther); }
0270
0271 friend DynamicIterator operator+(const difference_type theOffset,
0272 const DynamicIterator& theIter) noexcept
0273 {
0274 return theIter + theOffset;
0275 }
0276
0277 friend class DynamicIterator<!IsConstant>;
0278
0279 private:
0280 void setIndex(const size_t theIndex) noexcept
0281 {
0282 myIndex = theIndex;
0283 if (myIndex >= myUsedSize || myOwner == nullptr)
0284 {
0285 myCurrPtr = nullptr;
0286 myBlockEnd = nullptr;
0287 myBlockIndex = 0;
0288 return;
0289 }
0290
0291 myBlockIndex = myIndex >> myBlockShift;
0292 const size_t aLocalIndex = myIndex & myBlockMask;
0293 myCurrPtr = blockStart(myBlockIndex) + aLocalIndex;
0294 myBlockEnd = blockStart(myBlockIndex) + myInternalSize;
0295 }
0296
0297 TheItemType* blockStart(const size_t theBlockIndex) const noexcept
0298 {
0299 return myOwner->getArray()[theBlockIndex];
0300 }
0301
0302 private:
0303 const NCollection_DynamicArray* myOwner;
0304 size_t myIndex;
0305 size_t myUsedSize;
0306 size_t myInternalSize;
0307 size_t myBlockShift;
0308 size_t myBlockMask;
0309 size_t myBlockIndex;
0310 TheItemType* myCurrPtr;
0311 TheItemType* myBlockEnd;
0312 };
0313
0314 using iterator = DynamicIterator<false>;
0315 using const_iterator = DynamicIterator<true>;
0316 using Iterator = NCollection_Iterator<NCollection_DynamicArray<TheItemType>>;
0317
0318 public:
0319 const_iterator begin() const noexcept { return const_iterator(*this); }
0320
0321 iterator begin() noexcept { return iterator(*this); }
0322
0323 const_iterator cbegin() const noexcept { return const_iterator(*this); }
0324
0325 iterator end() noexcept { return iterator(myUsedSize, *this); }
0326
0327 const_iterator end() const noexcept { return const_iterator(myUsedSize, *this); }
0328
0329 const_iterator cend() const noexcept { return const_iterator(myUsedSize, *this); }
0330
0331 public:
0332 NCollection_DynamicArray(const size_t theIncrement)
0333 : myAlloc(),
0334 myInternalSize(roundUpPow2(theIncrement)),
0335 myBlockShift(log2Pow2(myInternalSize)),
0336 myBlockMask(myInternalSize - 1),
0337 myUsedSize(0)
0338 {
0339 }
0340
0341 NCollection_DynamicArray(const int theIncrement = 256)
0342 : NCollection_DynamicArray(static_cast<size_t>(theIncrement < 1 ? 1 : theIncrement))
0343 {
0344 }
0345
0346
0347 explicit NCollection_DynamicArray(const size_t theIncrement,
0348 const occ::handle<NCollection_BaseAllocator>& theAllocator)
0349 : myAlloc(allocator_type(theAllocator)),
0350 myInternalSize(roundUpPow2(theIncrement)),
0351 myBlockShift(log2Pow2(myInternalSize)),
0352 myBlockMask(myInternalSize - 1),
0353 myUsedSize(0)
0354 {
0355 }
0356
0357 explicit NCollection_DynamicArray(const int theIncrement,
0358 const occ::handle<NCollection_BaseAllocator>& theAllocator)
0359 : NCollection_DynamicArray(static_cast<size_t>(theIncrement < 1 ? 1 : theIncrement),
0360 theAllocator)
0361 {
0362 }
0363
0364
0365 explicit NCollection_DynamicArray(const size_t theIncrement, const allocator_type& theAllocator)
0366 : myAlloc(theAllocator),
0367 myInternalSize(roundUpPow2(theIncrement)),
0368 myBlockShift(log2Pow2(myInternalSize)),
0369 myBlockMask(myInternalSize - 1),
0370 myUsedSize(0)
0371 {
0372 }
0373
0374 explicit NCollection_DynamicArray(const int theIncrement, const allocator_type& theAllocator)
0375 : NCollection_DynamicArray(static_cast<size_t>(theIncrement < 1 ? 1 : theIncrement),
0376 theAllocator)
0377 {
0378 }
0379
0380
0381 NCollection_DynamicArray(const NCollection_DynamicArray& theOther)
0382 : myContainer(theOther.myContainer),
0383 myAlloc(theOther.myAlloc),
0384 myInternalSize(theOther.myInternalSize),
0385 myBlockShift(theOther.myBlockShift),
0386 myBlockMask(theOther.myBlockMask),
0387 myUsedSize(theOther.myUsedSize)
0388 {
0389 copyDate();
0390 }
0391
0392 NCollection_DynamicArray(NCollection_DynamicArray&& theOther) noexcept
0393 : myContainer(std::move(theOther.myContainer)),
0394 myAlloc(theOther.myAlloc),
0395 myInternalSize(theOther.myInternalSize),
0396 myBlockShift(theOther.myBlockShift),
0397 myBlockMask(theOther.myBlockMask),
0398 myUsedSize(theOther.myUsedSize)
0399 {
0400 theOther.myUsedSize = 0;
0401 }
0402
0403 ~NCollection_DynamicArray() { Clear(true); }
0404
0405
0406 size_t Size() const noexcept { return myUsedSize; }
0407
0408
0409 int Length() const noexcept { return static_cast<int>(myUsedSize); }
0410
0411
0412
0413 int Lower() const noexcept { return 0; }
0414
0415
0416
0417 int Upper() const noexcept { return static_cast<int>(myUsedSize) - 1; }
0418
0419
0420 bool IsEmpty() const noexcept { return myUsedSize == 0; }
0421
0422
0423 NCollection_DynamicArray& Assign(const NCollection_DynamicArray& theOther,
0424 const bool theOwnAllocator = true)
0425 {
0426 if (&theOther == this)
0427 {
0428 return *this;
0429 }
0430 if (!theOwnAllocator)
0431 {
0432 Clear(myAlloc != theOther.myAlloc);
0433 myAlloc = theOther.myAlloc;
0434 }
0435 else
0436 {
0437 Clear(false);
0438 }
0439 myContainer = theOther.myContainer;
0440 myInternalSize = theOther.myInternalSize;
0441 myBlockShift = theOther.myBlockShift;
0442 myBlockMask = theOther.myBlockMask;
0443 myUsedSize = theOther.myUsedSize;
0444 copyDate();
0445 return *this;
0446 }
0447
0448 NCollection_DynamicArray& Assign(NCollection_DynamicArray&& theOther)
0449 {
0450 if (&theOther == this)
0451 {
0452 return *this;
0453 }
0454 Clear(true);
0455 myContainer = std::move(theOther.myContainer);
0456 myAlloc = theOther.myAlloc;
0457 myInternalSize = theOther.myInternalSize;
0458 myBlockShift = theOther.myBlockShift;
0459 myBlockMask = theOther.myBlockMask;
0460 myUsedSize = theOther.myUsedSize;
0461 theOther.myUsedSize = 0;
0462 return *this;
0463 }
0464
0465
0466 NCollection_DynamicArray& operator=(const NCollection_DynamicArray& theOther)
0467 {
0468 return Assign(theOther, false);
0469 }
0470
0471
0472 NCollection_DynamicArray& operator=(NCollection_DynamicArray&& theOther) noexcept
0473 {
0474 return Assign(std::forward<NCollection_DynamicArray>(theOther));
0475 }
0476
0477
0478 reference Append(const TheItemType& theValue)
0479 {
0480 if (myUsedSize >= availableSize())
0481 {
0482 expandArray();
0483 }
0484 pointer aPnt = &at(myUsedSize++);
0485 myAlloc.construct(aPnt, theValue);
0486 return *aPnt;
0487 }
0488
0489
0490 reference Append(TheItemType&& theValue)
0491 {
0492 if (myUsedSize >= availableSize())
0493 {
0494 expandArray();
0495 }
0496 pointer aPnt = &at(myUsedSize++);
0497 myAlloc.construct(aPnt, std::forward<TheItemType>(theValue));
0498 return *aPnt;
0499 }
0500
0501
0502
0503
0504
0505 reference InsertAfter(const size_t theIndex, const TheItemType& theValue)
0506 {
0507 Standard_OutOfRange_Raise_if(theIndex >= myUsedSize,
0508 "NCollection_DynamicArray::InsertAfter: index out of range");
0509 Appended();
0510 for (size_t i = myUsedSize - 1; i > theIndex + 1; --i)
0511 {
0512 at(i) = std::move(at(i - 1));
0513 }
0514 at(theIndex + 1) = theValue;
0515 return at(theIndex + 1);
0516 }
0517
0518
0519 reference InsertAfter(const size_t theIndex, TheItemType&& theValue)
0520 {
0521 Standard_OutOfRange_Raise_if(theIndex >= myUsedSize,
0522 "NCollection_DynamicArray::InsertAfter: index out of range");
0523 Appended();
0524 for (size_t i = myUsedSize - 1; i > theIndex + 1; --i)
0525 {
0526 at(i) = std::move(at(i - 1));
0527 }
0528 at(theIndex + 1) = std::forward<TheItemType>(theValue);
0529 return at(theIndex + 1);
0530 }
0531
0532 reference InsertAfter(const int theIndex, const TheItemType& theValue)
0533 {
0534 Standard_OutOfRange_Raise_if(theIndex < 0,
0535 "NCollection_DynamicArray::InsertAfter: index out of range");
0536 return InsertAfter(static_cast<size_t>(theIndex), theValue);
0537 }
0538
0539 reference InsertAfter(const int theIndex, TheItemType&& theValue)
0540 {
0541 Standard_OutOfRange_Raise_if(theIndex < 0,
0542 "NCollection_DynamicArray::InsertAfter: index out of range");
0543 return InsertAfter(static_cast<size_t>(theIndex), std::forward<TheItemType>(theValue));
0544 }
0545
0546
0547
0548
0549
0550 reference InsertBefore(const size_t theIndex, const TheItemType& theValue)
0551 {
0552 Standard_OutOfRange_Raise_if(theIndex >= myUsedSize,
0553 "NCollection_DynamicArray::InsertBefore: index out of range");
0554 Appended();
0555 for (size_t i = myUsedSize - 1; i > theIndex; --i)
0556 {
0557 at(i) = std::move(at(i - 1));
0558 }
0559 at(theIndex) = theValue;
0560 return at(theIndex);
0561 }
0562
0563
0564 reference InsertBefore(const size_t theIndex, TheItemType&& theValue)
0565 {
0566 Standard_OutOfRange_Raise_if(theIndex >= myUsedSize,
0567 "NCollection_DynamicArray::InsertBefore: index out of range");
0568 Appended();
0569 for (size_t i = myUsedSize - 1; i > theIndex; --i)
0570 {
0571 at(i) = std::move(at(i - 1));
0572 }
0573 at(theIndex) = std::forward<TheItemType>(theValue);
0574 return at(theIndex);
0575 }
0576
0577 reference InsertBefore(const int theIndex, const TheItemType& theValue)
0578 {
0579 Standard_OutOfRange_Raise_if(theIndex < 0,
0580 "NCollection_DynamicArray::InsertBefore: index out of range");
0581 return InsertBefore(static_cast<size_t>(theIndex), theValue);
0582 }
0583
0584 reference InsertBefore(const int theIndex, TheItemType&& theValue)
0585 {
0586 Standard_OutOfRange_Raise_if(theIndex < 0,
0587 "NCollection_DynamicArray::InsertBefore: index out of range");
0588 return InsertBefore(static_cast<size_t>(theIndex), std::forward<TheItemType>(theValue));
0589 }
0590
0591 void EraseLast()
0592 {
0593 if (myUsedSize == 0)
0594 {
0595 return;
0596 }
0597 if constexpr (!std::is_trivially_destructible_v<TheItemType>)
0598 {
0599 TheItemType* aLastElem = &ChangeLast();
0600 myAlloc.destroy(aLastElem);
0601 }
0602 myUsedSize--;
0603 }
0604
0605
0606 reference Appended()
0607 {
0608 if (myUsedSize >= availableSize())
0609 {
0610 expandArray();
0611 }
0612 pointer aPnt = &at(myUsedSize++);
0613 myAlloc.construct(aPnt);
0614 return *aPnt;
0615 }
0616
0617
0618
0619
0620 template <typename... Args>
0621 reference EmplaceAppend(Args&&... theArgs)
0622 {
0623 if (myUsedSize >= availableSize())
0624 {
0625 expandArray();
0626 }
0627 pointer aPnt = &at(myUsedSize++);
0628 myAlloc.construct(aPnt, std::forward<Args>(theArgs)...);
0629 return *aPnt;
0630 }
0631
0632
0633
0634
0635
0636
0637 template <typename... Args>
0638 reference EmplaceValue(const size_t theIndex, Args&&... theArgs)
0639 {
0640 ensureStorageForIndex(theIndex);
0641 const bool isExisting = theIndex < myUsedSize;
0642 if (!isExisting)
0643 {
0644 for (; myUsedSize < theIndex; myUsedSize++)
0645 {
0646 pointer aPnt = &at(myUsedSize);
0647 myAlloc.construct(aPnt);
0648 }
0649 myUsedSize++;
0650 }
0651 pointer aPnt = &at(theIndex);
0652 if (isExisting)
0653 {
0654 if constexpr (!std::is_trivially_destructible_v<TheItemType>)
0655 {
0656 myAlloc.destroy(aPnt);
0657 }
0658 }
0659 myAlloc.construct(aPnt, std::forward<Args>(theArgs)...);
0660 return *aPnt;
0661 }
0662
0663 template <typename... Args>
0664 reference EmplaceValue(const int theIndex, Args&&... theArgs)
0665 {
0666 Standard_OutOfRange_Raise_if(theIndex < 0,
0667 "NCollection_DynamicArray::EmplaceValue: index out of range");
0668 return EmplaceValue(static_cast<size_t>(theIndex), std::forward<Args>(theArgs)...);
0669 }
0670
0671
0672 const_reference operator()(const size_t theIndex) const noexcept { return at(theIndex); }
0673
0674 const_reference operator()(const int theIndex) const noexcept
0675 {
0676 return at(static_cast<size_t>(theIndex));
0677 }
0678
0679
0680 const_reference operator[](const size_t theIndex) const noexcept { return at(theIndex); }
0681
0682 const_reference operator[](const int theIndex) const noexcept
0683 {
0684 return at(static_cast<size_t>(theIndex));
0685 }
0686
0687 const_reference Value(const size_t theIndex) const noexcept { return at(theIndex); }
0688
0689 const_reference Value(const int theIndex) const noexcept
0690 {
0691 return at(static_cast<size_t>(theIndex));
0692 }
0693
0694
0695 const_reference First() const noexcept { return getArray()[0][0]; }
0696
0697
0698 reference ChangeFirst() noexcept { return getArray()[0][0]; }
0699
0700
0701 const_reference Last() const noexcept { return at(myUsedSize - 1); }
0702
0703
0704 reference ChangeLast() noexcept { return at(myUsedSize - 1); }
0705
0706
0707 reference operator()(const size_t theIndex) noexcept { return at(theIndex); }
0708
0709 reference operator()(const int theIndex) noexcept { return at(static_cast<size_t>(theIndex)); }
0710
0711
0712 reference operator[](const size_t theIndex) noexcept { return at(theIndex); }
0713
0714 reference operator[](const int theIndex) noexcept { return at(static_cast<size_t>(theIndex)); }
0715
0716 reference ChangeValue(const size_t theIndex) noexcept { return at(theIndex); }
0717
0718 reference ChangeValue(const int theIndex) noexcept { return at(static_cast<size_t>(theIndex)); }
0719
0720
0721 reference SetValue(const size_t theIndex, const TheItemType& theValue)
0722 {
0723 ensureStorageForIndex(theIndex);
0724 const bool isExisting = theIndex < myUsedSize;
0725 if (!isExisting)
0726 {
0727 for (; myUsedSize < theIndex; myUsedSize++)
0728 {
0729 pointer aPnt = &at(myUsedSize);
0730 myAlloc.construct(aPnt);
0731 }
0732 myUsedSize++;
0733 }
0734 pointer aPnt = &at(theIndex);
0735 if (isExisting)
0736 {
0737 if constexpr (!std::is_trivially_destructible_v<TheItemType>)
0738 {
0739 myAlloc.destroy(aPnt);
0740 }
0741 }
0742 myAlloc.construct(aPnt, theValue);
0743 return *aPnt;
0744 }
0745
0746
0747 reference SetValue(const size_t theIndex, TheItemType&& theValue)
0748 {
0749 ensureStorageForIndex(theIndex);
0750 const bool isExisting = theIndex < myUsedSize;
0751 if (!isExisting)
0752 {
0753 for (; myUsedSize < theIndex; myUsedSize++)
0754 {
0755 pointer aPnt = &at(myUsedSize);
0756 myAlloc.construct(aPnt);
0757 }
0758 myUsedSize++;
0759 }
0760 pointer aPnt = &at(theIndex);
0761 if (isExisting)
0762 {
0763 if constexpr (!std::is_trivially_destructible_v<TheItemType>)
0764 {
0765 myAlloc.destroy(aPnt);
0766 }
0767 }
0768 myAlloc.construct(aPnt, std::forward<TheItemType>(theValue));
0769 return *aPnt;
0770 }
0771
0772 reference SetValue(const int theIndex, const TheItemType& theValue)
0773 {
0774 Standard_OutOfRange_Raise_if(theIndex < 0,
0775 "NCollection_DynamicArray::SetValue: index out of range");
0776 return SetValue(static_cast<size_t>(theIndex), theValue);
0777 }
0778
0779 reference SetValue(const int theIndex, TheItemType&& theValue)
0780 {
0781 Standard_OutOfRange_Raise_if(theIndex < 0,
0782 "NCollection_DynamicArray::SetValue: index out of range");
0783 return SetValue(static_cast<size_t>(theIndex), std::forward<TheItemType>(theValue));
0784 }
0785
0786 void Clear(const bool theReleaseMemory = false)
0787 {
0788 for (size_t aBlockInd = 0; aBlockInd < myContainer.Size(); aBlockInd++)
0789 {
0790 TheItemType* aCurStart = getArray()[aBlockInd];
0791 if constexpr (!std::is_trivially_destructible_v<TheItemType>)
0792 {
0793 const size_t aBlockStart = aBlockInd * myInternalSize;
0794 const size_t aCount = (myUsedSize > aBlockStart + myInternalSize)
0795 ? myInternalSize
0796 : (myUsedSize > aBlockStart ? myUsedSize - aBlockStart : 0);
0797 for (size_t anElemInd = 0; anElemInd < aCount; anElemInd++)
0798 {
0799 aCurStart[anElemInd].~TheItemType();
0800 }
0801 }
0802 if (theReleaseMemory)
0803 {
0804 myAlloc.deallocate(aCurStart, myInternalSize);
0805 }
0806 }
0807 if (theReleaseMemory)
0808 {
0809 myContainer.Clear(theReleaseMemory);
0810 }
0811 myUsedSize = 0;
0812 }
0813
0814 void SetIncrement(const size_t theIncrement) noexcept
0815 {
0816 if (myUsedSize != 0)
0817 {
0818 return;
0819 }
0820 myInternalSize = roundUpPow2(theIncrement);
0821 myBlockShift = log2Pow2(myInternalSize);
0822 myBlockMask = myInternalSize - 1;
0823 }
0824
0825 void SetIncrement(const int theIncrement) noexcept
0826 {
0827 SetIncrement(static_cast<size_t>(theIncrement < 1 ? 1 : theIncrement));
0828 }
0829
0830 friend iterator;
0831 friend const_iterator;
0832
0833 protected:
0834 size_t availableSize() const noexcept
0835 {
0836 return static_cast<size_t>(myContainer.Size()) << myBlockShift;
0837 }
0838
0839
0840 void ensureStorageForIndex(const size_t theIndex)
0841 {
0842 const size_t aRequiredBlocks = (theIndex >> myBlockShift) + 1;
0843 ensureBlockCount(aRequiredBlocks);
0844 }
0845
0846
0847 void ensureBlockCount(const size_t theBlockCount)
0848 {
0849 if (theBlockCount > myContainer.Capacity())
0850 {
0851 myContainer.Reserve(theBlockCount);
0852 }
0853 while (myContainer.Size() < theBlockCount)
0854 {
0855 expandArray();
0856 }
0857 }
0858
0859 TheItemType* expandArray()
0860 {
0861 TheItemType* aNewBlock = myAlloc.allocate(myInternalSize);
0862 myContainer.Append(aNewBlock);
0863 return aNewBlock;
0864 }
0865
0866 reference at(const size_t theInd) noexcept
0867 {
0868 return getArray()[theInd >> myBlockShift][theInd & myBlockMask];
0869 }
0870
0871 const_reference at(const size_t theInd) const noexcept
0872 {
0873 return getArray()[theInd >> myBlockShift][theInd & myBlockMask];
0874 }
0875
0876 void copyDate()
0877 {
0878 size_t aUsedSize = 0;
0879 for (size_t aBlockInd = 0; aBlockInd < myContainer.Size(); aBlockInd++)
0880 {
0881 TheItemType* aCurStart = getArray()[aBlockInd];
0882 TheItemType* aNewBlock = myAlloc.allocate(myInternalSize);
0883 if constexpr (std::is_trivially_copyable_v<TheItemType>)
0884 {
0885 const size_t aCount =
0886 (myUsedSize - aUsedSize < myInternalSize) ? myUsedSize - aUsedSize : myInternalSize;
0887 std::memcpy(aNewBlock, aCurStart, aCount * sizeof(TheItemType));
0888 aUsedSize += aCount;
0889 }
0890 else
0891 {
0892 for (size_t anElemInd = 0; anElemInd < myInternalSize && aUsedSize < myUsedSize;
0893 anElemInd++, aUsedSize++)
0894 {
0895 pointer aPnt = &aNewBlock[anElemInd];
0896 myAlloc.construct(aPnt, aCurStart[anElemInd]);
0897 }
0898 }
0899 getArray()[aBlockInd] = aNewBlock;
0900 }
0901 }
0902
0903
0904 TheItemType** getArray() noexcept { return myContainer.IsEmpty() ? nullptr : &myContainer[0]; }
0905
0906
0907 TheItemType* const* getArray() const noexcept
0908 {
0909 return myContainer.IsEmpty() ? nullptr : &myContainer[0];
0910 }
0911
0912
0913
0914 static constexpr size_t roundUpPow2(const size_t theValue) noexcept
0915 {
0916 size_t v = (theValue < 1 ? 1 : theValue);
0917 v--;
0918 v |= v >> 1;
0919 v |= v >> 2;
0920 v |= v >> 4;
0921 v |= v >> 8;
0922 v |= v >> 16;
0923 if constexpr (sizeof(size_t) > 4)
0924 {
0925 v |= v >> 32;
0926 }
0927 v++;
0928 return v;
0929 }
0930
0931
0932 static constexpr size_t log2Pow2(const size_t theValue) noexcept
0933 {
0934 size_t aShift = 0;
0935 size_t v = theValue;
0936 while (v > 1)
0937 {
0938 v >>= 1;
0939 ++aShift;
0940 }
0941 return aShift;
0942 }
0943
0944 protected:
0945 vector myContainer;
0946 allocator_type myAlloc;
0947 size_t myInternalSize;
0948 size_t myBlockShift;
0949 size_t myBlockMask;
0950 size_t myUsedSize;
0951 };
0952
0953 #endif