3b0866a8d832ce385da96b592717dadb83b8d005
[occt.git] / src / NCollection / NCollection_Sequence.hxx
1 // Created on: 2002-03-28
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2002-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #ifndef NCollection_Sequence_HeaderFile
22 #define NCollection_Sequence_HeaderFile
23
24 #include <NCollection_BaseCollection.hxx>
25 #include <NCollection_BaseSequence.hxx>
26
27 #ifndef No_Exception
28 #include <Standard_OutOfRange.hxx>
29 #include <Standard_NoSuchObject.hxx>
30 #endif
31
32 /**
33  * Purpose:     Definition of a sequence of elements indexed by
34  *              an Integer in range of 1..n
35  */              
36 template <class TheItemType> class NCollection_Sequence
37   : public NCollection_BaseCollection<TheItemType>,
38     public NCollection_BaseSequence
39 {
40
41  public:
42   //!   Class defining sequence node - for internal use by Sequence
43   class Node : public NCollection_SeqNode
44   {
45   public:
46     //! Constructor
47     Node (const TheItemType& theItem) :
48       NCollection_SeqNode ()
49       { myValue = theItem; }
50     //! Constant value access
51     const TheItemType& Value () const { return myValue; }
52     //! Variable value access
53     TheItemType&       ChangeValue () { return myValue; }
54     //! Memory allocation
55     DEFINE_STANDARD_ALLOC
56     DEFINE_NCOLLECTION_ALLOC
57
58   private:
59     TheItemType    myValue;
60   }; // End of nested class Node
61
62  public:
63   //!   Implementation of the Iterator interface.
64   class Iterator : public NCollection_BaseCollection<TheItemType>::Iterator,
65                    public NCollection_BaseSequence::Iterator
66   {
67   public:
68     //! Empty constructor - for later Init
69     Iterator  (void) {}
70     //! Constructor with initialisation
71     Iterator  (const NCollection_Sequence& theSeq,
72                const Standard_Boolean      isStart = Standard_True)
73       : NCollection_BaseSequence::Iterator (theSeq, isStart) {}
74     //! Assignment
75     Iterator& operator= (const Iterator& theIt)
76     {
77       NCollection_BaseSequence::Iterator& me = * this;
78       me.operator= (theIt);
79       return * this;
80     }
81     //! Check end
82     virtual Standard_Boolean More (void) const
83     { return (myCurrent!=NULL); }
84     //! Make step
85     virtual void Next (void)         
86     { if (myCurrent) myCurrent = (NCollection_SeqNode *) myCurrent->Next(); }
87     //! Constant value access
88     virtual const TheItemType& Value (void) const
89     { return ((const Node *)myCurrent)->Value(); }
90     //! Variable value access
91     virtual TheItemType& ChangeValue (void) const
92     { return ((Node *)myCurrent)->ChangeValue(); }
93   }; // End of nested class Iterator
94
95  public:
96   // ---------- PUBLIC METHODS ------------
97
98   //! Constructor
99   NCollection_Sequence(const Handle(NCollection_BaseAllocator)& theAllocator=0L)
100     : NCollection_BaseCollection<TheItemType>(theAllocator),
101       NCollection_BaseSequence() {}
102
103   //! Copy constructor
104   NCollection_Sequence (const NCollection_Sequence& theOther) :
105     NCollection_BaseCollection<TheItemType>(theOther.myAllocator),
106     NCollection_BaseSequence()
107   { *this = theOther; }
108
109   //! Number of items
110   virtual Standard_Integer Size (void) const
111   { return mySize; }
112
113   //! Number of items
114   Standard_Integer Length (void) const
115   { return mySize; }
116
117   //! Empty query
118   Standard_Boolean IsEmpty (void) const
119   { return (mySize==0); }
120
121   //! Reverse sequence
122   void Reverse (void)
123   { PReverse(); }
124
125   //! Exchange two members
126   void Exchange (const Standard_Integer I,
127                  const Standard_Integer J )
128   { PExchange(I, J); }
129
130   //! Static deleter to be passed to BaseSequence
131   static void delNode (NCollection_SeqNode * theNode, 
132                        Handle(NCollection_BaseAllocator)& theAl)
133   {
134     ((Node *) theNode)->~Node();
135     theAl->Free(theNode);
136   }
137
138   //! Clear the items out, take a new allocator if non null
139   void Clear (const Handle(NCollection_BaseAllocator)& theAllocator=0L)
140   {
141     ClearSeq (delNode, this->myAllocator);
142     if (!theAllocator.IsNull())
143       this->myAllocator = theAllocator;
144   }
145   
146   //! Replace this sequence by the items of theOther
147   NCollection_Sequence& operator= (const NCollection_Sequence& theOther)
148   { 
149     if (this == &theOther) 
150       return *this;
151     Clear (theOther.myAllocator);
152     Node * pCur = (Node *) theOther.myFirstItem;
153     while (pCur) {
154       Node* pNew = new (this->myAllocator) Node (pCur->Value());
155       PAppend (pNew);
156       pCur = (Node *) pCur->Next();
157     }
158     return * this;
159   }
160
161   //! Replace this sequence by the items of theOther collection
162   virtual void Assign (const NCollection_BaseCollection<TheItemType>& theOther)
163   {
164     if (this == &theOther)
165       return;
166     Clear ();
167     TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter = 
168       theOther.CreateIterator();
169     for (; anIter.More(); anIter.Next())
170       Append(anIter.Value());
171   }
172
173   //! Remove one item
174   void Remove (Iterator& thePosition)
175   { RemoveSeq (thePosition, delNode, this->myAllocator); }
176
177   //! Remove one item
178   void Remove (const Standard_Integer theIndex)
179   { RemoveSeq (theIndex, delNode, this->myAllocator); }
180
181   //! Remove range of items
182   void Remove (const Standard_Integer theFromIndex,
183                const Standard_Integer theToIndex)
184   { RemoveSeq (theFromIndex, theToIndex, delNode, this->myAllocator); }
185
186   //! Append one item
187   void Append (const TheItemType& theItem)
188   { PAppend (new (this->myAllocator) Node (theItem)); }
189
190   //! Append another sequence (making it empty)
191   void Append (NCollection_Sequence& theSeq)
192   {
193     if (myFirstItem == theSeq.myFirstItem) Assign (theSeq);
194     PAppend (theSeq);
195   }
196
197   //! Prepend one item
198   void Prepend (const TheItemType& theItem)
199   { PPrepend (new (this->myAllocator) Node (theItem)); }
200
201   //! Prepend another sequence (making it empty)
202   void Prepend (NCollection_Sequence& theSeq)
203   {
204     if (myFirstItem == theSeq.myFirstItem) Assign (theSeq);
205     PPrepend (theSeq);
206   }
207
208   //! InsertBefore theIndex theItem
209   void InsertBefore (const Standard_Integer theIndex, 
210                      const TheItemType&     theItem)
211   { InsertAfter (theIndex-1, theItem); }
212
213   //! InsertBefore theIndex another sequence
214   void InsertBefore (const Standard_Integer theIndex,
215                      NCollection_Sequence&  theSeq)
216   { InsertAfter (theIndex-1, theSeq); }
217   
218   //! InsertAfter the position of iterator
219   void InsertAfter  (Iterator&              thePosition,
220                      const TheItemType&     theItem)
221   { PInsertAfter (thePosition, new (this->myAllocator) Node (theItem)); }
222
223   //! InsertAfter theIndex theItem
224   void InsertAfter  (const Standard_Integer theIndex,
225                      NCollection_Sequence&  theSeq)
226   { PInsertAfter (theIndex, theSeq); }
227
228   //! InsertAfter theIndex another sequence
229   void InsertAfter (const Standard_Integer  theIndex, 
230                     const TheItemType&      theItem)
231   {
232 #if !defined No_Exception && !defined No_Standard_OutOfRange
233     if (theIndex < 0 || theIndex > mySize)
234       Standard_OutOfRange::Raise ("NCollection_Sequence::InsertAfter");
235 #endif
236     PInsertAfter (theIndex, new (this->myAllocator) Node (theItem));
237   }
238
239   //! Split in two sequences
240   void Split (const Standard_Integer theIndex, NCollection_Sequence& theSeq)
241   {
242     theSeq.Clear (this->myAllocator);
243     PSplit (theIndex, theSeq);
244   }
245
246   //! First item access
247   const TheItemType& First () const
248   {
249 #if !defined No_Exception && !defined No_Standard_NoSuchObject
250     if (mySize == 0)
251       Standard_NoSuchObject::Raise ("NCollection_Sequence::First");
252 #endif
253     return ((const Node *) myFirstItem) -> Value();
254   }
255
256   //! Last item access
257   const TheItemType& Last () const
258   {
259 #if !defined No_Exception && !defined No_Standard_NoSuchObject
260     if (mySize == 0)
261       Standard_NoSuchObject::Raise ("NCollection_Sequence::Last");
262 #endif
263     return ((const Node *) myLastItem) -> Value();
264   }
265
266   //! Constant item access by theIndex
267   const TheItemType& Value (const Standard_Integer theIndex) const
268   {
269 #if !defined No_Exception && !defined No_Standard_OutOfRange
270     if (theIndex <= 0 || theIndex > mySize)
271       Standard_OutOfRange::Raise ("NCollection_Sequence::Value");
272 #endif
273     NCollection_Sequence * const aLocalTHIS = (NCollection_Sequence *) this;
274     aLocalTHIS -> myCurrentItem  = Find (theIndex);
275     aLocalTHIS -> myCurrentIndex = theIndex;
276     return ((const Node *) myCurrentItem) -> Value();
277   }
278
279   //! Constant operator()
280   const TheItemType& operator() (const Standard_Integer theIndex) const
281   { return Value(theIndex); }
282
283   //! Variable item access by theIndex
284   TheItemType& ChangeValue (const Standard_Integer theIndex)
285   {
286 #if !defined No_Exception && !defined No_Standard_OutOfRange
287     if (theIndex <= 0 || theIndex > mySize)
288       Standard_OutOfRange::Raise ("NCollection_Sequence::ChangeValue");
289 #endif
290     myCurrentItem  = Find (theIndex);
291     myCurrentIndex = theIndex;
292     return ((Node *) myCurrentItem) -> ChangeValue();
293   }
294
295   //! Variable operator()
296   TheItemType& operator() (const Standard_Integer theIndex)
297   { return ChangeValue(theIndex); }
298
299   //! Set item value by theIndex
300   void SetValue (const Standard_Integer theIndex, 
301                  const TheItemType& theItem)
302   { ChangeValue (theIndex) = theItem; }
303
304   // ******** Destructor - clears the Sequence
305   ~NCollection_Sequence (void)
306   { Clear(); }
307
308
309  private:
310   // ----------- PRIVATE METHODS -----------
311
312   //! Creates Iterator for use on BaseCollection
313   virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& 
314     CreateIterator(void) const
315   { return *(new (this->IterAllocator()) Iterator(*this)); }
316
317   // ---------- FRIEND CLASSES ------------
318   friend class Iterator;
319
320 };
321
322 #endif