1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
16 #include <Standard_DomainError.hxx>
17 #include <Standard_NoSuchObject.hxx>
18 #include <Standard_OutOfRange.hxx>
19 #include <TCollection_BaseSequence.hxx>
20 #include <TCollection_SeqNode.hxx>
22 typedef void (*DelNode) (TCollection_SeqNode*);
24 TCollection_BaseSequence::TCollection_BaseSequence() :
35 // ----------------------------------
36 // Clear : Clear the Current Sequence
37 // ----------------------------------
38 void TCollection_BaseSequence::Clear(const Standard_Address delnode)
41 TCollection_SeqNode* p = (TCollection_SeqNode*) FirstItem;
42 TCollection_SeqNode* q;
46 ((DelNode)delnode) (q);
48 LastItem = FirstItem = CurrentItem = NULL;
52 void TCollection_BaseSequence::PAppend(const Standard_Address newnode)
55 FirstItem = LastItem = CurrentItem = newnode;
56 CurrentIndex = Size = 1;
59 ((TCollection_SeqNode*)LastItem)->Next() = (TCollection_SeqNode*)newnode;
65 // ---------------------------------------------------
66 // Append : Push a sequence at the end of the sequence
67 // ---------------------------------------------------
68 void TCollection_BaseSequence::PAppend(TCollection_BaseSequence& Other)
74 FirstItem = Other.FirstItem;
75 LastItem = Other.LastItem;
76 CurrentItem = FirstItem;
81 ((TCollection_SeqNode*)LastItem)->Next() = (TCollection_SeqNode*)Other.FirstItem;
82 if (Other.FirstItem) {
83 ((TCollection_SeqNode*)Other.FirstItem)->Previous() = (TCollection_SeqNode*)LastItem;
84 LastItem = Other.LastItem;
92 void TCollection_BaseSequence::PPrepend(const Standard_Address newnode)
95 FirstItem = LastItem = CurrentItem = newnode;
96 CurrentIndex = Size = 1;
99 ((TCollection_SeqNode*)FirstItem)->Previous() = (TCollection_SeqNode*) newnode;
100 ((TCollection_SeqNode*)newnode)->Next() = (TCollection_SeqNode*)FirstItem;
107 void TCollection_BaseSequence::PPrepend(TCollection_BaseSequence& Other)
113 FirstItem = Other.FirstItem;
114 LastItem = Other.LastItem;
116 CurrentItem = FirstItem;
120 if (Other.LastItem) ((TCollection_SeqNode*)Other.LastItem)->Next() = (TCollection_SeqNode*)FirstItem;
121 ((TCollection_SeqNode*)FirstItem)->Previous() = (TCollection_SeqNode*)Other.LastItem;
122 FirstItem = Other.FirstItem;
123 CurrentIndex += Other.Size;
128 // ---------------------------------------------------------
129 // Reverse : Reverse the order of a given sequence
130 // ---------------------------------------------------------
131 void TCollection_BaseSequence::Reverse()
133 TCollection_SeqNode* p = (TCollection_SeqNode*) FirstItem;
134 TCollection_SeqNode* tmp;
137 p->Next() = p->Previous();
141 tmp = (TCollection_SeqNode*)FirstItem;
142 FirstItem = LastItem;
144 if (Size != 0) CurrentIndex = Size + 1 - CurrentIndex;
148 void TCollection_BaseSequence::PInsertAfter(const Standard_Integer Index, const Standard_Address N)
153 TCollection_SeqNode* p = (TCollection_SeqNode*) Find(Index);
154 TCollection_SeqNode* newnode = (TCollection_SeqNode*) N;
155 newnode->Next() = p->Next();
156 newnode->Previous() = p;
157 if (Index == Size) LastItem = newnode;
158 else p->Next()->Previous() = newnode;
161 if (Index < CurrentIndex) CurrentIndex++;
165 // -------------------------------------------------------------------
166 // InsertAfter : Insert a sequence after a given index in the sequence
167 // -------------------------------------------------------------------
169 void TCollection_BaseSequence::PInsertAfter(const Standard_Integer Index, TCollection_BaseSequence& Other)
171 if (Index < 0 || Index > Size) Standard_OutOfRange::Raise();
172 if (Other.Size == 0) return;
176 TCollection_SeqNode* p = (TCollection_SeqNode*) Find(Index);
177 ((TCollection_SeqNode*)Other.FirstItem)->Previous() = p;
178 ((TCollection_SeqNode*)Other.LastItem)->Next() = p->Next();
179 if (Index == Size) LastItem = Other.LastItem;
180 else p->Next()->Previous() = (TCollection_SeqNode*)Other.LastItem;
181 p->Next() = (TCollection_SeqNode*)Other.FirstItem;
183 if (Index < CurrentIndex) CurrentIndex += Other.Size;
188 // ----------------------------------------
189 // Exchange : Exchange two elements in the sequence
190 // ----------------------------------------
191 void TCollection_BaseSequence::Exchange(const Standard_Integer I, const Standard_Integer J)
193 Standard_OutOfRange_Raise_if ( I <= 0 || J <= 0 || I > Size || J > Size,"" ) ;
202 TCollection_SeqNode* pi = (TCollection_SeqNode*) Find(I);
203 TCollection_SeqNode* pj = (TCollection_SeqNode*) Find(J);
205 // update the node before I
207 pi->Previous()->Next() = pj;
211 // update the node after J
213 pj->Next()->Previous() = pi;
217 if (pi->Next() == pj) { // I and J are consecutives, update them
218 pj->Previous() = pi->Previous();
220 pi->Next() = pj->Next();
223 else { // I and J are not consecutive
224 pi->Next()->Previous() = pj; // update the node after I
225 pj->Previous()->Next() = pi; // update the node before J
226 TCollection_SeqNode* tmp = pi->Next(); // update nodes I and J
227 pi->Next() = pj->Next();
229 tmp = pi->Previous();
230 pi->Previous() = pj->Previous();
231 pj->Previous() = tmp;
234 if (CurrentIndex == I) CurrentItem = pj;
235 else if (CurrentIndex == J) CurrentItem = pi;
238 void TCollection_BaseSequence::PSplit(const Standard_Integer Index, TCollection_BaseSequence& Sub)
240 Standard_OutOfRange_Raise_if( Index <= 0 || Index > Size,"" );
241 Standard_DomainError_Raise_if(this == &Sub,"No Split on myself!!");
243 TCollection_SeqNode* p = (TCollection_SeqNode*) Find(Index);
245 Sub.LastItem = LastItem;
246 Sub.Size = Size - Index + 1;
248 LastItem = p->Previous();
250 ((TCollection_SeqNode*)LastItem)->Next() = NULL;
252 if (CurrentIndex >= Index) {
254 CurrentItem = (TCollection_SeqNode*) FirstItem;
258 FirstItem = CurrentItem = NULL;
259 Size = CurrentIndex = 0;
262 Sub.FirstItem = Sub.CurrentItem = p;
263 p->Previous() = NULL;
264 Sub.CurrentIndex = 1;
267 void TCollection_BaseSequence::Remove(const Standard_Integer Index, const Standard_Address delnode)
269 Standard_OutOfRange_Raise_if(Index <= 0 || Index > Size,"" );
271 TCollection_SeqNode* p = (TCollection_SeqNode*) Find(Index);
273 p->Previous()->Next() = p->Next();
275 FirstItem = p->Next();
277 p->Next()->Previous() = p->Previous();
279 LastItem = p->Previous();
282 if (CurrentIndex > Index) CurrentIndex--;
283 else if (CurrentIndex == Index) {
285 CurrentItem = p->Next();
287 CurrentItem = (TCollection_SeqNode*) LastItem;
291 ((DelNode)delnode) (p);
294 // ---------------------
295 // Remove a set of items
296 // ---------------------
297 void TCollection_BaseSequence::Remove(const Standard_Integer From, const Standard_Integer To,
298 const Standard_Address delnode)
300 Standard_OutOfRange_Raise_if (From <= 0 || From > Size || To <= 0 || To > Size || From > To,"" );
302 TCollection_SeqNode* pfrom = (TCollection_SeqNode*) Find(From);
303 TCollection_SeqNode* pto = (TCollection_SeqNode*) Find(To);
305 if (pfrom->Previous())
306 pfrom->Previous()->Next() = pto->Next();
308 FirstItem = pto->Next();
310 pto->Next()->Previous() = pfrom->Previous();
312 LastItem = pfrom->Previous();
314 Size -= To - From + 1;
315 if (CurrentIndex > To)
316 CurrentIndex -= To - From + 1;
317 else if (CurrentIndex >= From) {
319 CurrentItem = pto->Next();
320 CurrentIndex = From; // AGV fix 24.05.01
322 CurrentItem = (TCollection_SeqNode*) LastItem;
328 for (i = From; i <= To; i++) {
330 pfrom = pfrom->Next();
331 ((DelNode)delnode) (pto);
335 Standard_Address TCollection_BaseSequence::Find(const Standard_Integer Index) const
338 TCollection_SeqNode* p;
339 if (Index <= CurrentIndex) {
340 if (Index < CurrentIndex / 2) {
341 p = (TCollection_SeqNode*) FirstItem;
342 for (i = 1; i < Index; i++) p = p->Next();
345 p = (TCollection_SeqNode*) CurrentItem;
346 for (i = CurrentIndex; i > Index; i--) p = p->Previous();
350 if (Index < (CurrentIndex + Size) / 2) {
351 p = (TCollection_SeqNode*) CurrentItem;
352 for (i = CurrentIndex; i < Index; i++) p = p->Next();
355 p = (TCollection_SeqNode*) LastItem;
356 for (i = Size; i > Index; i--) p = p->Previous();
362 //=======================================================================
365 //=======================================================================
367 void TCollection_BaseSequence::Nullify()
369 FirstItem = LastItem = CurrentItem = NULL;
370 CurrentIndex = Size = 0;