summaryrefslogtreecommitdiff
path: root/inc/NCollection_SparseArrayBase.hxx
blob: 7155c1203d8bf06efe5ae9b6c44c49e77491282b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
// File:      NCollection_SparseArrayBase.hxx
// Created:   23.01.07 11:12:02
// Author:    Andrey BETENEV
// Copyright: Open Cascade 2007

#ifndef NCollection_SparseArrayBase_HeaderFile
#define NCollection_SparseArrayBase_HeaderFile

#include <Standard.hxx>
#include <Standard_OutOfRange.hxx>

typedef size_t Standard_Size;

/**
* Base class for NCollection_SparseArray;  
* provides non-template implementation of general mechanics
* of block allocation, items creation / deletion etc.
*/

class NCollection_SparseArrayBase 
{
public:
  //!@name Type-independent public interface 
  //!@{

  //! Clears all the data
  Standard_EXPORT void Clear ();

  //! Returns number of currently contained items
  Standard_Integer Size () const { return mySize; }

  //! Check whether the value at given index is set
  Standard_EXPORT Standard_Boolean HasValue (const Standard_Integer theIndex) const;

  //! Deletes the item from the array; 
  //! returns True if that item was defined
  Standard_EXPORT Standard_Boolean UnsetValue (const Standard_Integer theIndex);

  //!@}

#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)
public: // work-around against obsolete SUN WorkShop 5.3 compiler
#else
private:
#endif

  /**
   * The block of data contains array of items, counter 
   * and bit field, allocated as single piece of memory addressed
   * from the blocks array (myData).
   * 
   * The Block structure provides a logical view on the block,
   * and provides methods to work with bit map.
   *
   * Note that NCollection_SparseArrayBase class takes responsibility 
   * for correct allocation/deallocation of all the data.
   */

  class Block {
  public:

    typedef unsigned char Cell; //!< type of items used to hold bits

    //! Number of bits in each cell
    static Standard_Size BitsPerCell() { return sizeof(Cell) * 8/*BITSPERBYTE*/; } 

  public:

    //! Initializes the block by pointer to block data 
    Block (const Standard_Address theAddr, const Standard_Size theNbItems, 
           const Standard_Size theItemSize)
      : Count((Standard_Size*)theAddr),
        Array((char*)theAddr + sizeof(Standard_Size)), 
        Bits ((Cell*)((char*)theAddr + sizeof(Standard_Size) + theNbItems * theItemSize))
    {
    }

    //! Compute required size for block data, in bytes
    static Standard_Size Size (const Standard_Size theNbItems, 
			       const Standard_Size theItemSize) 
    {
      return sizeof(Standard_Size) + 
             sizeof(Cell) * ( (theNbItems + BitsPerCell() - 1) / BitsPerCell() ) +
             theNbItems * theItemSize;
    }

    //! Returns address of array from address of block
    static char* ToArray (const Standard_Address theAddress, 
			  const Standard_Size /*theNbItems*/, 
			  const Standard_Size /*theItemSize*/) 
    {
      return (char*)theAddress + sizeof(Standard_Size);
    }

  public:

    //! Set bit for i-th item; returns non-null if that bit has 
    //! not been set previously
    Cell Set (Standard_Size i) 
    {
      Cell* abyte = Bits + i / BitsPerCell();
      Cell  amask = (Cell)( '\1' << ( i % BitsPerCell() ) );
      Cell  anold = (Cell)( *abyte & amask );
      *abyte = (Cell)( *abyte | amask );
      return ! anold;
    }

    //! Check bit for i-th item; returns non-null if that bit is set
    Cell IsSet (Standard_Size i) 
    {
      Cell* abyte = Bits + i / BitsPerCell();
      Cell  amask = (Cell)( '\1' << ( i % BitsPerCell() ) );
      return (Cell)( *abyte & amask );
    }

    //! Unset bit for i-th item; returns non-null if that bit 
    //! has been set previously
    Cell Unset (Standard_Size i) 
    {
      Cell* abyte = Bits + i / BitsPerCell();
      Cell  amask = (Cell)( '\1' << ( i % BitsPerCell() ) );
      Cell  anold = (Cell)( *abyte & amask );
      *abyte = (Cell)( *abyte & ~amask );
      return anold;
    }

  public:
    Standard_Size*   Count; //!< items counter 
    Standard_Address Array; //!< pointer to the data items array
    Cell*            Bits;  //!< bit map for defined/undefined flags
  };

public:
  /**
   * Iterator 
   */

