25b11948ace128e53bc58181d985a84cf5902b56
[occt.git] / src / NCollection / NCollection_SList.hxx
1 // File:        NCollection_SList.hxx
2 // Created:     17.04.02 10:12:48
3 // Author:      Alexander Kartomin (akm)
4 // Copyright:   Open Cascade 2002
5
6 #ifndef NCollection_SList_HeaderFile
7 #define NCollection_SList_HeaderFile
8
9 #include <NCollection_BaseCollection.hxx>
10
11 #if !defined No_Exception && !defined No_Standard_NoSuchObject
12 #include <Standard_NoSuchObject.hxx>
13 #endif
14
15 /**
16  * Purpose:     An SList is a LISP like list of Items.
17  *              An SList is :
18  *                . Empty.
19  *                . Or it has a Value and a  Tail  which is an other SList. 
20  *              
21  *              The Tail of an empty list is an empty list.
22  *              SList are  shared.  It  means   that they  can  be
23  *              modified through other lists.
24  *              SList may  be used  as Iterators. They  have Next,
25  *              More, and value methods. To iterate on the content
26  *              of the list S just do.
27  *              
28  *              SList Iterator;
29  *              for (Iterator = S; Iterator.More(); Iterator.Next())
30  *                X = Iterator.Value();
31  *            
32  *              Memory usage  is  automatically managed for  SLists
33  *              (using reference counts).
34  *             
35  * Example:
36  *              If S1 and S2 are SLists :
37  *              if S1.Value() is X.
38  *              
39  *              And the following is done :
40  *              S2 = S1;
41  *              S2.SetValue(Y);
42  *            
43  *              S1.Value() becomes also Y.   So SList must be used
44  *              with   care.  Mainly  the SetValue()    method  is
45  *              dangerous. 
46  */            
47 template <class TheItemType> class NCollection_SList
48   : public NCollection_BaseCollection<TheItemType>,
49     public NCollection_BaseCollection<TheItemType>::Iterator
50 {
51  public:
52   //!   The node of SList
53   class SListNode
54   {
55   private:
56     //! Constructor
57     SListNode (const TheItemType& theItem,
58                const NCollection_SList& theTail) :
59                  myCount(1),
60                  myValue(theItem) 
61     { myTail = new (theTail.myAllocator) NCollection_SList(theTail); }
62     //! Tail
63     NCollection_SList& Tail (void)
64     { return (*myTail); }
65     //! Value
66     TheItemType& Value (void)         
67     { return myValue; }
68     //! Clear
69     void Clear (void)
70     {
71       myTail->Clear();
72       myTail->myAllocator->Free(myTail);
73     }
74
75     DEFINE_STANDARD_ALLOC
76     DEFINE_NCOLLECTION_ALLOC
77
78   private:
79     // ---------- PRIVATE FIELDS ------------
80     Standard_Integer    myCount; //!< Reference count
81     NCollection_SList * myTail;  //!< The tail
82     TheItemType         myValue; //!< Datum
83
84     // Everything above is private. Only SList has an access
85     friend class NCollection_SList<TheItemType>;
86   }; // End of nested class SListNode
87
88  public:
89   // ---------- PUBLIC METHODS ------------
90
91   //! Empty constructor
92   NCollection_SList(const Handle(NCollection_BaseAllocator)& theAllocator=0L) :
93     NCollection_BaseCollection<TheItemType>(theAllocator),
94     myNode(NULL) {}
95
96   //! Constructor
97   NCollection_SList(const TheItemType&       theItem,
98                     const NCollection_SList& theTail) :
99     NCollection_BaseCollection<TheItemType>(theTail.myAllocator)
100   { myNode = new (theTail.myAllocator) SListNode(theItem,theTail); }
101
102   //! Copy constructor
103   NCollection_SList (const NCollection_SList& theOther) :
104     NCollection_BaseCollection<TheItemType>(theOther.myAllocator)
105   { 
106     myNode = theOther.myNode; 
107     if (myNode)
108       myNode->myCount++;
109   }
110
111   //! Clear the items out
112   void Clear (void)
113   {
114     if (!myNode)
115       return;
116     myNode->myCount--; 
117     if (myNode->myCount < 1)
118     {
119       myNode->Clear();
120       this->myAllocator->Free(myNode);
121     }
122     myNode = NULL;
123   }
124
125   //! Make this list identical to theOther
126   NCollection_SList& operator= (const NCollection_SList& theOther)
127   { 
128     if (myNode != theOther.myNode) 
129     {
130       if (theOther.myNode) 
131         theOther.myNode->myCount++;
132       Clear();
133       this->myAllocator = theOther.myAllocator;
134       myNode = theOther.myNode;
135     }
136     return *this;
137   }
138
139   //! Replace this list by the items of theOther collection
140   virtual void Assign (const NCollection_BaseCollection<TheItemType>& theOther)
141   {
142     if (this == &theOther) 
143       return;
144     Clear();
145     TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& anIter = 
146       theOther.CreateIterator();
147     if (!anIter.More())
148       return;
149     SListNode *aNode, *aPrevNode=NULL;
150     for (; anIter.More(); anIter.Next())
151     {
152       aNode = new (this->myAllocator) SListNode 
153         (anIter.Value(), NCollection_SList(this->myAllocator));
154       if (IsEmpty())
155         myNode = aNode;
156       else
157         aPrevNode->Tail().myNode = aNode;
158       aPrevNode = aNode;
159     }
160   }
161
162   //! IsEmpty query
163   Standard_Boolean IsEmpty (void) const
164   { return (myNode==NULL); }
165
166   //! Value - constant access
167   virtual const TheItemType& Value (void) const
168   {
169 #if !defined No_Exception && !defined No_Standard_NoSuchObject
170     if (IsEmpty())
171       Standard_NoSuchObject::Raise ("NCollection_SList::Value");
172 #endif
173     return myNode->Value();
174   }
175
176   //! ChangeValue - variable access
177   virtual TheItemType& ChangeValue (void) const
178   { 
179 #if !defined No_Exception && !defined No_Standard_NoSuchObject
180     if (IsEmpty())
181       Standard_NoSuchObject::Raise ("NCollection_SList::ChangeValue");
182 #endif
183     return myNode->Value();
184   }
185
186   //! SetValue
187   void SetValue (const TheItemType& theItem)
188   { 
189 #if !defined No_Exception && !defined No_Standard_NoSuchObject
190     if (IsEmpty())
191       Standard_NoSuchObject::Raise ("NCollection_SList::SetValue");
192 #endif
193     myNode->Value() = theItem;
194   }
195
196   //! Tail
197   const NCollection_SList& Tail (void) const
198   { 
199     if (!IsEmpty()) 
200       return  myNode->Tail();
201     else
202       return *this;
203   }
204
205   //! ChangeTail
206   NCollection_SList& ChangeTail (void)
207   { 
208     if (!IsEmpty()) 
209       return myNode->Tail();
210     else
211       return *this;
212   }
213
214   //! SetTail
215   void SetTail (NCollection_SList& theList)
216   { 
217     if (!IsEmpty())
218       myNode->Tail() = theList;
219     else
220       *this = theList;
221   }
222
223   //! Construct
224   void Construct(const TheItemType& theItem)
225   { *this = NCollection_SList (theItem, *this); }
226
227   //! Constructed
228   NCollection_SList Constructed(const TheItemType& theItem) const
229   { return NCollection_SList (theItem, *this); }
230
231   //! ToTail
232   void ToTail (void)
233   { *this = Tail(); }
234
235   //! Initialize (~Assign)
236   void Initialize (const NCollection_SList& theOther)
237   { *this = theOther; }
238
239   //! Init (virtual method of base iterator)
240   void Init (const NCollection_SList& theOther)
241   { *this = theOther; }
242
243   //! More (~!IsEmpty)
244   virtual Standard_Boolean More (void) const
245   { return !IsEmpty(); }
246
247   //! Next (~ToTail)
248   virtual void Next (void) 
249   { ToTail(); }
250
251   //! Size - Number of items
252   virtual Standard_Integer Size (void) const
253   { return (IsEmpty() ? 0 : 1+myNode->Tail().Size()); }
254
255   //! Destructor - clears the SList
256   ~NCollection_SList (void)
257   { Clear(); }
258
259
260  private:
261   // ----------- PRIVATE METHODS -----------
262
263   //! Creates Iterator for use on BaseCollection
264   virtual TYPENAME NCollection_BaseCollection<TheItemType>::Iterator& 
265     CreateIterator(void) const
266   { return *(new (this->IterAllocator()) NCollection_SList(*this)); }
267
268  private:
269   // ---------- PRIVATE FIELDS ------------
270   SListNode*    myNode;
271
272   friend class SListNode;
273 };
274
275 #endif