1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-16 10:08:36 +03:00
occt/src/NCollection/NCollection_Array2.hxx
dpasukhi 1103eb60af 0033370: Foundation Classes - Moving into STL and Boost functionality
NCollection containers update:
  - NCollection_Array1 - updated functionality
  - NCollection_Array2 - NCollection_Array1 as a wrapper for 2array
  - NCollection_Vector -> NCollection_DynamicArray was renamed and reworked.
TCollection:
  - Use static empty string to avoid allocations on empty string
 NCollection allocators update:
  - NCollection_Allocator - allocator that used Standard::Allocate
  - NCollection_OccAllocator - allocator-wrapper that used OCC BaseAllocator objects
  - NCollection_IncAllocator - rework to increase performance
Standard:
  - Rework functionality to use different allocation libs
  - Implement basic of new way to wrap allocations tools
  - Define 4 ways to allocation (defines in configure stage)
 Additional changes:
  - Hash function uses std::hash functionality
   - size_t as a hash value
  - New HashUtils with Murmur and FVN hash algo for x32 and x64
  - Deprecated _0.cxx and .gxx DE classes reorganized
  - Create own utility for std memory
  - Update Standard_Transient to be more platform-independent
 Math TK changes:
  - math_Vector -> match_BaseVector<>
    - Buffer decreased to cash 32 elements instead of 512
2023-12-04 13:37:09 +00:00

373 lines
13 KiB
C++

