1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 //#include <Dico_Dictionary.ixx> pas en gxx
16 #include <Standard_NoSuchObject.hxx>
21 // thecars[0] : caractere de consigne, caracterisant la cellule
22 // thecars[1] : indicateur de presence : 0 rien, ==thecar[0] item present
23 // thecars[2] : caractere du Sub ou 0
24 // thecars[3] : caractere du Next ou 0
26 // REMARQUE : Fonctions d acces dupliquees : TCollection_AsciiString / CString
27 // C est a chaque fois le MEME CODE, mais Length et Value ne sont pas obtenues
28 // de la meme maniere ...
29 // SearchCell pas duplique : la version String appelle la version CString
30 // Les autres fonctions doivent d abord evaluer la longueur de <name>
31 // Sur String, methode Length, mais sur CString, il faut evaluer par strlen
32 // String serait donc meilleur (plus systematique) MAIS suppose, sur appel
33 // CString, de constituer une TCollection_AsciiString ce qui peut couter ...
34 // CONCLUSION : Fonctions d acces par Nom dupliquees, pour optimisation
37 Dico_Dictionary::Dico_Dictionary ()
39 thecars[0] = thecars[1] = thecars[2] = thecars[3] = '\0';
40 thesub.Nullify(); thenext.Nullify();
43 void Dico_Dictionary::SetChar (const char car) { thecars[0] = car; }
48 Standard_Boolean Dico_Dictionary::HasItem
49 (const Standard_CString name, const Standard_Boolean exact) const
51 Handle(Dico_Dictionary) acell;
52 Standard_Integer stat;
54 SearchCell (name,strlen(name),name[0],1, acell,reslev,stat);
55 if (stat != 0 || reslev != 0) return Standard_False;
56 if (acell->HasIt()) return Standard_True;
57 if (!exact) { if (!acell->Complete(acell)) return Standard_False; }
58 return (acell->HasIt());
61 Standard_Boolean Dico_Dictionary::HasItem
62 (const TCollection_AsciiString& name, const Standard_Boolean exact) const
64 Handle(Dico_Dictionary) acell;
65 Standard_Integer stat;
67 SearchCell (name.ToCString(),name.Length(),name.Value(1),1, acell,reslev,stat);
68 if (stat != 0 || reslev != 0) return Standard_False;
69 if (acell->HasIt()) return Standard_True;
70 if (!exact) { if (!acell->Complete(acell)) return Standard_False; }
71 return (acell->HasIt());
76 const TheItem& Dico_Dictionary::Item
77 (const Standard_CString name, const Standard_Boolean exact) const
79 Handle(Dico_Dictionary) acell;
80 Standard_Integer stat;
82 SearchCell (name,strlen(name),name[0],1, acell,reslev,stat);
83 if (stat != 0 || reslev != 0)
84 Standard_NoSuchObject::Raise("Dictionary : Item");
85 if (acell->HasIt()) return acell->It();
86 if (!exact) { if (!acell->Complete(acell)) return acell->It(); }
87 if (!acell->HasIt()) Standard_NoSuchObject::Raise("Dictionary : Item");
91 const TheItem& Dico_Dictionary::Item
92 (const TCollection_AsciiString& name, const Standard_Boolean exact) const
94 Handle(Dico_Dictionary) acell;
95 Standard_Integer stat;
97 SearchCell (name.ToCString(),name.Length(),name.Value(1),1, acell,reslev,stat);
98 if (stat != 0 || reslev != 0)
99 Standard_NoSuchObject::Raise("Dictionary : Item");
100 if (acell->HasIt()) return acell->It();
101 if (!exact) { if (!acell->Complete(acell)) return acell->It(); }
102 if (!acell->HasIt()) Standard_NoSuchObject::Raise("Dictionary : Item");
103 return (acell->It());
108 Standard_Boolean Dico_Dictionary::GetItem
109 (const Standard_CString name,
110 TheItem& anitem, const Standard_Boolean exact) const
112 Handle(Dico_Dictionary) acell;
113 Standard_Integer stat;
114 Standard_Size reslev;
115 SearchCell (name,strlen(name),name[0],1, acell,reslev,stat);
116 if (stat != 0 || reslev != 0) return Standard_False;
117 if (acell->HasIt()) { anitem = acell->It(); return Standard_True; }
118 if (!exact) { if (!acell->Complete(acell)) return Standard_False; }
119 anitem = acell->It();
120 return (acell->HasIt());
123 Standard_Boolean Dico_Dictionary::GetItem
124 (const TCollection_AsciiString& name,
125 TheItem& anitem, const Standard_Boolean exact) const
127 Handle(Dico_Dictionary) acell;
128 Standard_Integer stat;
129 Standard_Size reslev;
130 SearchCell (name.ToCString(),name.Length(),name.Value(1),1, acell,reslev,stat);
131 if (stat != 0 || reslev != 0) return Standard_False;
132 if (acell->HasIt()) { anitem = acell->It(); return Standard_True; }
133 if (!exact) { if (!acell->Complete(acell)) return Standard_False; }
134 anitem = acell->It();
135 return (acell->HasIt());
140 void Dico_Dictionary::SetItem
141 (const Standard_CString name,
142 const TheItem& anitem, const Standard_Boolean exact)
144 Handle(Dico_Dictionary) acell;
145 Standard_Integer stat;
146 Standard_Size reslev;
147 Standard_Size namlen = strlen(name);
148 SearchCell (name,namlen,name[0],1, acell,reslev,stat);
149 if (!exact && !acell->HasIt())
150 { if (acell->Complete(acell)) { acell->SetIt(anitem); return; } }
151 if (stat < 0) { cout<<"Dictionary walk back not performed"<<endl; return; }
152 NewCell (name,namlen, acell,reslev,stat);
153 acell->SetIt(anitem);
157 void Dico_Dictionary::SetItem
158 (const TCollection_AsciiString& name,
159 const TheItem& anitem, const Standard_Boolean exact)
161 Handle(Dico_Dictionary) acell;
162 Standard_Integer stat;
163 Standard_Size reslev;
164 Standard_CString namval = name.ToCString();
165 Standard_Integer namlen = name.Length();
166 SearchCell (namval,namlen,name.Value(1),1, acell,reslev,stat);
167 if (!exact && !acell->HasIt())
168 { if (acell->Complete(acell)) { acell->SetIt(anitem); return; } }
169 if (stat < 0) { cout<<"Dictionary walk back not performed"<<endl; return; }
170 NewCell (namval,namlen, acell,reslev,stat);
171 acell->SetIt(anitem);
177 TheItem& Dico_Dictionary::NewItem
178 (const Standard_CString name,
179 Standard_Boolean& isvalued, const Standard_Boolean exact)
181 Handle(Dico_Dictionary) acell;
182 Standard_Integer stat;
183 Standard_Size reslev;
184 Standard_Size namlen = strlen(name);
185 SearchCell (name,namlen,name[0],1, acell,reslev,stat);
186 if (stat == 0 && reslev == 0) {
187 isvalued = acell->HasIt(); // ancien statut
188 acell->DeclIt(); // nouveau statut = value d office
189 return acell->ItAdr();
192 if (acell->Complete(acell))
193 { isvalued = acell->HasIt(); acell->DeclIt(); return acell->ItAdr(); }
195 if (stat < 0) { Standard_NoSuchObject::Raise("Dictionary : NewItem"); }
196 NewCell (name,namlen, acell,reslev,stat);
197 isvalued = acell->HasIt(); // ancien statut
198 acell->DeclIt(); // nouveau statut = value d office
199 return acell->ItAdr();
203 TheItem& Dico_Dictionary::NewItem
204 (const TCollection_AsciiString& name,
205 Standard_Boolean& isvalued, const Standard_Boolean exact)
207 Handle(Dico_Dictionary) acell;
208 Standard_Integer stat;
209 Standard_Size reslev;
210 Standard_Integer namlen = name.Length();
211 Standard_CString namval = name.ToCString();
212 SearchCell (namval,namlen,name.Value(1),1, acell,reslev,stat);
213 if (stat == 0 && reslev == 0) {
214 isvalued = acell->HasIt(); // ancien statut
215 acell->DeclIt(); // nouveau statut = value d office
216 return acell->ItAdr();
219 if (acell->Complete(acell))
220 { isvalued = acell->HasIt(); acell->DeclIt(); return acell->ItAdr(); }
222 if (stat < 0) { Standard_NoSuchObject::Raise("Dictionary : NewItem"); }
223 NewCell (namval,namlen, acell,reslev,stat);
224 isvalued = acell->HasIt(); // ancien statut
225 acell->DeclIt(); // nouveau statut = value d office
226 return acell->ItAdr();
229 // .... RemoveItem ....
231 Standard_Boolean Dico_Dictionary::RemoveItem
232 (const Standard_CString name,
233 const Standard_Boolean cln, const Standard_Boolean exact)
235 Handle(Dico_Dictionary) acell;
236 Standard_Integer stat;
237 Standard_Size reslev;
238 SearchCell (name,strlen(name),name[0],1, acell,reslev,stat);
239 // if (stat != 0) { cout<<"Dictionary : RemoveItem not found"<<endl; return; }
240 if (stat != 0) return Standard_False;
241 if (!exact && !acell->HasIt())
242 { if (!acell->Complete(acell)) return Standard_False; }
245 return Standard_True;
248 Standard_Boolean Dico_Dictionary::RemoveItem
249 (const TCollection_AsciiString& name,
250 const Standard_Boolean cln, const Standard_Boolean exact)
252 Handle(Dico_Dictionary) acell;
253 Standard_Integer stat;
254 Standard_Size reslev;
255 SearchCell (name.ToCString(),name.Length(),name.Value(1),1, acell,reslev,stat);
256 // if (stat != 0) { cout<<"Dictionary : RemoveItem not found"<<endl; return; }
257 if (stat != 0) return Standard_False;
258 if (!exact && !acell->HasIt())
259 { if (!acell->Complete(acell)) return Standard_False; }
262 return Standard_True;
265 // .... Methodes d Interet General ....
267 void Dico_Dictionary::Clean ()
271 if (!thesub->HasIt() && !thesub->HasSub()) { // alors prendre son Next
272 if (thesub->HasNext()) {
273 thesub = thesub->Next();
274 thecars[2] = thesub->CellChar();
283 if (!thenext->HasIt() && !thenext->HasSub()) { // alors prendre son Next
284 if (thenext->HasNext()) {
285 thenext = thenext->Next();
286 thecars[3] = thenext->CellChar();
295 Standard_Boolean Dico_Dictionary::IsEmpty () const
297 if (thecars[1] != '\0') return Standard_False;
298 if (!thesub.IsNull())
299 { if (!thesub->IsEmpty()) return Standard_False; }
300 if (!thenext.IsNull())
301 { if (!thenext->IsEmpty()) return Standard_False; }
302 return Standard_True;
305 void Dico_Dictionary::Clear ()
307 thecars[0] = thecars[1] = thecars[2] = thecars[3] = '\0';
308 thesub.Nullify(); thenext.Nullify();
312 Handle(Dico_Dictionary) Dico_Dictionary::Copy () const
314 Handle(Dico_Dictionary) newdic = new Dico_Dictionary;
315 // Handle(Dico_Dictionary)::DownCast(ShallowCopy());
316 newdic->GetCopied(this); // qui doit gerer completement thecars et item
320 // ########################################################################
322 // .... Routines internes ....
324 Standard_Boolean Dico_Dictionary::HasSub () const
325 { return (thecars[2] != '\0'); }
327 Handle(Dico_Dictionary) Dico_Dictionary::Sub () const { return thesub; }
329 Standard_Boolean Dico_Dictionary::HasNext () const
330 { return (thecars[3] != '\0'); }
332 Handle(Dico_Dictionary) Dico_Dictionary::Next () const { return thenext; }
334 void Dico_Dictionary::SetSub (const Handle(Dico_Dictionary)& acell)
336 thesub = acell; thecars[2] = '\0';
337 if (!acell.IsNull()) thecars[2] = acell->CellChar();
340 void Dico_Dictionary::SetNext (const Handle(Dico_Dictionary)& acell)
342 thenext = acell; thecars[3] = '\0';
343 if (!acell.IsNull()) thecars[3] = acell->CellChar();
346 // .... SearchCell ....
348 void Dico_Dictionary::SearchCell
349 (const Standard_CString name, const Standard_Size lmax,
350 const Standard_Character car, const Standard_Size level,
351 Handle(Dico_Dictionary)& acell,
352 Standard_Size& reslev, Standard_Integer& stat) const
354 reslev = lmax - level;
355 if (car > thecars[0]) {
356 if (thecars[3] == '\0') { acell = this; stat = 1; return; }
357 else { // ici, HasNext
358 if (thecars[3] > car) { acell = this; stat = 1; return; }
359 Standard_Integer stat2;
361 thenext->SearchCell (name,lmax,car,level,acell,lev2,stat2);
362 if (stat2 < 0) { acell = this; stat = 1; return; }
363 else { stat = stat2; reslev = lev2; return; }
366 else if (car == thecars[0]) {
367 if (reslev == 0 || thecars[2] == '\0') // c-a-d !HasSub
368 { acell = this; stat = 0; return; }
370 Standard_Character carsub = name[level]; // caractere no (level+1);
371 if (thecars[2] > carsub) { acell = this; stat = 0; return; }
372 Standard_Integer stat2;
374 thesub->SearchCell (name,lmax,carsub,level+1,acell,lev2,stat2);
375 if (stat2 < 0) { acell = this; stat = 0; return; }
376 else { stat = stat2; reslev = lev2; return; }
379 else /*if (car < thecars[0])*/{ acell = this; stat = -1; return; }
385 void Dico_Dictionary::NewCell
386 (const Standard_CString name, const Standard_Size namlen,
387 Handle(Dico_Dictionary)& acell,
388 const Standard_Size reslev, const Standard_Integer stat)
390 Standard_Size level = namlen - reslev;
391 if (stat > 0) { // Creer une cellule next
392 Handle(Dico_Dictionary) newcell = new Dico_Dictionary;
393 newcell->SetChar( name[level-1] ); // caractere no level
394 if (acell->HasNext()) newcell->SetNext(acell->Next());
395 acell->SetNext(newcell);
398 // A present, voir les sous-niveaux
399 for (Standard_Size i = level+1; i <= namlen; i ++) {
400 Handle(Dico_Dictionary) newcell = new Dico_Dictionary;
401 newcell->SetChar(name[i-1]);
402 if (acell->HasSub()) newcell->SetNext(acell->Sub());
403 acell->SetSub(newcell);
409 Standard_Boolean Dico_Dictionary::Complete
410 (Handle(Dico_Dictionary)& newcell) const
412 if (!HasSub()) { newcell = this; return HasIt(); }
413 if (HasIt()) { newcell = this; return Standard_False; }
414 if (thesub->HasNext()) { newcell = this; return Standard_False; }
415 return thesub->Complete (newcell);
419 // ## ## ## ## ## ## ## ## ## ## ## ## ##
420 // .... Actions Internes Unitaires ....
422 Standard_Boolean Dico_Dictionary::HasIt () const
423 { return (thecars[1] != '\0'); }
425 const TheItem& Dico_Dictionary::It () const { return theitem; }
427 TheItem& Dico_Dictionary::ItAdr () { return theitem; }
429 void Dico_Dictionary::SetIt (const TheItem& anitem)
430 { theitem = anitem; thecars[1] = thecars[0]; }
432 void Dico_Dictionary::DeclIt () { thecars[1] = thecars[0]; }
434 void Dico_Dictionary::RemoveIt () { thecars[1] = '\0'; }
436 Standard_Character Dico_Dictionary::CellChar () const
437 { return thecars[0]; }
439 void Dico_Dictionary::GetCopied (const Handle(Dico_Dictionary)& fromcell)
441 thecars[0] = fromcell->CellChar();
442 // On reprend l item s ilyena un
443 if (fromcell->HasIt()) {
444 thecars[1] = thecars[0];
445 theitem = fromcell->It();
447 else thecars[1] = '\0';
449 // On saute les noeuds vides
450 if (fromcell->HasSub()) {
451 thesub = fromcell->Sub()->Copy();
452 while (!thesub->HasIt() && !thesub->HasSub()) {
453 thesub = thesub->Next();
454 if (thesub.IsNull()) { thecars[2] = '\0'; break; }
455 else thecars[2] = thesub->CellChar();
459 if (fromcell->HasNext()) {
460 thenext = fromcell->Next()->Copy();
461 while (!thenext->HasIt() && !thenext->HasSub()) {
462 thenext = thenext->Next();
463 if (thenext.IsNull()) { thecars[3] = '\0'; break; }
464 else thecars[3] = thenext->CellChar();