0023498: Comparison always true in Units_Lexicon::Creates()
authorabv <abv@opencascade.com>
Fri, 30 Nov 2012 11:31:27 +0000 (15:31 +0400)
committerabv <abv@opencascade.com>
Fri, 30 Nov 2012 11:31:27 +0000 (15:31 +0400)
Method Units_Lexicon::Creates refactored
Further refactoring of Units_Lexicon::Creates() and Units_UnitsDictionary::Creates()

src/Units/Units_Lexicon.cxx
src/Units/Units_UnitsDictionary.cxx

index 8ec33ad..13b3cbc 100755 (executable)
@@ -24,6 +24,7 @@
 #include <Units_Token.hxx>
 #include <TCollection_HAsciiString.hxx>
 #include <TCollection_AsciiString.hxx>
+#include <OSD.hxx>
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -49,29 +50,15 @@ Units_Lexicon::Units_Lexicon()
 //purpose  : 
 //=======================================================================
 
-void Units_Lexicon::Creates(const Standard_CString afilename)
+static inline bool strrightadjust (char *str)
 {
-  char chain[256],line[256];
-  char oper[11],coeff[31];
-#if 0
-  char *Chain = chain ;
-  char *Line = line ;
-  char *Oper = oper ;
-  char *Coeff = coeff ;
-#endif
-  Standard_Integer fr;
-  Standard_Size i;
-  Standard_Real value;
-  Handle(Units_Token) token;
-  struct stat buf;
-
-#if 0
-  chain[255] = '\0' ;
-  oper[10] = '\0' ;
-  coeff[30] = '\0' ;
-#endif
+  for (size_t len = strlen(str); len > 0 && IsSpace (str[len-1]); len--)
+    str[len-1] = '\0';
+  return str[0] != '\0';
+}
 
