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