  class Iterator {
  public:
    // Public interface

    //! Restart iterations on the same array
    void Restart () { init(myArr); }

    //! Returns True if current item is available
    Standard_Boolean More () const { return myHasMore; }

    //! Advances to the next item
    Standard_EXPORT void Next ();

    //! Returns current index
    Standard_EXPORT Standard_Size Index () const 
    { 
      return myIBlock * myArr->myBlockSize + myInd;
    }

  protected:
    // Methods for descendant

    //! Empty constructor
    Standard_EXPORT Iterator (const NCollection_SparseArrayBase* theArray=0);

    //! Initialize by the specified array
    Standard_EXPORT void init (const NCollection_SparseArrayBase* theArray);

    //! Returns address of the current item
    Standard_Address value () const 
    { 
      return myArr->getItem (myBlock, myInd);
    }
    
  private:
    const NCollection_SparseArrayBase *myArr;
    Standard_Boolean myHasMore;
    Standard_Size myIBlock;
    Standard_Size myInd;
    Block myBlock;
  };
  friend class Iterator;

private:
  // Copy constructor and assignment operator are private thus not accessible
  NCollection_SparseArrayBase (const NCollection_SparseArrayBase&) {}
  void operator = (const NCollection_SparseArrayBase&) {}

protected:
  // Object life

  //! Constructor; initialized by size of item and of block (in items)
  NCollection_SparseArrayBase (Standard_Size theItemSize,
			       Standard_Size theBlockSize)
    : myItemSize(theItemSize), myBlockSize(theBlockSize), 
      myNbBlocks(0), mySize(0), myData(0)
  {
  }

  //! Destructor
  virtual ~NCollection_SparseArrayBase ()
  {
    Clear();
  }

protected:
  // Data access interface for descendants

  //! Creates Block structure for block pointed by theAddr
  Block getBlock (const Standard_Address theAddr) const
  {
    return Block (theAddr, myBlockSize, myItemSize);
  }

  //! Find address of the item in the block by index (in the block)
  Standard_Address getItem (const Block &theBlock, Standard_Size theInd) const
  {
    return ((char*)theBlock.Array) + myItemSize * theInd;
  }

  //! Direct const access to the item
  Standard_Address getValue (const Standard_Integer theIndex) const
  {
    Standard_OutOfRange_Raise_if (!HasValue(theIndex),"NCollection_SparseArray::Value()")
    return Block::ToArray(myData[theIndex/myBlockSize], myBlockSize, myItemSize) + 
           myItemSize * (theIndex % myBlockSize);
  }

  //! Set a value to the specified item; returns address of the set item
  Standard_EXPORT Standard_Address setValue (const Standard_Integer theIndex, 
                                             const Standard_Address theValue);

  //! Modification access to the item; allocates necessary space
  //! and marks the item as defined
  Standard_EXPORT Standard_Address changeValue (const Standard_Integer theIndex);

  //! Copy contents of theOther to this; 
  //! assumes that this and theOther have exactly the same type of arguments 
  Standard_EXPORT void assign (const NCollection_SparseArrayBase& theOther);

  //! Exchange contents of theOther and this; 
  //! assumes that this and theOther have exactly the same type of arguments 
  Standard_EXPORT void exchange (NCollection_SparseArrayBase& theOther);

protected:
  // Methods to be provided by descendant 

  //! Create new item at the specified address with default constructor
//  virtual void createItem (Standard_Address theAddress) = 0;
  
  //! Create new item at the specified address with copy constructor
  //! from existing item
  virtual void createItem (Standard_Address theAddress, Standard_Address theOther) = 0;
  
  //! Call destructor to the item 
  virtual void destroyItem (Standard_Address theAddress) = 0;

  //! Call assignment operator to the item
  virtual void copyItem (Standard_Address theAddress, Standard_Address theOther) = 0;

private:
  // Implementation of memory allocation/deallocation and access mechanics

  //! Allocate space for at least iBlock+1 blocks
  void allocData (const Standard_Size iBlock);

  //! Free specified block
  void freeBlock (const Standard_Size iBlock);

protected:
  Standard_Size     myItemSize;  //!< size of item
  Standard_Size     myBlockSize; //!< block size (in items)
  Standard_Size     myNbBlocks;  //!< allocated size of blocks table
  Standard_Size     mySize;      //!< number of currently defined items
  Standard_Address *myData;      //!< array of pointers to data blocks
};

#endif