// Created on: 2002-04-15
// Created by: Alexander Kartomin (akm)
// Copyright (c) 2002-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef NCollection_Array2_HeaderFile
#define NCollection_Array2_HeaderFile
#include <Standard_DimensionMismatch.hxx>
#include <Standard_OutOfMemory.hxx>
#include <NCollection_Allocator.hxx>
#include <Standard_OutOfRange.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_DefineAlloc.hxx>
// *********************************************** Template for Array2 class
/**
* Purpose: The class Array2 represents bi-dimensional arrays
* of fixed size known at run time.
* The ranges of indices are user defined.
*
* Class allocates one 1D array storing full data (all Rows and Columns)
* and extra 1D array storing pointers to each Row.
*
* Warning: Programs clients of such class must be independent
* of the range of the first element. Then, a C++ for
* loop must be written like this
*
* for (i = A.LowerRow(); i <= A.UpperRow(); i++)
* for (j = A.LowerCol(); j <= A.UpperCol(); j++)
*/
template <class TheItemType>
class NCollection_Array2 : public NCollection_Array1<TheItemType>
{
public:
//! Memory allocation
DEFINE_STANDARD_ALLOC;
DEFINE_NCOLLECTION_ALLOC;
public:
typedef NCollection_Allocator<TheItemType> allocator_type;
public:
// Define various type aliases for convenience
using value_type = typename NCollection_Array1<TheItemType>::value_type;
using size_type = typename NCollection_Array1<TheItemType>::size_type;
using difference_type = typename NCollection_Array1<TheItemType>::difference_type;
using pointer = typename NCollection_Array1<TheItemType>::pointer;
using const_pointer = typename NCollection_Array1<TheItemType>::const_pointer;
using reference = typename NCollection_Array1<TheItemType>::reference;
using const_reference = typename NCollection_Array1<TheItemType>::const_reference;
using iterator = typename NCollection_Array1<TheItemType>::iterator;
using const_iterator = typename NCollection_Array1<TheItemType>::const_iterator;
static int BeginPosition(Standard_Integer theRowLower,
Standard_Integer /*theRowUpper*/,
Standard_Integer theColLower,
Standard_Integer theColUpper)
{
// Calculate the offset for the beginning position
return theColLower + (theRowLower * (theColUpper - theColLower + 1));
}
static int LastPosition(Standard_Integer theRowLower,
Standard_Integer theRowUpper,
Standard_Integer theColLower,
Standard_Integer theColUpper)
{
return ((theRowUpper - theRowLower + 1) * (theColUpper - theColLower + 1)) + theColLower + (theRowLower * (theColUpper - theColLower + 1)) - 1;
}
public:
// ---------- PUBLIC METHODS ------------
//! Empty constructor; should be used with caution.
//! @sa methods Resize() and Move().
NCollection_Array2() :
NCollection_Array1<TheItemType>(),
myLowerRow(1),
mySizeRow(0),
myLowerCol(1),
mySizeCol(0)
{}
//! Constructor
NCollection_Array2(const Standard_Integer theRowLower,
const Standard_Integer theRowUpper,
const Standard_Integer theColLower,
const Standard_Integer theColUpper) :
NCollection_Array1<TheItemType>(BeginPosition(theRowLower, theRowUpper, theColLower, theColUpper),
LastPosition(theRowLower, theRowUpper, theColLower, theColUpper)),
myLowerRow(theRowLower),
mySizeRow(theRowUpper - theRowLower + 1),
myLowerCol(theColLower),
mySizeCol(theColUpper - theColLower + 1)
{}
//! Constructor
explicit NCollection_Array2(const allocator_type& theAlloc,
const Standard_Integer theRowLower,
const Standard_Integer theRowUpper,
const Standard_Integer theColLower,
const Standard_Integer theColUpper) :
NCollection_Array1<TheItemType>(theAlloc,
BeginPosition(theRowLower, theRowUpper, theColLower, theColUpper),
LastPosition(theRowLower, theRowUpper, theColLower, theColUpper)),
myLowerRow(theRowLower),
mySizeRow(theRowUpper - theRowLower + 1),
myLowerCol(theColLower),
mySizeCol(theColUpper - theColLower + 1)
{}
//! Copy constructor
NCollection_Array2(const NCollection_Array2& theOther) :
NCollection_Array1<TheItemType>(theOther),
myLowerRow(theOther.LowerRow()),
mySizeRow(theOther.NbRows()),
myLowerCol(theOther.LowerCol()),
mySizeCol(theOther.NbColumns())
{}
//! Move constructor
NCollection_Array2(NCollection_Array2&& theOther) noexcept:
NCollection_Array1<TheItemType>(std::forward<NCollection_Array2>(theOther)),
myLowerRow(theOther.LowerRow()),
mySizeRow(theOther.NbRows()),
myLowerCol(theOther.LowerCol()),
mySizeCol(theOther.NbColumns())
{}
//! C array-based constructor
explicit NCollection_Array2(const TheItemType& theBegin,
const Standard_Integer theRowLower,
const Standard_Integer theRowUpper,
const Standard_Integer theColLower,
const Standard_Integer theColUpper) :
NCollection_Array1<TheItemType>(theBegin,
BeginPosition(theRowLower, theRowUpper, theColLower, theColUpper),
LastPosition(theRowLower, theRowUpper, theColLower, theColUpper)),
myLowerRow(theRowLower),
mySizeRow(theRowUpper - theRowLower + 1),
myLowerCol(theColLower),
mySizeCol(theColUpper - theColLower + 1)
{}
//! Size (number of items)
Standard_Integer Size() const
{
return Length();
}
//! Length (number of items)
Standard_Integer Length() const
{
return NbRows() * NbColumns();
}
//! Returns number of rows
Standard_Integer NbRows() const
{
return static_cast<int>(mySizeRow);
}
//! Returns number of columns
Standard_Integer NbColumns() const
{
return static_cast<int>(mySizeCol);
}
//! Returns length of the row, i.e. number of columns
Standard_Integer RowLength() const
{
return NbColumns();
}
//! Returns length of the column, i.e. number of rows
Standard_Integer ColLength() const
{
return NbRows();
}
//! LowerRow
Standard_Integer LowerRow() const
{
return myLowerRow;
}
//! UpperRow
Standard_Integer UpperRow() const
{
return myLowerRow + static_cast<int>(mySizeRow) - 1;
}
//! LowerCol
Standard_Integer LowerCol() const
{
return myLowerCol;
}
//! UpperCol
Standard_Integer UpperCol() const
{
return myLowerCol + static_cast<int>(mySizeCol) - 1;
}
//! Assignment
NCollection_Array2& Assign(const NCollection_Array2& theOther)
{
if (&theOther == this)
{
return *this;
}
NCollection_Array1<TheItemType>::Assign(theOther);
return *this;
}
//! Move assignment.
//! This array will borrow all the data from theOther.
//! The moved object will be left uninitialized and should not be used anymore.
NCollection_Array2& Move(NCollection_Array2&& theOther)
{
if (&theOther == this)
{
return *this;
}
NCollection_Array1<TheItemType>::Move(theOther);
myLowerRow = theOther.myLowerRow;
mySizeRow = theOther.mySizeRow;
myLowerCol = theOther.myLowerCol;
mySizeCol = theOther.mySizeCol;
return *this;
}
//! Move assignment.
//! This array will borrow all the data from theOther.
//! The moved object will be left uninitialized and should not be used anymore.
NCollection_Array2& Move(NCollection_Array2& theOther)
{
return Move(std::move(theOther));
}
//! Assignment operator
NCollection_Array2& operator= (const NCollection_Array2& theOther)
{
return Assign(theOther);
}
//! Move assignment operator; @sa Move()
NCollection_Array2& operator= (NCollection_Array2&& theOther)
{
return Move(std::forward<NCollection_Array2>(theOther));
}
//! Constant value access
const_reference Value(const Standard_Integer theRow,
const Standard_Integer theCol) const
{
const size_t aPos = (theRow - myLowerRow) * mySizeCol + (theCol - myLowerCol);
return NCollection_Array1<TheItemType>::at(aPos);
}
//! operator() - alias to ChangeValue
const_reference operator() (const Standard_Integer theRow,
const Standard_Integer theCol) const
{
const size_t aPos = (theRow - myLowerRow) * mySizeCol + (theCol - myLowerCol);
return NCollection_Array1<TheItemType>::at(aPos);
}
//! Variable value access
reference ChangeValue(const Standard_Integer theRow,
const Standard_Integer theCol)
{
const size_t aPos = (theRow - myLowerRow) * mySizeCol + (theCol - myLowerCol);
return NCollection_Array1<TheItemType>::at(aPos);
}
//! operator() - alias to ChangeValue
reference operator() (const Standard_Integer theRow,
const Standard_Integer theCol)
{
return ChangeValue(theRow, theCol);
}
//! SetValue
void SetValue(const Standard_Integer theRow,
const Standard_Integer theCol,
const TheItemType& theItem)
{
const size_t aPos = (theRow - myLowerRow) * mySizeCol + (theCol - myLowerCol);
NCollection_Array1<TheItemType>::at(aPos) = theItem;
}
//! SetValue
void SetValue(const Standard_Integer theRow,
const Standard_Integer theCol,
TheItemType&& theItem)
{
const size_t aPos = (theRow - myLowerRow) * mySizeCol + (theCol - myLowerCol);
NCollection_Array1<TheItemType>::at(aPos) = std::forward<TheItemType>(theItem);
}
//! Resizes the array to specified bounds.
//! No re-allocation will be done if length of array does not change,
//! but existing values will not be discarded if theToCopyData set to FALSE.
//! @param theRowLower new lower Row of array
//! @param theRowUpper new upper Row of array
//! @param theColLower new lower Column of array
//! @param theColUpper new upper Column of array
//! @param theToCopyData flag to copy existing data into new array
void Resize(Standard_Integer theRowLower,
Standard_Integer theRowUpper,
Standard_Integer theColLower,
Standard_Integer theColUpper,
Standard_Boolean theToCopyData)
{
Standard_RangeError_Raise_if(theRowUpper < theRowLower ||
theColUpper < theColLower, "NCollection_Array2::Resize");
myLowerRow = theRowLower;
myLowerCol = theColLower;
if (!theToCopyData)
{
NCollection_Array1<TheItemType>::Resize(BeginPosition(theRowLower, theRowUpper, theColLower, theColUpper),
LastPosition(theRowLower, theRowUpper, theColLower, theColUpper),
false);
mySizeRow = theRowUpper - theRowLower + 1;
mySizeCol = theColUpper - theColLower + 1;
return;
}
NCollection_Array1<TheItemType> aTmpMovedCopy(std::move(*this));
TheItemType* anOldPointer = &aTmpMovedCopy.ChangeFirst();
NCollection_Array1<TheItemType>::Resize(BeginPosition(theRowLower, theRowUpper, theColLower, theColUpper),
LastPosition(theRowLower, theRowUpper, theColLower, theColUpper),
false);
const size_t aNewNbRows = theRowUpper - theRowLower + 1;
const size_t aNewNbCols = theColUpper - theColLower + 1;
const size_t aNbRowsToCopy = std::min<size_t>(mySizeRow, aNewNbRows);
const size_t aNbColsToCopy = std::min<size_t>(mySizeCol, aNewNbCols);
mySizeRow = aNewNbRows;
mySizeCol = aNewNbCols;
size_t aOldInter = 0;
for (size_t aRowIter = 0; aRowIter < aNbRowsToCopy; ++aRowIter)
{
for (size_t aColIter = 0; aColIter < aNbColsToCopy; ++aColIter)
{
NCollection_Array1<TheItemType>::at(aRowIter * aNewNbCols + aColIter) = std::move(anOldPointer[aOldInter++]);
}
}
}
protected:
// ---------- PROTECTED FIELDS -----------
Standard_Integer myLowerRow;
size_t mySizeRow;
Standard_Integer myLowerCol;
size_t mySizeCol;
// ----------- FRIEND CLASSES ------------
friend iterator;
friend const_iterator;
};
#endif