Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/opencascade/NCollection_SparseArrayBase.hxx was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Created on: 2007-01-23
0002 // Created by: Andrey BETENEV
0003 // Copyright (c) 2007-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef NCollection_SparseArrayBase_HeaderFile
0017 #define NCollection_SparseArrayBase_HeaderFile
0018 
0019 #include <Standard.hxx>
0020 #include <Standard_TypeDef.hxx>
0021 #include <Standard_OutOfRange.hxx>
0022 
0023 /**
0024  * Base class for NCollection_SparseArray;
0025  * provides non-template implementation of general mechanics
0026  * of block allocation, items creation / deletion etc.
0027  *
0028  * Type-specific item operations (construction, destruction, copy)
0029  * are provided by the derived template class via function pointers
0030  * passed as arguments to the protected methods.
0031  */
0032 
0033 class NCollection_SparseArrayBase
0034 {
0035 public:
0036   //!@name Function pointer types for type-specific item operations
0037   //!@{
0038 
0039   //! Copy-construct a new item at theAddress from theOther
0040   using CreateItemFunc = void (*)(void* theAddress, void* theOther);
0041   //! Destroy the item at theAddress
0042   using DestroyItemFunc = void (*)(void* theAddress);
0043   //! Copy-assign the item at theAddress from theOther
0044   using CopyItemFunc = void (*)(void* theAddress, void* theOther);
0045 
0046   //!@}
0047 
0048 public:
0049   //!@name Type-independent public interface
0050   //!@{
0051 
0052   //! Returns number of currently contained items
0053   size_t Size() const noexcept { return mySize; }
0054 
0055   //! Check whether the value at given index is set
0056   Standard_EXPORT bool HasValue(const size_t theIndex) const;
0057 
0058   //!@}
0059 
0060 private:
0061   /**
0062    * The block of data contains array of items, counter
0063    * and bit field, allocated as single piece of memory addressed
0064    * from the blocks array (myData).
0065    *
0066    * The Block structure provides a logical view on the block,
0067    * and provides methods to work with bit map.
0068    *
0069    * Note that NCollection_SparseArrayBase class takes responsibility
0070    * for correct allocation/deallocation of all the data.
0071    */
0072 
0073   class Block
0074   {
0075   public:
0076     typedef unsigned char Cell; //!< type of items used to hold bits
0077 
0078     //! Number of bits in each cell
0079     static constexpr size_t BitsPerCell() noexcept { return sizeof(Cell) * 8; }
0080 
0081   public:
0082     //! Initializes the block by pointer to block data
0083     Block(void* const theAddr, const size_t theNbItems, const size_t theItemSize)
0084         : Count((size_t*)theAddr),
0085           Array((char*)theAddr + sizeof(size_t)),
0086           Bits((Cell*)((char*)theAddr + sizeof(size_t) + theNbItems * theItemSize))
0087     {
0088     }
0089 
0090     //! Compute required size for block data, in bytes
0091     static constexpr size_t Size(const size_t theNbItems, const size_t theItemSize) noexcept
0092     {
0093       return sizeof(size_t) + sizeof(Cell) * ((theNbItems + BitsPerCell() - 1) / BitsPerCell())
0094              + theNbItems * theItemSize;
0095     }
0096 
0097     //! Returns address of array from address of block
0098     static char* ToArray(void* const theAddress,
0099                          const size_t /*theNbItems*/,
0100                          const size_t /*theItemSize*/) noexcept
0101     {
0102       return (char*)theAddress + sizeof(size_t);
0103     }
0104 
0105   public:
0106     //! Set bit for i-th item; returns non-null if that bit has
0107     //! not been set previously
0108     Cell Set(size_t i) noexcept
0109     {
0110       Cell* abyte = Bits + i / BitsPerCell();
0111       Cell  amask = (Cell)('\1' << (i % BitsPerCell()));
0112       Cell  anold = (Cell)(*abyte & amask);
0113       *abyte      = (Cell)(*abyte | amask);
0114       return !anold;
0115     }
0116 
0117     //! Check bit for i-th item; returns non-null if that bit is set
0118     Cell IsSet(size_t i) noexcept
0119     {
0120       Cell* abyte = Bits + i / BitsPerCell();
0121       Cell  amask = (Cell)('\1' << (i % BitsPerCell()));
0122       return (Cell)(*abyte & amask);
0123     }
0124 
0125     //! Unset bit for i-th item; returns non-null if that bit
0126     //! has been set previously
0127     Cell Unset(size_t i) noexcept
0128     {
0129       Cell* abyte = Bits + i / BitsPerCell();
0130       Cell  amask = (Cell)('\1' << (i % BitsPerCell()));
0131       Cell  anold = (Cell)(*abyte & amask);
0132       *abyte      = (Cell)(*abyte & ~amask);
0133       return anold;
0134     }
0135 
0136   public:
0137     size_t* Count; //!< items counter
0138     void*   Array; //!< pointer to the data items array
0139     Cell*   Bits;  //!< bit map for defined/undefined flags
0140   };
0141 
0142 public:
0143   /**
0144    * Iterator
0145    */
0146 
0147   class Iterator
0148   {
0149   public:
0150     // Public interface
0151 
0152     //! Restart iterations on the same array
0153     void Restart() { init(myArr); }
0154 
0155     //! Returns True if current item is available
0156     bool More() const noexcept { return myHasMore; }
0157 
0158     //! Advances to the next item
0159     Standard_EXPORT void Next();
0160 
0161     //! Returns current index
0162     size_t Index() const noexcept { return myIBlock * myArr->myBlockSize + myInd; }
0163 
0164   protected:
0165     // Methods for descendant
0166 
0167     //! Empty constructor
0168     Standard_EXPORT Iterator(const NCollection_SparseArrayBase* theArray = nullptr);
0169 
0170     //! Initialize by the specified array
0171     Standard_EXPORT void init(const NCollection_SparseArrayBase* theArray);
0172 
0173     //! Returns address of the current item
0174     void* value() const noexcept { return myArr->getItem(myBlock, myInd); }
0175 
0176   private:
0177     const NCollection_SparseArrayBase* myArr;
0178     bool                               myHasMore;
0179     size_t                             myIBlock;
0180     size_t                             myInd;
0181     Block                              myBlock;
0182   };
0183   friend class Iterator;
0184 
0185 private:
0186   // Copy constructor and assignment operator are deleted
0187   NCollection_SparseArrayBase(const NCollection_SparseArrayBase&)            = delete;
0188   NCollection_SparseArrayBase& operator=(const NCollection_SparseArrayBase&) = delete;
0189 
0190 protected:
0191   // Object life
0192 
0193   //! Constructor; initialized by size of item, block size, and item destructor function.
0194   //! @param theDestroyItem is stored to enable proper item destruction in the base destructor
0195   NCollection_SparseArrayBase(size_t          theItemSize,
0196                               size_t          theBlockSize,
0197                               DestroyItemFunc theDestroyItem) noexcept
0198       : myItemSize(theItemSize),
0199         myBlockSize(theBlockSize),
0200         myNbBlocks(0),
0201         mySize(0),
0202         myData(nullptr),
0203         myDestroyItem(theDestroyItem)
0204   {
0205   }
0206 
0207   //! Destructor; properly destroys all items and frees all memory.
0208   //! Uses the stored DestroyItemFunc, so no virtual dispatch is needed.
0209   ~NCollection_SparseArrayBase() { clearItems(myDestroyItem); }
0210 
0211 protected:
0212   // Data access interface for descendants
0213 
0214   //! Creates Block structure for block pointed by theAddr
0215   Block getBlock(void* const theAddr) const noexcept
0216   {
0217     return Block(theAddr, myBlockSize, myItemSize);
0218   }
0219 
0220   //! Find address of the item in the block by index (in the block)
0221   void* getItem(const Block& theBlock, size_t theInd) const noexcept
0222   {
0223     return ((char*)theBlock.Array) + myItemSize * theInd;
0224   }
0225 
0226   //! Direct const access to the item
0227   void* getValue(const size_t theIndex) const
0228   {
0229     Standard_OutOfRange_Raise_if(
0230       !HasValue(theIndex),
0231       "NCollection_SparseArray::Value()") return Block::ToArray(myData[theIndex / myBlockSize],
0232                                                                 myBlockSize,
0233                                                                 myItemSize)
0234       + myItemSize * (theIndex % myBlockSize);
0235   }
0236 
0237   //! Clears all items and frees all memory.
0238   //! @param theDestroyItem function to call destructor on each item
0239   Standard_EXPORT void clearItems(DestroyItemFunc theDestroyItem);
0240 
0241   //! Deletes the item at theIndex from the array;
0242   //! returns True if the item was defined.
0243   //! @param theDestroyItem function to call destructor on the item
0244   Standard_EXPORT bool unsetValue(const size_t theIndex, DestroyItemFunc theDestroyItem);
0245 
0246   //! Set a value to the specified item; returns address of the set item.
0247   //! @param theCreateItem function to copy-construct a new item
0248   //! @param theCopyItem function to copy-assign an existing item
0249   Standard_EXPORT void* setValue(const size_t   theIndex,
0250                                  void* const    theValue,
0251                                  CreateItemFunc theCreateItem,
0252                                  CopyItemFunc   theCopyItem);
0253 
0254   //! Copy contents of theOther to this;
0255   //! assumes that this and theOther have exactly the same type of arguments.
0256   //! @param theCreateItem function to copy-construct a new item
0257   //! @param theDestroyItem function to call destructor on an item
0258   //! @param theCopyItem function to copy-assign an existing item
0259   Standard_EXPORT void assign(const NCollection_SparseArrayBase& theOther,
0260                               CreateItemFunc                     theCreateItem,
0261                               DestroyItemFunc                    theDestroyItem,
0262                               CopyItemFunc                       theCopyItem);
0263 
0264   //! Exchange contents of theOther and this;
0265   //! assumes that this and theOther have exactly the same type of arguments
0266   Standard_EXPORT void exchange(NCollection_SparseArrayBase& theOther) noexcept;
0267 
0268 private:
0269   // Implementation of memory allocation/deallocation and access mechanics
0270 
0271   //! Allocate space for at least iBlock+1 blocks
0272   void allocData(const size_t iBlock);
0273 
0274   //! Free specified block, destroying all items via theDestroyItem
0275   void freeBlock(const size_t iBlock, DestroyItemFunc theDestroyItem);
0276 
0277 protected:
0278   size_t          myItemSize;    //!< size of item
0279   size_t          myBlockSize;   //!< block size (in items)
0280   size_t          myNbBlocks;    //!< allocated size of blocks table
0281   size_t          mySize;        //!< number of currently defined items
0282   void**          myData;        //!< array of pointers to data blocks
0283   DestroyItemFunc myDestroyItem; //!< function to call destructor on items
0284 };
0285 
0286 #endif