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