00001 /* 00002 Copyright (c) 2000-2002, 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 */ 00046 #include "Parse.h" 00047 00048 #include <ctype.h> // needed for isdigit 00049 #include <math.h> // needed for pow 00050 #include <string.h> // needed for strlen 00051 00052 /******************************************************************************/ 00053 /*********************** CLASS PARSE ******************************************/ 00054 /******************************************************************************/ 00055 00062 char Parse::gotoFirstNonSpace( char** strMsg ) 00063 { 00064 while(*strMsg && isspace(**strMsg) ) 00065 (*strMsg)++; 00066 return (*strMsg) ? **strMsg : '\0'; 00067 00068 } 00069 00078 char Parse::gotoFirstSpaceOrClosingBracket( char** strMsg ) 00079 { 00080 while( *strMsg && **strMsg!=' ' && **strMsg!=')' ) 00081 (*strMsg)++; 00082 return (*strMsg) ? **strMsg : '\0'; 00083 } 00084 00091 int Parse::gotoFirstOccurenceOf( char c, char** strMsg ) 00092 { 00093 int i=0; 00094 while(**strMsg && **strMsg != c ) 00095 { 00096 i++; 00097 (*strMsg)++; 00098 } 00099 if( ! **strMsg ) 00100 return -1; 00101 return i; 00102 } 00103 00111 int Parse::parseFirstInt( char** strMsg ) 00112 { 00113 int iRes = 0; 00114 bool bIsMin= false; 00115 char *str = *strMsg; 00116 00117 while( *str != '\0' && !isdigit(*str) && *str!='-') 00118 str++; // walk to first non digit or minus sign 00119 00120 00121 if( *str != '\0' && *str=='-') // if it was a minus sign, remember 00122 { 00123 bIsMin=true; 00124 str++; 00125 } 00126 00127 while( *str != '\0' && *str<='9' && *str>='0' ) // for all digits 00128 { 00129 iRes=iRes*10+(int)(*str-'0'); // multiply old res with 10 00130 str++; // and add new value 00131 } 00132 *strMsg = str; 00133 return (bIsMin) ? -iRes : iRes; 00134 } 00135 00144 double Parse::parseFirstDouble( char** strMsg ) 00145 { 00146 double dRes=0.0, dFrac=1.0; 00147 bool bIsMin=false, bInDecimal=false, bCont=true; 00148 char *str = *strMsg; 00149 00150 // go to first part of double (digit, minus sign or '.') 00151 while( *str != '\0' && !isdigit(*str) && *str!='-' && *str!='.') 00152 { 00153 // when NaN or nan is double value, return -1000.0 00154 if( (*str=='N' && strlen(str)>3 && *(str+1)=='a' && *(str+2)=='N') || 00155 (*str=='n' && strlen(str)>3 && *(str+1)=='a' && *(str+2)=='n') ) 00156 { 00157 *strMsg = str+3; 00158 return -1000.0; 00159 } 00160 else 00161 str++; 00162 } 00163 00164 if( *str != '\0' && *str=='-') // if minus sign, remember that 00165 { 00166 bIsMin=true; 00167 str++; 00168 } 00169 00170 while( *str != '\0' && bCont) // process the number bit by bit 00171 { 00172 if( *str=='.' ) // in decimal part after '.' 00173 bInDecimal = true; 00174 else if( bInDecimal && *str<='9' && *str>='0') // number and in decimal 00175 { 00176 dFrac=dFrac*10.0; // shift decimal part to right 00177 dRes += (double)(*str-'0')/dFrac; // and add number 00178 } 00179 else if( *str<='9' && *str>='0' ) // if number and not decimal 00180 dRes=dRes*10+(double)(*str-'0'); // shift left and add number 00181 else if( *str=='e' ) // 10.6e-08 // if to power e 00182 { 00183 if( *(str+1) == '+' ) // determine sign 00184 dRes *= pow(10, parseFirstInt(&str)); // and multiply with power 00185 else if( *(str+1) == '-' ) 00186 { 00187 str = str+2; // skip - 00188 dRes /= pow(10, parseFirstInt(&str)); // and divide by power 00189 } 00190 bCont = false; // after 'e' stop 00191 } 00192 else 00193 bCont = false; // all other cases stop 00194 00195 if( bCont == true ) // update when not stopped yet 00196 str++; 00197 } 00198 *strMsg = str; 00199 return (bIsMin && dRes != 0.0) ? -dRes : dRes; 00200 } 00201 00202 /******************************************************************************/ 00203 /********************** TESTING PURPOSES *************************************/ 00204 /******************************************************************************/ 00205 /* 00206 #include<iostream.h> 00207 00208 int main( void ) 00209 { 00210 double d = 13.6e+15; 00211 char str[] = "13.6e+15"; 00212 double d2 = 13.6e-15; 00213 char str2[] = "13.6e-15"; 00214 00215 char *strmsg; 00216 strmsg = &str[0]; 00217 cout << d << endl; 00218 cout << Parse::parseFirstDouble( &strmsg )<< endl; 00219 strmsg = &str2[0]; 00220 cout << d2 << endl; 00221 cout << Parse::parseFirstDouble( &strmsg ) << endl; 00222 return 0; 00223 } 00224 */