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