0023457: Slow text rendering
[occt.git] / src / NCollection / NCollection_Sequence.hxx
1 // Created on: 2002-03-28
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2002-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20 #ifndef NCollection_Sequence_HeaderFile
21 #define NCollection_Sequence_HeaderFile
22
23 #include <NCollection_BaseCollection.hxx>
24 #include <NCollection_BaseSequence.hxx>
25
26 #ifndef No_Exception
27 #include <Standard_OutOfRange.hxx>
28 #include <Standard_NoSuchObject.hxx>
29 #endif
30
31 /**
32  * Purpose:     Definition of a sequence of elements indexed by
33  *              an Integer in range of 1..n
34  */              
35 template <class TheItemType> class NCollection_Sequence
36   : public NCollection_BaseCollection<TheItemType>,
37     public NCollection_BaseSequence
38 {
39
40  public:
41   //!   Class defining sequence node - for internal use by Sequence
42   class Node : public NCollection_SeqNode
43   {
44   public:
45     //! Constructor
46     Node (const TheItemType& theItem) :
47       NCollection_SeqNode ()
48       { myValue = theItem; }
49     //! Constant value access
50     const TheItemType& Value () const { return myValue; }
51     //! Variable value access
52     TheItemType&       ChangeValue () { return myValue; }
53     //! Memory allocation
54     DEFINE_STANDARD_ALLOC
55     DEFINE_NCOLLECTION_ALLOC
56
57   private:
58     TheItemType    myValue;
59   }; // End of nested class Node
60
61  public:
62   //!   Implementation of the Iterator interface.
63   class Iterator : public NCollection_BaseCollection<TheItemType>::Iterator,
64                    public NCollection_BaseSequence::Iterator
65   {
66   public:
67     //! Empty constructor - for later Init
68     Iterator  (void) {}
69     //! Constructor with initialisation
70     Iterator  (const NCollection_Sequence& theSeq,
71                const Standard_Boolean      isStart = Standard_True)
72       : NCollection_BaseSequence::Iterator (theSeq, isStart) {}
73     //! Assignment
74     Iterator& operator= (const Iterator& theIt)
75     {
76       NCollection_BaseSequence::Iterator& me = * this;
77       me.operator= (theIt);
78       return * this;
79     }
80     //! Check end
81     virtual Standard_Boolean More (void) const
82     { return (myCurrent!=NULL); }
83     //! Make step
84     virtual void Next (void)         
85     { if (myCurrent) myCurrent = (NCollection_SeqNode *) myCurrent->Next(); }
86     //! Constant value access
87     virtual const TheItemType& Value (void) const
88     { return ((const Node *)myCurrent)->Value(); }
89     //! Variable value access
90     virtual TheItemType& ChangeValue (void) const
91     { return ((Node *)myCurrent)->ChangeValue(); }
92   }; // End of nested class Iterator
93
94  public:
95   // ---------- PUBLIC METHODS ------------
96
97   //! Constructor
98   NCollection_Sequence(const Handle(NCollection_BaseAllocator)& theAllocator=0L)
99     : NCollection_BaseCollection<TheItemType>(theAllocator),
100       NCollection_BaseSequence() {}
101
102   //! Copy constructor
103   NCollection_Sequence (const NCollection_Sequence& theOther) :
104     NCollection_BaseCollection<TheItemType>(theOther.myAllocator),
105     NCollection_BaseSequence()
106   { *this = theOther; }
107
108   //! Number of items
109   virtual Standard_Integer Size (void) const
110   { return mySize; }
111
112   //! Number of items
113   Standard_Integer Length (void) const
114   { return mySize; }
115
116   //! Method for consistency with other collections.
117   //! @return Lower bound (inclusive) for iteration.
118   Standard_Integer Lower() const
119   {
120     return 1;
121   }
122
123   //! Method for consistency with other collections.
124   //! @return Upper bound (inclusive) for iteration.
125   Standard_Integer Upper() const
126   {
127     return mySize;
128   }
129
130   //! Empty query
131   Standard_Boolean IsEmpty (void) const
132   { return (mySize==0); }
133
134   //! Reverse sequence
135   void Reverse (void)
136   { PReverse(); }
137
138   //! Exchange two members
139   void Exchange (const Standard_Integer I,
140                  const Standard_Integer J )
141   { PExchange(I, J); }
142
143   //! Static deleter to be passed to BaseSequence
144   static void delNode (NCollection_SeqNode * theNode, 
145                        Handle(NCollection_BaseAllocator)& theAl)
146   {
147     ((Node *) theNode)->~Node();
148     theAl->Free(theNode);
149   }
150
151   //! Clear the items out, take a new allocator if non null
152   void Clear (const Handle(NCollection_BaseAllocator)& theAllocator=0L)
153   {
154     ClearSeq (delNode, this->myAllocator);
155     if (!theAllocator.IsNull())
156       this->myAllocator = theAllocator;
157   }
158   
159   //! Replace this sequence by the items of theOther
160   NCollection_Sequence& operator= (const NCollection_Sequence& theOther)
161   { 
162     if (this == &theOther) 
163       return *this;
164     Clear (theOther.myAllocator);
165     Node * pCur = (Node *) theOther.myFirstItem;
166     while (pCur) {
167       Node* pNew = new (this->myAllocator) Node (pCur->Value());
168       PAppend (pNew);
169       pCur = (Node *) pCur->Next();
170     }
171     return * this;
172   }
173
174   //! Replace this sequence by the items of theOther collection
175   virtual void Assign (const NCollection_BaseCollection<TheItemType>& theOther)
176   {
177     if (this == &theOther)
178       return;
179     Clear ();
180     TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter = 
181       theOther.CreateIterator();
182     for (; anIter.More(); anIter.Next())
183       Append(anIter.Value());
184   }
185
186   //! Remove one item
187   void Remove (Iterator& thePosition)
188   { RemoveSeq (thePosition, delNode, this->myAllocator); }
189
190   //! Remove one item
191   void Remove (const Standard_Integer theIndex)
192   { RemoveSeq (theIndex, delNode, this->myAllocator); }
193
194   //! Remove range of items
195   void Remove (const Standard_Integer theFromIndex,
196                const Standard_Integer theToIndex)
197   { RemoveSeq (theFromIndex, theToIndex, delNode, this->myAllocator); }
198
199   //! Append one item
200   void Append (const TheItemType& theItem)
201   { PAppend (new (this->myAllocator) Node (theItem)); }
202
203   //! Append another sequence (making it empty)
204   void Append (NCollection_Sequence& theSeq)
205   {
206     if (myFirstItem == theSeq.myFirstItem) Assign (theSeq);
207     PAppend (theSeq);
208   }
209
210   //! Prepend one item
211   void Prepend (const TheItemType& theItem)
212   { PPrepend (new (this->myAllocator) Node (theItem)); }
213
214   //! Prepend another sequence (making it empty)
215   void Prepend (NCollection_Sequence& theSeq)
216   {
217     if (myFirstItem == theSeq.myFirstItem) Assign (theSeq);
218     PPrepend (theSeq);
219   }
220
221   //! InsertBefore theIndex theItem
222   void InsertBefore (const Standard_Integer theIndex, 
223                      const TheItemType&     theItem)
224   { InsertAfter (theIndex-1, theItem); }
225
226   //! InsertBefore theIndex another sequence
227   void InsertBefore (const Standard_Integer theIndex,
228                      NCollection_Sequence&  theSeq)
229   { InsertAfter (theIndex-1, theSeq); }
230   
231   //! InsertAfter the position of iterator
232   void InsertAfter  (Iterator&              thePosition,
233                      const TheItemType&     theItem)
234   { PInsertAfter (thePosition, new (this->myAllocator) Node (theItem)); }
235
236   //! InsertAfter theIndex theItem
237   void InsertAfter  (const Standard_Integer theIndex,
238                      NCollection_Sequence&  theSeq)
239   { PInsertAfter (theIndex, theSeq); }
240
241   //! InsertAfter theIndex another sequence
242   void InsertAfter (const Standard_Integer  theIndex, 
243                     const TheItemType&      theItem)
244   {
245 #if !defined No_Exception && !defined No_Standard_OutOfRange
246     if (theIndex < 0 || theIndex > mySize)
247       Standard_OutOfRange::Raise ("NCollection_Sequence::InsertAfter");
248 #endif
249     PInsertAfter (theIndex, new (this->myAllocator) Node (theItem));
250   }
251
252   //! Split in two sequences
253   void Split (const Standard_Integer theIndex, NCollection_Sequence& theSeq)
254   {
255     theSeq.Clear (this->myAllocator);
256     PSplit (theIndex, theSeq);
257   }
258
259   //! First item access
260   const TheItemType& First () const
261   {
262 #if !defined No_Exception && !defined No_Standard_NoSuchObject
263     if (mySize == 0)
264       Standard_NoSuchObject::Raise ("NCollection_Sequence::First");
265 #endif
266     return ((const Node *) myFirstItem) -> Value();
267   }
268
269   //! First item access
270   TheItemType& ChangeFirst()
271   {
272 #if !defined No_Exception && !defined No_Standard_NoSuchObject
273     if (mySize == 0)
274       Standard_NoSuchObject::Raise ("NCollection_Sequence::ChangeFirst");
275 #endif
276     return ((Node* )myFirstItem)->ChangeValue();
277   }
278
279   //! Last item access
280   const TheItemType& Last () const
281   {
282 #if !defined No_Exception && !defined No_Standard_NoSuchObject
283     if (mySize == 0)
284       Standard_NoSuchObject::Raise ("NCollection_Sequence::Last");
285 #endif
286     return ((const Node *) myLastItem) -> Value();
287   }
288
289   //! Last item access
290   TheItemType& ChangeLast()
291   {
292 #if !defined No_Exception && !defined No_Standard_NoSuchObject
293     if (mySize == 0)
294       Standard_NoSuchObject::Raise ("NCollection_Sequence::ChangeLast");
295 #endif
296     return ((Node* )myLastItem)->ChangeValue();
297   }
298
299   //! Constant item access by theIndex
300   const TheItemType& Value (const Standard_Integer theIndex) const
301   {
302 #if !defined No_Exception && !defined No_Standard_OutOfRange
303     if (theIndex <= 0 || theIndex > mySize)
304       Standard_OutOfRange::Raise ("NCollection_Sequence::Value");
305 #endif
306     NCollection_Sequence * const aLocalTHIS = (NCollection_Sequence *) this;
307     aLocalTHIS -> myCurrentItem  = Find (theIndex);
308     aLocalTHIS -> myCurrentIndex = theIndex;
309     return ((const Node *) myCurrentItem) -> Value();
310   }
311
312   //! Constant operator()
313   const TheItemType& operator() (const Standard_Integer theIndex) const
314   { return Value(theIndex); }
315
316   //! Variable item access by theIndex
317   TheItemType& ChangeValue (const Standard_Integer theIndex)
318   {
319 #if !defined No_Exception && !defined No_Standard_OutOfRange
320     if (theIndex <= 0 || theIndex > mySize)
321       Standard_OutOfRange::Raise ("NCollection_Sequence::ChangeValue");
322 #endif
323     myCurrentItem  = Find (theIndex);
324     myCurrentIndex = theIndex;
325     return ((Node *) myCurrentItem) -> ChangeValue();
326   }
327
328   //! Variable operator()
329   TheItemType& operator() (const Standard_Integer theIndex)
330   { return ChangeValue(theIndex); }
331
332   //! Set item value by theIndex
333   void SetValue (const Standard_Integer theIndex, 
334                  const TheItemType& theItem)
335   { ChangeValue (theIndex) = theItem; }
336
337   // ******** Destructor - clears the Sequence
338   ~NCollection_Sequence (void)
339   { Clear(); }
340
341
342  private:
343   // ----------- PRIVATE METHODS -----------
344
345   //! Creates Iterator for use on BaseCollection
346   virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& 
347     CreateIterator(void) const
348   { return *(new (this->IterAllocator()) Iterator(*this)); }
349
350   // ---------- FRIEND CLASSES ------------
351   friend class Iterator;
352
353 };
354
355 #endif