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