0025418: Debug output to be limited to OCC development 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-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <Units_UnitsDictionary.ixx>
18 #include <Units.hxx>
19
20 #include <Standard_Stream.hxx>
21
22 #include <stdio.h>
23 #include <sys/stat.h>
24
25 #include <Units_Token.hxx>
26 #include <Units_TokensSequence.hxx>
27 #include <Units_UnitsSequence.hxx>
28 #include <Units_Unit.hxx>
29 #include <Units_ShiftedUnit.hxx>
30 #include <Units_Dimensions.hxx>
31 #include <Units_QuantitiesSequence.hxx>
32 #include <Units_Quantity.hxx>
33 #include <Units_MathSentence.hxx>
34 #include <Units_UnitSentence.hxx>
35 #include <Units_UnitsLexicon.hxx>
36 #include <TCollection_HAsciiString.hxx>
37 #include <TCollection_AsciiString.hxx>
38 #include <TColStd_HSequenceOfHAsciiString.hxx>
39 #include <Units_Operators.hxx>
40 #include <OSD.hxx>
41
42 //=======================================================================
43 //function : Units_UnitsDictionary
44 //purpose  : 
45 //=======================================================================
46
47 Units_UnitsDictionary::Units_UnitsDictionary()
48 { }
49
50 //=======================================================================
51 //function : Creates
52 //purpose  : 
53 //=======================================================================
54
55 static inline bool strrightadjust (char *str)
56 {
57   for (size_t len = strlen(str); len > 0 && IsSpace (str[len-1]); len--)
58     str[len-1] = '\0';
59   return str[0] != '\0';
60 }
61
62 void Units_UnitsDictionary::Creates(const Standard_CString afilename)
63 {
64   Standard_Boolean ismove;
65   Standard_Integer i, j, k, charnumber, unitscomputed;
66   Standard_Real matrix[50][50], coeff=0, move=0;
67   Handle(Units_Token) token;
68   Handle(Units_UnitsSequence) theunitssequence;
69   Handle(Units_Unit) unit;
70   Handle(Units_ShiftedUnit) shiftedunit;
71   Handle(Units_Quantity) quantity;
72   
73   ifstream file(afilename, ios::in);
74   if(!file) {
75 #ifdef OCCT_DEBUG
76     cout<<"unable to open "<<afilename<<" for input"<<endl;
77 #endif
78     return;
79   }
80   
81   thefilename = new TCollection_HAsciiString(afilename);
82
83   struct stat buf;
84   if(!stat(afilename,&buf)) thetime = buf.st_ctime;
85
86   thequantitiessequence = new Units_QuantitiesSequence();
87   
88   // read file line by line
89   Standard_Integer numberofunits = 0;
90   for(;;) {
91     char line[256];
92     memset (line, 0, sizeof(line));
93     file.getline (line,255);
94     if (!file)
95       break;
96
97     // trim trailing spaces
98     if (! strrightadjust (line))
99       continue; // empty line
100
101     // lines starting with dot separate sections of the file
102     if(line[0]=='.') {
103
104       // if some units are collected in previous section, store them
105       if(numberofunits) {
106         unitscomputed = 0;
107         for(i=0; i<=numberofunits; i++)
108           matrix[i][i] = 1.;
109         for(i=0; i<=numberofunits; i++) {
110           if(matrix[i][0])
111             unitscomputed++;
112         }
113         while(unitscomputed != numberofunits+1) {
114           for(j=1; j<=numberofunits; j++) {
115             if(!matrix[j][0]) {
116               for(i=1; i<j; i++) {
117                 if(matrix[j][i] && matrix[i][0]) {
118                   matrix[j][0] = matrix[i][0]*matrix[j][i];
119                   unitscomputed++;
120                   if(unitscomputed == numberofunits+1)
121                     break;
122                 }
123               }
124               for(k=j+1; k<=numberofunits; k++) {
125                 if(matrix[k][j] && matrix[k][0]) {
126                   matrix[j][0] = matrix[k][0]/matrix[k][j];
127                   unitscomputed++;
128                   if(unitscomputed == numberofunits+1)
129                     break;
130                 }
131               }
132             }
133             if(unitscomputed == numberofunits+1)
134               break;
135           }
136         }
137         for(i=1;i<=theunitssequence->Length();i++) {
138           unit = theunitssequence->Value(i);
139           unit->Value(matrix[i][0]);
140         }
141       }
142           
143       // skip help string and read header
144       file.getline(line,255);
145       file.getline(line,255);
146
147       // header consists of dimension name (40 symbols) and factors
148       // for basic SI dimensions (mass, length, time, ...)
149       char name[41];
150       char MM[11], LL[11], TT[11], II[11], tt[11], NN[11], JJ[11], PP[11], SS[11];
151       memset(name,0x00,sizeof(name));
152       memset(MM,0x00,sizeof(MM));
153       memset(LL,0x00,sizeof(LL));
154       memset(TT,0x00,sizeof(TT));
155       memset(II,0x00,sizeof(II));
156       memset(tt,0x00,sizeof(tt));
157       memset(NN,0x00,sizeof(NN));
158       memset(JJ,0x00,sizeof(JJ));
159       memset(PP,0x00,sizeof(PP));
160       memset(SS,0x00,sizeof(SS));
161
162       sscanf (line, "%40c%10c%10c%10c%10c%10c%10c%10c%10c%10c",
163                     name, MM, LL, TT, II, tt, NN, JJ, PP, SS);
164       strrightadjust (name);
165
166       Standard_Real M=0., L=0., T=0., I=0., t=0., N=0., J=0., P=0., S=0.;
167       OSD::CStringToReal(MM, M);
168       OSD::CStringToReal(LL, L);
169       OSD::CStringToReal(TT, T);
170       OSD::CStringToReal(II, I);
171       OSD::CStringToReal(tt, t);
172       OSD::CStringToReal(NN, N);
173       OSD::CStringToReal(JJ, J);
174       OSD::CStringToReal(PP, P);
175       OSD::CStringToReal(SS, S);
176
177       Handle(Units_Dimensions) dimensions = 
178         new Units_Dimensions (M, L, T, I, t, N, J, P, S);
179
180       numberofunits = 0;
181       theunitssequence = new Units_UnitsSequence();
182       quantity = new Units_Quantity(name,dimensions,theunitssequence);
183       thequantitiessequence->Append(quantity);
184
185       // clean matrix of units
186       for(i=0; i<50; i++) {
187         for(j=0; j<50; j++)
188           matrix[i][j] = 0.;
189       }
190
191       // skip next line (dotted)
192       file.getline(line,255);
193     }
194
195     else {
196       // normal line defining a unit should contain:
197       // - unit name (51 symbol)
198       // - unit notation (27 symbols)
199       // - factor (27 symbols)
200       // - base unit (27 symbols)
201       char unite[52], symbol[28], convert[28], unit2[28];
202       memset(unite,  0x00,sizeof(unite));
203       memset(symbol, 0x00,sizeof(symbol));
204       memset(convert,0x00,sizeof(convert));
205       memset(unit2,  0x00,sizeof(unit2));
206
207       sscanf (line, "%51c%27c%27c%27c", unite, symbol, convert, unit2);
208
209       strrightadjust (unite);
210       strrightadjust (symbol);
211       strrightadjust (convert);
212       strrightadjust (unit2);
213       if (! unite[0] && ! symbol[0] && ! convert[0] && ! unit2[0])
214         continue; // empty line
215           
216       if(convert[0] == '[') {
217         coeff = 1.;
218         i = (Standard_Integer) strlen(convert);
219         convert[i-1] = 0;
220         ismove = Standard_True;
221         charnumber = 1;
222         if(unite[0]) {
223           numberofunits++;
224           shiftedunit = new Units_ShiftedUnit(unite);
225           shiftedunit->Quantity(quantity);
226           theunitssequence->Append(shiftedunit);
227         }
228       }
229       else {
230         ismove = Standard_False;
231         charnumber = 0;
232         if(unite[0]) {
233           numberofunits++;
234           unit = new Units_Unit(unite);
235           unit->Quantity(quantity);
236           theunitssequence->Append(unit);
237         }
238       }
239       
240       if(symbol[0]) {
241         Units::LexiconUnits(Standard_False)->AddToken(symbol,"U",0.);
242         Standard_Integer last = theunitssequence->Length();
243         theunitssequence->Value(last)->Symbol(symbol);
244       }
245           
246       if(convert[charnumber] == '(') {
247         i = (Standard_Integer) strlen(convert);
248         convert[i-1] = 0;
249         Units_MathSentence mathsentence(&convert[charnumber+1]);
250         if(ismove)
251           move  = (mathsentence.Evaluate())->Value();
252         else
253           coeff = (mathsentence.Evaluate())->Value();
254       }
255       else if(convert[0]) {
256         if(ismove) {
257           OSD::CStringToReal(&convert[charnumber], move);
258         }
259         else
260           OSD::CStringToReal(convert, coeff);
261       }
262       else {
263         coeff = 1.;
264       }
265
266       if(ismove) {
267         if(move) {
268           Standard_Integer last = theunitssequence->Length();
269           unit = theunitssequence->Value(last);
270           shiftedunit = *(Handle(Units_ShiftedUnit)*)&unit;
271           shiftedunit->Move(move);
272         }
273       }
274
275       if(unit2[0]) {
276         j = 0;
277         for(j=1;j<=theunitssequence->Length();j++)
278           if(theunitssequence->Value(j) == unit2)break;
279
280         if(j < numberofunits) {
281           matrix[numberofunits][j] = coeff;
282         }
283         else {
284           Units_UnitSentence unitsentence(unit2,thequantitiessequence);
285           matrix[numberofunits][0] = coeff*(unitsentence.Evaluate())->Value();
286         }
287       }
288       else {
289         if(numberofunits == 1) {
290           matrix[1][0] = coeff;
291           unit = theunitssequence->Value(numberofunits);
292           unit->Value(coeff);
293         }
294       }
295     }
296   }
297   file.close();
298 /*
299   Handle(Units_TokensSequence) tmpSeq = Units::LexiconUnits(Standard_False)->Sequence();
300   for(int ii=1; ii<=tmpSeq->Length(); ii++) {
301     token = tmpSeq->Value(ii);
302     cout<<"i="<<ii<<"  token:  "<<token->Word().ToCString()<<"   "
303       <<token->Mean().ToCString()<<"  "<<token->Value()<<endl;
304   }
305   cout<<endl;
306 */
307 }
308
309
310 //=======================================================================
311 //function : UpToDate
312 //purpose  : 
313 //=======================================================================
314
315 Standard_Boolean Units_UnitsDictionary::UpToDate() const
316 {
317   struct stat buf;
318   TCollection_AsciiString string = thefilename->String();
319   if(!stat(string.ToCString(),&buf)) {
320     if(thetime == buf.st_ctime) return Standard_True;
321   }
322
323   return Standard_False;
324 }
325
326
327 //=======================================================================
328 //function : ActiveUnit
329 //purpose  : 
330 //=======================================================================
331
332 TCollection_AsciiString Units_UnitsDictionary::ActiveUnit(const Standard_CString aquantity) const
333 {
334   Standard_Integer index1;
335   Handle(Units_Unit) unit;
336   Handle(Units_UnitsSequence) unitssequence;
337   Handle(Units_Quantity) quantity;
338
339   for(index1=1;index1<=thequantitiessequence->Length();index1++) {
340     quantity = thequantitiessequence->Value(index1);
341     if(quantity == aquantity) {
342       unitssequence = quantity->Sequence();
343       if(unitssequence->Length())
344         return unitssequence->Value(1)->SymbolsSequence()->Value(1)->String();
345       else {
346 #ifdef OCCT_DEBUG
347         cout<<" Pas d'unite active pour "<<aquantity<<endl;
348 #endif
349         return "";
350       }
351     }
352   }
353
354   cout<<" La grandeur physique "<<aquantity<<" n'existe pas."<<endl;
355   return "";
356 }