Panda3D
 All Classes Functions Variables Enumerations
pstrtod.cxx
00001 // Filename: pstrtod.cxx
00002 // Created by:  drose (13Jun09)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "pstrtod.h"
00016 
00017 #include <ctype.h>
00018 #include <math.h>
00019 
00020 
00021 ////////////////////////////////////////////////////////////////////
00022 //     Function: pstrtod
00023 //  Description: This function re-implements strtod, to avoid the
00024 //               problems that occur when the LC_NUMERIC locale gets
00025 //               set to anything other than "C".  Regardless of the
00026 //               user's locale, we need to be able to parse
00027 //               floating-point numbers internally understanding a "."
00028 //               as the decimal point.
00029 ////////////////////////////////////////////////////////////////////
00030 double
00031 pstrtod(const char *nptr, char **endptr) {
00032   // First, skip whitespace.
00033   const char *p = nptr;
00034   while (isspace(*p)) {
00035     ++p;
00036   }
00037 
00038   // Skip an optional leading sign.
00039   char sign = '+';
00040   if (*p == '+' || *p == '-') {
00041     sign = *p;
00042     ++p;
00043   }
00044 
00045   double value = 0.0;
00046 
00047   if (isalpha(*p)) {
00048     // For special cases like "inf" and "nan", pass these up to the
00049     // system implementation of strtod.
00050     return strtod(nptr, endptr);
00051   }
00052 
00053   // Start reading decimal digits to the left of the decimal point.
00054   bool found_digits = false;
00055   while (isdigit(*p)) {
00056     value = (value * 10.0) + (*p - '0');
00057     found_digits = true;
00058     ++p;
00059   }
00060   
00061   if (*p == '.') {
00062     ++p;
00063     // Read decimal digits to the right of the decimal point.
00064     double multiplicand = 0.1;
00065     while (isdigit(*p)) {
00066       value += (*p - '0') * multiplicand;
00067       ++p;
00068       found_digits = true;
00069       multiplicand *= 0.1;
00070     }
00071   }
00072   
00073   if (!found_digits) {
00074     // Not a valid float.
00075     if (endptr != NULL) {
00076       *endptr = (char *)nptr;
00077     }
00078     return 0.0;
00079   }
00080   
00081   if (tolower(*p) == 'e') {
00082     // There's an exponent.
00083     ++p;
00084     
00085     char esign = '+';
00086     if (*p == '+' || *p == '-') {
00087       esign = *p;
00088       ++p;
00089     }
00090     
00091     // Start reading decimal digits to the left of the decimal point.
00092     double evalue = 0.0;
00093     while (isdigit(*p)) {
00094       evalue = (evalue * 10.0) + (*p - '0');
00095       ++p;
00096     }
00097     
00098     if (esign == '-') {
00099       value /= pow(evalue, 10.0);
00100     } else {
00101       value *= pow(evalue, 10.0);
00102     }
00103   }        
00104 
00105   if (sign == '-') {
00106     value = -value;
00107   }
00108   
00109   if (endptr != NULL) {
00110     *endptr = (char *)p;
00111   }
00112   return value;
00113 }
00114 
00115 
00116 ////////////////////////////////////////////////////////////////////
00117 //     Function: patof
00118 //  Description: This function re-implements atof, to avoid the
00119 //               problems that occur when the LC_NUMERIC locale gets
00120 //               set to anything other than "C".  Regardless of the
00121 //               user's locale, we need to be able to parse
00122 //               floating-point numbers internally understanding a "."
00123 //               as the decimal point.
00124 ////////////////////////////////////////////////////////////////////
00125 double
00126 patof(const char *str) {
00127   return pstrtod(str, (char **)NULL);
00128 }
 All Classes Functions Variables Enumerations