b311480e |
1 | // Created on: 2001-01-29 |
2 | // Created by: Alexander GRIGORIEV |
973c2be1 |
3 | // Copyright (c) 2001-2014 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
973c2be1 |
7 | // This library is free software; you can redistribute it and / or modify it |
8 | // under the terms of the GNU Lesser General Public 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. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
7fd59977 |
15 | |
16 | #ifndef _Sequence_Declare_HeaderFile |
17 | #define _Sequence_Declare_HeaderFile |
18 | |
19 | #ifndef _Standard_Macro_HeaderFile |
20 | #include <Standard_Macro.hxx> |
21 | #endif |
22 | |
23 | // Declaration of Sequence (numbered list) class. |
24 | // Remarks on the current implementation: |
25 | // |
26 | // 1. Methods First() and Last() added |
27 | // 2. The method InsertAt(anIndex) replaces InsertBefore and InsertAfter. |
28 | // This method never throws exception "OutOfRange". Its behaviour: |
29 | // anIndex <= 1 => equivalent to Prepend() |
30 | // anIndex > Length() => equivalent to Append() |
31 | // else => equivalent to InsertBefore. |
32 | |
33 | // ******************************************************************* |
34 | // use the following somewhere in a header file; |
35 | // ClassName - name of the list class to create |
36 | // Type - type of members of the list |
37 | // ******************************************************************* |
38 | |
39 | #define DECLARE_SEQUENCE( ClassName, Type ) \ |
40 | \ |
41 | class ClassName { \ |
42 | public: \ |
43 | inline ClassName (); \ |
44 | inline ClassName (const ClassName& anOther); \ |
45 | inline ClassName& operator= (const ClassName& anOther); \ |
46 | inline Standard_Integer Length () const; \ |
47 | inline const Type& First () const; \ |
48 | inline const Type& Last () const; \ |
49 | inline const Type& Value (const Standard_Integer)const;\ |
50 | inline Type& ChangeValue (const Standard_Integer); \ |
51 | inline const Type& operator () (const Standard_Integer)const;\ |
52 | inline Type& operator () (const Standard_Integer); \ |
53 | \ |
54 | Standard_EXPORT virtual ~ClassName (); \ |
55 | Standard_EXPORT void Append (const Type& aVal); \ |
56 | Standard_EXPORT void Prepend (const Type& aVal); \ |
57 | Standard_EXPORT void InsertAt (const Standard_Integer, \ |
58 | const Type& aVal); \ |
59 | Standard_EXPORT void Clear (); \ |
60 | Standard_EXPORT void Remove (const Standard_Integer); \ |
61 | \ |
62 | private: \ |
63 | class Node { \ |
64 | private: \ |
65 | Type myValue; \ |
66 | Node * myPrev; \ |
67 | Node * myNext; \ |
68 | public: \ |
69 | Node (const Type& aValue, Node * aPrv, Node * aNxt) \ |
70 | : myValue (aValue), myPrev (aPrv), myNext (aNxt) {} \ |
71 | const Type& Value () const { return myValue; } \ |
72 | Type& ChangeValue () { return myValue; } \ |
73 | friend class ClassName; \ |
74 | }; \ |
75 | \ |
76 | Standard_EXPORT const void * FindItem (const Standard_Integer)const;\ |
77 | Standard_EXPORT void Assign (const ClassName& anOther); \ |
78 | \ |
79 | Node * myFirst; \ |
80 | Node * myLast; \ |
81 | Node * myCurrent; \ |
82 | Standard_Integer myICur; \ |
83 | Standard_Integer myLength; \ |
84 | }; \ |
85 | \ |
86 | inline ClassName::ClassName () : \ |
87 | myFirst (NULL), \ |
88 | myLast (NULL), \ |
89 | myCurrent (NULL), \ |
90 | myICur (0), \ |
91 | myLength (0) {} \ |
92 | \ |
93 | inline ClassName::ClassName (const ClassName& anOther) : \ |
94 | myFirst (NULL) \ |
95 | { \ |
96 | Assign (anOther); \ |
97 | } \ |
98 | \ |
99 | inline ClassName& ClassName::operator= (const ClassName& anOther) \ |
100 | { \ |
101 | Assign (anOther); \ |
102 | return * this; \ |
103 | } \ |
104 | \ |
105 | inline Standard_Integer ClassName::Length () const{ \ |
106 | return myLength; \ |
107 | } \ |
108 | \ |
109 | inline const Type& ClassName::First () const \ |
110 | { \ |
111 | return myFirst -> Value (); /* exception if out of range */ \ |
112 | } \ |
113 | \ |
114 | inline const Type& ClassName::Last () const \ |
115 | { \ |
116 | return myLast -> Value(); /* exception if out of range */ \ |
117 | } \ |
118 | \ |
119 | inline const Type& ClassName::Value (const Standard_Integer anI) const \ |
120 | { \ |
121 | const Node * anItem = (const Node *) FindItem (anI); \ |
122 | return anItem -> Value (); /* exception if out of range */ \ |
123 | } \ |
124 | \ |
125 | inline Type& ClassName::ChangeValue (const Standard_Integer anI) \ |
126 | { \ |
127 | Node * anItem = (Node *) FindItem (anI); \ |
128 | return anItem -> ChangeValue (); /* exception if out of range */ \ |
129 | } \ |
130 | \ |
131 | inline const Type& ClassName::operator() (const Standard_Integer anI) const \ |
132 | { \ |
133 | return Value (anI); \ |
134 | } \ |
135 | \ |
136 | inline Type& ClassName::operator() (const Standard_Integer anI) \ |
137 | { \ |
138 | return ChangeValue (anI); \ |
139 | } \ |
140 | |
141 | // ******************************************************************* |
142 | // use the following in a translation unit (*.cxx); |
143 | // |
144 | // ******************************************************************* |
145 | #define IMPLEMENT_SEQUENCE( ClassName, Type ) \ |
146 | const void * ClassName::FindItem (const Standard_Integer anI) const \ |
147 | { \ |
148 | if (anI < 1 || anI > myLength) return NULL; \ |
149 | Standard_Integer aCounter; \ |
150 | Node * aCurrent = (Node *) myCurrent; \ |
151 | Standard_Boolean aDir (Standard_False); \ |
152 | if (aCurrent == NULL) { \ |
153 | aCurrent = myFirst; \ |
154 | aCounter = anI - 1; \ |
155 | aDir = Standard_True; \ |
156 | }else{ \ |
157 | aCounter = Abs (anI - myICur); \ |
158 | if (anI <= aCounter) { \ |
159 | aCurrent = myFirst; \ |
160 | aCounter = anI - 1; \ |
161 | aDir = Standard_True; \ |
162 | }else if (myLength - anI < aCounter) { \ |
163 | aCurrent = myLast; \ |
164 | aCounter = myLength - anI; \ |
165 | }else if (anI > myICur) \ |
166 | aDir = Standard_True; \ |
167 | } \ |
168 | if (aDir) \ |
169 | while (aCounter--) aCurrent = aCurrent -> myNext; \ |
170 | else \ |
171 | while (aCounter--) aCurrent = aCurrent -> myPrev; \ |
172 | (Standard_Integer&) myICur = anI; \ |
173 | (Node *&) myCurrent = aCurrent; \ |
174 | return aCurrent; \ |
175 | } \ |
176 | \ |
177 | ClassName::~ClassName () \ |
178 | { \ |
179 | Clear (); \ |
180 | } \ |
181 | \ |
182 | void ClassName::Append (const Type& aVal) \ |
183 | { \ |
184 | Node * anItem = new Node (aVal, myLast, NULL); \ |
185 | if (myLength == 0) \ |
186 | myFirst = anItem; \ |
187 | else \ |
188 | myLast -> myNext = anItem; \ |
189 | myLast = anItem; \ |
190 | myLength++; \ |
191 | } \ |
192 | \ |
193 | void ClassName::Prepend (const Type& aVal) \ |
194 | { \ |
195 | Node * anItem = new Node (aVal, NULL, myFirst); \ |
196 | if (myLength == 0) \ |
197 | myLast = anItem; \ |
198 | else \ |
199 | myFirst -> myPrev = anItem; \ |
200 | myFirst = anItem; \ |
201 | myLength++; \ |
202 | if (myICur > 0) myICur++; \ |
203 | } \ |
204 | \ |
205 | void ClassName::InsertAt (const Standard_Integer anI, const Type& aVal) \ |
206 | { \ |
207 | if (anI <= 1) Prepend (aVal); \ |
208 | else if (anI > myLength) Append (aVal); \ |
209 | else if (FindItem(anI)) { \ |
210 | Node * anItem = new Node (aVal, myCurrent -> myPrev, myCurrent); \ |
211 | myCurrent -> myPrev = anItem; \ |
212 | if (anItem -> myPrev) anItem -> myPrev -> myNext = anItem; \ |
213 | myLength++; \ |
214 | myICur++; \ |
215 | } else ; \ |
216 | } \ |
217 | \ |
218 | void ClassName::Clear () \ |
219 | { \ |
220 | while (myFirst) { \ |
221 | Node * aCurr = myFirst -> myNext; \ |
222 | delete myFirst; \ |
223 | myFirst = aCurr; \ |
224 | } \ |
225 | myFirst = myLast = myCurrent = NULL; \ |
226 | myLength = 0; \ |
227 | myICur = 0; \ |
228 | } \ |
229 | \ |
230 | void ClassName::Remove (const Standard_Integer anI) \ |
231 | { \ |
232 | Node * anItem = (Node *) FindItem (anI); \ |
233 | if (anItem) { \ |
234 | if (myCurrent -> myPrev) { \ |
235 | myCurrent -> myPrev -> myNext = myCurrent -> myNext; \ |
236 | } \ |
237 | if (myCurrent -> myNext) { \ |
238 | myCurrent -> myNext -> myPrev = myCurrent -> myPrev; \ |
239 | myCurrent = myCurrent -> myNext; \ |
240 | }else{ \ |
241 | myCurrent = myCurrent -> myPrev; \ |
242 | myICur--; \ |
243 | } \ |
244 | if (myFirst == anItem) myFirst = myFirst -> myNext; \ |
245 | if (myLast == anItem) myLast = myLast -> myPrev; \ |
246 | delete anItem; \ |
247 | myLength--; \ |
248 | } \ |
249 | } \ |
250 | \ |
251 | void ClassName::Assign (const ClassName& anOther) \ |
252 | { \ |
253 | Clear (); \ |
254 | if (anOther.Length () == 0) return; \ |
255 | myFirst = new Node (anOther.First(), NULL, NULL); \ |
256 | Node * aPrevious = myFirst; \ |
257 | myLength = 1; \ |
258 | while (myLength < anOther.Length()) { \ |
259 | myLength++; \ |
260 | Node * aCurrent = new Node (anOther.Value(myLength), aPrevious, NULL); \ |
261 | aPrevious = aPrevious -> myNext = aCurrent; \ |
262 | } \ |
263 | myLast = aPrevious; \ |
264 | } \ |
265 | |
266 | #endif |