0031435: Data Exchange - Problem importing STEP files
[occt.git] / src / Interface / Interface_EntityCluster.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14
15 #include <Interface_EntityCluster.hxx>
16 #include <Interface_EntityIterator.hxx>
17 #include <Interface_EntityList.hxx>
18 #include <Standard_NullObject.hxx>
19 #include <Standard_OutOfRange.hxx>
20 #include <Standard_Transient.hxx>
21 #include <Standard_Type.hxx>
22 #include <NCollection_Sequence.hxx>
23
24 IMPLEMENT_STANDARD_RTTIEXT(Interface_EntityCluster,Standard_Transient)
25
26 // Un Cluster, ce sont 4 entites qui se suivent (dans le principe, nombre fixe,
27 // meme si pas 4). Elles sont remplies depuis 0. Il y a donc autant d Entites
28 // que de Handles non Nuls, plus le fait qu ils sont remplis dans l ordre
29 // Ainsi (avec Next), on consomme 5 Handles pour 4 Entites, avec une pointe
30 // pour 1 et 2 Entites (on reste a 5 Handles)
31 // Suppression : On retasse le Cluster pour que les Nulls soient tjrs a la fin
32 //  ....                        CONSTRUCTEURS                        ....
33 Interface_EntityCluster::Interface_EntityCluster ()    {  }
34
35     Interface_EntityCluster::Interface_EntityCluster
36   (const Handle(Standard_Transient)& ent)
37       {  theents[0] = ent;  }
38
39     Interface_EntityCluster::Interface_EntityCluster
40   (const Handle(Interface_EntityCluster)& ec)
41       {  thenext = ec;  }
42
43     Interface_EntityCluster::Interface_EntityCluster
44   (const Handle(Standard_Transient)& ent,
45    const Handle(Interface_EntityCluster)& ec)
46       {  theents[0] = ent;  thenext = ec;  }
47
48 //  ....                        AJOUT - SUPPRESSION                        ....
49
50     void  Interface_EntityCluster::Append
51   (const Handle(Standard_Transient)& ent)
52 {
53   if (ent.IsNull()) throw Standard_NullObject("Interface_EntityCluster Append");
54   if      (theents[0].IsNull()) theents[0] = ent;
55   else if (theents[1].IsNull()) theents[1] = ent;
56   else if (theents[2].IsNull()) theents[2] = ent;
57   else if (theents[3].IsNull()) theents[3] = ent;
58   else {                                // Si celui-ci est plein ...
59     if (thenext.IsNull()) thenext = new Interface_EntityCluster(ent);
60     else {
61       Handle(Interface_EntityCluster) aCurEntClust = thenext;
62       while (aCurEntClust->HasNext() && aCurEntClust->IsLocalFull())
63         aCurEntClust = aCurEntClust->thenext;
64       aCurEntClust->Append(ent);
65     }
66   }
67 }
68
69     Standard_Boolean  Interface_EntityCluster::Remove
70   (const Handle(Standard_Transient)& ent)
71 {
72   if (ent.IsNull()) throw Standard_NullObject("Interface_EntityCluster Remove");
73   Standard_Integer i;
74 //  <ent> est-il ici ? si oui, on a son rang
75   if      (ent == theents[0]) i = 1;
76   else if (ent == theents[1]) i = 2;
77   else if (ent == theents[2]) i = 3;
78   else if (ent == theents[3]) i = 4;
79
80 //  Sinon, passer au suivant, qui peut du coup devenir vide ->
81 //  On enleve le cluster vide de la liste (en principe cest le dernier)
82   else {                                // Pas trouve dans celui-ci ...
83     if (thenext.IsNull()) return Standard_False;
84     Standard_Integer res = thenext->Remove(ent);
85     if (res) thenext = thenext->Next();
86     return Standard_False;
87   }
88   return Remove(i);
89 }
90
91     Standard_Boolean  Interface_EntityCluster::Remove
92   (const Standard_Integer num)
93 {
94   if (num < 1) throw Standard_OutOfRange("EntityCluster : Remove");
95   Standard_Integer n = NbLocal();
96   if (num > n) {
97     if (thenext.IsNull()) throw Standard_OutOfRange("EntityCluster : Remove");
98     Standard_Boolean res = thenext->Remove (num-n);
99     if (res) thenext = thenext->Next();
100     return Standard_False;
101   }
102   for (Standard_Integer j = num; j < n; j --) theents[j-1] = theents[j];
103   theents[3].Nullify();     // On Nullify par la fin
104   return (n == 1);          // Ancien NbLocal == 1  -> devient nul
105 }
106
107 //  ....                        ACCES AUX DONNEES                        ....
108
109     Standard_Integer  Interface_EntityCluster::NbEntities() const 
110 {
111   Standard_Integer nb = NbLocal();
112   if (!thenext.IsNull()) nb += thenext->NbEntities();
113   return nb;
114 }
115
116     const Handle(Standard_Transient)&  Interface_EntityCluster::Value
117   (const Standard_Integer num) const
118 {
119   Standard_Integer nb = NbLocal(), aLocalNum=num;
120   if (num <= 0) throw Standard_OutOfRange("Interface EntityCluster : Value");
121   if (num > nb) { 
122     Handle(Interface_EntityCluster) aCurEntClust = thenext;
123     aLocalNum -= nb;
124     while (aLocalNum>aCurEntClust->NbLocal())
125     {
126       if (!aCurEntClust->HasNext()) throw Standard_OutOfRange("Interface EntityCluster : Value");
127       aCurEntClust = aCurEntClust->thenext;
128        aLocalNum-= nb;
129     }
130     return aCurEntClust->theents[aLocalNum - 1];
131   }
132   return theents[num-1];  // numerotation a partir de 0
133 }
134
135     void  Interface_EntityCluster::SetValue
136   (const Standard_Integer num, const Handle(Standard_Transient)& ent)
137 {    
138   if (ent.IsNull()) throw Standard_NullObject("Interface_EntityCluster SetValue");
139   Standard_Integer nb = NbLocal(), aLocalNum = num;
140   if (num <= 0) throw Standard_OutOfRange("Interface EntityCluster : SetValue");
141   if (num > nb)
142   {
143     Handle(Interface_EntityCluster) aCurEntClust = thenext;
144     aLocalNum -= nb;
145     while (aLocalNum > aCurEntClust->NbLocal())
146     {
147       if (thenext.IsNull()) throw Standard_OutOfRange("Interface EntityCluster : SetValue");
148       aCurEntClust = aCurEntClust->thenext;
149       aLocalNum -= nb;
150     }
151     aCurEntClust->theents[aLocalNum - 1] = ent;
152   }
153   else theents[num-1] = ent;  // numerotation a partir de 0
154 }
155
156     void  Interface_EntityCluster::FillIterator
157   (Interface_EntityIterator& iter) const 
158 {
159   if (!theents[0].IsNull()) iter.GetOneItem(theents[0]);
160   if (!theents[1].IsNull()) iter.GetOneItem(theents[1]);
161   if (!theents[2].IsNull()) iter.GetOneItem(theents[2]);
162   if (!theents[3].IsNull()) iter.GetOneItem(theents[3]);
163   if (!thenext.IsNull()) thenext->FillIterator(iter);
164 }
165
166 //  ....                    Actions atomiques internes                    ....
167
168 Standard_Boolean  Interface_EntityCluster::IsLocalFull () const 
169 {
170   // Solaris Forte C++ compiler insisted it couldn't cast this,
171   // even though it seems to do so elsewhere
172   Handle(Standard_Transient) tmp = Handle(Standard_Transient)(theents[3]);
173   return ( !tmp.IsNull() );
174 }
175
176     Standard_Integer  Interface_EntityCluster::NbLocal () const
177 {
178   Standard_Integer nb;
179   if      (!theents[3].IsNull()) nb = 4;
180   else if (!theents[2].IsNull()) nb = 3;
181   else if (!theents[1].IsNull()) nb = 2;
182   else if (!theents[0].IsNull()) nb = 1;
183   else                           nb = 0;
184   return nb;
185 }
186
187     Standard_Boolean  Interface_EntityCluster::HasNext () const 
188       {  return (!thenext.IsNull());  }
189
190     Handle(Interface_EntityCluster)  Interface_EntityCluster::Next () const 
191       {  return thenext;  }
192
193 Interface_EntityCluster::~Interface_EntityCluster()
194 {
195   if (!thenext.IsNull())
196   {
197     //Loading entities into the collection 
198     //for deletion in reverse order(avoiding the recursion)
199     NCollection_Sequence<Handle(Interface_EntityCluster)> aNColOfEntClust;
200     Handle(Interface_EntityCluster) aCurEntClust = thenext;
201     while (aCurEntClust->HasNext())
202     {
203       aNColOfEntClust.Append(aCurEntClust);
204       aCurEntClust = aCurEntClust->Next();
205     }
206     aNColOfEntClust.Append(aCurEntClust);
207     aNColOfEntClust.Reverse();
208     for (NCollection_Sequence<Handle(Interface_EntityCluster)>::Iterator anEntClustIter(aNColOfEntClust);
209       anEntClustIter.More(); anEntClustIter.Next())
210     {
211       //Nullifying and destruction all fields of each entity in the collection
212       for (Standard_Integer anInd = 0; anInd < anEntClustIter.ChangeValue()->NbLocal(); ++anInd)
213       {
214         anEntClustIter.ChangeValue()->theents[anInd].Nullify();
215       }
216       anEntClustIter.ChangeValue()->thenext.Nullify();
217     }
218   }
219   for (Standard_Integer anInd = 0; anInd < NbLocal(); ++anInd)
220   {
221     theents[anInd].Nullify();
222   }
223   thenext.Nullify();
224 }
225
226