0024971: Incomplete interface of NCollection classes
[occt.git] / src / NCollection / NCollection_Array1.hxx
1 // Created on: 2002-04-15
2 // Created by: Alexander Kartomin (akm)
3 // Copyright (c) 2002-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifndef NCollection_Array1_HeaderFile
17 #define NCollection_Array1_HeaderFile
18
19 #include <Standard_DimensionMismatch.hxx>
20 #include <Standard_OutOfMemory.hxx>
21 #include <Standard_OutOfRange.hxx>
22
23 #include <NCollection_DefineAlloc.hxx>
24 #include <NCollection_StlIterator.hxx>
25
26 // *********************************************** Template for Array1 class
27
28 /**
29 * Purpose:     The class Array1 represents unidimensional arrays 
30 *              of fixed size known at run time. 
31 *              The range of the index is user defined.
32 *              An array1 can be constructed with a "C array".
33 *              This functionality is useful to call methods expecting
34 *              an Array1. It allows to carry the bounds inside the arrays.
35 *              
36 * Examples:    Item tab[100]; //  An example with a C array
37 *              Array1OfItem ttab (tab[0],1,100);
38 *              
39 *              Array1OfItem tttab (ttab(10),10,20); // a slice of ttab
40 *              
41 *              If you want to reindex an array from 1 to Length do :
42 *              
43 *              Array1 tab1(tab(tab.Lower()),1,tab.Length());
44 *                          
45 * Warning:     Programs client of such a class must be independant
46 *              of the range of the first element. Then, a C++ for
47 *              loop must be written like this
48 *              
49 *              for (i = A.Lower(); i <= A.Upper(); i++)
50 *              
51 * Changes:     In  comparison  to  TCollection  the  flag  isAllocated  was
52 *              renamed into myDeletable (alike in  the Array2).  For naming
53 *              compatibility the method IsAllocated remained in class along
54 *              with IsDeletable.
55 */              
56 template <class TheItemType>
57 class NCollection_Array1
58 {
59 public:
60   //! STL-compliant typedef for value type
61   typedef TheItemType value_type;
62
63 public:
64   //! Implementation of the Iterator interface.
65   class Iterator
66   {
67   public:
68
69     //! Empty constructor - for later Init
70     Iterator (void) :
71       myPtrCur (NULL),
72       myPtrEnd (NULL)
73     {
74       //
75     }
76
77     //! Constructor with initialization
78     Iterator (const NCollection_Array1& theArray, Standard_Boolean theToEnd = Standard_False) :
79       myPtrEnd (const_cast<TheItemType*> (&theArray.Last() + 1))
80     {
81       myPtrCur = theToEnd ? myPtrEnd : const_cast<TheItemType*> (&theArray.First());
82     }
83
84     //! Initialisation
85     void Init (const NCollection_Array1& theArray)
86     { 
87       myPtrCur = const_cast<TheItemType*> (&theArray.First());
88       myPtrEnd = const_cast<TheItemType*> (&theArray.Last() + 1);
89     }
90
91     //! Assignment
92     Iterator& operator= (const Iterator& theOther)
93     {
94       myPtrCur = theOther.myPtrCur;
95       myPtrEnd = theOther.myPtrEnd;
96       return *this;
97     }
98
99     //! Check end
100     Standard_Boolean More (void) const
101     { return myPtrCur < myPtrEnd; }
102     
103     //! Increment operator
104     void Next (void)
105     { ++myPtrCur; }
106
107     //! Decrement operator
108     void Previous()
109     { --myPtrCur; }
110
111     //! Offset operator.
112     void Offset (ptrdiff_t theOffset)
113     { myPtrCur += theOffset; }
114
115     //! Difference operator.
116     ptrdiff_t Differ (const Iterator& theOther) const
117     { return myPtrCur - theOther.myPtrCur; }
118
119     //! Constant value access
120     const TheItemType& Value (void) const
121     { return *myPtrCur; }
122
123     //! Variable value access
124     TheItemType& ChangeValue (void) const 
125     { return *myPtrCur; }
126
127     //! Performs comparison of two iterators
128     Standard_Boolean IsEqual (const Iterator& theOther) const
129     { return myPtrCur == theOther.myPtrCur; }
130
131   private:
132     TheItemType* myPtrCur; //!< Pointer to the current element in the array
133     TheItemType* myPtrEnd; //!< Pointer to the past-the-end element in the array
134   }; // End of the nested class Iterator
135
136   //! Shorthand for a regular iterator type.
137   typedef NCollection_StlIterator<std::random_access_iterator_tag, Iterator, TheItemType, false> iterator;
138
139   //! Shorthand for a constant iterator type.
140   typedef NCollection_StlIterator<std::random_access_iterator_tag, Iterator, TheItemType, true> const_iterator;
141
142   //! Returns an iterator pointing to the first element in the array.
143   iterator begin() const { return Iterator (*this, false); }
144
145   //! Returns an iterator referring to the past-the-end element in the array.
146   iterator end() const { return Iterator (*this, true); }
147   
148   //! Returns a const iterator pointing to the first element in the array.
149   const_iterator cbegin() const { return Iterator (*this, false); }
150
151   //! Returns a const iterator referring to the past-the-end element in the array.
152   const_iterator cend() const { return Iterator (*this, true); }
153
154  public:
155   // ---------- PUBLIC METHODS ------------
156
157   //! Constructor
158   NCollection_Array1(const Standard_Integer theLower,
159                      const Standard_Integer theUpper) :
160                 myLowerBound                             (theLower),
161                 myUpperBound                             (theUpper),
162                 myDeletable                              (Standard_True)
163   {
164     Standard_RangeError_Raise_if (theUpper < theLower, "NCollection_Array1::Create");
165     TheItemType* pBegin = new TheItemType[Length()];
166     Standard_OutOfMemory_Raise_if (!pBegin, "NCollection_Array1 : Allocation failed");
167
168     myData = pBegin - theLower;
169   }
170
171   //! Copy constructor 
172   NCollection_Array1 (const NCollection_Array1& theOther) :
173     myLowerBound                                (theOther.Lower()),
174     myUpperBound                                (theOther.Upper()),
175     myDeletable                                 (Standard_True)
176   {
177     TheItemType* pBegin = new TheItemType[Length()];
178     Standard_OutOfMemory_Raise_if (!pBegin, "NCollection_Array1 : Allocation failed");
179     myData = pBegin - myLowerBound;
180
181     *this = theOther;
182   }
183
184   //! C array-based constructor
185   NCollection_Array1 (const TheItemType& theBegin,
186                       const Standard_Integer theLower,
187                       const Standard_Integer theUpper) :
188     myLowerBound                                (theLower),
189     myUpperBound                                (theUpper),
190     myDeletable                                 (Standard_False)
191   {
192     Standard_RangeError_Raise_if (theUpper < theLower, "NCollection_Array1::Create");
193     myData = (TheItemType *) &theBegin - theLower; 
194   }
195
196   //! Initialise the items with theValue
197   void Init (const TheItemType& theValue) 
198   {
199     TheItemType *pCur = &myData[myLowerBound], *pEnd=&myData[myUpperBound];
200     for(; pCur <= pEnd; pCur++)
201       *pCur = (TheItemType&) theValue;
202   }
203
204   //! Size query
205   Standard_Integer Size (void) const
206   { return Length(); }
207   //! Length query (the same)
208   Standard_Integer Length (void) const
209   { return (myUpperBound-myLowerBound+1); }
210
211   //! Lower bound
212   Standard_Integer Lower (void) const
213   { return myLowerBound; }
214   //! Upper bound
215   Standard_Integer Upper (void) const
216   { return myUpperBound; }
217
218   //! myDeletable flag
219   Standard_Boolean IsDeletable (void) const
220   { return myDeletable; }
221
222   //! IsAllocated flag - for naming compatibility
223   Standard_Boolean IsAllocated (void) const
224   { return myDeletable; }
225
226   //! Assignment
227   NCollection_Array1& Assign (const NCollection_Array1& theOther)
228   {
229     if (&theOther == this)
230       return *this;
231     Standard_DimensionMismatch_Raise_if (Length() != theOther.Length(), "NCollection_Array1::operator=");
232     TheItemType * pMyItem        = &myData[myLowerBound];
233     TheItemType * const pEndItem = &(theOther.myData)[theOther.myUpperBound];
234     TheItemType * pItem          = &(theOther.myData)[theOther.myLowerBound];
235     while (pItem <= pEndItem) * pMyItem ++ = * pItem ++;
236     return *this; 
237   }
238
239   //! Assignment operator
240   NCollection_Array1& operator= (const NCollection_Array1& theOther)
241   { 
242     return Assign (theOther);
243   }
244
245   //! @return first element
246   const TheItemType& First() const
247   {
248     return myData[myLowerBound];
249   }
250
251   //! @return first element
252   TheItemType& ChangeFirst()
253   {
254     return myData[myLowerBound];
255   }
256
257   //! @return last element
258   const TheItemType& Last() const
259   {
260     return myData[myUpperBound];
261   }
262
263   //! @return last element
264   TheItemType& ChangeLast()
265   {
266     return myData[myUpperBound];
267   }
268
269   //! Constant value access
270   const TheItemType& Value (const Standard_Integer theIndex) const
271   {
272     Standard_OutOfRange_Raise_if (theIndex < myLowerBound || theIndex > myUpperBound, "NCollection_Array1::Value");
273     return myData[theIndex];
274   }
275
276   //! operator() - alias to Value
277   const TheItemType& operator() (const Standard_Integer theIndex) const
278   { return Value (theIndex); }
279
280   //! Variable value access
281   TheItemType& ChangeValue (const Standard_Integer theIndex)
282   {
283     Standard_OutOfRange_Raise_if (theIndex < myLowerBound || theIndex > myUpperBound, "NCollection_Array1::ChangeValue");
284     return myData[theIndex];
285   }
286
287   //! operator() - alias to ChangeValue
288   TheItemType& operator() (const Standard_Integer theIndex)
289   { return ChangeValue (theIndex); }
290
291   //! Set value 
292   void SetValue (const Standard_Integer theIndex,
293                  const TheItemType&     theItem)
294   {
295     Standard_OutOfRange_Raise_if (theIndex < myLowerBound || theIndex > myUpperBound, "NCollection_Array1::SetValue");
296     myData[theIndex] = theItem;
297   }
298
299   //! Destructor - releases the memory
300   ~NCollection_Array1 (void)
301   { if (myDeletable) delete [] &(myData[myLowerBound]); }
302
303  protected:
304   // ---------- PROTECTED FIELDS -----------
305   Standard_Integer     myLowerBound;
306   Standard_Integer     myUpperBound;
307   Standard_Boolean     myDeletable; //!< Flag showing who allocated the array
308   TheItemType*         myData;      //!< Pointer to '0'th array item
309 };
310
311 #endif