0025790: Drop unimplemented method ShallowCopy() from TCollection_HSequence.cdl
[occt.git] / src / TCollection / TCollection_BaseSequence.cxx
CommitLineData
b311480e 1// Copyright (c) 1998-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 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
973c2be1 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.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
b311480e 14
7fd59977 15#include <TCollection_BaseSequence.ixx>
16#include <Standard_NoSuchObject.hxx>
17#include <Standard_OutOfRange.hxx>
18#include <Standard_DomainError.hxx>
19#include <TCollection_SeqNode.hxx>
20
21typedef void (*DelNode) (TCollection_SeqNode*);
22
23TCollection_BaseSequence::TCollection_BaseSequence() :
24 FirstItem(NULL),
25 LastItem(NULL),
26 CurrentItem(NULL),
27 CurrentIndex(0),
28 Size(0)
29{
30}
31
32
33
34// ----------------------------------
35// Clear : Clear the Current Sequence
36// ----------------------------------
37void TCollection_BaseSequence::Clear(const Standard_Address delnode)
38{
39 Size = 0;
40 TCollection_SeqNode* p = (TCollection_SeqNode*) FirstItem;
41 TCollection_SeqNode* q;
42 while (p) {
43 q = p;
44 p = p->Next();
45 ((DelNode)delnode) (q);
46 }
47 LastItem = FirstItem = CurrentItem = NULL;
48 CurrentIndex = 0;
49}
50
51void TCollection_BaseSequence::PAppend(const Standard_Address newnode)
52{
53 if (Size == 0) {
54 FirstItem = LastItem = CurrentItem = newnode;
55 CurrentIndex = Size = 1;
56 }
57 else {
58 ((TCollection_SeqNode*)LastItem)->Next() = (TCollection_SeqNode*)newnode;
59 LastItem = newnode;
60 Size++;
61 }
62}
63
64// ---------------------------------------------------
65// Append : Push a sequence at the end of the sequence
66// ---------------------------------------------------
67void TCollection_BaseSequence::PAppend(TCollection_BaseSequence& Other)
68{
69 if (Size == 0) {
70 Size = Other.Size;
71 FirstItem = Other.FirstItem;
72 LastItem = Other.LastItem;
73 CurrentItem = FirstItem;
74 CurrentIndex = 1;
75 }
76 else {
77 Size += Other.Size;
78 ((TCollection_SeqNode*)LastItem)->Next() = (TCollection_SeqNode*)Other.FirstItem;
79 if (Other.FirstItem) {
80 ((TCollection_SeqNode*)Other.FirstItem)->Previous() = (TCollection_SeqNode*)LastItem;
81 LastItem = Other.LastItem;
82 }
83 }
84 Other.Nullify();
85}
86
87
88
89void TCollection_BaseSequence::PPrepend(const Standard_Address newnode)
90{
91 if (Size == 0) {
92 FirstItem = LastItem = CurrentItem = newnode;
93 CurrentIndex = Size = 1;
94 }
95 else {
96 ((TCollection_SeqNode*)FirstItem)->Previous() = (TCollection_SeqNode*) newnode;
97 ((TCollection_SeqNode*)newnode)->Next() = (TCollection_SeqNode*)FirstItem;
98 FirstItem = newnode;
99 Size++;
100 CurrentIndex++;
101 }
102}
103
104void TCollection_BaseSequence::PPrepend(TCollection_BaseSequence& Other)
105{
106 if (Size == 0) {
107 Size = Other.Size;
108 FirstItem = Other.FirstItem;
109 LastItem = Other.LastItem;
110 CurrentIndex = 1;
111 CurrentItem = FirstItem;
112 }
113 else {
114 Size += Other.Size;
115 if (Other.LastItem) ((TCollection_SeqNode*)Other.LastItem)->Next() = (TCollection_SeqNode*)FirstItem;
116 ((TCollection_SeqNode*)FirstItem)->Previous() = (TCollection_SeqNode*)Other.LastItem;
117 FirstItem = Other.FirstItem;
118 CurrentIndex += Other.Size;
119 }
120 Other.Nullify();
121}
122
123// ---------------------------------------------------------
124// Reverse : Reverse the order of a given sequence
125// ---------------------------------------------------------
126void TCollection_BaseSequence::Reverse()
127{
128 TCollection_SeqNode* p = (TCollection_SeqNode*) FirstItem;
129 TCollection_SeqNode* tmp;
130 while (p) {
131 tmp = p->Next();
132 p->Next() = p->Previous();
133 p->Previous() = tmp;
134 p = tmp;
135 }
136 tmp = (TCollection_SeqNode*)FirstItem;
137 FirstItem = LastItem;
138 LastItem = tmp;
139 if (Size != 0) CurrentIndex = Size + 1 - CurrentIndex;
140}
141
142
143void TCollection_BaseSequence::PInsertAfter(const Standard_Integer Index, const Standard_Address N)
144{
145 if (Index == 0)
146 PPrepend(N);
147 else {
148 TCollection_SeqNode* p = (TCollection_SeqNode*) Find(Index);
149 TCollection_SeqNode* newnode = (TCollection_SeqNode*) N;
150 newnode->Next() = p->Next();
151 newnode->Previous() = p;
152 if (Index == Size) LastItem = newnode;
153 else p->Next()->Previous() = newnode;
154 p->Next() = newnode;
155 Size++;
156 if (Index < CurrentIndex) CurrentIndex++;
157 }
158}
159
160// -------------------------------------------------------------------
161// InsertAfter : Insert a sequence after a given index in the sequence
162// -------------------------------------------------------------------
163
164void TCollection_BaseSequence::PInsertAfter(const Standard_Integer Index, TCollection_BaseSequence& Other)
165{
166 if (Index < 0 || Index > Size) Standard_OutOfRange::Raise();
167 if (Other.Size == 0) return;
168 if (Index == 0)
169 PPrepend( Other );
170 else {
171 TCollection_SeqNode* p = (TCollection_SeqNode*) Find(Index);
172 ((TCollection_SeqNode*)Other.FirstItem)->Previous() = p;
173 ((TCollection_SeqNode*)Other.LastItem)->Next() = p->Next();
174 if (Index == Size) LastItem = Other.LastItem;
175 else p->Next()->Previous() = (TCollection_SeqNode*)Other.LastItem;
176 p->Next() = (TCollection_SeqNode*)Other.FirstItem;
177 Size += Other.Size;
178 if (Index < CurrentIndex) CurrentIndex += Other.Size;
179 Other.Nullify();
180 }
181}
182
183// ----------------------------------------
184// Exchange : Exchange two elements in the sequence
185// ----------------------------------------
186void TCollection_BaseSequence::Exchange(const Standard_Integer I, const Standard_Integer J)
187{
188 Standard_OutOfRange_Raise_if ( I <= 0 || J <= 0 || I > Size || J > Size,"" ) ;
189
190 // Assume I < J
191 if (I == J) return;
192 if (J < I) {
193 Exchange(J,I);
194 return;
195 }
196
197 TCollection_SeqNode* pi = (TCollection_SeqNode*) Find(I);
198 TCollection_SeqNode* pj = (TCollection_SeqNode*) Find(J);
199
200 // update the node before I
201 if (pi->Previous())
202 pi->Previous()->Next() = pj;
203 else
204 FirstItem = pj;
205
206 // update the node after J
207 if (pj->Next())
208 pj->Next()->Previous() = pi;
209 else
210 LastItem = pi;
211
212 if (pi->Next() == pj) { // I and J are consecutives, update them
213 pj->Previous() = pi->Previous();
214 pi->Previous() = pj;
215 pi->Next() = pj->Next();
216 pj->Next() = pi;
217 }
218 else { // I and J are not consecutive
219 pi->Next()->Previous() = pj; // update the node after I
220 pj->Previous()->Next() = pi; // update the node before J
221 TCollection_SeqNode* tmp = pi->Next(); // update nodes I and J
222 pi->Next() = pj->Next();
223 pj->Next() = tmp;
224 tmp = pi->Previous();
225 pi->Previous() = pj->Previous();
226 pj->Previous() = tmp;
227 }
228
229 if (CurrentIndex == I) CurrentItem = pj;
230 else if (CurrentIndex == J) CurrentItem = pi;
231}
232
233void TCollection_BaseSequence::PSplit(const Standard_Integer Index, TCollection_BaseSequence& Sub)
234{
235 Standard_OutOfRange_Raise_if( Index <= 0 || Index > Size,"" );
236 Standard_DomainError_Raise_if(this == &Sub,"No Split on myself!!");
237
238 TCollection_SeqNode* p = (TCollection_SeqNode*) Find(Index);
239
240 Sub.LastItem = LastItem;
241 Sub.Size = Size - Index + 1;
242
243 LastItem = p->Previous();
244 if (LastItem) {
245 ((TCollection_SeqNode*)LastItem)->Next() = NULL;
246 Size = Index - 1;
247 if (CurrentIndex >= Index) {
248 CurrentIndex = 1;
249 CurrentItem = (TCollection_SeqNode*) FirstItem;
250 }
251 }
252 else {
253 FirstItem = CurrentItem = NULL;
254 Size = CurrentIndex = 0;
255 }
256
257 Sub.FirstItem = Sub.CurrentItem = p;
258 p->Previous() = NULL;
259 Sub.CurrentIndex = 1;
260}
261
262void TCollection_BaseSequence::Remove(const Standard_Integer Index, const Standard_Address delnode)
263{
264 Standard_OutOfRange_Raise_if(Index <= 0 || Index > Size,"" );
265
266 TCollection_SeqNode* p = (TCollection_SeqNode*) Find(Index);
267 if (p->Previous())
268 p->Previous()->Next() = p->Next();
269 else
270 FirstItem = p->Next();
271 if (p->Next())
272 p->Next()->Previous() = p->Previous();
273 else
274 LastItem = p->Previous();
275
276 Size--;
277 if (CurrentIndex > Index) CurrentIndex--;
278 else if (CurrentIndex == Index) {
279 if (p->Next())
280 CurrentItem = p->Next();
281 else {
282 CurrentItem = (TCollection_SeqNode*) LastItem;
283 CurrentIndex = Size;
284 }
285 }
286 ((DelNode)delnode) (p);
287}
288
289// ---------------------
290// Remove a set of items
291// ---------------------
292void TCollection_BaseSequence::Remove(const Standard_Integer From, const Standard_Integer To,
293 const Standard_Address delnode)
294{
295 Standard_OutOfRange_Raise_if (From <= 0 || From > Size || To <= 0 || To > Size || From > To,"" );
296
297 TCollection_SeqNode* pfrom = (TCollection_SeqNode*) Find(From);
298 TCollection_SeqNode* pto = (TCollection_SeqNode*) Find(To);
299
300 if (pfrom->Previous())
301 pfrom->Previous()->Next() = pto->Next();
302 else
303 FirstItem = pto->Next();
304 if (pto->Next())
305 pto->Next()->Previous() = pfrom->Previous();
306 else
307 LastItem = pfrom->Previous();
308
309 Size -= To - From + 1;
310 if (CurrentIndex > To)
311 CurrentIndex -= To - From + 1;
312 else if (CurrentIndex >= From) {
313 if (pto->Next()) {
314 CurrentItem = pto->Next();
315 CurrentIndex = From; // AGV fix 24.05.01
316 } else {
317 CurrentItem = (TCollection_SeqNode*) LastItem;
318 CurrentIndex = Size;
319 }
320 }
321
322 Standard_Integer i;
323 for (i = From; i <= To; i++) {
324 pto = pfrom;
325 pfrom = pfrom->Next();
326 ((DelNode)delnode) (pto);
327 }
328}
329
330Standard_Address TCollection_BaseSequence::Find(const Standard_Integer Index) const
331{
332 Standard_Integer i;
333 TCollection_SeqNode* p;
334 if (Index <= CurrentIndex) {
335 if (Index < CurrentIndex / 2) {
336 p = (TCollection_SeqNode*) FirstItem;
337 for (i = 1; i < Index; i++) p = p->Next();
338 }
339 else {
340 p = (TCollection_SeqNode*) CurrentItem;
341 for (i = CurrentIndex; i > Index; i--) p = p->Previous();
342 }
343 }
344 else {
345 if (Index < (CurrentIndex + Size) / 2) {
346 p = (TCollection_SeqNode*) CurrentItem;
347 for (i = CurrentIndex; i < Index; i++) p = p->Next();
348 }
349 else {
350 p = (TCollection_SeqNode*) LastItem;
351 for (i = Size; i > Index; i--) p = p->Previous();
352 }
353 }
354 return p;
355}
356
357//=======================================================================
358//function : Nullify
359//purpose :
360//=======================================================================
361
362void TCollection_BaseSequence::Nullify()
363{
364 FirstItem = LastItem = CurrentItem = NULL;
365 CurrentIndex = Size = 0;
366}