0023335: Array overrun is possible. The value of 'i' index could reach 200 in Interfa...
[occt.git] / src / Interface / Interface_MSG.cxx
1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
2 //
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
7 //
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
10 //
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
17
18
19 #include <Standard_Stream.hxx>
20
21
22 #include <Interface_MSG.ixx>
23 #include <TCollection_HAsciiString.hxx>
24 #include <Dico_DictionaryOfTransient.hxx>
25 #include <Dico_DictionaryOfInteger.hxx>
26 #include <Dico_IteratorOfDictionaryOfInteger.hxx>
27 #include <Dico_IteratorOfDictionaryOfTransient.hxx>
28 #include <TColStd_HSequenceOfHAsciiString.hxx>
29 #include <OSD_Process.hxx>
30 #include <Quantity_Date.hxx>
31
32 #include <Standard_DomainError.hxx>
33 #include <stdio.h>
34
35
36 static Handle(Dico_DictionaryOfTransient) thedic;
37 static Handle(Dico_DictionaryOfInteger)   thelist;
38 static Handle(TColStd_HSequenceOfHAsciiString) thedup;
39 static Standard_Boolean theprint  = Standard_True;
40 static Standard_Boolean therec    = Standard_False;
41 static Standard_Boolean therun    = Standard_False;
42 static Standard_Boolean theraise  = Standard_False;
43
44 static char blank[] =
45 "                                                                            ";
46 static Standard_Integer maxblank = (Standard_Integer) strlen(blank);
47
48
49 Interface_MSG::Interface_MSG (const Standard_CString key)
50     : thekey (key) , theval (NULL)
51 {
52   
53 }
54
55
56 Interface_MSG::Interface_MSG
57   (const Standard_CString key, const Standard_Integer i1)
58     : thekey (key) , theval (NULL)
59 {
60   char mess[300];
61   sprintf (mess, Interface_MSG::Translated(thekey), i1);
62   theval = new char[strlen (mess) + 1];
63   strcpy (theval,mess);
64 }
65
66
67 Interface_MSG::Interface_MSG
68   (const Standard_CString key, const Standard_Integer i1, const Standard_Integer i2)
69     : thekey (key) , theval (NULL)
70 {
71   char mess[300];
72   sprintf (mess, Interface_MSG::Translated(thekey), i1,i2);
73   theval = new char[strlen (mess) + 1];
74   strcpy (theval,mess);
75 }
76
77
78 Interface_MSG::Interface_MSG
79   (const Standard_CString key, const Standard_Real r1, const Standard_Integer intervals)
80     : thekey (key) , theval (NULL)
81 {
82   char mess[300];
83   sprintf (mess, Interface_MSG::Translated(thekey),
84            (intervals < 0 ? r1 : Interface_MSG::Intervalled(r1,intervals)) );
85   theval = new char[strlen (mess) + 1];
86   strcpy (theval,mess);
87 }
88
89
90 Interface_MSG::Interface_MSG
91   (const Standard_CString key, const Standard_CString str)
92     : thekey (key) , theval (NULL)
93 {
94   char mess[300];
95   sprintf (mess, Interface_MSG::Translated(thekey), str);
96   theval = new char[strlen (mess) + 1];
97   strcpy (theval,mess);
98 }
99
100
101 Interface_MSG::Interface_MSG
102   (const Standard_CString key,
103    const Standard_Integer val, const Standard_CString str)
104     : thekey (key) , theval (NULL)
105 {
106   char mess[300];
107   sprintf (mess, Interface_MSG::Translated(thekey), val, str);
108   theval = new char[strlen (mess) + 1];
109   strcpy (theval,mess);
110 }
111
112
113 Standard_CString  Interface_MSG::Value () const
114 {  return (theval ? theval : Interface_MSG::Translated(thekey));
115  }
116
117
118 void  Interface_MSG::Destroy ()
119 {
120   if (theval)  {
121     delete [] theval;
122     theval = NULL;
123   }
124 }
125
126
127 Interface_MSG::operator Standard_CString () const
128 {
129   return Value();
130 }
131
132
133 //  ###########    Lecture Ecriture Fichier    ##########
134
135 Standard_Integer  Interface_MSG::Read (Standard_IStream& S)
136 {
137   Standard_Integer i,nb = 0;
138   char buf[200], key[200];
139   buf[0] = '\0';
140   while (S.getline (buf,200)) {
141     if (buf[0] == '@' && buf[1] == '@') continue;
142     if (buf[0] == '\0') continue;
143     if (buf[0] == '@') {
144       nb ++;
145       for (i = 1; i <= 199; i ++) {
146         key[i-1] = buf[i];
147         if (buf[i] == '\0') break;
148       }
149     }
150     else Record (key,buf);
151     buf[0] = '\0';
152   }
153   return nb;
154 }
155
156     Standard_Integer  Interface_MSG::Read (const Standard_CString file)
157 {
158   ifstream S(file);
159   if (!S) return -1;
160   return Read (S);
161 }
162
163     Standard_Integer  Interface_MSG::Write
164   (Standard_OStream& S, const Standard_CString rootkey)
165 {
166   Standard_Integer nb = 0;
167   if (thedic.IsNull()) return nb;
168   if (rootkey[0] != '\0') S<<"@@ ROOT:"<<rootkey<<endl;
169   Dico_IteratorOfDictionaryOfTransient iter (thedic,rootkey);
170   for (iter.Start(); iter.More(); iter.Next()) {
171     S<<"@"<<iter.Name()<<"\n";
172     Handle(TCollection_HAsciiString) str =
173       Handle(TCollection_HAsciiString)::DownCast(iter.Value());
174     if (str.IsNull()) continue;
175     nb ++;
176     S<<str->ToCString()<<"\n";
177   }
178   S<<flush;
179   return nb;
180 }
181
182
183 //  ###########   EXPLOITATION   ##########
184
185 Standard_Boolean  Interface_MSG::IsKey (const Standard_CString key)
186 {
187   return (key[0] == '^');
188 }
189
190
191 Standard_CString  Interface_MSG::Translated (const Standard_CString key)
192 {
193   if (!therun) return key;
194   if (!thedic.IsNull()) {
195     Handle(TCollection_HAsciiString) str;
196     if (thedic->GetItem(key,str)) return str->ToCString();
197   }
198   if (theprint) cout<<" **  Interface_MSG:Translate ?? "<<key<<"  **"<<endl;
199   if (therec) {
200     Standard_Boolean deja;
201     if (thelist.IsNull()) thelist = new Dico_DictionaryOfInteger;
202     Standard_Integer& nb = thelist->NewItem (key,deja);
203     if (!deja) nb = 0;  nb ++;
204   }
205   if (theraise) Standard_DomainError::Raise ("Interface_MSG : Translate");
206   return key;
207 }
208
209
210 void  Interface_MSG::Record
211   (const Standard_CString key, const Standard_CString item)
212 {
213   if (thedic.IsNull()) thedic = new Dico_DictionaryOfTransient;
214   Standard_Boolean deja;
215   Handle(TCollection_HAsciiString) dup;
216   Handle(Standard_Transient)& res = thedic->NewItem (key,deja);
217   Handle(TCollection_HAsciiString) str = new TCollection_HAsciiString (item);
218   res = str;
219   if (!deja) return;
220   if (theprint) cout<<" **  Interface_MSG:Record ?? "<<key<<" ** "<<item<<"  **"<<endl;
221   if (therec) {
222     if (thedup.IsNull()) thedup = new TColStd_HSequenceOfHAsciiString();
223     dup = new TCollection_HAsciiString(key);
224     thedup->Append(dup);
225     dup = new TCollection_HAsciiString(item);
226     thedup->Append(dup);
227   }
228   if (theraise) Standard_DomainError::Raise ("Interface_MSG : Record");
229 }
230
231
232 void  Interface_MSG::SetTrace
233   (const Standard_Boolean toprint, const Standard_Boolean torecord)
234 {
235   theprint = toprint;
236   therec = torecord;
237 }
238
239
240 void  Interface_MSG::SetMode (const Standard_Boolean running,
241                               const Standard_Boolean raising)
242 {
243   therun = running;  theraise = raising;
244 }
245
246
247 void  Interface_MSG::PrintTrace (Standard_OStream& S)
248 {
249   Handle(TCollection_HAsciiString) dup;
250   Standard_Integer i, nb = 0;
251   if (!thedup.IsNull()) nb = thedup->Length()/2;
252   for (i = 1; i <= nb; i ++) {
253     dup = thedup->Value(2*i-1);
254     S<<"** DUP:"<<dup->ToCString();
255     dup = thedup->Value(2*i);
256     S<<" ** "<<dup->ToCString()<<endl;
257   }
258
259   if (thelist.IsNull()) return;
260   Dico_IteratorOfDictionaryOfInteger iter (thelist);
261   for (iter.Start(); iter.More(); iter.Next()) {
262     S<<"** MSG(NB="<<iter.Value()<<"): "<<iter.Name()<<endl;
263   }
264 }
265
266
267 //  ###########    ARRONDIS DE FLOTTANTS    ############
268
269 Standard_Real  Interface_MSG::Intervalled
270   (const Standard_Real val,
271    const Standard_Integer order, const Standard_Boolean upper)
272 {
273   Standard_Real vl = (val > 0. ? val : -val);
274   Standard_Real bl = 1., bu = 1.;
275   if (vl >= 1.) {
276     bu = 10.;
277     for (Standard_Integer i = 0; i < 200; i ++) {
278       if (vl <  bu) break;
279       bl = bu;  bu *= 10.;
280     }
281   } else {
282     bl = 0.1;
283     for (Standard_Integer i = 0; i < 200; i ++) {
284       if (vl >= bl) break;
285       bu = bl;  bl /= 10.;
286     }
287     if (vl == 0.) return 0.;
288   }
289
290   Standard_Real rst = vl/bl;
291   if        (order <= 1) rst = (upper ? 10. : 1.);
292   else if   (order == 2) {
293     if (rst <= 3.) rst = (upper ?  3. : 1.);
294     else           rst = (upper ? 10. : 3.);
295   } else if (order == 3) {
296     if      (rst <= 2.) rst = (upper ?  2. : 1.);
297     else if (rst <= 5.) rst = (upper ?  5. : 2.);
298     else                rst = (upper ? 10. : 5.);
299   } else if (order == 4) {
300     if      (rst <= 2.) rst = (upper ?  2. : 1.);
301     else if (rst <= 3.) rst = (upper ?  3. : 2.);
302     else if (rst <= 6.) rst = (upper ?  6. : 3.);
303     else                rst = (upper ? 10. : 6.);
304   }
305   else if (order <= 6) {
306     if      (rst <= 1.5) rst = (upper ?  1.5 : 1. );
307     else if (rst <= 2. ) rst = (upper ?  2.  : 1.5);
308     else if (rst <= 3. ) rst = (upper ?  3.  : 2. );
309     else if (rst <= 5. ) rst = (upper ?  5.  : 3. );
310     else if (rst <= 7. ) rst = (upper ?  7.  : 5. );
311     else                 rst = (upper ? 10.  : 7. );
312   }
313   else {   // n a de sens que jusqu a 10 ...
314     if      (rst <= 1.2) rst = (upper ?  1.2 : 1. );
315     else if (rst <= 1.5) rst = (upper ?  1.5 : 1.2);
316     else if (rst <= 2. ) rst = (upper ?  2.  : 1.5);
317     else if (rst <= 2.5) rst = (upper ?  2.5 : 2. );
318     else if (rst <= 3. ) rst = (upper ?  3.  : 2.5);
319     else if (rst <= 4. ) rst = (upper ?  4.  : 3. );
320     else if (rst <= 5. ) rst = (upper ?  5.  : 4. );
321     else if (rst <= 6. ) rst = (upper ?  6.  : 5. );
322     else if (rst <= 8. ) rst = (upper ?  8.  : 6. );
323     else                 rst = (upper ? 10.  : 8. );
324   }
325   return ((val < 0.) ? -(bl*rst) : (bl*rst) );
326 }
327
328
329 //  ###########    DATES    ############
330
331 void  Interface_MSG::TDate (const Standard_CString text,
332                             const Standard_Integer yy,
333                             const Standard_Integer mm,
334                             const Standard_Integer dd,
335                             const Standard_Integer hh,
336                             const Standard_Integer mn,
337                             const Standard_Integer ss,
338                             const Standard_CString format)
339 {
340 //  valeurs nulles : en tete (avec au moins une non nulle, la derniere)
341 //  -> completees avec les valeurs actuelle (system date)
342 //  tout nul on laisse
343
344   //svv #2 Standard_Integer y1 , m1 , d1 , h1 , n1 , s1;
345   Standard_Integer y2 = yy, m2 = mm, d2 = dd, h2 = hh, n2 = mn, s2 = ss;
346   if (yy == 0 && ss != 0) {
347 //  completion
348     OSD_Process pourdate;
349     Quantity_Date ladate = pourdate.SystemDate ();
350     if ( yy == 0) {
351       y2 = ladate.Year();
352       if ( mm == 0) {
353         m2 = ladate.Month();
354         if (dd == 0) {
355           d2 = ladate.Day();
356           if (hh == 0) {
357             h2 = ladate.Hour();
358             if (mn == 0) {
359               n2 = ladate.Minute();
360               s2 = ladate.Second();
361             }
362           }
363         }
364       }
365     }
366   }
367   char *pText=(char *)text;
368   if (!format || format[0] == '\0')
369     sprintf(pText,"%4.4d-%2.2d-%2.2d:%2.2d-%2.2d-%2.2d",y2,m2,d2,h2,n2,s2);
370   else if ((format[0] == 'c' || format[0] == 'C') && format[1] == ':')
371     sprintf (pText,&format[2],y2,m2,d2,h2,n2,s2);
372 }
373
374
375 Standard_Boolean  Interface_MSG::NDate (const Standard_CString text,
376                                         Standard_Integer& yy,
377                                         Standard_Integer& mm,
378                                         Standard_Integer& dd,
379                                         Standard_Integer& hh,
380                                         Standard_Integer& mn,
381                                         Standard_Integer& ss)
382 {
383   Standard_Integer i ,num = 1;
384   for (i = 0; text[i] != '\0'; i ++) {
385     char val = text[i];
386     if (val >= 48 && val <= 57) {
387       if ( (num & 1) == 0) num ++;
388       if (num ==  1) yy = yy*10 + (val-48);
389       if (num ==  3) mm = mm*10 + (val-48);
390       if (num ==  5) dd = dd*10 + (val-48);
391       if (num ==  7) hh = hh*10 + (val-48);
392       if (num ==  9) mn = mn*10 + (val-48);
393       if (num == 11) ss = ss*10 + (val-48);
394     }
395     else if ( (num & 1) != 0) num ++;
396   }
397   return (num > 0);
398 }
399
400
401 Standard_Integer  Interface_MSG::CDate (const Standard_CString text1,
402                                         const Standard_CString text2)
403 {
404   Standard_Integer i1=0,i2=0,i3=0,i4=0,i5=0,i6=0,j1=0,j2=0,j3=0,j4=0,j5=0,j6=0;
405   if (!NDate (text1,i1,i2,i3,i4,i5,i6)) return 0;
406   if (!NDate (text2,j1,j2,j3,j4,j5,j6)) return 0;
407   if (i1 < j1) return -1;
408   if (i1 > j1) return  1;
409   if (i2 < j2) return -1;
410   if (i2 > j2) return  1;
411   if (i3 < j3) return -1;
412   if (i3 > j3) return  1;
413   if (i4 < j4) return -1;
414   if (i4 > j4) return  1;
415   if (i5 < j5) return -1;
416   if (i5 > j5) return  1;
417   if (i6 < j6) return -1;
418   if (i6 > j6) return  1;
419   return 0;
420 }
421
422
423 Standard_CString  Interface_MSG::Blanks (const Standard_Integer val,
424                                          const Standard_Integer max)
425 {
426  Standard_Integer count;
427   if (val < 0)  return Interface_MSG::Blanks (-val,max-1);
428   if      (val <         10) count = 9;
429   else if (val <        100) count = 8;
430   else if (val <       1000) count = 7;
431   else if (val <      10000) count = 6;
432   else if (val <     100000) count = 5;
433   else if (val <    1000000) count = 4;
434   else if (val <   10000000) count = 3;
435   else if (val <  100000000) count = 2;
436   else if (val < 1000000000) count = 1;
437   else count = 0;
438   count = count + max - 10;
439   if (count < 0) count = 0;
440   return &blank [maxblank - count];
441 }
442
443
444 Standard_CString  Interface_MSG::Blanks (const Standard_CString val,
445                                          const Standard_Integer max)
446 {
447   Standard_Integer lng = (Standard_Integer) strlen(val);
448   if (lng > maxblank || lng > max) return "";
449   return &blank [maxblank - max + lng];
450 }
451
452
453 Standard_CString  Interface_MSG::Blanks
454   (const Standard_Integer count)
455 {
456   if (count <= 0) return "";
457   if (count >= maxblank) return blank;
458   return &blank [maxblank-count];
459 }
460
461
462 void  Interface_MSG::Print (Standard_OStream& S, const Standard_CString val,
463                             const Standard_Integer max,
464                             const Standard_Integer just)
465 {
466   if (max > maxblank)  {  Print(S,val,maxblank,just);  return;  }
467   Standard_Integer lng = (Standard_Integer) strlen (val);
468   if (lng > max)  {  S << val;  return;  }
469   Standard_Integer m1 = (max-lng) /2;
470   Standard_Integer m2 = max-lng - m1;
471   if      (just <  0) S<<val<<&blank[maxblank-m1-m2];
472   else if (just == 0) S<<&blank[maxblank-m1]<<val<<&blank[maxblank-m2];
473   else                S<<&blank[maxblank-m1-m2]<<val;
474 }