410a6a927d460eb43ef4f102000919734feb62f4
[occt.git] / src / NCollection / NCollection_List.hxx
1 // Created on: 2002-04-17
2 // Created by: Alexander Kartomin (akm)
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_List_HeaderFile
17 #define NCollection_List_HeaderFile
18
19 #include <NCollection_TListIterator.hxx>
20 #include <NCollection_StlIterator.hxx>
21
22 #if !defined No_Exception && !defined No_Standard_NoSuchObject
23 #include <Standard_NoSuchObject.hxx>
24 #endif
25
26 /**
27  * Purpose:      Simple list to link  items together keeping the first 
28  *               and the last one.
29  *               Inherits BaseList, adding the data item to each node.
30  */               
31 template <class TheItemType> class NCollection_List
32   : public NCollection_BaseCollection<TheItemType>,
33     public NCollection_BaseList
34 {
35 public:
36   //! STL-compliant typedef for value type
37   typedef TheItemType value_type;
38
39 public:
40   typedef NCollection_TListNode<TheItemType>     ListNode;
41   typedef NCollection_TListIterator<TheItemType> Iterator;
42
43   //! Shorthand for a regular iterator type.
44   typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, false> iterator;
45
46   //! Shorthand for a constant iterator type.
47   typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, true> const_iterator;
48
49   //! Returns an iterator pointing to the first element in the list.
50   iterator begin() const { return Iterator (*this); }
51
52   //! Returns an iterator referring to the past-the-end element in the list.
53   iterator end() const { return Iterator(); }
54
55   //! Returns a const iterator pointing to the first element in the list.
56   const_iterator cbegin() const { return Iterator (*this); }
57
58   //! Returns a const iterator referring to the past-the-end element in the list.
59   const_iterator cend() const { return Iterator(); }
60
61  public:
62   // ---------- PUBLIC METHODS ------------
63
64   //! Constructor
65   NCollection_List(const Handle(NCollection_BaseAllocator)& theAllocator=0L) :
66     NCollection_BaseCollection<TheItemType>(theAllocator),
67     NCollection_BaseList() {}
68
69   //! Copy constructor
70   NCollection_List (const NCollection_List& theOther) :
71     NCollection_BaseCollection<TheItemType>(theOther.myAllocator),
72     NCollection_BaseList()
73   { *this = theOther; }
74
75   //! Size - Number of items
76   virtual Standard_Integer Size (void) const
77   { return Extent(); }
78
79   //! Replace this list by the items of theOther collection
80   virtual void Assign (const NCollection_BaseCollection<TheItemType>& theOther)
81   {
82     if (this == &theOther) 
83       return;
84     Clear();
85     TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter = 
86       theOther.CreateIterator();
87     for (; anIter.More(); anIter.Next())
88     {
89       ListNode* pNew = new (this->myAllocator) ListNode(anIter.Value());
90       PAppend(pNew);
91     }
92   }
93
94   //! Replace this list by the items of another list (theOther parameter)
95   void Assign (const NCollection_List& theOther)
96   {
97     if (this != &theOther) {
98       Clear();
99       appendList(theOther.PFirst());
100     }
101   }
102
103   //! Replace this list by the items of theOther list
104   NCollection_List& operator= (const NCollection_List& theOther)
105   { 
106     if (this != &theOther) {
107       Clear (theOther.myAllocator);
108       appendList(theOther.PFirst());
109     }
110     return *this;
111   }
112
113   //! Clear this list
114   void Clear (const Handle(NCollection_BaseAllocator)& theAllocator=0L)
115   {
116     PClear (ListNode::delNode, this->myAllocator);
117     if (!theAllocator.IsNull())
118       this->myAllocator = theAllocator;
119   }
120
121   //! First item
122   const TheItemType& First (void) const
123   {
124 #if !defined No_Exception && !defined No_Standard_NoSuchObject
125     if (IsEmpty())
126       Standard_NoSuchObject::Raise ("NCollection_List::First");
127 #endif
128     return ((const ListNode *) PFirst())->Value();
129   }
130
131   //! Last item
132   const TheItemType& Last (void) const
133   { 
134 #if !defined No_Exception && !defined No_Standard_NoSuchObject
135     if (IsEmpty())
136       Standard_NoSuchObject::Raise ("NCollection_List::Last");
137 #endif
138     return ((const ListNode *) PLast())->Value();
139   }
140
141   //! Append one item at the end
142   TheItemType& Append (const TheItemType& theItem)
143   { 
144     ListNode * pNew = new (this->myAllocator) ListNode(theItem);
145     PAppend(pNew);
146     return ((ListNode *) PLast())->ChangeValue();
147   }
148
149   //! Append one item at the end and output iterator
150   //!   pointing at the appended item
151   void Append (const TheItemType& theItem, Iterator& theIter)
152   { 
153     ListNode * pNew = new (this->myAllocator) ListNode(theItem);
154     PAppend(pNew, theIter);
155   }
156
157   //! Append another list at the end
158   void Append (NCollection_List& theOther)
159   { 
160     if (this == &theOther || theOther.Extent()<1)
161       return;
162     if (this->myAllocator == theOther.myAllocator)
163     {
164       // Then we take the list and glue it to our end - 
165       // deallocation will bring no problem
166       PAppend(theOther);
167     }
168     else
169     {
170       // No - this list has different memory scope
171       appendList(theOther.myFirst);
172       theOther.Clear();
173     }
174   }
175
176   //! Prepend one item at the beginning
177   TheItemType& Prepend (const TheItemType& theItem)
178   { 
179     ListNode * pNew = new (this->myAllocator) ListNode(theItem);
180     PPrepend(pNew);
181     return ((ListNode *) PFirst())->ChangeValue();
182   }
183
184   //! Prepend another list at the beginning
185   void Prepend (NCollection_List& theOther)
186   { 
187     if (this == &theOther || theOther.Extent()<1) 
188       return;
189     if (this->myAllocator == theOther.myAllocator)
190     {
191       // Then we take the list and glue it to our head - 
192       // deallocation will bring no problem
193       PPrepend(theOther);
194     }
195     else
196     {
197       // No - this list has different memory scope
198       Iterator it(*this);
199       prependList(theOther.PFirst(), it);
200       theOther.Clear();
201     }
202   }
203
204   //! RemoveFirst item
205   void RemoveFirst (void) 
206   { PRemoveFirst (ListNode::delNode, this->myAllocator); }
207
208   //! Remove item
209   void Remove (Iterator& theIter) 
210   { 
211     PRemove (theIter, ListNode::delNode, this->myAllocator); 
212   }
213
214   //! InsertBefore
215   TheItemType& InsertBefore (const TheItemType& theItem,
216                              Iterator& theIter) 
217   { 
218     ListNode * pNew = new (this->myAllocator) ListNode(theItem);
219     PInsertBefore (pNew, theIter);
220     return pNew -> ChangeValue();
221   }
222
223   //! InsertBefore
224   void InsertBefore (NCollection_List& theOther,
225                      Iterator& theIter) 
226   {
227     if (this == &theOther) 
228       return;
229   
230     if (this->myAllocator == theOther.myAllocator)
231     {
232       // Then we take the list and glue it to our head - 
233       // deallocation will bring no problem
234       PInsertBefore (theOther, theIter);
235     }
236     else
237     {
238       // No - this list has different memory scope
239       prependList(theOther.myFirst, theIter);
240       theOther.Clear();
241     }
242   }
243
244   //! InsertAfter
245   TheItemType& InsertAfter (const TheItemType& theItem,
246                             Iterator& theIter) 
247   {
248     ListNode * pNew = new (this->myAllocator) ListNode(theItem);
249     PInsertAfter (pNew, theIter);
250     return pNew -> ChangeValue();
251   }
252
253   //! InsertAfter
254   void InsertAfter (NCollection_List& theOther,
255                     Iterator& theIter) 
256   {
257     if (!theIter.More())
258     {
259       Append(theOther);
260       return;
261     }
262     if (this->myAllocator == theOther.myAllocator)
263     {
264       // Then we take the list and glue it to our head - 
265       // deallocation will bring no problem
266       PInsertAfter (theOther, theIter);
267     }
268     else
269     {
270       // No - this list has different memory scope
271 #if !defined No_Exception && !defined No_Standard_NoSuchObject
272       if (!theIter.More())
273         Standard_NoSuchObject::Raise ("NCollection_List::InsertAfter");
274 #endif
275       Iterator anIter;
276       anIter.myPrevious = theIter.myCurrent;
277       anIter.myCurrent = theIter.myCurrent->Next();
278       prependList(theOther.PFirst(), anIter);
279       theOther.Clear();
280     }
281   }
282
283   //! Reverse the list
284   void Reverse ()
285   { PReverse(); }
286
287   //! Destructor - clears the List
288   ~NCollection_List (void)
289   { Clear(); }
290
291  private:
292   // ----------- PRIVATE METHODS -----------
293
294   //! Creates Iterator for use on BaseCollection
295   virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& 
296     CreateIterator(void) const
297   { return *(new (this->IterAllocator()) Iterator(*this)); }
298
299   //! append the list headed by the given ListNode
300   void appendList(const NCollection_ListNode * pCur) {
301     while (pCur) {
302       NCollection_ListNode * pNew =
303         new (this->myAllocator) ListNode(((const ListNode *)(pCur))->Value());
304       PAppend(pNew);
305       pCur = pCur->Next();
306     }
307   }
308
309   //! insert the list headed by the given ListNode before the given iterator
310   void prependList(const NCollection_ListNode * pCur, Iterator& theIter) {
311     while (pCur) {
312       NCollection_ListNode * pNew =
313         new (this->myAllocator) ListNode (((const ListNode *)(pCur))->Value());
314       PInsertBefore(pNew, theIter);
315       pCur = pCur->Next();
316     }
317   }
318 };
319
320 #endif