c3e029b0c41dcedbaf3003aad467b3f845a84dbb
[occt.git] / src / Dico / Dico_Dictionary.gxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 //
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.
8 //
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.
11 //
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.
18
19 //#include <Dico_Dictionary.ixx>  pas en gxx
20 #include <Standard_NoSuchObject.hxx>
21 #include <string.h>
22
23
24
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
29
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
39
40
41 Dico_Dictionary::Dico_Dictionary ()
42 {
43   thecars[0] = thecars[1] = thecars[2] = thecars[3] = '\0';
44   thesub.Nullify(); thenext.Nullify();
45 }
46
47     void Dico_Dictionary::SetChar (const char car)  {  thecars[0] = car;  }
48
49
50 //  ....                        HasItem                                ....
51
52     Standard_Boolean Dico_Dictionary::HasItem
53   (const Standard_CString name, const Standard_Boolean exact) const
54 {
55   Handle(Dico_Dictionary) acell;
56   Standard_Integer stat;
57   Standard_Size reslev;
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());
63 }
64
65     Standard_Boolean Dico_Dictionary::HasItem
66   (const TCollection_AsciiString& name, const Standard_Boolean exact) const
67 {
68   Handle(Dico_Dictionary) acell;
69   Standard_Integer stat;
70   Standard_Size reslev;
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());
76 }
77
78 //  ....                        Item                                ....
79
80     const TheItem& Dico_Dictionary::Item
81   (const Standard_CString name, const Standard_Boolean exact) const
82 {
83   Handle(Dico_Dictionary) acell;
84   Standard_Integer stat;
85   Standard_Size reslev;
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");
92   return (acell->It());
93 }
94
95     const TheItem& Dico_Dictionary::Item
96   (const TCollection_AsciiString& name, const Standard_Boolean exact) const
97 {
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());
108 }
109
110 //  ....                        GetItem                                ....
111
112     Standard_Boolean Dico_Dictionary::GetItem
113   (const Standard_CString name,
114    TheItem& anitem, const Standard_Boolean exact) const
115 {
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());
125 }
126
127     Standard_Boolean Dico_Dictionary::GetItem
128   (const TCollection_AsciiString& name,
129    TheItem& anitem, const Standard_Boolean exact) const
130 {
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());
140 }
141
142 //  ....                        SetItem                                ....
143
144     void Dico_Dictionary::SetItem
145   (const Standard_CString name,
146    const TheItem& anitem, const Standard_Boolean exact)
147 {
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);
158 }
159
160
161     void Dico_Dictionary::SetItem
162   (const TCollection_AsciiString& name,
163    const TheItem& anitem, const Standard_Boolean exact)
164 {
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);
176 }
177
178
179 //  ....                        NewItem                                ....
180
181     TheItem& Dico_Dictionary::NewItem
182   (const Standard_CString name,
183    Standard_Boolean& isvalued, const Standard_Boolean exact)
184 {
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();
194   }
195   if (!exact) {
196     if (acell->Complete(acell))
197       {  isvalued = acell->HasIt(); acell->DeclIt();  return acell->ItAdr();  }
198   }
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();
204 }
205
206
207     TheItem& Dico_Dictionary::NewItem
208   (const TCollection_AsciiString& name,
209    Standard_Boolean& isvalued, const Standard_Boolean exact)
210 {
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();
221   }
222   if (!exact) {
223     if (acell->Complete(acell))
224       {  isvalued = acell->HasIt(); acell->DeclIt();  return acell->ItAdr();  }
225   }
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();
231 }
232
233 //  ....                        RemoveItem                                ....
234
235     Standard_Boolean Dico_Dictionary::RemoveItem
236   (const Standard_CString name,
237    const Standard_Boolean cln, const Standard_Boolean exact)
238 {
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;  }
247   acell->RemoveIt();
248   if (cln) Clean();
249   return Standard_True;
250 }
251
252     Standard_Boolean Dico_Dictionary::RemoveItem
253   (const TCollection_AsciiString& name,
254    const Standard_Boolean cln, const Standard_Boolean exact)
255 {
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;  }
264   acell->RemoveIt();
265   if (cln) Clean();
266   return Standard_True;
267 }
268
269 //  ....                Methodes d Interet General                        ....
270
271     void Dico_Dictionary::Clean ()
272 {
273   if (HasSub()) {
274     thesub->Clean();
275     if (!thesub->HasIt() && !thesub->HasSub()) {    // alors prendre son Next
276       if (thesub->HasNext()) {
277         thesub = thesub->Next();
278         thecars[2] = thesub->CellChar();
279       } else {
280         thesub.Nullify();
281         thecars[2] = '\0';
282       }
283     }
284   }
285   if (HasNext()) {
286     thenext->Clean();
287     if (!thenext->HasIt() && !thenext->HasSub()) {    // alors prendre son Next
288       if (thenext->HasNext()) {
289         thenext = thenext->Next();
290         thecars[3] = thenext->CellChar();
291       } else {
292         thenext.Nullify();
293         thecars[3] = '\0';
294       }
295     }
296   }
297 }
298
299     Standard_Boolean Dico_Dictionary::IsEmpty () const
300 {
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;
307 }
308
309     void Dico_Dictionary::Clear ()
310 {
311   thecars[0] = thecars[1] = thecars[2] = thecars[3] = '\0';
312   thesub.Nullify();  thenext.Nullify();
313 }
314
315
316     Handle(Dico_Dictionary) Dico_Dictionary::Copy () const
317 {
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
321   return newdic;
322 }
323
324 //  ########################################################################
325
326 // ....                        Routines internes                        ....
327
328     Standard_Boolean Dico_Dictionary::HasSub () const
329       {  return (thecars[2] != '\0');  }
330
331     Handle(Dico_Dictionary) Dico_Dictionary::Sub () const   { return thesub;  }
332
333     Standard_Boolean Dico_Dictionary::HasNext () const
334       {  return (thecars[3] != '\0');  }
335
336     Handle(Dico_Dictionary) Dico_Dictionary::Next () const  { return thenext; }
337
338     void Dico_Dictionary::SetSub (const Handle(Dico_Dictionary)& acell)
339 {
340   thesub = acell;      thecars[2] = '\0';
341   if (!acell.IsNull()) thecars[2] = acell->CellChar();
342 }
343
344     void Dico_Dictionary::SetNext (const Handle(Dico_Dictionary)& acell)
345 {
346   thenext = acell;     thecars[3] = '\0';
347   if (!acell.IsNull()) thecars[3] = acell->CellChar();
348 }
349
350 //  ....                            SearchCell                            ....
351
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
357 {
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;
364       Standard_Size lev2;
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;  }
368     }
369   }
370   else if (car == thecars[0]) {
371     if (reslev == 0 || thecars[2] == '\0')      // c-a-d !HasSub
372                                 {  acell = this;  stat   =  0;    return;  }
373     else {
374       Standard_Character carsub = name[level];  // caractere no (level+1);
375       if (thecars[2] > carsub)  {  acell = this;  stat   =  0;    return;  }
376       Standard_Integer stat2;
377       Standard_Size lev2;
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;  }
381     }
382   }
383   else if (car < thecars[0])    {  acell = this;  stat   = -1;    return;  }
384 }
385
386
387 //  ....                            NewCell                            ....
388
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)
393 {
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);
400     acell = newcell;
401   }
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);
408     acell = newcell;
409   }
410 }
411
412
413     Standard_Boolean Dico_Dictionary::Complete
414   (Handle(Dico_Dictionary)& newcell) const
415 {
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);
420 }
421
422
423 //  ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##
424 //  ....                    Actions Internes Unitaires                    ....
425
426     Standard_Boolean Dico_Dictionary::HasIt () const
427       {  return (thecars[1] != '\0');  }
428
429     const TheItem& Dico_Dictionary::It () const           {  return theitem;  }
430
431     TheItem& Dico_Dictionary::ItAdr ()                    {  return theitem;  }
432
433     void Dico_Dictionary::SetIt (const TheItem& anitem)
434       {  theitem = anitem;  thecars[1] = thecars[0];  }
435
436     void Dico_Dictionary::DeclIt ()              {  thecars[1] = thecars[0];  }
437
438     void Dico_Dictionary::RemoveIt ()                  {  thecars[1] = '\0';  }
439
440     Standard_Character Dico_Dictionary::CellChar () const
441       {  return thecars[0];  }
442
443     void Dico_Dictionary::GetCopied (const Handle(Dico_Dictionary)& fromcell)
444 {
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();
450   }
451   else thecars[1] = '\0';
452
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();
460     }
461   }
462
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();
469     }
470   }
471 }