0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / LDOM / LDOM_DeclareSequence.hxx
1 // Created on: 2001-01-29
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2001-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
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    }                                                                          \
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