Back to home page

EIC code displayed by LXR

 
 

    


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

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