98cf5e3457cf7515a7b945ead35c937148b32912
[occt.git] / src / NCollection / NCollection_Array1.hxx
1 // File:        NCollection_Array1.hxx
2 // Created:     15.04.02 17:05:16
3 // Author:      Alexander Kartomin (akm)
4 //              <a-kartomin@opencascade.com>
5 // Copyright:   Open Cascade 2002
6
7 #ifndef NCollection_Array1_HeaderFile
8 #define NCollection_Array1_HeaderFile
9
10 #ifndef No_Exception
11 #include <Standard_DimensionMismatch.hxx>
12 #include <Standard_OutOfMemory.hxx>
13 #include <Standard_OutOfRange.hxx>
14 #endif
15
16 #include <NCollection_BaseCollection.hxx>
17
18 // *********************************************** Template for Array1 class
19
20 /**
21 * Purpose:     The class Array1 represents unidimensional arrays 
22 *              of fixed size known at run time. 
23 *              The range of the index is user defined.
24 *              An array1 can be constructed with a "C array".
25 *              This functionality is useful to call methods expecting
26 *              an Array1. It allows to carry the bounds inside the arrays.
27 *              
28 * Examples:    Item tab[100]; //  An example with a C array
29 *              Array1OfItem ttab (tab[0],1,100);
30 *              
31 *              Array1OfItem tttab (ttab(10),10,20); // a slice of ttab
32 *              
33 *              If you want to reindex an array from 1 to Length do :
34 *              
35 *              Array1 tab1(tab(tab.Lower()),1,tab.Length());
36 *                          
37 * Warning:     Programs client of such a class must be independant
38 *              of the range of the first element. Then, a C++ for
39 *              loop must be written like this
40 *              
41 *              for (i = A.Lower(); i <= A.Upper(); i++)
42 *              
43 * Changes:     In  comparison  to  TCollection  the  flag  isAllocated  was
44 *              renamed into myDeletable (alike in  the Array2).  For naming
45 *              compatibility the method IsAllocated remained in class along
46 *              with IsDeletable.
47 */              
48 template <class TheItemType> class NCollection_Array1
49   : public NCollection_BaseCollection<TheItemType>
50 {
51
52  public:
53   //! Implementation of the Iterator interface.
54   class Iterator : public NCollection_BaseCollection<TheItemType>::Iterator
55   {
56   public:
57     //! Empty constructor - for later Init
58     Iterator  (void) :
59       myCurrent (0),
60       myArray   (NULL) {}
61     //! Constructor with initialisation
62     Iterator  (const NCollection_Array1& theArray) :
63       myCurrent (theArray.Lower()),
64       myArray   ((NCollection_Array1 *) &theArray) {}
65     //! Initialisation
66     void Init (const NCollection_Array1& theArray)
67     { 
68       myCurrent = theArray.Lower();
69       myArray   = (NCollection_Array1 *) &theArray; 
70     }
71     //! Check end
72     virtual Standard_Boolean More (void) const
73     { return (myCurrent<=myArray->Upper()); }
74     //! Make step
75     virtual void Next (void)         
76     { myCurrent++; }
77     //! Constant value access
78     virtual const TheItemType& Value (void) const
79     { return myArray->Value(myCurrent); }
80     //! Variable value access
81     virtual TheItemType& ChangeValue (void) const 
82     { return myArray->ChangeValue(myCurrent); }
83   private:
84     Standard_Integer    myCurrent; //!< Index of the current item
85     NCollection_Array1* myArray;   //!< Pointer to the array being iterated
86   }; // End of the nested class Iterator
87
88  public:
89   // ---------- PUBLIC METHODS ------------
90
91   //! Constructor
92   NCollection_Array1(const Standard_Integer theLower,
93                      const Standard_Integer theUpper) :
94                 NCollection_BaseCollection<TheItemType>  (),
95                 myLowerBound                             (theLower),
96                 myUpperBound                             (theUpper),
97                 myDeletable                              (Standard_True)
98   {
99 #if !defined No_Exception && !defined No_Standard_RangeError
100     if (theUpper < theLower)
101       Standard_RangeError::Raise ("NCollection_Array1::Create");
102 #endif
103     TheItemType* pBegin = new TheItemType[Length()];
104 #if !defined No_Exception && !defined No_Standard_OutOfMemory
105     if (!pBegin)
106       Standard_OutOfMemory::Raise ("NCollection_Array1 : Allocation failed");
107 #endif
108
109     myData = pBegin - theLower;
110   }
111
112   //! Copy constructor 
113   NCollection_Array1 (const NCollection_Array1& theOther) :
114     NCollection_BaseCollection<TheItemType>     (),
115     myLowerBound                                (theOther.Lower()),
116     myUpperBound                                (theOther.Upper()),
117     myDeletable                                 (Standard_True)
118   {
119     TheItemType* pBegin = new TheItemType[Length()];
120 #if !defined No_Exception && !defined No_Standard_OutOfMemory
121     if (!pBegin)
122       Standard_OutOfMemory::Raise ("NCollection_Array1 : Allocation failed");
123 #endif
124     myData = pBegin - myLowerBound;
125
126     *this = theOther;
127   }
128
129   //! C array-based constructor
130   NCollection_Array1 (const TheItemType& theBegin,
131                       const Standard_Integer theLower,
132                       const Standard_Integer theUpper) :
133     NCollection_BaseCollection<TheItemType>     (),
134     myLowerBound                                (theLower),
135     myUpperBound                                (theUpper),
136     myDeletable                                 (Standard_False)
137   {
138 #if !defined No_Exception && !defined No_Standard_RangeError
139     if (theUpper < theLower)
140       Standard_RangeError::Raise ("NCollection_Array1::Array1");
141 #endif
142     myData = (TheItemType *) &theBegin - theLower; 
143   }
144
145   //! Initialise the items with theValue
146   void Init (const TheItemType& theValue) 
147   {
148     TheItemType *pCur = &myData[myLowerBound], *pEnd=&myData[myUpperBound];
149     for(; pCur <= pEnd; pCur++)
150       *pCur = (TheItemType&) theValue;
151   }
152
153   //! Size query
154   virtual Standard_Integer Size (void) const
155   { return Length(); }
156   //! Length query (the same)
157   Standard_Integer Length (void) const
158   { return (myUpperBound-myLowerBound+1); }
159
160   //! Lower bound
161   Standard_Integer Lower (void) const
162   { return myLowerBound; }
163   //! Upper bound
164   Standard_Integer Upper (void) const
165   { return myUpperBound; }
166
167   //! myDeletable flag
168   Standard_Boolean IsDeletable (void) const
169   { return myDeletable; }
170
171   //! IsAllocated flag - for naming compatibility
172   Standard_Boolean IsAllocated (void) const
173   { return myDeletable; }
174
175   //! Assign (any collection to this array)
176   // Copies items from the other collection into the allocated
177   // storage. Raises an exception when sizes differ.
178   virtual void Assign (const NCollection_BaseCollection<TheItemType>& theOther)
179   {
180     if (&theOther == this)
181       return;
182 #if !defined No_Exception && !defined No_Standard_DimensionMismatch
183     if (Length() != theOther.Size())
184       Standard_DimensionMismatch::Raise ("NCollection_Array1::Assign");
185 #endif
186     TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter2 = 
187       theOther.CreateIterator();
188     TheItemType * const pEndItem = &myData[myUpperBound];
189     for (TheItemType * pItem = &myData[myLowerBound];
190          pItem <= pEndItem;   anIter2.Next())
191       * pItem ++ = anIter2.Value();
192   }
193
194   //! operator= (array to array)
195   NCollection_Array1& operator= (const NCollection_Array1& theOther)
196   {
197     if (&theOther == this)
198       return *this;
199 #if !defined No_Exception && !defined No_Standard_DimensionMismatch
200     if (Length() != theOther.Length())
201       Standard_DimensionMismatch::Raise ("NCollection_Array1::operator=");
202 #endif
203     TheItemType * pMyItem        = &myData[myLowerBound];
204     TheItemType * const pEndItem = &(theOther.myData)[theOther.myUpperBound];
205     TheItemType * pItem          = &(theOther.myData)[theOther.myLowerBound];
206     while (pItem <= pEndItem) * pMyItem ++ = * pItem ++;
207     return *this; 
208   }
209
210   //! Constant value access
211   const TheItemType& Value (const Standard_Integer theIndex) const
212   {
213 #if !defined No_Exception && !defined No_Standard_OutOfRange
214     if (theIndex < myLowerBound || theIndex > myUpperBound)
215       Standard_OutOfRange::Raise ("NCollection_Array1::Value");
216 #endif
217     return myData[theIndex];
218   }
219
220   //! operator() - alias to Value
221   const TheItemType& operator() (const Standard_Integer theIndex) const
222   { return Value (theIndex); }
223
224   //! Variable value access
225   TheItemType& ChangeValue (const Standard_Integer theIndex)
226   {
227 #if !defined No_Exception && !defined No_Standard_OutOfRange
228     if (theIndex < myLowerBound || theIndex > myUpperBound)
229       Standard_OutOfRange::Raise ("NCollection_Array1::ChangeValue");
230 #endif
231     return myData[theIndex];
232   }
233
234   //! operator() - alias to ChangeValue
235   TheItemType& operator() (const Standard_Integer theIndex)
236   { return ChangeValue (theIndex); }
237
238   //! Set value 
239   void SetValue (const Standard_Integer theIndex,
240                  const TheItemType&     theItem)
241   {
242 #if !defined No_Exception && !defined No_Standard_OutOfRange
243     if (theIndex < myLowerBound || theIndex > myUpperBound)
244       Standard_OutOfRange::Raise ("NCollection_Array1::SetValue");
245 #endif
246     myData[theIndex] = theItem;
247   }
248
249   //! Destructor - releases the memory
250   ~NCollection_Array1 (void)
251   { if (myDeletable) delete [] &(myData[myLowerBound]); }
252
253  private:
254   // ----------- PRIVATE METHODS -----------
255
256   // ******** Creates Iterator for use on BaseCollection
257   virtual
258   TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& 
259                         CreateIterator(void) const
260   { return *(new (this->IterAllocator()) Iterator(*this)); }
261
262  protected:
263   // ---------- PROTECTED FIELDS -----------
264   Standard_Integer     myLowerBound;
265   Standard_Integer     myUpperBound;
266   Standard_Boolean     myDeletable; //!< Flag showing who allocated the array
267   TheItemType*         myData;      //!< Pointer to '0'th array item
268 };
269
270 #endif