Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:04:18

0001 // Copyright (c) 2002-2023 OPEN CASCADE SAS
0002 //
0003 // This file is part of Open CASCADE Technology software library.
0004 //
0005 // This library is free software; you can redistribute it and/or modify it under
0006 // the terms of the GNU Lesser General Public License version 2.1 as published
0007 // by the Free Software Foundation, with special exception defined in the file
0008 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0009 // distribution for complete text of the license and disclaimer of any warranty.
0010 //
0011 // Alternatively, this file may be used under the terms of Open CASCADE
0012 // commercial license or contractual agreement.
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 //! Class NCollection_DynamicArray (dynamic array of objects)
0036 //!
0037 //! The array's indices always start at 0.
0038 //!
0039 //! The Vector is always created with 0 length. It can be enlarged by two means:
0040 //!  1. Calling the method Append (val) - then "val" is added to the end of the
0041 //!     vector (the vector length is incremented)
0042 //!  2. Calling the method SetValue (i, val)  - if "i" is greater than or equal
0043 //!     to the current length of the vector,  the vector is enlarged to accomo-
0044 //!     date this index
0045 //!
0046 //! The methods Append and SetValue return  a non-const reference  to the copied
0047 //! object  inside  the vector.  This reference  is guaranteed to be valid until
0048 //! the vector is destroyed. It can be used to access the vector member directly
0049 //! or to pass its address to other data structures.
0050 //!
0051 //! The vector iterator remembers the length of the vector  at the moment of the
0052 //! creation or initialisation of the iterator.   Therefore the iteration begins
0053 //! at index 0  and stops at the index equal to (remembered_length-1).  It is OK
0054 //! to enlarge the vector during the iteration.
0055 template <class TheItemType>
0056 class NCollection_DynamicArray
0057 {
0058 public:
0059   //! Memory allocation
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   // Define various type aliases for convenience
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: //! @name public methods
0115 
0116   NCollection_DynamicArray(const Standard_Integer theIncrement = 256) :
0117     myContainer(),
0118     myAlloc(),
0119     myInternalSize(theIncrement),
0120     myUsedSize(0)
0121   {}
0122 
0123   // Constructor taking an allocator
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   // Constructor taking an allocator
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   //! Copy constructor
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   //! Total number of items
0166   Standard_Integer Length() const
0167   {
0168     return static_cast<int>(myUsedSize);
0169   }
0170 
0171   //! Total number of items in the vector
0172   Standard_Integer Size() const
0173   {
0174     return Length();
0175   }
0176 
0177   //! Method for consistency with other collections.
0178   //! @return Lower bound (inclusive) for iteration.
0179   Standard_Integer Lower() const
0180   {
0181     return 0;
0182   }
0183 
0184   //! Method for consistency with other collections.
0185   //! @return Upper bound (inclusive) for iteration.
0186   Standard_Integer Upper() const
0187   {
0188     return Length() - 1;
0189   }
0190 
0191   //! Empty query
0192   Standard_Boolean IsEmpty() const
0193   {
0194     return myUsedSize == 0;
0195   }
0196 
0197   //! Assignment to the collection of the same type
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   //! Assignment operator
0237   NCollection_DynamicArray& operator= (const NCollection_DynamicArray& theOther)
0238   {
0239     return Assign(theOther, false);
0240   }
0241 
0242   //! Assignment operator
0243   NCollection_DynamicArray& operator= (NCollection_DynamicArray&& theOther)
0244   {
0245     return Assign(std::forward<NCollection_DynamicArray>(theOther));
0246   }
0247 
0248   //! Append
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   //! Append
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   //! Appends an empty value and returns the reference to it
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   //! Operator() - query the const value
0296   const_reference operator() (const Standard_Integer theIndex) const
0297   {
0298     return Value(theIndex);
0299   }
0300 
0301   //! Operator[] - query the const value
0302   const_reference operator[] (const Standard_Integer theIndex) const
0303   {
0304     return Value(theIndex);
0305   }
0306 
0307   //! Operator[] - query the const value
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   //! @return first element
0319   const_reference First() const
0320   {
0321     return getArray()[0][0];
0322   }
0323 
0324   //! @return first element
0325   reference ChangeFirst()
0326   {
0327     return getArray()[0][0];
0328   }
0329 
0330   //! @return last element
0331   const_reference Last() const
0332   {
0333     return at(myUsedSize - 1);
0334   }
0335 
0336   //! @return last element
0337   reference ChangeLast()
0338   {
0339     return at(myUsedSize - 1);
0340   }
0341 
0342   //! Operator() - query the value
0343   reference operator() (const Standard_Integer theIndex)
0344   {
0345     return ChangeValue(theIndex);
0346   }
0347 
0348   //! Operator[] - query the value
0349   reference operator[] (const Standard_Integer theIndex)
0350   {
0351     return ChangeValue(theIndex);
0352   }
0353 
0354   //! Operator[] - query the value
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   //! SetValue () - set or append a value
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   //! SetValue () - set or append a value
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   //! Wrapper to extract array
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 // NCollection_DynamicArray_HeaderFile