include/foreign/tiny_obj_loader.hh
// Tries to parse a floating point number located at s.
//
// s_end should be a location in the string where reading should absolutely
// stop. For example at the end of the string, to prevent buffer overflows.
//
// Parses the following EBNF grammar:
//   sign    = "+" | "-" ;
//   END     = ? anything not in digit ?
//   digit   = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
//   integer = [sign] , digit , {digit} ;
//   decimal = integer , ["." , integer] ;
//   float   = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ;
//
//  Valid strings are for example:
//   -0  +3.1417e+2  -0.0E-3  1.0324  -1.41   11e2
//
// If the parsing is a success, result is set to the parsed value and true
// is returned.
//
// The function is greedy and will parse until any of the following happens:
//  - a non-conforming character is encountered.
//  - s_end is reached.
//
// The following situations triggers a failure:
//  - s >= s_end.
//  - parse failure.
//
Tries to parse a floating point number located at s.
s_end should be a location in the string where reading should absolutely
stop. For example at the end of the string, to prevent buffer overflows.

Parses the following EBNF grammar:
sign    = "+" | "-" ;
END     = . anything not in digit .



If the parsing is a success, result is set to the parsed value and true
is returned.

The function is greedy and will parse until any of the following happens:
a non-conforming character is encountered.

The following situations triggers a failure:
s >= s_end.
parse failure.
Tries to parse a floating point number located at s . s_end should be a location in the string where reading should absolutely stop . For example at the end of the string to prevent buffer overflows . Parses the following EBNF grammar : sign = " + " | " - " ; END = . anything not in digit . If the parsing is a success result is set to the parsed value and true is returned . The function is greedy and will parse until any of the following happens : a non - conforming character is encountered . The following situations triggers a failure : s > = s_end . parse failure .
static bool tryParseDouble(const char *s, const char *s_end, double *result) {
  if (s >= s_end) {
    return false;
  }
  double mantissa = 0.0;
  int exponent = 0;
  char sign = '+';
  char exp_sign = '+';
  char const *curr = s;
  int read = 0;
  bool end_not_reached = false;
  if (*curr == '+' || *curr == '-') {
    sign = *curr;
    curr++;
  } else if (IS_DIGIT(*curr)) { 
  } else {
    goto fail;
  }
  end_not_reached = (curr != s_end);
  while (end_not_reached && IS_DIGIT(*curr)) {
    mantissa *= 10;
    mantissa += static_cast<int>(*curr - 0x30);
    curr++;
    read++;
    end_not_reached = (curr != s_end);
  }
  if (read == 0) goto fail;
  if (!end_not_reached) goto assemble;
  if (*curr == '.') {
    curr++;
    read = 1;
    end_not_reached = (curr != s_end);
    while (end_not_reached && IS_DIGIT(*curr)) {
      static const double pow_lut[] = {
          1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001,
      };
      const int lut_entries = sizeof pow_lut / sizeof pow_lut[0];
      mantissa += static_cast<int>(*curr - 0x30) *
                  (read < lut_entries ? pow_lut[read] : std::pow(10.0, -read));
      read++;
      curr++;
      end_not_reached = (curr != s_end);
    }
  } else if (*curr == 'e' || *curr == 'E') {
  } else {
    goto assemble;
  }
  if (!end_not_reached) goto assemble;
  if (*curr == 'e' || *curr == 'E') {
    curr++;
    end_not_reached = (curr != s_end);
    if (end_not_reached && (*curr == '+' || *curr == '-')) {
      exp_sign = *curr;
      curr++;
    } else if (IS_DIGIT(*curr)) { 
    } else {
      goto fail;
    }
    read = 0;
    end_not_reached = (curr != s_end);
    while (end_not_reached && IS_DIGIT(*curr)) {
      exponent *= 10;
      exponent += static_cast<int>(*curr - 0x30);
      curr++;
      read++;
      end_not_reached = (curr != s_end);
    }
    exponent *= (exp_sign == '+' ? 1 : -1);
    if (read == 0) goto fail;
  }
assemble:
  *result =
      (sign == '+' ? 1 : -1) *
      (exponent ? std::ldexp(mantissa * std::pow(5.0, exponent), exponent) : mantissa);
  return true;
fail:
  return false;
}
static bool tryParseDouble ( const char * s , const char * s_end , double * result ) { if ( s >= s_end ) { return false ; } double mantissa = 0.0 ; int exponent = 0 ; char sign = ' ' ; char exp_sign = ' ' ; char const * curr = s ; int read = 0 ; bool end_not_reached = false ; if ( * curr == ' ' || * curr == ' ' ) { sign = * curr ; curr ++ ; } else if ( IS_DIGIT ( * curr ) ) { } else { goto fail ; } end_not_reached = ( curr != s_end ) ; while ( end_not_reached && IS_DIGIT ( * curr ) ) { mantissa *= 10 ; mantissa += static_cast < int > ( * curr - 0x30 ) ; curr ++ ; read ++ ; end_not_reached = ( curr != s_end ) ; } if ( read == 0 ) goto fail ; if ( ! end_not_reached ) goto assemble ; if ( * curr == ' ' ) { curr ++ ; read = 1 ; end_not_reached = ( curr != s_end ) ; while ( end_not_reached && IS_DIGIT ( * curr ) ) { static const double pow_lut [ ] = { 1.0 , 0.1 , 0.01 , 0.001 , 0.0001 , 0.00001 , 0.000001 , 0.0000001 , } ; const int lut_entries = sizeof pow_lut / sizeof pow_lut [ 0 ] ; mantissa += static_cast < int > ( * curr - 0x30 ) * ( read < lut_entries ? pow_lut [ read ] : std :: pow ( 10.0 , - read ) ) ; read ++ ; curr ++ ; end_not_reached = ( curr != s_end ) ; } } else if ( * curr == ' ' || * curr == ' ' ) { } else { goto assemble ; } if ( ! end_not_reached ) goto assemble ; if ( * curr == ' ' || * curr == ' ' ) { curr ++ ; end_not_reached = ( curr != s_end ) ; if ( end_not_reached && ( * curr == ' ' || * curr == ' ' ) ) { exp_sign = * curr ; curr ++ ; } else if ( IS_DIGIT ( * curr ) ) { } else { goto fail ; } read = 0 ; end_not_reached = ( curr != s_end ) ; while ( end_not_reached && IS_DIGIT ( * curr ) ) { exponent *= 10 ; exponent += static_cast < int > ( * curr - 0x30 ) ; curr ++ ; read ++ ; end_not_reached = ( curr != s_end ) ; } exponent *= ( exp_sign == ' ' ? 1 : -1 ) ; if ( read == 0 ) goto fail ; } assemble : * result = ( sign == ' ' ? 1 : -1 ) * ( exponent ? std :: ldexp ( mantissa * std :: pow ( 5.0 , exponent ) , exponent ) : mantissa ) ; return true ; fail : return false ; }
Tries to parse a floating point number located at s.
s_end should be a location in the string where reading should absolutely
stop.
Tries to parse a floating point number located at s . s_end should be a location in the string where reading should absolutely stop .
// This exponent is base 2 rather than 10. // However the exponent we parse is supposed to be one of ten, // thus we must take care to convert the exponent/and or the // mantissa to a * 2^E, where a is the mantissa and E is the // exponent. // To get the final double we will use ldexp, it requires the // exponent to be in base 2. // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED // TO JUMP OVER DEFINITIONS. // How many characters were read in a loop. // Tells whether a loop terminated due to reaching s_end. /*
          BEGIN PARSING.
  */ // Find out what sign we've got. /* Pass through. */ // Read the integer part. // We must make sure we actually got something. // We allow numbers of form "#", "###" etc. // Read the decimal part. // NOTE: Don't use powf here, it will absolutely murder precision. // Read the exponent part. // Figure out if a sign is present and if it is. /* Pass through. */ // Empty E is not allowed.