-  //for(i=0; i<=255; i++)chain[i]=0;
+void Units_Lexicon::Creates(const Standard_CString afilename)
+{
   ifstream file(afilename, ios::in);
   if(!file) {
     cout<<"unable to open "<<afilename<<" for input"<<endl;
@@ -81,52 +68,42 @@ void Units_Lexicon::Creates(const Standard_CString afilename)
   thefilename = new TCollection_HAsciiString(afilename);
   thesequenceoftokens = new Units_TokensSequence();
 
+  struct stat buf;
   if(!stat(afilename,&buf)) thetime = buf.st_ctime;
 
-  //for(i=0; i<=255; i++)line[i]=0;
+  // read file line-by-line; each line has fixed format:
+  // first 30 symbols for prefix or symbol (e.g. "k" for kilo)
+  // then 10 symbols for operation
+  // then 30 symbols for numeric parameter (e.g. multiplier)
+  // line can be shorter if last fields are empty
+  Handle(Units_Token) token;
+  for (int nline = 0; ; nline++) {
+    char line[256];
+    memset (line, 0, sizeof(line));
+    if (! file.getline (line, 255))
+      break;
 
-  while(file.getline(line,255)) {
-    Standard_Size len = strlen( line ) ;
-    if(len == 1) continue; //skl - ???
-    for ( i = 0 ; i < 30 ; i++ ) {
-      if ( i < len )
-        fr=sscanf(&line[i],"%c",&chain[i]);
-      else
-        chain[i] = 0 ;
-    }
-    for ( i = 0 ; i < 10 ; i++ ) {
-      if ( 30+i < len )
-        fr=sscanf(&line[30+i],"%c",&oper[i]);
-      else
-        oper[i] = 0 ;
-    }
-    for ( i = 0 ; i < 30 ; i++ ) {
-      if ( 40+i < len )
-        fr=sscanf(&line[40+i],"%c",&coeff[i]);
-      else
-        coeff[i] = 0 ;
-    }
-#if 0
-    cout << "Lexiconsscanf(%c          )" << endl << "Chain" << Chain << endl
-         << "Oper" << Oper << endl
-         << "Coeff" << Coeff << endl ;
-#endif
-    i=29;
-    while( i>=0 && ( chain[i] == ' ' || !chain[i] ))
-      chain[i--]=0;
-    if(i<0) continue;
-    i=9;
-    while( i>=0 && ( oper [i] == ' ' || !oper [i] ))
-      oper[i--]=0;
-    i=29;
-    while( i>=0 && ( coeff[i] == ' ' || !coeff[i] ))
-      coeff[i--]=0;
-
-    if(coeff[0])
-      value = atof(coeff);
-    else
-      value = 0.;
+    // trim trailing white space
+    if (! strrightadjust (line)) // empty line
+      continue;
 
+    // split line to parts
+    char chain[31], oper[11], coeff[31];
+    for (int i=0; i < 31; i++) chain[i] = '\0';
+    for (int i=0; i < 11; i++) oper[i]  = '\0';
+    for (int i=0; i < 31; i++) coeff[i] = '\0';
+
+    sscanf (line, "%30c%10c%30c", chain, oper, coeff);
+
+    // remove trailing spaces and check values
+    if (! strrightadjust (chain))
+      continue;
+    strrightadjust (oper);
+    double value = 0;
+    if (strrightadjust (coeff))
+      OSD::CStringToReal (coeff, value);
+
+    // add token
     if(thesequenceoftokens->IsEmpty()) {
       token = new Units_Token(chain,oper,value);
       thesequenceoftokens->Prepend(token);
@@ -134,9 +111,6 @@ void Units_Lexicon::Creates(const Standard_CString afilename)
     else {
       AddToken(chain,oper,value);
     }
-
-    for(i=0; i<255; i++)
-      line[i]=0;
   }
   file.close();
 }
index 1dc82bb..ccd7744 100755 (executable)
 // purpose or non-infringement. Please see the License for the specific terms
 // and conditions governing the rights and limitations under the License.
 
-
-#define PRO13136       //GG_090498
-//                     Ne pas utiliser la fonction systeme atof() qui
-//                     depend de la localisation
-
 #include <Units_UnitsDictionary.ixx>
 #include <Units.hxx>
 
 #include <Units_Operators.hxx>
 #include <OSD.hxx>
 
-#ifdef PRO13136                //Temporaire en attendant OSD::CStringToReal()
-static char DecimalPoint = '\0' ;
 
+// GG 09.04.98 PRO13136
+// Ne pas utiliser la fonction systeme atof() qui
+// depend de la localisation
+static char DecimalPoint = '\0';
 static void GetDecimalPoint() {
   Standard_Real f = 1.1 ;
   char str[5] ;
@@ -72,8 +69,6 @@ static void GetDecimalPoint() {
 //#endif
   DecimalPoint = str[1] ;
 }
-#endif
-// Make the RealToCString reciprocal conversion.
 
 //=======================================================================
 //function : Units_UnitsDictionary
@@ -88,47 +83,25 @@ Units_UnitsDictionary::Units_UnitsDictionary()
 //purpose  : 
 //=======================================================================
 
+static inline bool strrightadjust (char *str)
+{
+  for (size_t len = strlen(str); len > 0 && IsSpace (str[len-1]); len--)
+    str[len-1] = '\0';
+  return str[0] != '\0';
+}
+
 void Units_UnitsDictionary::Creates(const Standard_CString afilename)
 {
-  Standard_Boolean ismove,emptyline;
-  Standard_Integer charnumber,unitscomputed;
-  Standard_Integer fr,i,j,k;
-  char MM[11],LL[11],TT[11],II[11],tt[11],NN[11],JJ[11],PP[11],SS[11];
-  Standard_Real M=0,L=0,T=0,I=0,t=0,N=0,J=0,P=0,S=0;
-  char unite[52];
-  char symbol[28],unit2[28];
-  char line[256],convert[256];
-  //char name[81];
-  //char name[80]; //skl
-  char name[41]; // skl for OCC13438
-#if 0
-  char *Unite = unite ;
-  char *Symbol = symbol ;
-  char *Unit2 = unit2 ;
-  char *Line = line ;
-  char *Convert = convert ;
-  char *Name = name ;
-#endif
+  Standard_Boolean ismove;
+  Standard_Integer i, j, k, charnumber, unitscomputed;
   Standard_Real matrix[50][50], coeff=0, move=0;
   Handle(Units_Token) token;
   Handle(Units_UnitsSequence) theunitssequence;
   Handle(Units_Unit) unit;
   Handle(Units_ShiftedUnit) shiftedunit;
-  Handle(Units_Dimensions) dimensions;
   Handle(Units_Quantity) quantity;
   
-  struct stat buf;
-
-  unite[51] = '\0' ;
-  symbol[27] = '\0' ;
-  unit2[27] = '\0' ;
-  line[255] = '\0' ;
-  convert[255] = '\0' ;
-  //name[80]  = '\0' ;
-  name[40]  = '\0' ; // skl for OCC13438
-
   ifstream file(afilename, ios::in);
-
   if(!file) {
     cout<<"unable to open "<<afilename<<" for input"<<endl;
     return;
@@ -136,21 +109,28 @@ void Units_UnitsDictionary::Creates(const Standard_CString afilename)
   
   thefilename = new TCollection_HAsciiString(afilename);
 
+  struct stat buf;
   if(!stat(afilename,&buf)) thetime = (Standard_Integer)buf.st_ctime;
 
   thequantitiessequence = new Units_QuantitiesSequence();
   
+  // read file line by line
   Standard_Integer numberofunits = 0;
-  
   for(;;) {
-    file.getline(line,255);
+    char line[256];
+    memset (line, 0, sizeof(line));
+    file.getline (line,255);
     if (!file)
       break;
-    fr = (Standard_Integer) strlen(line);
-    if(fr <= 1)
-      continue;
-    //if( !file || line[0] == '.') { //skl
+
+    // trim trailing spaces
+    if (! strrightadjust (line))
+      continue; // empty line
+
+    // lines starting with dot separate sections of the file
     if(line[0]=='.') {
+
+      // if some units are collected in previous section, store them
       if(numberofunits) {
         unitscomputed = 0;
         for(i=0; i<=numberofunits; i++)
@@ -189,32 +169,30 @@ void Units_UnitsDictionary::Creates(const Standard_CString afilename)
         }
       }
          
-      //if(!file) break; //skl
+      // skip help string and read header
       file.getline(line,255);
       file.getline(line,255);
-      fr = (Standard_Integer) strlen(line);
-         
-#if 0 // skl for OCC13438
-      //for(i=0; i<80; i++)name[i] = 0;
-      for(i=0; i<41; i++) name[i] = 0;
-      M = L = T = I = t = N = J = P = S = 0.;
-      //fr = sscanf(line,"%80c%d%d%d%d%d%d%d%d%d",
-      fr = sscanf(line,"%40c%f%f%f%f%f%f%f%f%f",
-                  &name,&M,&L,&T,&I,&t,&N,&J,&P,&S);
-      cout << "UnitsDictionarysscanf(%40c)Name" << Name << endl ;
-#else
-      for(i=0; i<11; i++)MM[i] = 0;
-      for(i=0; i<11; i++)LL[i] = 0;
-      for(i=0; i<11; i++)TT[i] = 0;
-      for(i=0; i<11; i++)II[i] = 0;
-      for(i=0; i<11; i++)tt[i] = 0;
-      for(i=0; i<11; i++)NN[i] = 0;
-      for(i=0; i<11; i++)JJ[i] = 0;
-      for(i=0; i<11; i++)PP[i] = 0;
-      for(i=0; i<11; i++)SS[i] = 0;
-
-      fr = sscanf(line,"%40c%10c%10c%10c%10c%10c%10c%10c%10c%10c",
-                 name,MM,LL,TT,II,tt,NN,JJ,PP,SS);
+
+      // header consists of dimension name (40 symbols) and factors
+      // for basic SI dimensions (mass, length, time, ...)
+      char name[41];
+      char MM[11], LL[11], TT[11], II[11], tt[11], NN[11], JJ[11], PP[11], SS[11];
+      for (i=0; i < 41; i++) name[i] = '\0';
+      for (i=0; i < 11; i++) MM[i] = '\0';
+      for (i=0; i < 11; i++) LL[i] = '\0';
+      for (i=0; i < 11; i++) TT[i] = '\0';
+      for (i=0; i < 11; i++) II[i] = '\0';
+      for (i=0; i < 11; i++) tt[i] = '\0';
+      for (i=0; i < 11; i++) NN[i] = '\0';
+      for (i=0; i < 11; i++) JJ[i] = '\0';
+      for (i=0; i < 11; i++) PP[i] = '\0';
+      for (i=0; i < 11; i++) SS[i] = '\0';
+
+      sscanf (line, "%40c%10c%10c%10c%10c%10c%10c%10c%10c%10c",
+                   name, MM, LL, TT, II, tt, NN, JJ, PP, SS);
+      strrightadjust (name);
+
+      Standard_Real M=0., L=0., T=0., I=0., t=0., N=0., J=0., P=0., S=0.;
       OSD::CStringToReal(MM, M);
       OSD::CStringToReal(LL, L);
       OSD::CStringToReal(TT, T);
@@ -224,15 +202,9 @@ void Units_UnitsDictionary::Creates(const Standard_CString afilename)
       OSD::CStringToReal(JJ, J);
       OSD::CStringToReal(PP, P);
       OSD::CStringToReal(SS, S);
-      //for ( i = 0 ; i < 80 ; i++ ) {
-      //  fr = sscanf(&line[i],"%c",&name[i]);
-      //}
-# if 0
-      cout << "UnitsDictionarysscanf(%c  )Name" << Name << endl ;
-# endif
-      //fr = sscanf(&line[80],"%d%d%d%d%d%d%d%d%d",
-      //            &M,&L,&T,&I,&t,&N,&J,&P,&S);
-#endif
+
+      Handle(Units_Dimensions) dimensions = 
+        new Units_Dimensions (M, L, T, I, t, N, J, P, S);
 
 #ifdef DEB
       /*cout << " Name of Dimension : " << name << endl ;
@@ -244,101 +216,41 @@ void Units_UnitsDictionary::Creates(const Standard_CString afilename)
                   << J << " " << P << " " << S << endl;*/
 #endif
 
-      i = 39;
-      while( i >= 0 && ( name[i] == ' ' || !name[i]))
-        name[i--] = 0;
-      dimensions = new Units_Dimensions(M,L,T,I,t,N,J,P,S);
-      
       numberofunits = 0;
       theunitssequence = new Units_UnitsSequence();
       quantity = new Units_Quantity(name,dimensions,theunitssequence);
       thequantitiessequence->Append(quantity);
-         
+
+      // clean matrix of units
       for(i=0; i<50; i++) {
         for(j=0; j<50; j++)
           matrix[i][j] = 0.;
       }
+
+      // skip next line (dotted)
       file.getline(line,255);
     }
 
-    else { // line[0] != '.'
-#if 0
-      for(i=0; i<51; i++)
-        unite  [i] = 0;
-      for(i=0; i<27; i++)
-        symbol [i] = 0;
-      for(i=0; i<27; i++)
-        convert[i] = 0;
-      for(i=0; i<27; i++)
-        unit2  [i] = 0;
-      fr = sscanf(line,"%51c%27c%27c%27c",&unite,&symbol,&convert,&unit2);
-      cout << "UnitsDictionarysscanf(%51c%27c%27c%27c)" << endl
-           << "Unite" << Unite << endl << "Symbol" << Symbol << endl
-           << "Convert" << Convert << endl 
-           << "Unit2" << Unit2 << endl ;
-#else
-      Standard_Integer len = (Standard_Integer) strlen( line ) ;
-      for ( i=0 ; i<51 ; i++ ) {
-        if ( i<len )
-          fr = sscanf(&line[i],"%c",&unite[i]);
-        else
-          unite[i] = 0 ;
-      }
-      for ( i=0 ; i<27 ; i++ ) {
-        if ( 51+i < len )
-          fr = sscanf(&line[51+i],"%c",&symbol[i]);
-        else
-          symbol[i] = 0 ;
-      }
-      for ( i=0 ; i<27 ; i++ ) {
-        if ( 78+i < len )
-          fr = sscanf(&line[78+i],"%c",&convert[i]);
-        else
-          convert[i] = 0 ;
-      }
-      for ( i=0 ; i<27 ; i++ ) {
-        if ( 105+i < len )
-          fr = sscanf(&line[105+i],"%c",&unit2[i]);
-        else
-          unit2[i] = 0 ;
-      }
-# if 0
-      cout << "UnitsDictionarysscanf(%c              )" << endl
-           << "Unite" << Unite << endl << "Symbol" << Symbol << endl
-           << "Convert" << Convert << endl 
-           << "Unit2" << Unit2 << endl ;
-# endif
-#endif
-
-      if(fr == -1) continue;
-
-      emptyline = Standard_True;
-
-      i = 50;
-      while(i >= 0 && (unite  [i] == ' ' || !unite  [i]))
-        unite  [i--] = 0;
-      if(i >= 0)
-        emptyline = Standard_False;
-
-      i = 26;
-      while(i >= 0 && (symbol [i] == ' ' || !symbol [i]))
-        symbol [i--] = 0;
-      if(i >= 0)
-        emptyline = Standard_False;
-
-      i = 26;
-      while(i >= 0 && (convert[i] == ' ' || !convert[i]))
-        convert[i--] = 0;
-      if(i >= 0)
-        emptyline = Standard_False;
-
-      i = 26;
-      while(i >= 0 && (unit2  [i] == ' ' || !unit2  [i]))
-        unit2  [i--] = 0;
-      if(i >= 0)
-        emptyline = Standard_False;
-
-      if(emptyline) continue;
+    else {
+      // normal line defining a unit should contain:
+      // - unit name (51 symbol)
+      // - unit notation (27 symbols)
+      // - factor (27 symbols)
+      // - base unit (27 symbols)
+      char unite[52], symbol[28], convert[28], unit2[28];
+      for (i=0; i < 52; i++) unite  [i] = '\0';
+      for (i=0; i < 28; i++) symbol [i] = '\0';
+      for (i=0; i < 28; i++) convert[i] = '\0';
+      for (i=0; i < 28; i++) unit2  [i] = '\0';
+
+      sscanf (line, "%51c%27c%27c%27c", unite, symbol, convert, unit2);
+
+      strrightadjust (unite);
+      strrightadjust (symbol);
+      strrightadjust (convert);
+      strrightadjust (unit2);
+      if (! unite[0] && ! symbol[0] && ! convert[0] && ! unit2[0])
+        continue; // empty line
          
       if(convert[0] == '[') {
         coeff = 1.;
@@ -380,19 +292,11 @@ void Units_UnitsDictionary::Creates(const Standard_CString afilename)
           coeff = (mathsentence.Evaluate())->Value();
       }
       else if(convert[0]) {
-#ifdef PRO13136
         if(ismove) {
           OSD::CStringToReal(&convert[charnumber], move);
         }
         else
           OSD::CStringToReal(convert, coeff);
-#else
-        if(ismove) {
-          move = atof(&convert[charnumber]);
-        }
-        else
-          coeff = atof(convert);
-#endif
       }
       else {
         coeff = 1.;