0023483: Use appropriate type for handling integer time
[occt.git] / src / Units / Units_UnitsDictionary.cxx
1 // Created on: 1992-06-24
2 // Created by: Gilles DEBARBOUILLE
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21 #include <Units_UnitsDictionary.ixx>
22 #include <Units.hxx>
23
24 #include <Standard_Stream.hxx>
25
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 #include <stdio.h>
30 #ifdef HAVE_STDLIB_H
31 # include <stdlib.h>
32 #endif
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
35 #endif
36 #if defined (HAVE_SYS_STAT_H) || defined(WNT)
37 # include <sys/stat.h>
38 #endif
39
40 #include <Units_Token.hxx>
41 #include <Units_TokensSequence.hxx>
42 #include <Units_UnitsSequence.hxx>
43 #include <Units_Unit.hxx>
44 #include <Units_ShiftedUnit.hxx>
45 #include <Units_Dimensions.hxx>
46 #include <Units_QuantitiesSequence.hxx>
47 #include <Units_Quantity.hxx>
48 #include <Units_MathSentence.hxx>
49 #include <Units_UnitSentence.hxx>
50 #include <Units_UnitsLexicon.hxx>
51 #include <TCollection_HAsciiString.hxx>
52 #include <TCollection_AsciiString.hxx>
53 #include <TColStd_HSequenceOfHAsciiString.hxx>
54 #include <Units_Operators.hxx>
55 #include <OSD.hxx>
56
57
58 // GG 09.04.98 PRO13136
59 // Ne pas utiliser la fonction systeme atof() qui
60 // depend de la localisation
61 static char DecimalPoint = '\0';
62 static void GetDecimalPoint() {
63   Standard_Real f = 1.1 ;
64   char str[5] ;
65
66   sprintf(str,"%.1f",f) ;
67 //#ifdef DEB
68 //  printf("Local System is  %s\n",str) ;
69 //#endif
70   DecimalPoint = str[1] ;
71 }
72
73 //=======================================================================
74 //function : Units_UnitsDictionary
75 //purpose  : 
76 //=======================================================================
77
78 Units_UnitsDictionary::Units_UnitsDictionary()
79 { }
80
81 //=======================================================================
82 //function : Creates
83 //purpose  : 
84 //=======================================================================
85
86 static inline bool strrightadjust (char *str)
87 {
88   for (size_t len = strlen(str); len > 0 && IsSpace (str[len-1]); len--)
89     str[len-1] = '\0';
90   return str[0] != '\0';
91 }
92
93 void Units_UnitsDictionary::Creates(const Standard_CString afilename)
94 {
95   Standard_Boolean ismove;
96   Standard_Integer i, j, k, charnumber, unitscomputed;
97   Standard_Real matrix[50][50], coeff=0, move=0;
98   Handle(Units_Token) token;
99   Handle(Units_UnitsSequence) theunitssequence;
100   Handle(Units_Unit) unit;
101   Handle(Units_ShiftedUnit) shiftedunit;
102   Handle(Units_Quantity) quantity;
103   
104   ifstream file(afilename, ios::in);
105   if(!file) {
106     cout<<"unable to open "<<afilename<<" for input"<<endl;
107     return;
108   }
109   
110   thefilename = new TCollection_HAsciiString(afilename);
111
112   struct stat buf;
113   if(!stat(afilename,&buf)) thetime = buf.st_ctime;
114
115   thequantitiessequence = new Units_QuantitiesSequence();
116   
117   // read file line by line
118   Standard_Integer numberofunits = 0;
119   for(;;) {
120     char line[256];
121     memset (line, 0, sizeof(line));
122     file.getline (line,255);
123     if (!file)
124       break;
125
126     // trim trailing spaces
127     if (! strrightadjust (line))
128       continue; // empty line
129
130     // lines starting with dot separate sections of the file
131     if(line[0]=='.') {
132
133       // if some units are collected in previous section, store them
134       if(numberofunits) {
135         unitscomputed = 0;
136         for(i=0; i<=numberofunits; i++)
137           matrix[i][i] = 1.;
138         for(i=0; i<=numberofunits; i++) {
139           if(matrix[i][0])
140             unitscomputed++;
141         }
142         while(unitscomputed != numberofunits+1) {
143           for(j=1; j<=numberofunits; j++) {
144             if(!matrix[j][0]) {
145               for(i=1; i<j; i++) {
146                 if(matrix[j][i] && matrix[i][0]) {
147                   matrix[j][0] = matrix[i][0]*matrix[j][i];
148                   unitscomputed++;
149                   if(unitscomputed == numberofunits+1)
150                     break;
151                 }
152               }
153               for(k=j+1; k<=numberofunits; k++) {
154                 if(matrix[k][j] && matrix[k][0]) {
155                   matrix[j][0] = matrix[k][0]/matrix[k][j];
156                   unitscomputed++;
157                   if(unitscomputed == numberofunits+1)
158                     break;
159                 }
160               }
161             }
162             if(unitscomputed == numberofunits+1)
163               break;
164           }
165         }
166         for(i=1;i<=theunitssequence->Length();i++) {
167           unit = theunitssequence->Value(i);
168           unit->Value(matrix[i][0]);
169         }
170       }
171           
172       // skip help string and read header
173       file.getline(line,255);
174       file.getline(line,255);
175
176       // header consists of dimension name (40 symbols) and factors
177       // for basic SI dimensions (mass, length, time, ...)
178       char name[41];
179       char MM[11], LL[11], TT[11], II[11], tt[11], NN[11], JJ[11], PP[11], SS[11];
180       for (i=0; i < 41; i++) name[i] = '\0';
181       for (i=0; i < 11; i++) MM[i] = '\0';
182       for (i=0; i < 11; i++) LL[i] = '\0';
183       for (i=0; i < 11; i++) TT[i] = '\0';
184       for (i=0; i < 11; i++) II[i] = '\0';
185       for (i=0; i < 11; i++) tt[i] = '\0';
186       for (i=0; i < 11; i++) NN[i] = '\0';
187       for (i=0; i < 11; i++) JJ[i] = '\0';
188       for (i=0; i < 11; i++) PP[i] = '\0';
189       for (i=0; i < 11; i++) SS[i] = '\0';
190
191       sscanf (line, "%40c%10c%10c%10c%10c%10c%10c%10c%10c%10c",
192                     name, MM, LL, TT, II, tt, NN, JJ, PP, SS);
193       strrightadjust (name);
194
195       Standard_Real M=0., L=0., T=0., I=0., t=0., N=0., J=0., P=0., S=0.;
196       OSD::CStringToReal(MM, M);
197       OSD::CStringToReal(LL, L);
198       OSD::CStringToReal(TT, T);
199       OSD::CStringToReal(II, I);
200       OSD::CStringToReal(tt, t);
201       OSD::CStringToReal(NN, N);
202       OSD::CStringToReal(JJ, J);
203       OSD::CStringToReal(PP, P);
204       OSD::CStringToReal(SS, S);
205
206       Handle(Units_Dimensions) dimensions = 
207         new Units_Dimensions (M, L, T, I, t, N, J, P, S);
208
209 #ifdef DEB
210       /*cout << " Name of Dimension : " << name << endl ;
211           cout << MM << " " << LL << " " << TT << " " 
212                    << II << " " << tt << " " << NN << " " 
213                    << JJ << " " << PP << " " << SS << endl;
214           cout << M << " " << L << " " << T << " " 
215                    << I << " " << t << " " << N << " " 
216                    << J << " " << P << " " << S << endl;*/
217 #endif
218
219       numberofunits = 0;
220       theunitssequence = new Units_UnitsSequence();
221       quantity = new Units_Quantity(name,dimensions,theunitssequence);
222       thequantitiessequence->Append(quantity);
223
224       // clean matrix of units
225       for(i=0; i<50; i++) {
226         for(j=0; j<50; j++)
227           matrix[i][j] = 0.;
228       }
229
230       // skip next line (dotted)
231       file.getline(line,255);
232     }
233
234     else {
235       // normal line defining a unit should contain:
236       // - unit name (51 symbol)
237       // - unit notation (27 symbols)
238       // - factor (27 symbols)
239       // - base unit (27 symbols)
240       char unite[52], symbol[28], convert[28], unit2[28];
241       for (i=0; i < 52; i++) unite  [i] = '\0';
242       for (i=0; i < 28; i++) symbol [i] = '\0';
243       for (i=0; i < 28; i++) convert[i] = '\0';
244       for (i=0; i < 28; i++) unit2  [i] = '\0';
245
246       sscanf (line, "%51c%27c%27c%27c", unite, symbol, convert, unit2);
247
248       strrightadjust (unite);
249       strrightadjust (symbol);
250       strrightadjust (convert);
251       strrightadjust (unit2);
252       if (! unite[0] && ! symbol[0] && ! convert[0] && ! unit2[0])
253         continue; // empty line
254           
255       if(convert[0] == '[') {
256         coeff = 1.;
257         i = (Standard_Integer) strlen(convert);
258         convert[i-1] = 0;
259         ismove = Standard_True;
260         charnumber = 1;
261         if(unite[0]) {
262           numberofunits++;
263           shiftedunit = new Units_ShiftedUnit(unite);
264           shiftedunit->Quantity(quantity);
265           theunitssequence->Append(shiftedunit);
266         }
267       }
268       else {
269         ismove = Standard_False;
270         charnumber = 0;
271         if(unite[0]) {
272           numberofunits++;
273           unit = new Units_Unit(unite);
274           unit->Quantity(quantity);
275           theunitssequence->Append(unit);
276         }
277       }
278       
279       if(symbol[0]) {
280         Units::LexiconUnits(Standard_False)->AddToken(symbol,"U",0.);
281         Standard_Integer last = theunitssequence->Length();
282         theunitssequence->Value(last)->Symbol(symbol);
283       }
284           
285       if(convert[charnumber] == '(') {
286         i = (Standard_Integer) strlen(convert);
287         convert[i-1] = 0;
288         Units_MathSentence mathsentence(&convert[charnumber+1]);
289         if(ismove)
290           move  = (mathsentence.Evaluate())->Value();
291         else
292           coeff = (mathsentence.Evaluate())->Value();
293       }
294       else if(convert[0]) {
295         if(ismove) {
296           OSD::CStringToReal(&convert[charnumber], move);
297         }
298         else
299           OSD::CStringToReal(convert, coeff);
300       }
301       else {
302         coeff = 1.;
303       }
304
305       if(ismove) {
306         if(move) {
307           Standard_Integer last = theunitssequence->Length();
308           unit = theunitssequence->Value(last);
309           shiftedunit = *(Handle_Units_ShiftedUnit*)&unit;
310           shiftedunit->Move(move);
311         }
312       }
313
314       if(unit2[0]) {
315         j = 0;
316         for(j=1;j<=theunitssequence->Length();j++)
317           if(theunitssequence->Value(j) == unit2)break;
318
319         if(j < numberofunits) {
320           matrix[numberofunits][j] = coeff;
321         }
322         else {
323           Units_UnitSentence unitsentence(unit2,thequantitiessequence);
324           matrix[numberofunits][0] = coeff*(unitsentence.Evaluate())->Value();
325         }
326       }
327       else {
328         if(numberofunits == 1) {
329           matrix[1][0] = coeff;
330           unit = theunitssequence->Value(numberofunits);
331           unit->Value(coeff);
332         }
333       }
334     }
335   }
336   file.close();
337 /*
338   Handle(Units_TokensSequence) tmpSeq = Units::LexiconUnits(Standard_False)->Sequence();
339   for(int ii=1; ii<=tmpSeq->Length(); ii++) {
340     token = tmpSeq->Value(ii);
341     cout<<"i="<<ii<<"  token:  "<<token->Word().ToCString()<<"   "
342       <<token->Mean().ToCString()<<"  "<<token->Value()<<endl;
343   }
344   cout<<endl;
345 */
346 }
347
348
349 //=======================================================================
350 //function : UpToDate
351 //purpose  : 
352 //=======================================================================
353
354 Standard_Boolean Units_UnitsDictionary::UpToDate() const
355 {
356   struct stat buf;
357   TCollection_AsciiString string = thefilename->String();
358   if(!stat(string.ToCString(),&buf)) {
359     if(thetime == buf.st_ctime) return Standard_True;
360   }
361
362   return Standard_False;
363 }
364
365
366 //=======================================================================
367 //function : ActiveUnit
368 //purpose  : 
369 //=======================================================================
370
371 TCollection_AsciiString Units_UnitsDictionary::ActiveUnit(const Standard_CString aquantity) const
372 {
373   Standard_Integer index1;
374   Handle(Units_Unit) unit;
375   Handle(Units_UnitsSequence) unitssequence;
376   Handle(Units_Quantity) quantity;
377
378   for(index1=1;index1<=thequantitiessequence->Length();index1++) {
379     quantity = thequantitiessequence->Value(index1);
380     if(quantity == aquantity) {
381       unitssequence = quantity->Sequence();
382       if(unitssequence->Length())
383         return unitssequence->Value(1)->SymbolsSequence()->Value(1)->String();
384       else {
385         cout<<" Pas d'unite active pour "<<aquantity<<endl;
386         return "";
387       }
388     }
389   }
390
391   cout<<" La grandeur physique "<<aquantity<<" n'existe pas."<<endl;
392   return "";
393 }