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