00001 /* 00002 Copyright (c) 2000-2003, Jelle Kok, University of Amsterdam 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without 00006 modification, are permitted provided that the following conditions are met: 00007 00008 1. Redistributions of source code must retain the above copyright notice, this 00009 list of conditions and the following disclaimer. 00010 00011 2. Redistributions in binary form must reproduce the above copyright notice, 00012 this list of conditions and the following disclaimer in the documentation 00013 and/or other materials provided with the distribution. 00014 00015 3. Neither the name of the University of Amsterdam nor the names of its 00016 contributors may be used to endorse or promote products derived from this 00017 software without specific prior written permission. 00018 00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00020 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00021 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00022 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 00023 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00024 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00025 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00026 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00027 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00028 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 */ 00030 00047 #include "Parse.h" 00048 00049 #include <ctype.h> // needed for isdigit 00050 #include <math.h> // needed for pow 00051 #include <string.h> // needed for strlen 00052 00053 /*****************************************************************************/ 00054 /********************** CLASS PARSE ******************************************/ 00055 /*****************************************************************************/ 00056 00063 char Parse::gotoFirstNonSpace( char** strMsg ) 00064 { 00065 while(*strMsg && isspace(**strMsg) ) 00066 (*strMsg)++; 00067 return (*strMsg) ? **strMsg : '\0'; 00068 00069 } 00070 00079 char Parse::gotoFirstSpaceOrClosingBracket( char** strMsg ) 00080 { 00081 while( *strMsg && **strMsg!=' ' && **strMsg!=')' ) 00082 (*strMsg)++; 00083 return (*strMsg) ? **strMsg : '\0'; 00084 } 00085 00092 int Parse::gotoFirstOccurenceOf( char c, char** strMsg ) 00093 { 00094 int i=0; 00095 while(**strMsg && **strMsg != c ) 00096 { 00097 i++; 00098 (*strMsg)++; 00099 } 00100 if( ! **strMsg ) 00101 return -1; 00102 return i; 00103 } 00104 00112 int Parse::parseFirstInt( char** strMsg ) 00113 { 00114 int iRes = 0; 00115 bool bIsMin= false; 00116 char *str = *strMsg; 00117 00118 while( *str != '\0' && !isdigit(*str) && *str!='-') 00119 str++; // walk to first non digit or minus sign 00120 00121 00122 if( *str != '\0' && *str=='-') // if it was a minus sign, remember 00123 { 00124 bIsMin=true; 00125 str++; 00126 } 00127 00128 while( *str != '\0' && *str<='9' && *str>='0' ) // for all digits 00129 { 00130 iRes=iRes*10+(int)(*str-'0'); // multiply old res with 10 00131 str++; // and add new value 00132 } 00133 *strMsg = str; 00134 return (bIsMin) ? -iRes : iRes; 00135 } 00136 00145 double Parse::parseFirstDouble( char** strMsg ) 00146 { 00147 double dRes=0.0, dFrac=1.0; 00148 bool bIsMin=false, bInDecimal=false, bCont=true; 00149 char *str = *strMsg; 00150 00151 // go to first part of double (digit, minus sign or '.') 00152 while( *str != '\0' && !isdigit(*str) && *str!='-' && *str!='.') 00153 { 00154 // when NaN or nan is double value, return -1000.0 00155 if( (*str=='N' && strlen(str)>3 && *(str+1)=='a' && *(str+2)=='N') || 00156 (*str=='n' && strlen(str)>3 && *(str+1)=='a' && *(str+2)=='n') ) 00157 { 00158 *strMsg = str+3; 00159 return -1000.0; 00160 } 00161 else 00162 str++; 00163 } 00164 00165 if( *str != '\0' && *str=='-') // if minus sign, remember that 00166 { 00167 bIsMin=true; 00168 str++; 00169 } 00170 00171 while( *str != '\0' && bCont) // process the number bit by bit 00172 { 00173 if( *str=='.' ) // in decimal part after '.' 00174 bInDecimal = true; 00175 else if( bInDecimal && *str<='9' && *str>='0') // number and in decimal 00176 { 00177 dFrac=dFrac*10.0; // shift decimal part to right 00178 dRes += (double)(*str-'0')/dFrac; // and add number 00179 } 00180 else if( *str<='9' && *str>='0' ) // if number and not decimal 00181 dRes=dRes*10+(double)(*str-'0'); // shift left and add number 00182 else if( *str=='e' ) // 10.6e-08 // if to power e 00183 { 00184 if( *(str+1) == '+' ) // determine sign 00185 dRes *= pow(10, parseFirstInt(&str)); // and multiply with power 00186 else if( *(str+1) == '-' ) 00187 { 00188 str = str+2; // skip - 00189 dRes /= pow(10, parseFirstInt(&str)); // and divide by power 00190 } 00191 bCont = false; // after 'e' stop 00192 } 00193 else 00194 bCont = false; // all other cases stop 00195 00196 if( bCont == true ) // update when not stopped yet 00197 str++; 00198 } 00199 *strMsg = str; 00200 return (bIsMin && dRes != 0.0) ? -dRes : dRes; 00201 } 00202 00203 /*****************************************************************************/ 00204 /********************* TESTING PURPOSES **************************************/ 00205 /*****************************************************************************/ 00206 /* 00207 #include<iostream.h> 00208 00209 int main( void ) 00210 { 00211 double d = 13.6e+15; 00212 char str[] = "13.6e+15"; 00213 double d2 = 13.6e-15; 00214 char str2[] = "13.6e-15"; 00215 00216 char *strmsg; 00217 strmsg = &str[0]; 00218 cout << d << endl; 00219 cout << Parse::parseFirstDouble( &strmsg )<< endl; 00220 strmsg = &str2[0]; 00221 cout << d2 << endl; 00222 cout << Parse::parseFirstDouble( &strmsg ) << endl; 00223 return 0; 00224 } 00225 */