0024428: Implementation of LGPL license
[occt.git] / src / NCollection / NCollection_Sequence.hxx
1 // Created on: 2002-03-28
2 // Created by: Alexander GRIGORIEV
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
8 // under the terms of the GNU Lesser General Public 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_Sequence_HeaderFile
17 #define NCollection_Sequence_HeaderFile
18
19 #include <NCollection_BaseCollection.hxx>
20 #include <NCollection_BaseSequence.hxx>
21
22 #ifndef No_Exception
23 #include <Standard_OutOfRange.hxx>
24 #include <Standard_NoSuchObject.hxx>
25 #endif
26
27 /**
28  * Purpose:     Definition of a sequence of elements indexed by
29  *              an Integer in range of 1..n
30  */              
31 template <class TheItemType> class NCollection_Sequence
32   : public NCollection_BaseCollection<TheItemType>,
33     public NCollection_BaseSequence
34 {
35
36  public:
37   //!   Class defining sequence node - for internal use by Sequence
38   class Node : public NCollection_SeqNode
39   {
40   public:
41     //! Constructor
42     Node (const TheItemType& theItem) :
43       NCollection_SeqNode ()
44       { myValue = theItem; }
45     //! Constant value access
46     const TheItemType& Value () const { return myValue; }
47     //! Variable value access
48     TheItemType&       ChangeValue () { return myValue; }
49     //! Memory allocation
50     DEFINE_STANDARD_ALLOC
51     DEFINE_NCOLLECTION_ALLOC
52
53   private:
54     TheItemType    myValue;
55   }; // End of nested class Node
56
57  public:
58   //!   Implementation of the Iterator interface.
59   class Iterator : public NCollection_BaseCollection<TheItemType>::Iterator,
60                    public NCollection_BaseSequence::Iterator
61   {
62   public:
63     //! Empty constructor - for later Init
64     Iterator  (void) {}
65     //! Constructor with initialisation
66     Iterator  (const NCollection_Sequence& theSeq,
67                const Standard_Boolean      isStart = Standard_True)
68       : NCollection_BaseSequence::Iterator (theSeq, isStart) {}
69     //! Assignment
70     Iterator& operator= (const Iterator& theIt)
71     {
72       NCollection_BaseSequence::Iterator& me = * this;
73       me.operator= (theIt);
74       return * this;
75     }
76     //! Check end
77     virtual Standard_Boolean More (void) const
78     { return (myCurrent!=NULL); }
79     //! Make step
80     virtual void Next (void)         
81     { if (myCurrent) myCurrent = (NCollection_SeqNode *) myCurrent->Next(); }
82     //! Constant value access
83     virtual const TheItemType& Value (void) const
84     { return ((const Node *)myCurrent)->Value(); }
85     //! Variable value access
86     virtual TheItemType& ChangeValue (void) const
87     { return ((Node *)myCurrent)->ChangeValue(); }
88   }; // End of nested class Iterator
89
90  public:
91   // ---------- PUBLIC METHODS ------------
92
93   //! Constructor
94   NCollection_Sequence(const Handle(NCollection_BaseAllocator)& theAllocator=0L)
95     : NCollection_BaseCollection<TheItemType>(theAllocator),
96       NCollection_BaseSequence() {}
97
98   //! Copy constructor
99   NCollection_Sequence (const NCollection_Sequence& theOther) :
100     NCollection_BaseCollection<TheItemType>(theOther.myAllocator),
101     NCollection_BaseSequence()
102   { *this = theOther; }
103
104   //! Number of items
105   virtual Standard_Integer Size (void) const
106   { return mySize; }
107
108   //! Number of items
109   Standard_Integer Length (void) const
110   { return mySize; }
111
112   //! Method for consistency with other collections.
113   //! @return Lower bound (inclusive) for iteration.
114   Standard_Integer Lower() const
115   {
116     return 1;
117   }
118
119   //! Method for consistency with other collections.
120   //! @return Upper bound (inclusive) for iteration.
121   Standard_Integer Upper() const
122   {
123     return mySize;
124   }
125
126   //! Empty query
127   Standard_Boolean IsEmpty (void) const
128   { return (mySize==0); }
129
130   //! Reverse sequence
131   void Reverse (void)
132   { PReverse(); }
133
134   //! Exchange two members
135   void Exchange (const Standard_Integer I,
136                  const Standard_Integer J )
137   { PExchange(I, J); }
138
139   //! Static deleter to be passed to BaseSequence
140   static void delNode (NCollection_SeqNode * theNode, 
141                        Handle(NCollection_BaseAllocator)& theAl)
142   {
143     ((Node *) theNode)->~Node();
144     theAl->Free(theNode);
145   }
146
147   //! Clear the items out, take a new allocator if non null
148   void Clear (const Handle(NCollection_BaseAllocator)& theAllocator=0L)
149   {
150     ClearSeq (delNode, this->myAllocator);
151     if (!theAllocator.IsNull())
152       this->myAllocator = theAllocator;
153   }
154   
155   //! Replace this sequence by the items of theOther
156   NCollection_Sequence& operator= (const NCollection_Sequence& theOther)
157   { 
158     if (this == &theOther) 
159       return *this;
160     Clear (theOther.myAllocator);
161     Node * pCur = (Node *) theOther.myFirstItem;
162     while (pCur) {
163       Node* pNew = new (this->myAllocator) Node (pCur->Value());
164       PAppend (pNew);
165       pCur = (Node *) pCur->Next();
166     }
167     return * this;
168   }
169
170   //! Replace this sequence by the items of theOther collection
171   virtual void Assign (const NCollection_BaseCollection<TheItemType>& theOther)
172   {
173     if (this == &theOther)
174       return;
175     Clear ();
176     TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter = 
177       theOther.CreateIterator();
178     for (; anIter.More(); anIter.Next())
179       Append(anIter.Value());
180   }
181
182   //! Remove one item
183   void Remove (Iterator& thePosition)
184   { RemoveSeq (thePosition, delNode, this->myAllocator); }
185
186   //! Remove one item
187   void Remove (const Standard_Integer theIndex)
188   { RemoveSeq (theIndex, delNode, this->myAllocator); }
189
190   //! Remove range of items
191   void Remove (const Standard_Integer theFromIndex,
192                const Standard_Integer theToIndex)
193   { RemoveSeq (theFromIndex, theToIndex, delNode, this->myAllocator); }
194
195   //! Append one item
196   void Append (const TheItemType& theItem)
197   { PAppend (new (this->myAllocator) Node (theItem)); }
198
199   //! Append another sequence (making it empty)
200   void Append (NCollection_Sequence& theSeq)
201   {
202     if (myFirstItem == theSeq.myFirstItem) Assign (theSeq);
203     PAppend (theSeq);
204   }
205
206   //! Prepend one item
207   void Prepend (const TheItemType& theItem)
208   { PPrepend (new (this->myAllocator) Node (theItem)); }
209
210   //! Prepend another sequence (making it empty)
211   void Prepend (NCollection_Sequence& theSeq)
212   {
213     if (myFirstItem == theSeq.myFirstItem) Assign (theSeq);
214     PPrepend (theSeq);
215   }
216
217   //! InsertBefore theIndex theItem
218   void InsertBefore (const Standard_Integer theIndex, 
219                      const TheItemType&     theItem)
220   { InsertAfter (theIndex-1, theItem); }
221
222   //! InsertBefore theIndex another sequence
223   void InsertBefore (const Standard_Integer theIndex,
224                      NCollection_Sequence&  theSeq)
225   { InsertAfter (theIndex-1, theSeq); }
226   
227   //! InsertAfter the position of iterator
228   void InsertAfter  (Iterator&              thePosition,
229                      const TheItemType&     theItem)
230   { PInsertAfter (thePosition, new (this->myAllocator) Node (theItem)); }
231
232   //! InsertAfter theIndex theItem
233   void InsertAfter  (const Standard_Integer theIndex,
234                      NCollection_Sequence&  theSeq)
235   { PInsertAfter (theIndex, theSeq); }
236
237   //! InsertAfter theIndex another sequence
238   void InsertAfter (const Standard_Integer  theIndex, 
239                     const TheItemType&      theItem)
240   {
241 #if !defined No_Exception && !defined No_Standard_OutOfRange
242     if (theIndex < 0 || theIndex > mySize)
243       Standard_OutOfRange::Raise ("NCollection_Sequence::InsertAfter");
244 #endif
245     PInsertAfter (theIndex, new (this->myAllocator) Node (theItem));
246   }
247
248   //! Split in two sequences
249   void Split (const Standard_Integer theIndex, NCollection_Sequence& theSeq)
250   {
251     theSeq.Clear (this->myAllocator);
252     PSplit (theIndex, theSeq);
253   }
254
255   //! First item access
256   const TheItemType& First () const
257   {
258 #if !defined No_Exception && !defined No_Standard_NoSuchObject
259     if (mySize == 0)
260       Standard_NoSuchObject::Raise ("NCollection_Sequence::First");
261 #endif
262     return ((const Node *) myFirstItem) -> Value();
263   }
264
265   //! First item access
266   TheItemType& ChangeFirst()
267   {
268 #if !defined No_Exception && !defined No_Standard_NoSuchObject
269     if (mySize == 0)
270       Standard_NoSuchObject::Raise ("NCollection_Sequence::ChangeFirst");
271 #endif
272     return ((Node* )myFirstItem)->ChangeValue();
273   }
274
275   //! Last item access
276   const TheItemType& Last () const
277   {
278 #if !defined No_Exception && !defined No_Standard_NoSuchObject
279     if (mySize == 0)
280       Standard_NoSuchObject::Raise ("NCollection_Sequence::Last");
281 #endif
282     return ((const Node *) myLastItem) -> Value();
283   }
284
285   //! Last item access
286   TheItemType& ChangeLast()
287   {
288 #if !defined No_Exception && !defined No_Standard_NoSuchObject
289     if (mySize == 0)
290       Standard_NoSuchObject::Raise ("NCollection_Sequence::ChangeLast");
291 #endif
292     return ((Node* )myLastItem)->ChangeValue();
293   }
294
295   //! Constant item access by theIndex
296   const TheItemType& Value (const Standard_Integer theIndex) const
297   {
298 #if !defined No_Exception && !defined No_Standard_OutOfRange
299     if (theIndex <= 0 || theIndex > mySize)
300       Standard_OutOfRange::Raise ("NCollection_Sequence::Value");
301 #endif
302     NCollection_Sequence * const aLocalTHIS = (NCollection_Sequence *) this;
303     aLocalTHIS -> myCurrentItem  = Find (theIndex);
304     aLocalTHIS -> myCurrentIndex = theIndex;
305     return ((const Node *) myCurrentItem) -> Value();
306   }
307
308   //! Constant operator()
309   const TheItemType& operator() (const Standard_Integer theIndex) const
310   { return Value(theIndex); }
311
312   //! Variable item access by theIndex
313   TheItemType& ChangeValue (const Standard_Integer theIndex)
314   {
315 #if !defined No_Exception && !defined No_Standard_OutOfRange
316     if (theIndex <= 0 || theIndex > mySize)
317       Standard_OutOfRange::Raise ("NCollection_Sequence::ChangeValue");
318 #endif
319     myCurrentItem  = Find (theIndex);
320     myCurrentIndex = theIndex;
321     return ((Node *) myCurrentItem) -> ChangeValue();
322   }
323
324   //! Variable operator()
325   TheItemType& operator() (const Standard_Integer theIndex)
326   { return ChangeValue(theIndex); }
327
328   //! Set item value by theIndex
329   void SetValue (const Standard_Integer theIndex, 
330                  const TheItemType& theItem)
331   { ChangeValue (theIndex) = theItem; }
332
333   // ******** Destructor - clears the Sequence
334   ~NCollection_Sequence (void)
335   { Clear(); }
336
337
338  private:
339   // ----------- PRIVATE METHODS -----------
340
341   //! Creates Iterator for use on BaseCollection
342   virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& 
343     CreateIterator(void) const
344   { return *(new (this->IterAllocator()) Iterator(*this)); }
345
346   // ---------- FRIEND CLASSES ------------
347   friend class Iterator;
348
349 };
350
351 #endif