File indexing completed on 2025-01-18 10:04:18
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_BasePointerVector.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_BasePointerVector.hxx>
0025 #include <NCollection_DefineAlloc.hxx>
0026 #include <NCollection_Allocator.hxx>
0027 #include <NCollection_Iterator.hxx>
0028 #include <NCollection_OccAllocator.hxx>
0029 #include <StdFail_NotDone.hxx>
0030 #include <NCollection_IndexedIterator.hxx>
0031
0032 #include <locale>
0033 #include <vector>
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 template <class TheItemType>
0056 class NCollection_DynamicArray
0057 {
0058 public:
0059
0060 DEFINE_STANDARD_ALLOC;
0061 DEFINE_NCOLLECTION_ALLOC;
0062 public:
0063 typedef NCollection_OccAllocator<TheItemType> allocator_type;
0064 typedef NCollection_BasePointerVector vector;
0065 public:
0066
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 = TheItemType&;
0073 using reference = TheItemType&;
0074 using const_reference = const TheItemType&;
0075
0076 public:
0077
0078 using iterator = NCollection_IndexedIterator<std::random_access_iterator_tag, NCollection_DynamicArray, value_type, false>;
0079 using const_iterator = NCollection_IndexedIterator<std::random_access_iterator_tag, NCollection_DynamicArray, value_type, true>;
0080 using Iterator = NCollection_Iterator<NCollection_DynamicArray<TheItemType>>;
0081
0082 public:
0083
0084 const_iterator begin() const
0085 {
0086 return const_iterator(*this);
0087 }
0088
0089 iterator begin()
0090 {
0091 return iterator(*this);
0092 }
0093
0094 const_iterator cbegin() const
0095 {
0096 return const_iterator(*this);
0097 }
0098
0099 iterator end()
0100 {
0101 return iterator(myUsedSize, *this);
0102 }
0103
0104 const_iterator end() const
0105 {
0106 return const_iterator(myUsedSize, *this);
0107 }
0108
0109 const_iterator cend() const
0110 {
0111 return const_iterator(myUsedSize, *this);
0112 }
0113
0114 public:
0115
0116 NCollection_DynamicArray(const Standard_Integer theIncrement = 256) :
0117 myContainer(),
0118 myAlloc(),
0119 myInternalSize(theIncrement),
0120 myUsedSize(0)
0121 {}
0122
0123
0124 explicit NCollection_DynamicArray(const Standard_Integer theIncrement,
0125 const Handle(NCollection_BaseAllocator)& theAllocator) :
0126 myContainer(),
0127 myAlloc(allocator_type(theAllocator)),
0128 myInternalSize(theIncrement),
0129 myUsedSize(0)
0130 {}
0131
0132
0133 explicit NCollection_DynamicArray(const Standard_Integer theIncrement,
0134 const allocator_type& theAllocator) :
0135 myContainer(),
0136 myAlloc(theAllocator),
0137 myInternalSize(theIncrement),
0138 myUsedSize(0)
0139 {}
0140
0141
0142 NCollection_DynamicArray(const NCollection_DynamicArray& theOther) :
0143 myContainer(theOther.myContainer),
0144 myAlloc(theOther.myAlloc),
0145 myInternalSize(theOther.myInternalSize),
0146 myUsedSize(theOther.myUsedSize)
0147 {
0148 copyDate();
0149 }
0150
0151 NCollection_DynamicArray(NCollection_DynamicArray&& theOther) noexcept :
0152 myContainer(std::move(theOther.myContainer)),
0153 myAlloc(theOther.myAlloc),
0154 myInternalSize(theOther.myInternalSize),
0155 myUsedSize(theOther.myUsedSize)
0156 {
0157 theOther.myUsedSize = 0;
0158 }
0159
0160 ~NCollection_DynamicArray()
0161 {
0162 Clear(true);
0163 }
0164
0165
0166 Standard_Integer Length() const
0167 {
0168 return static_cast<int>(myUsedSize);
0169 }
0170
0171
0172 Standard_Integer Size() const
0173 {
0174 return Length();
0175 }
0176
0177
0178
0179 Standard_Integer Lower() const
0180 {
0181 return 0;
0182 }
0183
0184
0185
0186 Standard_Integer Upper() const
0187 {
0188 return Length() - 1;
0189 }
0190
0191
0192 Standard_Boolean IsEmpty() const
0193 {
0194 return myUsedSize == 0;
0195 }
0196
0197
0198 NCollection_DynamicArray& Assign(const NCollection_DynamicArray& theOther,
0199 const bool theOwnAllocator = true)
0200 {
0201 if (&theOther == this)
0202 {
0203 return *this;
0204 }
0205 if (!theOwnAllocator)
0206 {
0207 Clear(myAlloc != theOther.myAlloc);
0208 myAlloc = theOther.myAlloc;
0209 }
0210 else
0211 {
0212 Clear(false);
0213 }
0214 myContainer = theOther.myContainer;
0215 myInternalSize = theOther.myInternalSize;
0216 myUsedSize = theOther.myUsedSize;
0217 copyDate();
0218 return *this;
0219 }
0220
0221 NCollection_DynamicArray& Assign(NCollection_DynamicArray&& theOther)
0222 {
0223 if (&theOther == this)
0224 {
0225 return *this;
0226 }
0227 Clear(true);
0228 myContainer = std::move(theOther.myContainer);
0229 myAlloc = theOther.myAlloc;
0230 myInternalSize = theOther.myInternalSize;
0231 myUsedSize = theOther.myUsedSize;
0232 theOther.myUsedSize = 0;
0233 return *this;
0234 }
0235
0236
0237 NCollection_DynamicArray& operator= (const NCollection_DynamicArray& theOther)
0238 {
0239 return Assign(theOther, false);
0240 }
0241
0242
0243 NCollection_DynamicArray& operator= (NCollection_DynamicArray&& theOther)
0244 {
0245 return Assign(std::forward<NCollection_DynamicArray>(theOther));
0246 }
0247
0248
0249 reference Append(const TheItemType& theValue)
0250 {
0251 if (myUsedSize >= availableSize())
0252 {
0253 expandArray();
0254 }
0255 pointer aPnt = &at(myUsedSize++);
0256 myAlloc.construct(aPnt, theValue);
0257 return *aPnt;
0258 }
0259
0260
0261 reference Append(TheItemType&& theValue)
0262 {
0263 if (myUsedSize >= availableSize())
0264 {
0265 expandArray();
0266 }
0267 pointer aPnt = &at(myUsedSize++);
0268 myAlloc.construct(aPnt, std::forward<TheItemType>(theValue));
0269 return *aPnt;
0270 }
0271
0272 void EraseLast()
0273 {
0274 if (myUsedSize == 0)
0275 {
0276 return;
0277 }
0278 TheItemType* aLastElem = &ChangeLast();
0279 myAlloc.destroy(aLastElem);
0280 myUsedSize--;
0281 }
0282
0283
0284 reference Appended()
0285 {
0286 if (myUsedSize >= availableSize())
0287 {
0288 expandArray();
0289 }
0290 pointer aPnt = &at(myUsedSize++);
0291 myAlloc.construct(aPnt);
0292 return *aPnt;
0293 }
0294
0295
0296 const_reference operator() (const Standard_Integer theIndex) const
0297 {
0298 return Value(theIndex);
0299 }
0300
0301
0302 const_reference operator[] (const Standard_Integer theIndex) const
0303 {
0304 return Value(theIndex);
0305 }
0306
0307
0308 const_reference operator[] (const size_t theIndex) const
0309 {
0310 return at(theIndex);
0311 }
0312
0313 const_reference Value(const Standard_Integer theIndex) const
0314 {
0315 return at(static_cast<int>(theIndex));
0316 }
0317
0318
0319 const_reference First() const
0320 {
0321 return getArray()[0][0];
0322 }
0323
0324
0325 reference ChangeFirst()
0326 {
0327 return getArray()[0][0];
0328 }
0329
0330
0331 const_reference Last() const
0332 {
0333 return at(myUsedSize - 1);
0334 }
0335
0336
0337 reference ChangeLast()
0338 {
0339 return at(myUsedSize - 1);
0340 }
0341
0342
0343 reference operator() (const Standard_Integer theIndex)
0344 {
0345 return ChangeValue(theIndex);
0346 }
0347
0348
0349 reference operator[] (const Standard_Integer theIndex)
0350 {
0351 return ChangeValue(theIndex);
0352 }
0353
0354
0355 reference operator[] (const size_t theIndex)
0356 {
0357 return at(theIndex);
0358 }
0359
0360 reference ChangeValue(const Standard_Integer theIndex)
0361 {
0362 return at(static_cast<int>(theIndex));
0363 }
0364
0365
0366 reference SetValue(const Standard_Integer theIndex,
0367 const TheItemType& theValue)
0368 {
0369 const size_t aBlockInd = static_cast<size_t>(theIndex / myInternalSize);
0370 const size_t anIndex = static_cast<size_t>(theIndex);
0371 for (size_t aInd = myContainer.Size(); aInd <= aBlockInd; aInd++)
0372 {
0373 expandArray();
0374 }
0375 if (myUsedSize <= anIndex)
0376 {
0377 for (; myUsedSize < anIndex; myUsedSize++)
0378 {
0379 pointer aPnt = &at(myUsedSize);
0380 myAlloc.construct(aPnt);
0381 }
0382 myUsedSize++;
0383 }
0384 pointer aPnt = &at(anIndex);
0385 myAlloc.construct(aPnt, theValue);
0386 return *aPnt;
0387 }
0388
0389
0390 reference SetValue(const Standard_Integer theIndex,
0391 TheItemType&& theValue)
0392 {
0393 const size_t aBlockInd = static_cast<size_t>(theIndex / myInternalSize);
0394 const size_t anIndex = static_cast<size_t>(theIndex);
0395 for (size_t aInd = myContainer.Size(); aInd <= aBlockInd; aInd++)
0396 {
0397 expandArray();
0398 }
0399 if (myUsedSize <= anIndex)
0400 {
0401 for (; myUsedSize < anIndex; myUsedSize++)
0402 {
0403 pointer aPnt = &at(myUsedSize);
0404 myAlloc.construct(aPnt);
0405 }
0406 myUsedSize++;
0407 }
0408 pointer aPnt = &at(anIndex);
0409 myAlloc.construct(aPnt, std::forward<TheItemType>(theValue));
0410 return *aPnt;
0411 }
0412
0413 void Clear(const bool theReleaseMemory = false)
0414 {
0415 size_t aUsedSize = 0;
0416 for (size_t aBlockInd = 0; aBlockInd < myContainer.Size(); aBlockInd++)
0417 {
0418 TheItemType* aCurStart = getArray()[aBlockInd];
0419 for (size_t anElemInd = 0; anElemInd < myInternalSize && aUsedSize < myUsedSize; anElemInd++, aUsedSize++)
0420 {
0421 aCurStart[anElemInd].~TheItemType();
0422 }
0423 if (theReleaseMemory)
0424 myAlloc.deallocate(aCurStart, myInternalSize);
0425 }
0426 if (theReleaseMemory)
0427 myContainer.Clear(theReleaseMemory);
0428 myUsedSize = 0;
0429 }
0430
0431 void SetIncrement(const Standard_Integer theIncrement)
0432 {
0433 if (myUsedSize != 0)
0434 {
0435 return;
0436 }
0437 myInternalSize = static_cast<size_t>(theIncrement);
0438 }
0439
0440 friend iterator;
0441 friend const_iterator;
0442
0443 protected:
0444
0445 size_t availableSize() const
0446 {
0447 return myContainer.Size() * myInternalSize;
0448 }
0449
0450 TheItemType* expandArray()
0451 {
0452 TheItemType* aNewBlock = myAlloc.allocate(myInternalSize);
0453 myContainer.Append(aNewBlock);
0454 return aNewBlock;
0455 }
0456
0457 reference at(const size_t theInd)
0458 {
0459 return getArray()[theInd / myInternalSize][theInd % myInternalSize];
0460 }
0461
0462 const_reference at(const size_t theInd) const
0463 {
0464 return getArray()[theInd / myInternalSize][theInd % myInternalSize];
0465 }
0466
0467 void copyDate()
0468 {
0469 size_t aUsedSize = 0;
0470 for (size_t aBlockInd = 0; aBlockInd < myContainer.Size(); aBlockInd++)
0471 {
0472 TheItemType* aCurStart = getArray()[aBlockInd];
0473 TheItemType* aNewBlock = myAlloc.allocate(myInternalSize);
0474 for (size_t anElemInd = 0; anElemInd < myInternalSize && aUsedSize < myUsedSize; anElemInd++, aUsedSize++)
0475 {
0476 pointer aPnt = &aNewBlock[anElemInd];
0477 myAlloc.construct(aPnt, aCurStart[anElemInd]);
0478 }
0479 getArray()[aBlockInd] = aNewBlock;
0480 }
0481 }
0482
0483
0484 TheItemType** getArray() const { return (TheItemType**) myContainer.GetArray(); }
0485
0486 protected:
0487
0488 vector myContainer;
0489 allocator_type myAlloc;
0490 size_t myInternalSize;
0491 size_t myUsedSize;
0492 };
0493
0494 #endif