Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-17 08:35:47

0001 // Copyright (c) 2021 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_AliasedArray_HeaderFile
0015 #define _NCollection_AliasedArray_HeaderFile
0016 
0017 #include <Standard_DimensionMismatch.hxx>
0018 #include <Standard_OutOfMemory.hxx>
0019 #include <Standard_OutOfRange.hxx>
0020 #include <Standard_TypeMismatch.hxx>
0021 #include <Standard_Macro.hxx>
0022 
0023 //! Defines an array of values of configurable size.
0024 //! For instance, this class allows defining an array of 32-bit or 64-bit integer values with
0025 //! bitness determined in runtime. The element size in bytes (stride) should be specified at
0026 //! construction time. Indexation starts from 0 index. As actual type of element varies at runtime,
0027 //! element accessors are defined as templates. Memory for array is allocated with the given
0028 //! alignment (template parameter).
0029 template <int MyAlignSize = 16>
0030 class NCollection_AliasedArray
0031 {
0032 public:
0033   DEFINE_STANDARD_ALLOC
0034 public:
0035   //! Empty constructor.
0036   NCollection_AliasedArray(Standard_Integer theStride)
0037       : myData(NULL),
0038         myStride(theStride),
0039         mySize(0),
0040         myDeletable(false)
0041   {
0042     if (theStride <= 0)
0043     {
0044       throw Standard_RangeError("NCollection_AliasedArray, stride should be positive");
0045     }
0046   }
0047 
0048   //! Constructor
0049   NCollection_AliasedArray(Standard_Integer theStride, Standard_Integer theLength)
0050       : myData(NULL),
0051         myStride(theStride),
0052         mySize(theLength),
0053         myDeletable(true)
0054   {
0055     if (theLength <= 0 || myStride <= 0)
0056     {
0057       throw Standard_RangeError("NCollection_AliasedArray, stride and length should be positive");
0058     }
0059     myData = (Standard_Byte*)Standard::AllocateAligned(SizeBytes(), MyAlignSize);
0060     if (myData == NULL)
0061     {
0062       throw Standard_OutOfMemory("NCollection_AliasedArray, allocation failed");
0063     }
0064   }
0065 
0066   //! Copy constructor
0067   NCollection_AliasedArray(const NCollection_AliasedArray& theOther)
0068       : myData(NULL),
0069         myStride(theOther.myStride),
0070         mySize(theOther.mySize),
0071         myDeletable(false)
0072   {
0073     if (mySize != 0)
0074     {
0075       myDeletable = true;
0076       myData      = (Standard_Byte*)Standard::AllocateAligned(SizeBytes(), MyAlignSize);
0077       if (myData == NULL)
0078       {
0079         throw Standard_OutOfMemory("NCollection_AliasedArray, allocation failed");
0080       }
0081       Assign(theOther);
0082     }
0083   }
0084 
0085   //! Move constructor
0086   NCollection_AliasedArray(NCollection_AliasedArray&& theOther) Standard_Noexcept
0087       : myData(theOther.myData),
0088         myStride(theOther.myStride),
0089         mySize(theOther.mySize),
0090         myDeletable(theOther.myDeletable)
0091   {
0092     theOther.myDeletable = false;
0093   }
0094 
0095   //! Constructor wrapping pre-allocated C-array of values without copying them.
0096   template <typename Type_t>
0097   NCollection_AliasedArray(const Type_t& theBegin, Standard_Integer theLength)
0098       : myData((Standard_Byte*)&theBegin),
0099         myStride((int)sizeof(Type_t)),
0100         mySize(theLength),
0101         myDeletable(false)
0102   {
0103     if (theLength <= 0)
0104     {
0105       throw Standard_RangeError("NCollection_AliasedArray, length should be positive");
0106     }
0107   }
0108 
0109   //! Returns an element size in bytes.
0110   Standard_Integer Stride() const { return myStride; }
0111 
0112   //! Size query
0113   Standard_Integer Size() const { return mySize; }
0114 
0115   //! Length query (the same as Size())
0116   Standard_Integer Length() const { return mySize; }
0117 
0118   //! Return TRUE if array has zero length.
0119   Standard_Boolean IsEmpty() const { return mySize == 0; }
0120 
0121   //! Lower bound
0122   Standard_Integer Lower() const { return 0; }
0123 
0124   //! Upper bound
0125   Standard_Integer Upper() const { return mySize - 1; }
0126 
0127   //! myDeletable flag
0128   Standard_Boolean IsDeletable() const { return myDeletable; }
0129 
0130   //! IsAllocated flag - for naming compatibility
0131   Standard_Boolean IsAllocated() const { return myDeletable; }
0132 
0133   //! Return buffer size in bytes.
0134   Standard_Size SizeBytes() const { return size_t(myStride) * size_t(mySize); }
0135 
0136   //! Copies data of theOther array to this.
0137   //! This array should be pre-allocated and have the same length as theOther;
0138   //! otherwise exception Standard_DimensionMismatch is thrown.
0139   NCollection_AliasedArray& Assign(const NCollection_AliasedArray& theOther)
0140   {
0141     if (&theOther != this)
0142     {
0143       if (myStride != theOther.myStride || mySize != theOther.mySize)
0144       {
0145         throw Standard_DimensionMismatch(
0146           "NCollection_AliasedArray::Assign(), arrays have different size");
0147       }
0148       if (myData != NULL)
0149       {
0150         memcpy(myData, theOther.myData, SizeBytes());
0151       }
0152     }
0153     return *this;
0154   }
0155 
0156   //! Move assignment.
0157   //! This array will borrow all the data from theOther.
0158   //! The moved object will keep pointer to the memory buffer and
0159   //! range, but it will not free the buffer on destruction.
0160   NCollection_AliasedArray& Move(NCollection_AliasedArray& theOther)
0161   {
0162     if (&theOther != this)
0163     {
0164       if (myDeletable)
0165       {
0166         Standard::FreeAligned(myData);
0167       }
0168       myStride             = theOther.myStride;
0169       mySize               = theOther.mySize;
0170       myDeletable          = theOther.myDeletable;
0171       myData               = theOther.myData;
0172       theOther.myDeletable = false;
0173     }
0174     return *this;
0175   }
0176 
0177   //! Assignment operator; @sa Assign()
0178   NCollection_AliasedArray& operator=(const NCollection_AliasedArray& theOther)
0179   {
0180     return Assign(theOther);
0181   }
0182 
0183   //! Move assignment operator; @sa Move()
0184   NCollection_AliasedArray& operator=(NCollection_AliasedArray&& theOther)
0185   {
0186     return Move(theOther);
0187   }
0188 
0189   //! Resizes the array to specified bounds.
0190   //! No re-allocation will be done if length of array does not change,
0191   //! but existing values will not be discarded if theToCopyData set to FALSE.
0192   //! @param theLength new length of array
0193   //! @param theToCopyData flag to copy existing data into new array
0194   void Resize(Standard_Integer theLength, Standard_Boolean theToCopyData)
0195   {
0196     if (theLength <= 0)
0197     {
0198       throw Standard_RangeError("NCollection_AliasedArray::Resize, length should be positive");
0199     }
0200     if (mySize == theLength)
0201     {
0202       return;
0203     }
0204 
0205     const Standard_Integer anOldLen  = mySize;
0206     const Standard_Byte*   anOldData = myData;
0207     mySize                           = theLength;
0208     if (!theToCopyData && myDeletable)
0209     {
0210       Standard::FreeAligned(myData);
0211     }
0212     myData = (Standard_Byte*)Standard::AllocateAligned(SizeBytes(), MyAlignSize);
0213     if (myData == NULL)
0214     {
0215       throw Standard_OutOfMemory("NCollection_AliasedArray, allocation failed");
0216     }
0217     if (!theToCopyData)
0218     {
0219       myDeletable = true;
0220       return;
0221     }
0222 
0223     const size_t aLenCopy = size_t(Min(anOldLen, theLength)) * size_t(myStride);
0224     memcpy(myData, anOldData, aLenCopy);
0225     if (myDeletable)
0226     {
0227       Standard::FreeAligned(anOldData);
0228     }
0229     myDeletable = true;
0230   }
0231 
0232   //! Destructor - releases the memory
0233   ~NCollection_AliasedArray()
0234   {
0235     if (myDeletable)
0236     {
0237       Standard::FreeAligned(myData);
0238     }
0239   }
0240 
0241 public:
0242   //! Access raw bytes of specified element.
0243   const Standard_Byte* value(Standard_Integer theIndex) const
0244   {
0245     Standard_OutOfRange_Raise_if(theIndex < 0 || theIndex >= mySize,
0246                                  "NCollection_AliasedArray::value(), out of range index");
0247     return myData + size_t(myStride) * size_t(theIndex);
0248   }
0249 
0250   //! Access raw bytes of specified element.
0251   Standard_Byte* changeValue(Standard_Integer theIndex)
0252   {
0253     Standard_OutOfRange_Raise_if(theIndex < 0 || theIndex >= mySize,
0254                                  "NCollection_AliasedArray::changeValue(), out of range index");
0255     return myData + size_t(myStride) * size_t(theIndex);
0256   }
0257 
0258   //! Initialize the items with theValue
0259   template <typename Type_t>
0260   void Init(const Type_t& theValue)
0261   {
0262     for (Standard_Integer anIter = 0; anIter < mySize; ++anIter)
0263     {
0264       ChangeValue<Type_t>(anIter) = theValue;
0265     }
0266   }
0267 
0268   //! Access element with specified position and type.
0269   //! This method requires size of a type matching stride value.
0270   template <typename Type_t>
0271   const Type_t& Value(Standard_Integer theIndex) const
0272   {
0273     Standard_TypeMismatch_Raise_if(size_t(myStride) != sizeof(Type_t),
0274                                    "NCollection_AliasedArray::Value(), wrong type");
0275     return *reinterpret_cast<const Type_t*>(value(theIndex));
0276   }
0277 
0278   //! Access element with specified position and type.
0279   //! This method requires size of a type matching stride value.
0280   template <typename Type_t>
0281   void Value(Standard_Integer theIndex, Type_t& theValue) const
0282   {
0283     Standard_TypeMismatch_Raise_if(size_t(myStride) != sizeof(Type_t),
0284                                    "NCollection_AliasedArray::Value(), wrong type");
0285     theValue = *reinterpret_cast<const Type_t*>(value(theIndex));
0286   }
0287 
0288   //! Access element with specified position and type.
0289   //! This method requires size of a type matching stride value.
0290   template <typename Type_t>
0291   Type_t& ChangeValue(Standard_Integer theIndex)
0292   {
0293     Standard_TypeMismatch_Raise_if(size_t(myStride) != sizeof(Type_t),
0294                                    "NCollection_AliasedArray::ChangeValue(), wrong type");
0295     return *reinterpret_cast<Type_t*>(changeValue(theIndex));
0296   }
0297 
0298   //! Access element with specified position and type.
0299   //! This method allows wrapping element into smaller type (e.g. to alias 2-components within
0300   //! 3-component vector).
0301   template <typename Type_t>
0302   const Type_t& Value2(Standard_Integer theIndex) const
0303   {
0304     Standard_TypeMismatch_Raise_if(size_t(myStride) < sizeof(Type_t),
0305                                    "NCollection_AliasedArray::Value2(), wrong type");
0306     return *reinterpret_cast<const Type_t*>(value(theIndex));
0307   }
0308 
0309   //! Access element with specified position and type.
0310   //! This method allows wrapping element into smaller type (e.g. to alias 2-components within
0311   //! 3-component vector).
0312   template <typename Type_t>
0313   void Value2(Standard_Integer theIndex, Type_t& theValue) const
0314   {
0315     Standard_TypeMismatch_Raise_if(size_t(myStride) < sizeof(Type_t),
0316                                    "NCollection_AliasedArray::Value2(), wrong type");
0317     theValue = *reinterpret_cast<const Type_t*>(value(theIndex));
0318   }
0319 
0320   //! Access element with specified position and type.
0321   //! This method allows wrapping element into smaller type (e.g. to alias 2-components within
0322   //! 3-component vector).
0323   template <typename Type_t>
0324   Type_t& ChangeValue2(Standard_Integer theIndex)
0325   {
0326     Standard_TypeMismatch_Raise_if(size_t(myStride) < sizeof(Type_t),
0327                                    "NCollection_AliasedArray::ChangeValue2(), wrong type");
0328     return *reinterpret_cast<Type_t*>(changeValue(theIndex));
0329   }
0330 
0331   //! Return first element
0332   template <typename Type_t>
0333   const Type_t& First() const
0334   {
0335     return Value<Type_t>(0);
0336   }
0337 
0338   //! Return first element
0339   template <typename Type_t>
0340   Type_t& ChangeFirst()
0341   {
0342     return ChangeValue<Type_t>(0);
0343   }
0344 
0345   //! Return last element
0346   template <typename Type_t>
0347   const Type_t& Last() const
0348   {
0349     return Value<Type_t>(mySize - 1);
0350   }
0351 
0352   //! Return last element
0353   template <typename Type_t>
0354   Type_t& ChangeLast()
0355   {
0356     return Value<Type_t>(mySize - 1);
0357   }
0358 
0359 protected:
0360   Standard_Byte*   myData;      //!< data pointer
0361   Standard_Integer myStride;    //!< element size
0362   Standard_Integer mySize;      //!< number of elements
0363   Standard_Boolean myDeletable; //!< flag showing who allocated the array
0364 };
0365 
0366 #endif // _NCollection_AliasedArray_HeaderFile