999cda098adec55e143db63a0c89fd6c246c9a72
[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 reslev,stat;
57   SearchCell (name,strlen(name),name[0],1, acell,reslev,stat);
58   if (stat != 0 || reslev != 0) return Standard_False;
59   if (acell->HasIt()) return Standard_True;
60   if (!exact)    {  if (!acell->Complete(acell)) return Standard_False;  }
61   return (acell->HasIt());
62 }
63
64     Standard_Boolean Dico_Dictionary::HasItem
65   (const TCollection_AsciiString& name, const Standard_Boolean exact) const
66 {
67   Handle(Dico_Dictionary) acell;
68   Standard_Integer reslev,stat;
69   SearchCell (name.ToCString(),name.Length(),name.Value(1),1, acell,reslev,stat);
70   if (stat != 0 || reslev != 0) return Standard_False;
71   if (acell->HasIt()) return Standard_True;
72   if (!exact)    {  if (!acell->Complete(acell)) return Standard_False;  }
73   return (acell->HasIt());
74 }
75
76 //  ....                        Item                                ....
77
78     const TheItem& Dico_Dictionary::Item
79   (const Standard_CString name, const Standard_Boolean exact) const
80 {
81   Handle(Dico_Dictionary) acell;
82   Standard_Integer reslev,stat;
83   SearchCell (name,strlen(name),name[0],1, acell,reslev,stat);
84   if (stat != 0 || reslev != 0)
85     Standard_NoSuchObject::Raise("Dictionary : Item");
86   if (acell->HasIt()) return acell->It();
87   if (!exact)    {  if (!acell->Complete(acell)) return acell->It();  }
88   if (!acell->HasIt()) Standard_NoSuchObject::Raise("Dictionary : Item");
89   return (acell->It());
90 }
91
92     const TheItem& Dico_Dictionary::Item
93   (const TCollection_AsciiString& name, const Standard_Boolean exact) const
94 {
95   Handle(Dico_Dictionary) acell;
96   Standard_Integer reslev,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());
104 }
105
106 //  ....                        GetItem                                ....
107
108     Standard_Boolean Dico_Dictionary::GetItem
109   (const Standard_CString name,
110    TheItem& anitem, const Standard_Boolean exact) const
111 {
112   Handle(Dico_Dictionary) acell;
113   Standard_Integer reslev,stat;
114   SearchCell (name,strlen(name),name[0],1, acell,reslev,stat);
115   if (stat != 0 || reslev != 0) return Standard_False;
116   if (acell->HasIt())    {  anitem = acell->It();  return Standard_True;  }
117   if (!exact)      {  if (!acell->Complete(acell)) return Standard_False;  }
118   anitem = acell->It();
119   return (acell->HasIt());
120 }
121
122     Standard_Boolean Dico_Dictionary::GetItem
123   (const TCollection_AsciiString& name,
124    TheItem& anitem, const Standard_Boolean exact) const
125 {
126   Handle(Dico_Dictionary) acell;
127   Standard_Integer reslev,stat;
128   SearchCell (name.ToCString(),name.Length(),name.Value(1),1, acell,reslev,stat);
129   if (stat != 0 || reslev != 0) return Standard_False;
130   if (acell->HasIt())    {  anitem = acell->It();  return Standard_True;  }
131   if (!exact)      {  if (!acell->Complete(acell)) return Standard_False;  }
132   anitem = acell->It();
133   return (acell->HasIt());
134 }
135
136 //  ....                        SetItem                                ....
137
138     void Dico_Dictionary::SetItem
139   (const Standard_CString name,
140    const TheItem& anitem, const Standard_Boolean exact)
141 {
142   Handle(Dico_Dictionary) acell;
143   Standard_Integer reslev,stat;
144   Standard_Integer namlen = strlen(name);
145   SearchCell (name,namlen,name[0],1, acell,reslev,stat);
146   if (!exact && !acell->HasIt())
147     {  if (acell->Complete(acell)) { acell->SetIt(anitem); return; }  }
148   if (stat < 0) {  cout<<"Dictionary walk back not performed"<<endl; return;  }
149   NewCell (name,namlen, acell,reslev,stat);
150   acell->SetIt(anitem);
151 }
152
153
154     void Dico_Dictionary::SetItem
155   (const TCollection_AsciiString& name,
156    const TheItem& anitem, const Standard_Boolean exact)
157 {
158   Handle(Dico_Dictionary) acell;
159   Standard_Integer reslev,stat;
160   Standard_CString namval = name.ToCString();
161   Standard_Integer namlen = name.Length();
162   SearchCell (namval,namlen,name.Value(1),1, acell,reslev,stat);
163   if (!exact && !acell->HasIt())
164     {  if (acell->Complete(acell)) { acell->SetIt(anitem); return; }  }
165   if (stat < 0) {  cout<<"Dictionary walk back not performed"<<endl; return;  }
166   NewCell (namval,namlen, acell,reslev,stat);
167   acell->SetIt(anitem);
168 }
169
170
171 //  ....                        NewItem                                ....
172
173     TheItem& Dico_Dictionary::NewItem
174   (const Standard_CString name,
175    Standard_Boolean& isvalued, const Standard_Boolean exact)
176 {
177   Handle(Dico_Dictionary) acell;
178   Standard_Integer reslev,stat;
179   Standard_Integer namlen = strlen(name);
180   SearchCell (name,namlen,name[0],1, acell,reslev,stat);
181   if (stat == 0 && reslev == 0) {
182     isvalued = acell->HasIt();    // ancien statut
183     acell->DeclIt();              // nouveau statut = value d office
184     return acell->ItAdr();
185   }
186   if (!exact) {
187     if (acell->Complete(acell))
188       {  isvalued = acell->HasIt(); acell->DeclIt();  return acell->ItAdr();  }
189   }
190   if (stat < 0) {   Standard_NoSuchObject::Raise("Dictionary : NewItem");  }
191   NewCell (name,namlen, acell,reslev,stat);
192   isvalued = acell->HasIt();    // ancien statut
193   acell->DeclIt();              // nouveau statut = value d office
194   return acell->ItAdr();
195 }
196
197
198     TheItem& Dico_Dictionary::NewItem
199   (const TCollection_AsciiString& name,
200    Standard_Boolean& isvalued, const Standard_Boolean exact)
201 {
202   Handle(Dico_Dictionary) acell;
203   Standard_Integer reslev,stat;
204   Standard_Integer namlen = name.Length();
205   Standard_CString namval = name.ToCString();
206   SearchCell (namval,namlen,name.Value(1),1, acell,reslev,stat);
207   if (stat == 0 && reslev == 0) {
208     isvalued = acell->HasIt();    // ancien statut
209     acell->DeclIt();              // nouveau statut = value d office
210     return acell->ItAdr();
211   }
212   if (!exact) {
213     if (acell->Complete(acell))
214       {  isvalued = acell->HasIt(); acell->DeclIt();  return acell->ItAdr();  }
215   }
216   if (stat < 0) {   Standard_NoSuchObject::Raise("Dictionary : NewItem");  }
217   NewCell (namval,namlen, acell,reslev,stat);
218   isvalued = acell->HasIt();    // ancien statut
219   acell->DeclIt();              // nouveau statut = value d office
220   return acell->ItAdr();
221 }
222
223 //  ....                        RemoveItem                                ....
224
225     Standard_Boolean Dico_Dictionary::RemoveItem
226   (const Standard_CString name,
227    const Standard_Boolean cln, const Standard_Boolean exact)
228 {
229   Handle(Dico_Dictionary) acell;
230   Standard_Integer reslev,stat;
231   SearchCell (name,strlen(name),name[0],1, acell,reslev,stat);
232 //  if (stat != 0) { cout<<"Dictionary : RemoveItem not found"<<endl; return; }
233   if (stat != 0) return Standard_False;
234   if (!exact && !acell->HasIt())
235     {  if (!acell->Complete(acell)) return Standard_False;  }
236   acell->RemoveIt();
237   if (cln) Clean();
238   return Standard_True;
239 }
240
241     Standard_Boolean Dico_Dictionary::RemoveItem
242   (const TCollection_AsciiString& name,
243    const Standard_Boolean cln, const Standard_Boolean exact)
244 {
245   Handle(Dico_Dictionary) acell;
246   Standard_Integer reslev,stat;
247   SearchCell (name.ToCString(),name.Length(),name.Value(1),1, acell,reslev,stat);
248 //  if (stat != 0) { cout<<"Dictionary : RemoveItem not found"<<endl; return; }
249   if (stat != 0) return Standard_False;
250   if (!exact && !acell->HasIt())
251     {  if (!acell->Complete(acell)) return Standard_False;  }
252   acell->RemoveIt();
253   if (cln) Clean();
254   return Standard_True;
255 }
256
257 //  ....                Methodes d Interet General                        ....
258
259     void Dico_Dictionary::Clean ()
260 {
261   if (HasSub()) {
262     thesub->Clean();
263     if (!thesub->HasIt() && !thesub->HasSub()) {    // alors prendre son Next
264       if (thesub->HasNext()) {
265         thesub = thesub->Next();
266         thecars[2] = thesub->CellChar();
267       } else {
268         thesub.Nullify();
269         thecars[2] = '\0';
270       }
271     }
272   }
273   if (HasNext()) {
274     thenext->Clean();
275     if (!thenext->HasIt() && !thenext->HasSub()) {    // alors prendre son Next
276       if (thenext->HasNext()) {
277         thenext = thenext->Next();
278         thecars[3] = thenext->CellChar();
279       } else {
280         thenext.Nullify();
281         thecars[3] = '\0';
282       }
283     }
284   }
285 }
286
287     Standard_Boolean Dico_Dictionary::IsEmpty () const
288 {
289   if (thecars[1] != '\0') return Standard_False;
290   if (!thesub.IsNull())
291     {  if (!thesub->IsEmpty()) return Standard_False;  }
292   if (!thenext.IsNull())
293     {  if (!thenext->IsEmpty()) return Standard_False;  }
294   return Standard_True;
295 }
296
297     void Dico_Dictionary::Clear ()
298 {
299   thecars[0] = thecars[1] = thecars[2] = thecars[3] = '\0';
300   thesub.Nullify();  thenext.Nullify();
301 }
302
303
304     Handle(Dico_Dictionary) Dico_Dictionary::Copy () const
305 {
306   Handle(Dico_Dictionary) newdic = new Dico_Dictionary;
307 //    Handle(Dico_Dictionary)::DownCast(ShallowCopy());
308   newdic->GetCopied(this);    // qui doit gerer completement thecars et item
309   return newdic;
310 }
311
312 //  ########################################################################
313
314 // ....                        Routines internes                        ....
315
316     Standard_Boolean Dico_Dictionary::HasSub () const
317       {  return (thecars[2] != '\0');  }
318
319     Handle(Dico_Dictionary) Dico_Dictionary::Sub () const   { return thesub;  }
320
321     Standard_Boolean Dico_Dictionary::HasNext () const
322       {  return (thecars[3] != '\0');  }
323
324     Handle(Dico_Dictionary) Dico_Dictionary::Next () const  { return thenext; }
325
326     void Dico_Dictionary::SetSub (const Handle(Dico_Dictionary)& acell)
327 {
328   thesub = acell;      thecars[2] = '\0';
329   if (!acell.IsNull()) thecars[2] = acell->CellChar();
330 }
331
332     void Dico_Dictionary::SetNext (const Handle(Dico_Dictionary)& acell)
333 {
334   thenext = acell;     thecars[3] = '\0';
335   if (!acell.IsNull()) thecars[3] = acell->CellChar();
336 }
337
338 //  ....                            SearchCell                            ....
339
340     void Dico_Dictionary::SearchCell
341       (const Standard_CString name,  const Standard_Integer lmax,
342        const Standard_Character car, const Standard_Integer level,
343        Handle(Dico_Dictionary)& acell,
344        Standard_Integer& reslev,     Standard_Integer& stat) const
345 {
346   reslev = lmax - level;
347   if      (car > thecars[0]) {
348     if (thecars[3] == '\0')     {  acell = this;  stat   =  1;    return;  }
349     else {                                      // ici, HasNext
350       if (thecars[3] > car)     {  acell = this;  stat   =  1;    return;  }
351       Standard_Integer lev2,stat2;
352       thenext->SearchCell (name,lmax,car,level,acell,lev2,stat2);
353       if (stat2 < 0)            {  acell = this;  stat   =  1;    return;  }
354       else                      {  stat = stat2;  reslev = lev2;  return;  }
355     }
356   }
357   else if (car == thecars[0]) {
358     if (reslev == 0 || thecars[2] == '\0')      // c-a-d !HasSub
359                                 {  acell = this;  stat   =  0;    return;  }
360     else {
361       Standard_Character carsub = name[level];  // caractere no (level+1);
362       if (thecars[2] > carsub)  {  acell = this;  stat   =  0;    return;  }
363       Standard_Integer lev2,stat2;
364       thesub->SearchCell (name,lmax,carsub,level+1,acell,lev2,stat2);
365       if (stat2 < 0)            {  acell = this;  stat   =  0;    return;  }
366       else                      {  stat = stat2;  reslev = lev2;  return;  }
367     }
368   }
369   else if (car < thecars[0])    {  acell = this;  stat   = -1;    return;  }
370 }
371
372
373 //  ....                            NewCell                            ....
374
375     void Dico_Dictionary::NewCell
376   (const Standard_CString name, const Standard_Integer namlen,
377    Handle(Dico_Dictionary)& acell,
378    const Standard_Integer reslev, const Standard_Integer stat)
379 {
380   Standard_Integer level = namlen - reslev;
381   if (stat > 0) {    // Creer une cellule next
382     Handle(Dico_Dictionary) newcell = new Dico_Dictionary;
383     newcell->SetChar( name[level-1] );      // caractere no level
384     if (acell->HasNext()) newcell->SetNext(acell->Next());
385     acell->SetNext(newcell);
386     acell = newcell;
387   }
388 //  A present, voir les sous-niveaux
389   for (Standard_Integer i = level+1; i <= namlen; i ++) {
390     Handle(Dico_Dictionary) newcell = new Dico_Dictionary;
391     newcell->SetChar(name[i-1]);
392     if (acell->HasSub()) newcell->SetNext(acell->Sub());
393     acell->SetSub(newcell);
394     acell = newcell;
395   }
396 }
397
398
399     Standard_Boolean Dico_Dictionary::Complete
400   (Handle(Dico_Dictionary)& newcell) const
401 {
402   if (!HasSub())            {  newcell = this; return HasIt();  }
403   if (HasIt())              {  newcell = this; return Standard_False;  }
404   if (thesub->HasNext())    {  newcell = this; return Standard_False;  }
405   return thesub->Complete (newcell);
406 }
407
408
409 //  ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##
410 //  ....                    Actions Internes Unitaires                    ....
411
412     Standard_Boolean Dico_Dictionary::HasIt () const
413       {  return (thecars[1] != '\0');  }
414
415     const TheItem& Dico_Dictionary::It () const           {  return theitem;  }
416
417     TheItem& Dico_Dictionary::ItAdr ()                    {  return theitem;  }
418
419     void Dico_Dictionary::SetIt (const TheItem& anitem)
420       {  theitem = anitem;  thecars[1] = thecars[0];  }
421
422     void Dico_Dictionary::DeclIt ()              {  thecars[1] = thecars[0];  }
423
424     void Dico_Dictionary::RemoveIt ()                  {  thecars[1] = '\0';  }
425
426     Standard_Character Dico_Dictionary::CellChar () const
427       {  return thecars[0];  }
428
429     void Dico_Dictionary::GetCopied (const Handle(Dico_Dictionary)& fromcell)
430 {
431   thecars[0] = fromcell->CellChar();
432 //  On reprend l item s ilyena un
433   if (fromcell->HasIt()) {
434     thecars[1] = thecars[0];
435     theitem = fromcell->It();
436   }
437   else thecars[1] = '\0';
438
439 //  On saute les noeuds vides
440   if (fromcell->HasSub()) {
441     thesub   = fromcell->Sub()->Copy();
442     while (!thesub->HasIt() && !thesub->HasSub()) {
443       thesub = thesub->Next();
444       if (thesub.IsNull()) { thecars[2] = '\0'; break; }
445       else                   thecars[2] = thesub->CellChar();
446     }
447   }
448
449   if (fromcell->HasNext()) {
450     thenext  = fromcell->Next()->Copy();
451     while (!thenext->HasIt() && !thenext->HasSub()) {
452       thenext = thenext->Next();
453       if (thenext.IsNull()) { thecars[3] = '\0'; break; }
454       else                    thecars[3] = thenext->CellChar();
455     }
456   }
457 }