0022898: IGES import fails in german environment
[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 //function : Units_UnitsDictionary
59 //purpose  : 
60 //=======================================================================
61
62 Units_UnitsDictionary::Units_UnitsDictionary()
63 { }
64
65 //=======================================================================
66 //function : Creates
67 //purpose  : 
68 //=======================================================================
69
70 static inline bool strrightadjust (char *str)
71 {
72   for (size_t len = strlen(str); len > 0 && IsSpace (str[len-1]); len--)
73     str[len-1] = '\0';
74   return str[0] != '\0';
75 }
76
77 void Units_UnitsDictionary::Creates(const Standard_CString afilename)
78 {
79   Standard_Boolean ismove;
80   Standard_Integer i, j, k, charnumber, unitscomputed;
81   Standard_Real matrix[50][50], coeff=0, move=0;
82   Handle(Units_Token) token;
83   Handle(Units_UnitsSequence) theunitssequence;
84   Handle(Units_Unit) unit;
85   Handle(Units_ShiftedUnit) shiftedunit;
86   Handle(Units_Quantity) quantity;
87   
88   ifstream file(afilename, ios::in);
89   if(!file) {
90     cout<<"unable to open "<<afilename<<" for input"<<endl;
91     return;
92   }
93   
94   thefilename = new TCollection_HAsciiString(afilename);
95
96   struct stat buf;
97   if(!stat(afilename,&buf)) thetime = buf.st_ctime;
98
99   thequantitiessequence = new Units_QuantitiesSequence();
100   
101   // read file line by line
102   Standard_Integer numberofunits = 0;
103   for(;;) {
104     char line[256];
105     memset (line, 0, sizeof(line));
106     file.getline (line,255);
107     if (!file)
108       break;
109
110     // trim trailing spaces
111     if (! strrightadjust (line))
112       continue; // empty line
113
114     // lines starting with dot separate sections of the file
115     if(line[0]=='.') {
116
117       // if some units are collected in previous section, store them
118       if(numberofunits) {
119         unitscomputed = 0;
120         for(i=0; i<=numberofunits; i++)
121           matrix[i][i] = 1.;
122         for(i=0; i<=numberofunits; i++) {
123           if(matrix[i][0])
124             unitscomputed++;
125         }
126         while(unitscomputed != numberofunits+1) {
127           for(j=1; j<=numberofunits; j++) {
128             if(!matrix[j][0]) {
129               for(i=1; i<j; i++) {
130                 if(matrix[j][i] && matrix[i][0]) {
131                   matrix[j][0] = matrix[i][0]*matrix[j][i];
132                   unitscomputed++;
133                   if(unitscomputed == numberofunits+1)
134                     break;
135                 }
136               }
137               for(k=j+1; k<=numberofunits; k++) {
138                 if(matrix[k][j] && matrix[k][0]) {
139                   matrix[j][0] = matrix[k][0]/matrix[k][j];
140                   unitscomputed++;
141                   if(unitscomputed == numberofunits+1)
142                     break;
143                 }
144               }
145             }
146             if(unitscomputed == numberofunits+1)
147               break;
148           }
149         }
150         for(i=1;i<=theunitssequence->Length();i++) {
151           unit = theunitssequence->Value(i);
152           unit->Value(matrix[i][0]);
153         }
154       }
155           
156       // skip help string and read header
157       file.getline(line,255);
158       file.getline(line,255);
159
160       // header consists of dimension name (40 symbols) and factors
161       // for basic SI dimensions (mass, length, time, ...)
162       char name[41];
163       char MM[11], LL[11], TT[11], II[11], tt[11], NN[11], JJ[11], PP[11], SS[11];
164       for (i=0; i < 41; i++) name[i] = '\0';
165       for (i=0; i < 11; i++) MM[i] = '\0';
166       for (i=0; i < 11; i++) LL[i] = '\0';
167       for (i=0; i < 11; i++) TT[i] = '\0';
168       for (i=0; i < 11; i++) II[i] = '\0';
169       for (i=0; i < 11; i++) tt[i] = '\0';
170       for (i=0; i < 11; i++) NN[i] = '\0';
171       for (i=0; i < 11; i++) JJ[i] = '\0';
172       for (i=0; i < 11; i++) PP[i] = '\0';
173       for (i=0; i < 11; i++) SS[i] = '\0';
174
175       sscanf (line, "%40c%10c%10c%10c%10c%10c%10c%10c%10c%10c",
176                     name, MM, LL, TT, II, tt, NN, JJ, PP, SS);
177       strrightadjust (name);
178
179       Standard_Real M=0., L=0., T=0., I=0., t=0., N=0., J=0., P=0., S=0.;
180       OSD::CStringToReal(MM, M);
181       OSD::CStringToReal(LL, L);
182       OSD::CStringToReal(TT, T);
183       OSD::CStringToReal(II, I);
184       OSD::CStringToReal(tt, t);
185       OSD::CStringToReal(NN, N);
186       OSD::CStringToReal(JJ, J);
187       OSD::CStringToReal(PP, P);
188       OSD::CStringToReal(SS, S);
189
190       Handle(Units_Dimensions) dimensions = 
191         new Units_Dimensions (M, L, T, I, t, N, J, P, S);
192
193 #ifdef DEB
194       /*cout << " Name of Dimension : " << name << endl ;
195           cout << MM << " " << LL << " " << TT << " " 
196                    << II << " " << tt << " " << NN << " " 
197                    << JJ << " " << PP << " " << SS << endl;
198           cout << M << " " << L << " " << T << " " 
199                    << I << " " << t << " " << N << " " 
200                    << J << " " << P << " " << S << endl;*/
201 #endif
202
203       numberofunits = 0;
204       theunitssequence = new Units_UnitsSequence();
205       quantity = new Units_Quantity(name,dimensions,theunitssequence);
206       thequantitiessequence->Append(quantity);
207
208       // clean matrix of units
209       for(i=0; i<50; i++) {
210         for(j=0; j<50; j++)
211           matrix[i][j] = 0.;
212       }
213
214       // skip next line (dotted)
215       file.getline(line,255);
216     }
217
218     else {
219       // normal line defining a unit should contain:
220       // - unit name (51 symbol)
221       // - unit notation (27 symbols)
222       // - factor (27 symbols)
223       // - base unit (27 symbols)
224       char unite[52], symbol[28], convert[28], unit2[28];
225       for (i=0; i < 52; i++) unite  [i] = '\0';
226       for (i=0; i < 28; i++) symbol [i] = '\0';
227       for (i=0; i < 28; i++) convert[i] = '\0';
228       for (i=0; i < 28; i++) unit2  [i] = '\0';
229
230       sscanf (line, "%51c%27c%27c%27c", unite, symbol, convert, unit2);
231
232       strrightadjust (unite);
233       strrightadjust (symbol);
234       strrightadjust (convert);
235       strrightadjust (unit2);
236       if (! unite[0] && ! symbol[0] && ! convert[0] && ! unit2[0])
237         continue; // empty line
238           
239       if(convert[0] == '[') {
240         coeff = 1.;
241         i = (Standard_Integer) strlen(convert);
242         convert[i-1] = 0;
243         ismove = Standard_True;
244         charnumber = 1;
245         if(unite[0]) {
246           numberofunits++;
247           shiftedunit = new Units_ShiftedUnit(unite);
248           shiftedunit->Quantity(quantity);
249           theunitssequence->Append(shiftedunit);
250         }
251       }
252       else {
253         ismove = Standard_False;
254         charnumber = 0;
255         if(unite[0]) {
256           numberofunits++;
257           unit = new Units_Unit(unite);
258           unit->Quantity(quantity);
259           theunitssequence->Append(unit);
260         }
261       }
262       
263       if(symbol[0]) {
264         Units::LexiconUnits(Standard_False)->AddToken(symbol,"U",0.);
265         Standard_Integer last = theunitssequence->Length();
266         theunitssequence->Value(last)->Symbol(symbol);
267       }
268           
269       if(convert[charnumber] == '(') {
270         i = (Standard_Integer) strlen(convert);
271         convert[i-1] = 0;
272         Units_MathSentence mathsentence(&convert[charnumber+1]);
273         if(ismove)
274           move  = (mathsentence.Evaluate())->Value();
275         else
276           coeff = (mathsentence.Evaluate())->Value();
277       }
278       else if(convert[0]) {
279         if(ismove) {
280           OSD::CStringToReal(&convert[charnumber], move);
281         }
282         else
283           OSD::CStringToReal(convert, coeff);
284       }
285       else {
286         coeff = 1.;
287       }
288
289       if(ismove) {
290         if(move) {
291           Standard_Integer last = theunitssequence->Length();
292           unit = theunitssequence->Value(last);
293           shiftedunit = *(Handle_Units_ShiftedUnit*)&unit;
294           shiftedunit->Move(move);
295         }
296       }
297
298       if(unit2[0]) {
299         j = 0;
300         for(j=1;j<=theunitssequence->Length();j++)
301           if(theunitssequence->Value(j) == unit2)break;
302
303         if(j < numberofunits) {
304           matrix[numberofunits][j] = coeff;
305         }
306         else {
307           Units_UnitSentence unitsentence(unit2,thequantitiessequence);
308           matrix[numberofunits][0] = coeff*(unitsentence.Evaluate())->Value();
309         }
310       }
311       else {
312         if(numberofunits == 1) {
313           matrix[1][0] = coeff;
314           unit = theunitssequence->Value(numberofunits);
315           unit->Value(coeff);
316         }
317       }
318     }
319   }
320   file.close();
321 /*
322   Handle(Units_TokensSequence) tmpSeq = Units::LexiconUnits(Standard_False)->Sequence();
323   for(int ii=1; ii<=tmpSeq->Length(); ii++) {
324     token = tmpSeq->Value(ii);
325     cout<<"i="<<ii<<"  token:  "<<token->Word().ToCString()<<"   "
326       <<token->Mean().ToCString()<<"  "<<token->Value()<<endl;
327   }
328   cout<<endl;
329 */
330 }
331
332
333 //=======================================================================
334 //function : UpToDate
335 //purpose  : 
336 //=======================================================================
337
338 Standard_Boolean Units_UnitsDictionary::UpToDate() const
339 {
340   struct stat buf;
341   TCollection_AsciiString string = thefilename->String();
342   if(!stat(string.ToCString(),&buf)) {
343     if(thetime == buf.st_ctime) return Standard_True;
344   }
345
346   return Standard_False;
347 }
348
349
350 //=======================================================================
351 //function : ActiveUnit
352 //purpose  : 
353 //=======================================================================
354
355 TCollection_AsciiString Units_UnitsDictionary::ActiveUnit(const Standard_CString aquantity) const
356 {
357   Standard_Integer index1;
358   Handle(Units_Unit) unit;
359   Handle(Units_UnitsSequence) unitssequence;
360   Handle(Units_Quantity) quantity;
361
362   for(index1=1;index1<=thequantitiessequence->Length();index1++) {
363     quantity = thequantitiessequence->Value(index1);
364     if(quantity == aquantity) {
365       unitssequence = quantity->Sequence();
366       if(unitssequence->Length())
367         return unitssequence->Value(1)->SymbolsSequence()->Value(1)->String();
368       else {
369         cout<<" Pas d'unite active pour "<<aquantity<<endl;
370         return "";
371       }
372     }
373   }
374
375   cout<<" La grandeur physique "<<aquantity<<" n'existe pas."<<endl;
376   return "";
377 }