1 // Created on: 2002-04-17
2 // Created by: Alexander Kartomin (akm)
3 // Copyright (c) 2002-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #ifndef NCollection_List_HeaderFile
17 #define NCollection_List_HeaderFile
19 #include <NCollection_TListIterator.hxx>
20 #include <NCollection_StlIterator.hxx>
22 #include <Standard_NoSuchObject.hxx>
25 * Purpose: Simple list to link items together keeping the first
27 * Inherits BaseList, adding the data item to each node.
29 template <class TheItemType>
30 class NCollection_List : public NCollection_BaseList
33 //! STL-compliant typedef for value type
34 typedef TheItemType value_type;
37 typedef NCollection_TListNode<TheItemType> ListNode;
38 typedef NCollection_TListIterator<TheItemType> Iterator;
40 //! Shorthand for a regular iterator type.
41 typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, false> iterator;
43 //! Shorthand for a constant iterator type.
44 typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, true> const_iterator;
46 //! Returns an iterator pointing to the first element in the list.
47 iterator begin() const { return Iterator (*this); }
49 //! Returns an iterator referring to the past-the-end element in the list.
50 iterator end() const { return Iterator(); }
52 //! Returns a const iterator pointing to the first element in the list.
53 const_iterator cbegin() const { return Iterator (*this); }
55 //! Returns a const iterator referring to the past-the-end element in the list.
56 const_iterator cend() const { return Iterator(); }
59 // ---------- PUBLIC METHODS ------------
61 //! Empty constructor.
62 NCollection_List() : NCollection_BaseList(Handle(NCollection_BaseAllocator)()) {}
65 explicit NCollection_List(const Handle(NCollection_BaseAllocator)& theAllocator) : NCollection_BaseList(theAllocator) {}
68 NCollection_List (const NCollection_List& theOther) :
69 NCollection_BaseList(theOther.myAllocator)
71 appendList(theOther.PFirst());
75 NCollection_List(NCollection_List&& theOther) noexcept :
76 NCollection_BaseList(theOther.myAllocator)
78 this->operator=(std::forward<NCollection_List>(theOther));
81 //! Size - Number of items
82 Standard_Integer Size (void) const
85 //! Replace this list by the items of another list (theOther parameter).
86 //! This method does not change the internal allocator.
87 NCollection_List& Assign (const NCollection_List& theOther)
89 if (this != &theOther) {
91 appendList(theOther.PFirst());
96 //! Replacement operator
97 NCollection_List& operator= (const NCollection_List& theOther)
99 return Assign (theOther);
103 NCollection_List& operator= (NCollection_List&& theOther) noexcept
105 if (this == &theOther)
109 Clear(theOther.myAllocator);
110 myFirst = theOther.myFirst;
111 myLast = theOther.myLast;
112 myLength = theOther.myLength;
113 theOther.myFirst = theOther.myLast = nullptr;
114 theOther.myLength = 0;
119 void Clear (const Handle(NCollection_BaseAllocator)& theAllocator=0L)
121 PClear (ListNode::delNode);
122 if (!theAllocator.IsNull())
123 this->myAllocator = theAllocator;
127 const TheItemType& First (void) const
129 Standard_NoSuchObject_Raise_if (IsEmpty(), "NCollection_List::First");
130 return ((const ListNode *) PFirst())->Value();
133 //! First item (non-const)
134 TheItemType& First (void)
136 Standard_NoSuchObject_Raise_if (IsEmpty(), "NCollection_List::First");
137 return ((ListNode *) PFirst())->ChangeValue();
141 const TheItemType& Last (void) const
143 Standard_NoSuchObject_Raise_if (IsEmpty(), "NCollection_List::Last");
144 return ((const ListNode *) PLast())->Value();
147 //! Last item (non-const)
148 TheItemType& Last (void)
150 Standard_NoSuchObject_Raise_if (IsEmpty(), "NCollection_List::Last");
151 return ((ListNode *) PLast())->ChangeValue();
154 //! Append one item at the end
155 TheItemType& Append (const TheItemType& theItem)
157 ListNode * pNew = new (this->myAllocator) ListNode(theItem);
159 return ((ListNode *) PLast())->ChangeValue();
162 //! Append one item at the end
163 TheItemType& Append (TheItemType&& theItem)
165 ListNode * pNew = new (this->myAllocator) ListNode(std::forward<TheItemType>(theItem));
167 return ((ListNode *) PLast())->ChangeValue();
170 //! Append one item at the end and output iterator
171 //! pointing at the appended item
172 void Append (const TheItemType& theItem, Iterator& theIter)
174 ListNode * pNew = new (this->myAllocator) ListNode(theItem);
175 PAppend(pNew, theIter);
178 //! Append one item at the end and output iterator
179 //! pointing at the appended item
180 void Append (TheItemType&& theItem, Iterator& theIter)
182 ListNode * pNew = new (this->myAllocator) ListNode(std::forward<TheItemType>(theItem));
183 PAppend(pNew, theIter);
186 //! Append another list at the end.
187 //! After this operation, theOther list will be cleared.
188 void Append (NCollection_List& theOther)
190 if (this == &theOther || theOther.Extent()<1)
192 if (this->myAllocator == theOther.myAllocator)
194 // Then we take the list and glue it to our end -
195 // deallocation will bring no problem
200 // No - this list has different memory scope
201 appendList(theOther.myFirst);
206 //! Prepend one item at the beginning
207 TheItemType& Prepend (const TheItemType& theItem)
209 ListNode * pNew = new (this->myAllocator) ListNode(theItem);
211 return ((ListNode *) PFirst())->ChangeValue();
214 //! Prepend one item at the beginning
215 TheItemType& Prepend (TheItemType&& theItem)
217 ListNode * pNew = new (this->myAllocator) ListNode(std::forward<TheItemType>(theItem));
219 return ((ListNode *) PFirst())->ChangeValue();
222 //! Prepend another list at the beginning
223 void Prepend (NCollection_List& theOther)
225 if (this == &theOther || theOther.Extent()<1)
227 if (this->myAllocator == theOther.myAllocator)
229 // Then we take the list and glue it to our head -
230 // deallocation will bring no problem
235 // No - this list has different memory scope
237 prependList(theOther.PFirst(), it);
243 void RemoveFirst (void)
244 { PRemoveFirst (ListNode::delNode); }
246 //! Remove item pointed by iterator theIter;
247 //! theIter is then set to the next item
248 void Remove (Iterator& theIter)
250 PRemove (theIter, ListNode::delNode);
253 //! Remove the first occurrence of the object.
254 template<typename TheValueType> // instantiate this method on first call only for types defining equality operator
255 Standard_Boolean Remove (const TheValueType& theObject)
257 for (Iterator anIter (*this); anIter.More(); anIter.Next())
259 if (anIter.Value() == theObject)
262 return Standard_True;
265 return Standard_False;
269 TheItemType& InsertBefore (const TheItemType& theItem,
272 ListNode * pNew = new (this->myAllocator) ListNode(theItem);
273 PInsertBefore (pNew, theIter);
274 return pNew -> ChangeValue();
278 TheItemType& InsertBefore (TheItemType&& theItem,
281 ListNode * pNew = new (this->myAllocator) ListNode(std::forward<TheItemType>(theItem));
282 PInsertBefore (pNew, theIter);
283 return pNew -> ChangeValue();
287 void InsertBefore (NCollection_List& theOther,
290 if (this == &theOther)
293 if (this->myAllocator == theOther.myAllocator)
295 // Then we take the list and glue it to our head -
296 // deallocation will bring no problem
297 PInsertBefore (theOther, theIter);
301 // No - this list has different memory scope
302 prependList(theOther.myFirst, theIter);
308 TheItemType& InsertAfter (const TheItemType& theItem,
311 ListNode * pNew = new (this->myAllocator) ListNode(theItem);
312 PInsertAfter (pNew, theIter);
313 return pNew -> ChangeValue();
317 TheItemType& InsertAfter (TheItemType&& theItem,
320 ListNode * pNew = new (this->myAllocator) ListNode(std::forward<TheItemType>(theItem));
321 PInsertAfter (pNew, theIter);
322 return pNew -> ChangeValue();
326 void InsertAfter (NCollection_List& theOther,
334 if (this->myAllocator == theOther.myAllocator)
336 // Then we take the list and glue it to our head -
337 // deallocation will bring no problem
338 PInsertAfter (theOther, theIter);
342 // No - this list has different memory scope
344 anIter.myPrevious = theIter.myCurrent;
345 anIter.myCurrent = theIter.myCurrent->Next();
346 prependList(theOther.PFirst(), anIter);
355 //! Return true if object is stored in the list.
356 template<typename TheValueType> // instantiate this method on first call only for types defining equality operator
357 Standard_Boolean Contains (const TheValueType& theObject) const
359 for (Iterator anIter (*this); anIter.More(); anIter.Next())
361 if (anIter.Value() == theObject)
363 return Standard_True;
366 return Standard_False;
369 //! Destructor - clears the List
370 virtual ~NCollection_List (void)
374 // ----------- PRIVATE METHODS -----------
376 //! append the list headed by the given ListNode
377 void appendList(const NCollection_ListNode * pCur) {
379 NCollection_ListNode * pNew =
380 new (this->myAllocator) ListNode(((const ListNode *)(pCur))->Value());
386 //! insert the list headed by the given ListNode before the given iterator
387 void prependList(const NCollection_ListNode * pCur, Iterator& theIter) {
389 NCollection_ListNode * pNew =
390 new (this->myAllocator) ListNode (((const ListNode *)(pCur))->Value());
391 PInsertBefore(pNew, theIter);