b311480e |
1 | // Created on: 2002-03-28 |
2 | // Created by: Alexander GRIGORIEV |
973c2be1 |
3 | // Copyright (c) 2002-2014 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
b311480e |
15 | |
7fd59977 |
16 | #ifndef NCollection_Sequence_HeaderFile |
17 | #define NCollection_Sequence_HeaderFile |
18 | |
7fd59977 |
19 | #include <NCollection_BaseSequence.hxx> |
79a35943 |
20 | #include <NCollection_StlIterator.hxx> |
7fd59977 |
21 | |
7fd59977 |
22 | #include <Standard_OutOfRange.hxx> |
23 | #include <Standard_NoSuchObject.hxx> |
7fd59977 |
24 | |
7fd59977 |
25 | /** |
26 | * Purpose: Definition of a sequence of elements indexed by |
27 | * an Integer in range of 1..n |
28 | */ |
ddf2fe8e |
29 | template <class TheItemType> |
30 | class NCollection_Sequence : public NCollection_BaseSequence |
7fd59977 |
31 | { |
79a35943 |
32 | public: |
33 | //! STL-compliant typedef for value type |
34 | typedef TheItemType value_type; |
7fd59977 |
35 | |
79a35943 |
36 | public: |
7fd59977 |
37 | //! Class defining sequence node - for internal use by Sequence |
38 | class Node : public NCollection_SeqNode |
39 | { |
40 | public: |
41 | //! Constructor |
42 | Node (const TheItemType& theItem) : |
43 | NCollection_SeqNode () |
44 | { myValue = theItem; } |
45 | //! Constant value access |
46 | const TheItemType& Value () const { return myValue; } |
47 | //! Variable value access |
48 | TheItemType& ChangeValue () { return myValue; } |
7fd59977 |
49 | |
50 | private: |
51 | TheItemType myValue; |
52 | }; // End of nested class Node |
53 | |
54 | public: |
55 | //! Implementation of the Iterator interface. |
ddf2fe8e |
56 | class Iterator : public NCollection_BaseSequence::Iterator |
7fd59977 |
57 | { |
58 | public: |
59 | //! Empty constructor - for later Init |
60 | Iterator (void) {} |
61 | //! Constructor with initialisation |
62 | Iterator (const NCollection_Sequence& theSeq, |
63 | const Standard_Boolean isStart = Standard_True) |
64 | : NCollection_BaseSequence::Iterator (theSeq, isStart) {} |
7fd59977 |
65 | //! Check end |
ddf2fe8e |
66 | Standard_Boolean More (void) const |
7fd59977 |
67 | { return (myCurrent!=NULL); } |
68 | //! Make step |
ddf2fe8e |
69 | void Next (void) |
79a35943 |
70 | { |
71 | if (myCurrent) |
72 | { |
73 | myPrevious = myCurrent; |
74 | myCurrent = myCurrent->Next(); |
75 | } |
76 | } |
7fd59977 |
77 | //! Constant value access |
ddf2fe8e |
78 | const TheItemType& Value (void) const |
7fd59977 |
79 | { return ((const Node *)myCurrent)->Value(); } |
80 | //! Variable value access |
ddf2fe8e |
81 | TheItemType& ChangeValue (void) const |
7fd59977 |
82 | { return ((Node *)myCurrent)->ChangeValue(); } |
79a35943 |
83 | //! Performs comparison of two iterators. |
ddf2fe8e |
84 | Standard_Boolean IsEqual (const Iterator& theOther) const |
79a35943 |
85 | { |
86 | return myCurrent == theOther.myCurrent; |
87 | } |
7fd59977 |
88 | }; // End of nested class Iterator |
89 | |
79a35943 |
90 | //! Shorthand for a regular iterator type. |
91 | typedef NCollection_StlIterator<std::bidirectional_iterator_tag, Iterator, TheItemType, false> iterator; |
92 | |
93 | //! Shorthand for a constant iterator type. |
94 | typedef NCollection_StlIterator<std::bidirectional_iterator_tag, Iterator, TheItemType, true> const_iterator; |
95 | |
96 | //! Returns an iterator pointing to the first element in the sequence. |
97 | iterator begin() const { return Iterator (*this, true); } |
98 | |
99 | //! Returns an iterator referring to the past-the-end element in the sequence. |
100 | iterator end() const { Iterator anIter (*this, false); anIter.Next(); return anIter; } |
101 | |
102 | //! Returns a const iterator pointing to the first element in the sequence. |
103 | const_iterator cbegin() const { return Iterator (*this, true); } |
104 | |
105 | //! Returns a const iterator referring to the past-the-end element in the sequence. |
106 | const_iterator cend() const { Iterator anIter (*this, false); anIter.Next(); return anIter; } |
107 | |
7fd59977 |
108 | public: |
109 | // ---------- PUBLIC METHODS ------------ |
110 | |
b6a0525b |
111 | //! Empty constructor. |
112 | NCollection_Sequence() : NCollection_BaseSequence(Handle(NCollection_BaseAllocator)()) {} |
113 | |
7fd59977 |
114 | //! Constructor |
b6a0525b |
115 | explicit NCollection_Sequence (const Handle(NCollection_BaseAllocator)& theAllocator) : NCollection_BaseSequence(theAllocator) {} |
7fd59977 |
116 | |
117 | //! Copy constructor |
118 | NCollection_Sequence (const NCollection_Sequence& theOther) : |
ddf2fe8e |
119 | NCollection_BaseSequence(theOther.myAllocator) |
120 | { |
121 | Assign (theOther); |
122 | } |
7fd59977 |
123 | |
124 | //! Number of items |
ddf2fe8e |
125 | Standard_Integer Size (void) const |
7fd59977 |
126 | { return mySize; } |
127 | |
128 | //! Number of items |
129 | Standard_Integer Length (void) const |
130 | { return mySize; } |
131 | |
a174a3c5 |
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 | |
7fd59977 |
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 | { |
ddf2fe8e |
170 | ClearSeq (delNode); |
7fd59977 |
171 | if (!theAllocator.IsNull()) |
172 | this->myAllocator = theAllocator; |
173 | } |
174 | |
5e452c37 |
175 | //! Replace this sequence by the items of theOther. |
176 | //! This method does not change the internal allocator. |
ddf2fe8e |
177 | NCollection_Sequence& Assign (const NCollection_Sequence& theOther) |
7fd59977 |
178 | { |
395a5977 |
179 | if (this != &theOther) |
180 | { |
181 | Clear(); |
182 | appendSeq((const Node *)theOther.myFirstItem); |
7fd59977 |
183 | } |
184 | return * this; |
185 | } |
186 | |
ddf2fe8e |
187 | //! Replacement operator |
188 | NCollection_Sequence& operator= (const NCollection_Sequence& theOther) |
7fd59977 |
189 | { |
ddf2fe8e |
190 | return Assign (theOther); |
7fd59977 |
191 | } |
192 | |
193 | //! Remove one item |
194 | void Remove (Iterator& thePosition) |
ddf2fe8e |
195 | { RemoveSeq (thePosition, delNode); } |
7fd59977 |
196 | |
197 | //! Remove one item |
198 | void Remove (const Standard_Integer theIndex) |
ddf2fe8e |
199 | { RemoveSeq (theIndex, delNode); } |
7fd59977 |
200 | |
201 | //! Remove range of items |
202 | void Remove (const Standard_Integer theFromIndex, |
203 | const Standard_Integer theToIndex) |
ddf2fe8e |
204 | { RemoveSeq (theFromIndex, theToIndex, delNode); } |
7fd59977 |
205 | |
206 | //! Append one item |
207 | void Append (const TheItemType& theItem) |
208 | { PAppend (new (this->myAllocator) Node (theItem)); } |
209 | |
210 | //! Append another sequence (making it empty) |
211 | void Append (NCollection_Sequence& theSeq) |
212 | { |
395a5977 |
213 | if (this == &theSeq || theSeq.IsEmpty()) |
214 | return; |
215 | if (this->myAllocator == theSeq.myAllocator) |
216 | { |
217 | // Then we take the sequence and glue it to our end - |
218 | // deallocation will bring no problem |
219 | PAppend(theSeq); |
220 | } |
221 | else |
222 | { |
223 | // No - this sequence has different memory scope |
224 | appendSeq((const Node *)theSeq.myFirstItem); |
225 | theSeq.Clear(); |
226 | } |
7fd59977 |
227 | } |
228 | |
229 | //! Prepend one item |
230 | void Prepend (const TheItemType& theItem) |
231 | { PPrepend (new (this->myAllocator) Node (theItem)); } |
232 | |
233 | //! Prepend another sequence (making it empty) |
234 | void Prepend (NCollection_Sequence& theSeq) |
235 | { |
395a5977 |
236 | if (this == &theSeq || theSeq.IsEmpty()) |
237 | return; |
238 | if (this->myAllocator == theSeq.myAllocator) |
239 | { |
240 | // Then we take the sequence and glue it to our head - |
241 | // deallocation will bring no problem |
242 | PPrepend(theSeq); |
243 | } |
244 | else |
245 | { |
246 | // No - this sequence has different memory scope |
247 | prependSeq((const Node *)theSeq.myFirstItem, 1); |
248 | theSeq.Clear(); |
249 | } |
7fd59977 |
250 | } |
251 | |
252 | //! InsertBefore theIndex theItem |
253 | void InsertBefore (const Standard_Integer theIndex, |
254 | const TheItemType& theItem) |
255 | { InsertAfter (theIndex-1, theItem); } |
256 | |
395a5977 |
257 | //! InsertBefore theIndex another sequence (making it empty) |
7fd59977 |
258 | void InsertBefore (const Standard_Integer theIndex, |
259 | NCollection_Sequence& theSeq) |
260 | { InsertAfter (theIndex-1, theSeq); } |
261 | |
262 | //! InsertAfter the position of iterator |
263 | void InsertAfter (Iterator& thePosition, |
264 | const TheItemType& theItem) |
265 | { PInsertAfter (thePosition, new (this->myAllocator) Node (theItem)); } |
266 | |
395a5977 |
267 | //! InsertAfter theIndex another sequence (making it empty) |
7fd59977 |
268 | void InsertAfter (const Standard_Integer theIndex, |
269 | NCollection_Sequence& theSeq) |
395a5977 |
270 | { |
271 | if (this == &theSeq || theSeq.IsEmpty()) |
272 | return; |
273 | if (this->myAllocator == theSeq.myAllocator) |
274 | { |
275 | // Then we take the list and glue it to our head - |
276 | // deallocation will bring no problem |
277 | PInsertAfter(theIndex, theSeq); |
278 | } |
279 | else |
280 | { |
281 | // No - this sequence has different memory scope |
282 | prependSeq((const Node *)theSeq.myFirstItem, theIndex + 1); |
283 | theSeq.Clear(); |
284 | } |
285 | } |
7fd59977 |
286 | |
395a5977 |
287 | //! InsertAfter theIndex theItem |
7fd59977 |
288 | void InsertAfter (const Standard_Integer theIndex, |
289 | const TheItemType& theItem) |
290 | { |
e3a6386d |
291 | Standard_OutOfRange_Raise_if (theIndex < 0 || theIndex > mySize, "NCollection_Sequence::InsertAfter"); |
7fd59977 |
292 | PInsertAfter (theIndex, new (this->myAllocator) Node (theItem)); |
293 | } |
294 | |
295 | //! Split in two sequences |
296 | void Split (const Standard_Integer theIndex, NCollection_Sequence& theSeq) |
297 | { |
298 | theSeq.Clear (this->myAllocator); |
299 | PSplit (theIndex, theSeq); |
300 | } |
301 | |
302 | //! First item access |
303 | const TheItemType& First () const |
304 | { |
e3a6386d |
305 | Standard_NoSuchObject_Raise_if (mySize == 0, "NCollection_Sequence::First"); |
7fd59977 |
306 | return ((const Node *) myFirstItem) -> Value(); |
307 | } |
308 | |
a174a3c5 |
309 | //! First item access |
310 | TheItemType& ChangeFirst() |
311 | { |
e3a6386d |
312 | Standard_NoSuchObject_Raise_if (mySize == 0, "NCollection_Sequence::ChangeFirst"); |
a174a3c5 |
313 | return ((Node* )myFirstItem)->ChangeValue(); |
314 | } |
315 | |
7fd59977 |
316 | //! Last item access |
317 | const TheItemType& Last () const |
318 | { |
e3a6386d |
319 | Standard_NoSuchObject_Raise_if (mySize == 0, "NCollection_Sequence::Last"); |
7fd59977 |
320 | return ((const Node *) myLastItem) -> Value(); |
321 | } |
322 | |
a174a3c5 |
323 | //! Last item access |
324 | TheItemType& ChangeLast() |
325 | { |
e3a6386d |
326 | Standard_NoSuchObject_Raise_if (mySize == 0, "NCollection_Sequence::ChangeLast"); |
a174a3c5 |
327 | return ((Node* )myLastItem)->ChangeValue(); |
328 | } |
329 | |
7fd59977 |
330 | //! Constant item access by theIndex |
331 | const TheItemType& Value (const Standard_Integer theIndex) const |
332 | { |
e3a6386d |
333 | Standard_OutOfRange_Raise_if (theIndex <= 0 || theIndex > mySize, "NCollection_Sequence::Value"); |
334 | |
7fd59977 |
335 | NCollection_Sequence * const aLocalTHIS = (NCollection_Sequence *) this; |
336 | aLocalTHIS -> myCurrentItem = Find (theIndex); |
337 | aLocalTHIS -> myCurrentIndex = theIndex; |
338 | return ((const Node *) myCurrentItem) -> Value(); |
339 | } |
340 | |
341 | //! Constant operator() |
342 | const TheItemType& operator() (const Standard_Integer theIndex) const |
343 | { return Value(theIndex); } |
344 | |
345 | //! Variable item access by theIndex |
346 | TheItemType& ChangeValue (const Standard_Integer theIndex) |
347 | { |
e3a6386d |
348 | Standard_OutOfRange_Raise_if (theIndex <= 0 || theIndex > mySize, "NCollection_Sequence::ChangeValue"); |
349 | |
7fd59977 |
350 | myCurrentItem = Find (theIndex); |
351 | myCurrentIndex = theIndex; |
352 | return ((Node *) myCurrentItem) -> ChangeValue(); |
353 | } |
354 | |
355 | //! Variable operator() |
356 | TheItemType& operator() (const Standard_Integer theIndex) |
357 | { return ChangeValue(theIndex); } |
358 | |
359 | //! Set item value by theIndex |
360 | void SetValue (const Standard_Integer theIndex, |
361 | const TheItemType& theItem) |
362 | { ChangeValue (theIndex) = theItem; } |
363 | |
364 | // ******** Destructor - clears the Sequence |
6928e351 |
365 | virtual ~NCollection_Sequence (void) |
7fd59977 |
366 | { Clear(); } |
367 | |
7fd59977 |
368 | private: |
7fd59977 |
369 | |
370 | // ---------- FRIEND CLASSES ------------ |
371 | friend class Iterator; |
372 | |
395a5977 |
373 | // ----------- PRIVATE METHODS ----------- |
374 | |
375 | //! append the sequence headed by the given Node |
376 | void appendSeq(const Node * pCur) |
377 | { |
378 | while (pCur) |
379 | { |
380 | Node* pNew = new (this->myAllocator) Node(pCur->Value()); |
381 | PAppend(pNew); |
382 | pCur = (const Node *)pCur->Next(); |
383 | } |
384 | } |
385 | |
386 | //! insert the sequence headed by the given Node before the item with the given index |
387 | void prependSeq(const Node * pCur, Standard_Integer ind) |
388 | { |
389 | ind--; |
390 | while (pCur) |
391 | { |
392 | Node* pNew = new (this->myAllocator) Node(pCur->Value()); |
393 | PInsertAfter(ind++, pNew); |
394 | pCur = (const Node *)pCur->Next(); |
395 | } |
396 | } |
397 | |
7fd59977 |
398 | }; |
399 | |
7fd59977 |
400 | #endif |