1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
19 //#include <Dico_Dictionary.ixx> pas en gxx
20 #include <Standard_NoSuchObject.hxx>
25 // thecars[0] : caractere de consigne, caracterisant la cellule
26 // thecars[1] : indicateur de presence : 0 rien, ==thecar[0] item present
27 // thecars[2] : caractere du Sub ou 0
28 // thecars[3] : caractere du Next ou 0
30 // REMARQUE : Fonctions d acces dupliquees : TCollection_AsciiString / CString
31 // C est a chaque fois le MEME CODE, mais Length et Value ne sont pas obtenues
32 // de la meme maniere ...
33 // SearchCell pas duplique : la version String appelle la version CString
34 // Les autres fonctions doivent d abord evaluer la longueur de <name>
35 // Sur String, methode Length, mais sur CString, il faut evaluer par strlen
36 // String serait donc meilleur (plus systematique) MAIS suppose, sur appel
37 // CString, de constituer une TCollection_AsciiString ce qui peut couter ...
38 // CONCLUSION : Fonctions d acces par Nom dupliquees, pour optimisation
41 Dico_Dictionary::Dico_Dictionary ()
43 thecars[0] = thecars[1] = thecars[2] = thecars[3] = '\0';
44 thesub.Nullify(); thenext.Nullify();
47 void Dico_Dictionary::SetChar (const char car) { thecars[0] = car; }
52 Standard_Boolean Dico_Dictionary::HasItem
53 (const Standard_CString name, const Standard_Boolean exact) const
55 Handle(Dico_Dictionary) acell;
56 Standard_Integer stat;
58 SearchCell (name,strlen(name),name[0],1, acell,reslev,stat);
59 if (stat != 0 || reslev != 0) return Standard_False;
60 if (acell->HasIt()) return Standard_True;
61 if (!exact) { if (!acell->Complete(acell)) return Standard_False; }
62 return (acell->HasIt());
65 Standard_Boolean Dico_Dictionary::HasItem
66 (const TCollection_AsciiString& name, const Standard_Boolean exact) const
68 Handle(Dico_Dictionary) acell;
69 Standard_Integer stat;
71 SearchCell (name.ToCString(),name.Length(),name.Value(1),1, acell,reslev,stat);
72 if (stat != 0 || reslev != 0) return Standard_False;
73 if (acell->HasIt()) return Standard_True;
74 if (!exact) { if (!acell->Complete(acell)) return Standard_False; }
75 return (acell->HasIt());
80 const TheItem& Dico_Dictionary::Item
81 (const Standard_CString name, const Standard_Boolean exact) const
83 Handle(Dico_Dictionary) acell;
84 Standard_Integer stat;
86 SearchCell (name,strlen(name),name[0],1, acell,reslev,stat);
87 if (stat != 0 || reslev != 0)
88 Standard_NoSuchObject::Raise("Dictionary : Item");
89 if (acell->HasIt()) return acell->It();
90 if (!exact) { if (!acell->Complete(acell)) return acell->It(); }
91 if (!acell->HasIt()) Standard_NoSuchObject::Raise("Dictionary : Item");
95 const TheItem& Dico_Dictionary::Item
96 (const TCollection_AsciiString& name, const Standard_Boolean exact) const
98 Handle(Dico_Dictionary) acell;
99 Standard_Integer stat;
100 Standard_Size reslev;
101 SearchCell (name.ToCString(),name.Length(),name.Value(1),1, acell,reslev,stat);
102 if (stat != 0 || reslev != 0)
103 Standard_NoSuchObject::Raise("Dictionary : Item");
104 if (acell->HasIt()) return acell->It();
105 if (!exact) { if (!acell->Complete(acell)) return acell->It(); }
106 if (!acell->HasIt()) Standard_NoSuchObject::Raise("Dictionary : Item");
107 return (acell->It());
112 Standard_Boolean Dico_Dictionary::GetItem
113 (const Standard_CString name,
114 TheItem& anitem, const Standard_Boolean exact) const
116 Handle(Dico_Dictionary) acell;
117 Standard_Integer stat;
118 Standard_Size reslev;
119 SearchCell (name,strlen(name),name[0],1, acell,reslev,stat);
120 if (stat != 0 || reslev != 0) return Standard_False;
121 if (acell->HasIt()) { anitem = acell->It(); return Standard_True; }
122 if (!exact) { if (!acell->Complete(acell)) return Standard_False; }
123 anitem = acell->It();
124 return (acell->HasIt());
127 Standard_Boolean Dico_Dictionary::GetItem
128 (const TCollection_AsciiString& name,
129 TheItem& anitem, const Standard_Boolean exact) const
131 Handle(Dico_Dictionary) acell;
132 Standard_Integer stat;
133 Standard_Size reslev;
134 SearchCell (name.ToCString(),name.Length(),name.Value(1),1, acell,reslev,stat);
135 if (stat != 0 || reslev != 0) return Standard_False;
136 if (acell->HasIt()) { anitem = acell->It(); return Standard_True; }
137 if (!exact) { if (!acell->Complete(acell)) return Standard_False; }
138 anitem = acell->It();
139 return (acell->HasIt());
144 void Dico_Dictionary::SetItem
145 (const Standard_CString name,
146 const TheItem& anitem, const Standard_Boolean exact)
148 Handle(Dico_Dictionary) acell;
149 Standard_Integer stat;
150 Standard_Size reslev;
151 Standard_Size namlen = strlen(name);
152 SearchCell (name,namlen,name[0],1, acell,reslev,stat);
153 if (!exact && !acell->HasIt())
154 { if (acell->Complete(acell)) { acell->SetIt(anitem); return; } }
155 if (stat < 0) { cout<<"Dictionary walk back not performed"<<endl; return; }
156 NewCell (name,namlen, acell,reslev,stat);
157 acell->SetIt(anitem);
161 void Dico_Dictionary::SetItem
162 (const TCollection_AsciiString& name,
163 const TheItem& anitem, const Standard_Boolean exact)
165 Handle(Dico_Dictionary) acell;
166 Standard_Integer stat;
167 Standard_Size reslev;
168 Standard_CString namval = name.ToCString();
169 Standard_Integer namlen = name.Length();
170 SearchCell (namval,namlen,name.Value(1),1, acell,reslev,stat);
171 if (!exact && !acell->HasIt())
172 { if (acell->Complete(acell)) { acell->SetIt(anitem); return; } }
173 if (stat < 0) { cout<<"Dictionary walk back not performed"<<endl; return; }
174 NewCell (namval,namlen, acell,reslev,stat);
175 acell->SetIt(anitem);
181 TheItem& Dico_Dictionary::NewItem
182 (const Standard_CString name,
183 Standard_Boolean& isvalued, const Standard_Boolean exact)
185 Handle(Dico_Dictionary) acell;
186 Standard_Integer stat;
187 Standard_Size reslev;
188 Standard_Size namlen = strlen(name);
189 SearchCell (name,namlen,name[0],1, acell,reslev,stat);
190 if (stat == 0 && reslev == 0) {
191 isvalued = acell->HasIt(); // ancien statut
192 acell->DeclIt(); // nouveau statut = value d office
193 return acell->ItAdr();
196 if (acell->Complete(acell))
197 { isvalued = acell->HasIt(); acell->DeclIt(); return acell->ItAdr(); }
199 if (stat < 0) { Standard_NoSuchObject::Raise("Dictionary : NewItem"); }
200 NewCell (name,namlen, acell,reslev,stat);
201 isvalued = acell->HasIt(); // ancien statut
202 acell->DeclIt(); // nouveau statut = value d office
203 return acell->ItAdr();
207 TheItem& Dico_Dictionary::NewItem
208 (const TCollection_AsciiString& name,
209 Standard_Boolean& isvalued, const Standard_Boolean exact)
211 Handle(Dico_Dictionary) acell;
212 Standard_Integer stat;
213 Standard_Size reslev;
214 Standard_Integer namlen = name.Length();
215 Standard_CString namval = name.ToCString();
216 SearchCell (namval,namlen,name.Value(1),1, acell,reslev,stat);
217 if (stat == 0 && reslev == 0) {
218 isvalued = acell->HasIt(); // ancien statut
219 acell->DeclIt(); // nouveau statut = value d office
220 return acell->ItAdr();
223 if (acell->Complete(acell))
224 { isvalued = acell->HasIt(); acell->DeclIt(); return acell->ItAdr(); }
226 if (stat < 0) { Standard_NoSuchObject::Raise("Dictionary : NewItem"); }
227 NewCell (namval,namlen, acell,reslev,stat);
228 isvalued = acell->HasIt(); // ancien statut
229 acell->DeclIt(); // nouveau statut = value d office
230 return acell->ItAdr();
233 // .... RemoveItem ....
235 Standard_Boolean Dico_Dictionary::RemoveItem
236 (const Standard_CString name,
237 const Standard_Boolean cln, const Standard_Boolean exact)
239 Handle(Dico_Dictionary) acell;
240 Standard_Integer stat;
241 Standard_Size reslev;
242 SearchCell (name,strlen(name),name[0],1, acell,reslev,stat);
243 // if (stat != 0) { cout<<"Dictionary : RemoveItem not found"<<endl; return; }
244 if (stat != 0) return Standard_False;
245 if (!exact && !acell->HasIt())
246 { if (!acell->Complete(acell)) return Standard_False; }
249 return Standard_True;
252 Standard_Boolean Dico_Dictionary::RemoveItem
253 (const TCollection_AsciiString& name,
254 const Standard_Boolean cln, const Standard_Boolean exact)
256 Handle(Dico_Dictionary) acell;
257 Standard_Integer stat;
258 Standard_Size reslev;
259 SearchCell (name.ToCString(),name.Length(),name.Value(1),1, acell,reslev,stat);
260 // if (stat != 0) { cout<<"Dictionary : RemoveItem not found"<<endl; return; }
261 if (stat != 0) return Standard_False;
262 if (!exact && !acell->HasIt())
263 { if (!acell->Complete(acell)) return Standard_False; }
266 return Standard_True;
269 // .... Methodes d Interet General ....
271 void Dico_Dictionary::Clean ()
275 if (!thesub->HasIt() && !thesub->HasSub()) { // alors prendre son Next
276 if (thesub->HasNext()) {
277 thesub = thesub->Next();
278 thecars[2] = thesub->CellChar();
287 if (!thenext->HasIt() && !thenext->HasSub()) { // alors prendre son Next
288 if (thenext->HasNext()) {
289 thenext = thenext->Next();
290 thecars[3] = thenext->CellChar();
299 Standard_Boolean Dico_Dictionary::IsEmpty () const
301 if (thecars[1] != '\0') return Standard_False;
302 if (!thesub.IsNull())
303 { if (!thesub->IsEmpty()) return Standard_False; }
304 if (!thenext.IsNull())
305 { if (!thenext->IsEmpty()) return Standard_False; }
306 return Standard_True;
309 void Dico_Dictionary::Clear ()
311 thecars[0] = thecars[1] = thecars[2] = thecars[3] = '\0';
312 thesub.Nullify(); thenext.Nullify();
316 Handle(Dico_Dictionary) Dico_Dictionary::Copy () const
318 Handle(Dico_Dictionary) newdic = new Dico_Dictionary;
319 // Handle(Dico_Dictionary)::DownCast(ShallowCopy());
320 newdic->GetCopied(this); // qui doit gerer completement thecars et item
324 // ########################################################################
326 // .... Routines internes ....
328 Standard_Boolean Dico_Dictionary::HasSub () const
329 { return (thecars[2] != '\0'); }
331 Handle(Dico_Dictionary) Dico_Dictionary::Sub () const { return thesub; }
333 Standard_Boolean Dico_Dictionary::HasNext () const
334 { return (thecars[3] != '\0'); }
336 Handle(Dico_Dictionary) Dico_Dictionary::Next () const { return thenext; }
338 void Dico_Dictionary::SetSub (const Handle(Dico_Dictionary)& acell)
340 thesub = acell; thecars[2] = '\0';
341 if (!acell.IsNull()) thecars[2] = acell->CellChar();
344 void Dico_Dictionary::SetNext (const Handle(Dico_Dictionary)& acell)
346 thenext = acell; thecars[3] = '\0';
347 if (!acell.IsNull()) thecars[3] = acell->CellChar();
350 // .... SearchCell ....
352 void Dico_Dictionary::SearchCell
353 (const Standard_CString name, const Standard_Size lmax,
354 const Standard_Character car, const Standard_Size level,
355 Handle(Dico_Dictionary)& acell,
356 Standard_Size& reslev, Standard_Integer& stat) const
358 reslev = lmax - level;
359 if (car > thecars[0]) {
360 if (thecars[3] == '\0') { acell = this; stat = 1; return; }
361 else { // ici, HasNext
362 if (thecars[3] > car) { acell = this; stat = 1; return; }
363 Standard_Integer stat2;
365 thenext->SearchCell (name,lmax,car,level,acell,lev2,stat2);
366 if (stat2 < 0) { acell = this; stat = 1; return; }
367 else { stat = stat2; reslev = lev2; return; }
370 else if (car == thecars[0]) {
371 if (reslev == 0 || thecars[2] == '\0') // c-a-d !HasSub
372 { acell = this; stat = 0; return; }
374 Standard_Character carsub = name[level]; // caractere no (level+1);
375 if (thecars[2] > carsub) { acell = this; stat = 0; return; }
376 Standard_Integer stat2;
378 thesub->SearchCell (name,lmax,carsub,level+1,acell,lev2,stat2);
379 if (stat2 < 0) { acell = this; stat = 0; return; }
380 else { stat = stat2; reslev = lev2; return; }
383 else if (car < thecars[0]) { acell = this; stat = -1; return; }
389 void Dico_Dictionary::NewCell
390 (const Standard_CString name, const Standard_Size namlen,
391 Handle(Dico_Dictionary)& acell,
392 const Standard_Size reslev, const Standard_Integer stat)
394 Standard_Size level = namlen - reslev;
395 if (stat > 0) { // Creer une cellule next
396 Handle(Dico_Dictionary) newcell = new Dico_Dictionary;
397 newcell->SetChar( name[level-1] ); // caractere no level
398 if (acell->HasNext()) newcell->SetNext(acell->Next());
399 acell->SetNext(newcell);
402 // A present, voir les sous-niveaux
403 for (Standard_Size i = level+1; i <= namlen; i ++) {
404 Handle(Dico_Dictionary) newcell = new Dico_Dictionary;
405 newcell->SetChar(name[i-1]);
406 if (acell->HasSub()) newcell->SetNext(acell->Sub());
407 acell->SetSub(newcell);
413 Standard_Boolean Dico_Dictionary::Complete
414 (Handle(Dico_Dictionary)& newcell) const
416 if (!HasSub()) { newcell = this; return HasIt(); }
417 if (HasIt()) { newcell = this; return Standard_False; }
418 if (thesub->HasNext()) { newcell = this; return Standard_False; }
419 return thesub->Complete (newcell);
423 // ## ## ## ## ## ## ## ## ## ## ## ## ##
424 // .... Actions Internes Unitaires ....
426 Standard_Boolean Dico_Dictionary::HasIt () const
427 { return (thecars[1] != '\0'); }
429 const TheItem& Dico_Dictionary::It () const { return theitem; }
431 TheItem& Dico_Dictionary::ItAdr () { return theitem; }
433 void Dico_Dictionary::SetIt (const TheItem& anitem)
434 { theitem = anitem; thecars[1] = thecars[0]; }
436 void Dico_Dictionary::DeclIt () { thecars[1] = thecars[0]; }
438 void Dico_Dictionary::RemoveIt () { thecars[1] = '\0'; }
440 Standard_Character Dico_Dictionary::CellChar () const
441 { return thecars[0]; }
443 void Dico_Dictionary::GetCopied (const Handle(Dico_Dictionary)& fromcell)
445 thecars[0] = fromcell->CellChar();
446 // On reprend l item s ilyena un
447 if (fromcell->HasIt()) {
448 thecars[1] = thecars[0];
449 theitem = fromcell->It();
451 else thecars[1] = '\0';
453 // On saute les noeuds vides
454 if (fromcell->HasSub()) {
455 thesub = fromcell->Sub()->Copy();
456 while (!thesub->HasIt() && !thesub->HasSub()) {
457 thesub = thesub->Next();
458 if (thesub.IsNull()) { thecars[2] = '\0'; break; }
459 else thecars[2] = thesub->CellChar();
463 if (fromcell->HasNext()) {
464 thenext = fromcell->Next()->Copy();
465 while (!thenext->HasIt() && !thenext->HasSub()) {
466 thenext = thenext->Next();
467 if (thenext.IsNull()) { thecars[3] = '\0'; break; }
468 else thecars[3] = thenext->CellChar();