0027197: Configuration - fix compilation issues when using mingw
[occt.git] / src / Dico / Dico_Dictionary.gxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
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.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 //#include <Dico_Dictionary.ixx>  pas en gxx
16 #include <Standard_NoSuchObject.hxx>
17 #include <string.h>
18
19
20
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
25
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
35
36
37 Dico_Dictionary::Dico_Dictionary ()
38 {
39   thecars[0] = thecars[1] = thecars[2] = thecars[3] = '\0';
40   thesub.Nullify(); thenext.Nullify();
41 }
42
43     void Dico_Dictionary::SetChar (const char car)  {  thecars[0] = car;  }
44
45
46 //  ....                        HasItem                                ....
47
48     Standard_Boolean Dico_Dictionary::HasItem
49   (const Standard_CString name, const Standard_Boolean exact) const
50 {
51   Handle(Dico_Dictionary) acell;
52   Standard_Integer stat;
53   Standard_Size reslev;
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());
59 }
60
61     Standard_Boolean Dico_Dictionary::HasItem
62   (const TCollection_AsciiString& name, const Standard_Boolean exact) const
63 {
64   Handle(Dico_Dictionary) acell;
65   Standard_Integer stat;
66   Standard_Size reslev;
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());
72 }
73
74 //  ....                        Item                                ....
75
76     const TheItem& Dico_Dictionary::Item
77   (const Standard_CString name, const Standard_Boolean exact) const
78 {
79   Handle(Dico_Dictionary) acell;
80   Standard_Integer stat;
81   Standard_Size reslev;
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");
88   return (acell->It());
89 }
90
91     const TheItem& Dico_Dictionary::Item
92   (const TCollection_AsciiString& name, const Standard_Boolean exact) const
93 {
94   Handle(Dico_Dictionary) acell;
95   Standard_Integer stat;
96   Standard_Size reslev;
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 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());
121 }
122
123     Standard_Boolean Dico_Dictionary::GetItem
124   (const TCollection_AsciiString& name,
125    TheItem& anitem, const Standard_Boolean exact) const
126 {
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());
136 }
137
138 //  ....                        SetItem                                ....
139
140     void Dico_Dictionary::SetItem
141   (const Standard_CString name,
142    const TheItem& anitem, const Standard_Boolean exact)
143 {
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);
154 }
155
156
157     void Dico_Dictionary::SetItem
158   (const TCollection_AsciiString& name,
159    const TheItem& anitem, const Standard_Boolean exact)
160 {
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);
172 }
173
174
175 //  ....                        NewItem                                ....
176
177     TheItem& Dico_Dictionary::NewItem
178   (const Standard_CString name,
179    Standard_Boolean& isvalued, const Standard_Boolean exact)
180 {
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();
190   }
191   if (!exact) {
192     if (acell->Complete(acell))
193       {  isvalued = acell->HasIt(); acell->DeclIt();  return acell->ItAdr();  }
194   }
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();
200 }
201
202
203     TheItem& Dico_Dictionary::NewItem
204   (const TCollection_AsciiString& name,
205    Standard_Boolean& isvalued, const Standard_Boolean exact)
206 {
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();
217   }
218   if (!exact) {
219     if (acell->Complete(acell))
220       {  isvalued = acell->HasIt(); acell->DeclIt();  return acell->ItAdr();  }
221   }
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();
227 }
228
229 //  ....                        RemoveItem                                ....
230
231     Standard_Boolean Dico_Dictionary::RemoveItem
232   (const Standard_CString name,
233    const Standard_Boolean cln, const Standard_Boolean exact)
234 {
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;  }
243   acell->RemoveIt();
244   if (cln) Clean();
245   return Standard_True;
246 }
247
248     Standard_Boolean Dico_Dictionary::RemoveItem
249   (const TCollection_AsciiString& name,
250    const Standard_Boolean cln, const Standard_Boolean exact)
251 {
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;  }
260   acell->RemoveIt();
261   if (cln) Clean();
262   return Standard_True;
263 }
264
265 //  ....                Methodes d Interet General                        ....
266
267     void Dico_Dictionary::Clean ()
268 {
269   if (HasSub()) {
270     thesub->Clean();
271     if (!thesub->HasIt() && !thesub->HasSub()) {    // alors prendre son Next
272       if (thesub->HasNext()) {
273         thesub = thesub->Next();
274         thecars[2] = thesub->CellChar();
275       } else {
276         thesub.Nullify();
277         thecars[2] = '\0';
278       }
279     }
280   }
281   if (HasNext()) {
282     thenext->Clean();
283     if (!thenext->HasIt() && !thenext->HasSub()) {    // alors prendre son Next
284       if (thenext->HasNext()) {
285         thenext = thenext->Next();
286         thecars[3] = thenext->CellChar();
287       } else {
288         thenext.Nullify();
289         thecars[3] = '\0';
290       }
291     }
292   }
293 }
294
295     Standard_Boolean Dico_Dictionary::IsEmpty () const
296 {
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;
303 }
304
305     void Dico_Dictionary::Clear ()
306 {
307   thecars[0] = thecars[1] = thecars[2] = thecars[3] = '\0';
308   thesub.Nullify();  thenext.Nullify();
309 }
310
311
312     Handle(Dico_Dictionary) Dico_Dictionary::Copy () const
313 {
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
317   return newdic;
318 }
319
320 //  ########################################################################
321
322 // ....                        Routines internes                        ....
323
324     Standard_Boolean Dico_Dictionary::HasSub () const
325       {  return (thecars[2] != '\0');  }
326
327     Handle(Dico_Dictionary) Dico_Dictionary::Sub () const   { return thesub;  }
328
329     Standard_Boolean Dico_Dictionary::HasNext () const
330       {  return (thecars[3] != '\0');  }
331
332     Handle(Dico_Dictionary) Dico_Dictionary::Next () const  { return thenext; }
333
334     void Dico_Dictionary::SetSub (const Handle(Dico_Dictionary)& acell)
335 {
336   thesub = acell;      thecars[2] = '\0';
337   if (!acell.IsNull()) thecars[2] = acell->CellChar();
338 }
339
340     void Dico_Dictionary::SetNext (const Handle(Dico_Dictionary)& acell)
341 {
342   thenext = acell;     thecars[3] = '\0';
343   if (!acell.IsNull()) thecars[3] = acell->CellChar();
344 }
345
346 //  ....                            SearchCell                            ....
347
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
353 {
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;
360       Standard_Size lev2;
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;  }
364     }
365   }
366   else if (car == thecars[0]) {
367     if (reslev == 0 || thecars[2] == '\0')      // c-a-d !HasSub
368                                 {  acell = this;  stat   =  0;    return;  }
369     else {
370       Standard_Character carsub = name[level];  // caractere no (level+1);
371       if (thecars[2] > carsub)  {  acell = this;  stat   =  0;    return;  }
372       Standard_Integer stat2;
373       Standard_Size lev2;
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;  }
377     }
378   }
379   else /*if (car < thecars[0])*/{  acell = this;  stat   = -1;    return;  }
380 }
381
382
383 //  ....                            NewCell                            ....
384
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)
389 {
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);
396     acell = newcell;
397   }
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);
404     acell = newcell;
405   }
406 }
407
408
409     Standard_Boolean Dico_Dictionary::Complete
410   (Handle(Dico_Dictionary)& newcell) const
411 {
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);
416 }
417
418
419 //  ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##
420 //  ....                    Actions Internes Unitaires                    ....
421
422     Standard_Boolean Dico_Dictionary::HasIt () const
423       {  return (thecars[1] != '\0');  }
424
425     const TheItem& Dico_Dictionary::It () const           {  return theitem;  }
426
427     TheItem& Dico_Dictionary::ItAdr ()                    {  return theitem;  }
428
429     void Dico_Dictionary::SetIt (const TheItem& anitem)
430       {  theitem = anitem;  thecars[1] = thecars[0];  }
431
432     void Dico_Dictionary::DeclIt ()              {  thecars[1] = thecars[0];  }
433
434     void Dico_Dictionary::RemoveIt ()                  {  thecars[1] = '\0';  }
435
436     Standard_Character Dico_Dictionary::CellChar () const
437       {  return thecars[0];  }
438
439     void Dico_Dictionary::GetCopied (const Handle(Dico_Dictionary)& fromcell)
440 {
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();
446   }
447   else thecars[1] = '\0';
448
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();
456     }
457   }
458
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();
465     }
466   }
467 }