📄 cpl_strtod.cpp
字号:
/* pick off the optional n-char-sequence */ p = strchr (sc, ')'); if (p == 0) sc--; /* pretend the '(' doesn't belong */ else if (p == sc) { /* no n-char-sequence */ *pnan = 0; sc++; } else { /* This could be a little more meticulous... */ *pnan = (char *)malloc((p - sc) + 1); if (*pnan == 0) sc--; /* out of memory */ else { memcpy (*pnan, sc, (p - sc) - 1); (*pnan)[p - sc] = '\0'; } } } else *pnan = 0; if (endptr) *endptr = sc; *pld = (sign == '-') ? -1.0L : +1.0L; return FP_NAN; } /* Do we have a hexadecimal floating-point constant? */ if (_Memcasecmp (sc, "0X", 2) == 0) { sc += 2; base = 16; } else base = 10; /* get the digits/hexits before the exponent */ for (ndigit = nsig = nzero = 0, olead = opoint = -1;; ++sc) { if (*sc == point) { /* found a decimal point */ if (0 <= opoint) break; /* already seen point */ else opoint = ndigit; } else if (*sc == '0') { /* saw a zero */ ++nzero; ++ndigit; } else if ((base == 16 && !isxdigit (*sc)) || (base == 10 && !isdigit (*sc))) break; else { /* found a nonzero digit */ if (olead < 0) olead = nzero; else { /* deliver zeros */ for (; 0 < nzero && nsig < SIG_MAX; --nzero) buf[nsig++] = 0; } ++ndigit; if (nsig < SIG_MAX) { /* deliver digit */ if (base == 10) buf[nsig++] = *sc - '0'; else { p = (char *) strchr (hexits, tolower (*sc)); buf[nsig++] = p - hexits; } } } } if (ndigit == 0) { /* no digits? return not-a-double */ if (endptr) *endptr = (char *) s; return FP_ZERO; } /* skip trailing digits */ for (; 0 < nsig && buf[nsig - 1] == 0; --nsig) ; /* compute significand */ pc = buf; pl = lo + (nsig >> 3); for (*pl = 0, n = nsig; 0 < n; --n) { if ((n & 7) == 0) *--pl = *pc++; else *pl = *pl * base + *pc++; } fac = facpow = (base == 10) ? 1e8L : +4294967296.0L; for (x = (double) *lo, n = 0; ++n <= (nsig >> 3);) { if (lo[n] != 0UL) x += fac * lo[n]; fac *= facpow; } /* fold in any explicit exponent */ lexp = 0; if ((base == 10 && (*sc == 'e' || *sc == 'E')) || (base == 16 && (*sc == 'p' || *sc == 'P'))) { scsav = sc; esign = *++sc == '+' || *sc == '-' ? *sc++ : '+'; if (!isdigit (*sc)) *sc = *scsav; /* ill-formed exponent */ else { /* exponent looks valid */ for (; isdigit (*sc); ++sc) if (lexp < 10000) lexp = lexp * 10 + (*sc - '0'); /* else overflow */ if (esign == '-') lexp = -lexp; } } if (endptr) *endptr = (char *) sc; if (opoint < 0) lexp += ndigit - nsig; else lexp += opoint - olead - nsig; sexp = (lexp < SHRT_MIN) ? SHRT_MIN : ((lexp < SHRT_MAX) ? (short) lexp : SHRT_MAX); if (base == 10) *pld = _Ldtento (x, sexp); else#ifdef HAVE_FREXPL *pld = ldexpl (x, (int) (sexp) << 2);#else *pld = ldexp (x, (int) (sexp) << 2);#endif if (sign == '-') *pld = -*pld; return FP_NORMAL;}/* exported functions *//************************************************************************//* CPLAtofDelim() *//************************************************************************//** * Converts ASCII string to floating point number. * * This function converts the initial portion of the string pointed to * by nptr to double floating point representation. The behaviour is the * same as * * CPLStrtodDelim(nptr, (char **)NULL, point); * * This function does the same as standard atof(3), but does not take locale * in account. Instead of locale defined decimal delimiter you can specify * your own one. Also see notes for CPLAtof() function. * * @param nptr Pointer to string to convert. * @param point Decimal delimiter. * * @return Converted value, if any. */double CPLAtofDelim(const char *nptr, char point){ return CPLStrtodDelim(nptr, 0, point);}/************************************************************************//* CPLAtof() *//************************************************************************//** * Converts ASCII string to floating point number. * * This function converts the initial portion of the string pointed to * by nptr to double floating point representation. The behaviour is the * same as * * CPLStrtod(nptr, (char **)NULL); * * This function does the same as standard atof(3), but does not take * locale in account. That means, the decimal delimiter is always '.' * (decimal point). Use CPLAtofDelim() function if you want to specify * custom delimiter. * * IMPORTANT NOTE. * Existance of this function does not mean you should always use it. * Sometimes you should use standard locale aware atof(3) and its family. When * you need to process the user's input (for example, command line parameters) * use atof(3), because user works in localized environment and her input will * be done accordingly the locale set. In particular that means we should not * make assumptions about character used as decimal delimiter, it can be * either "." or ",". * But when you are parsing some ASCII file in predefined format, you most * likely need CPLAtof(), because such files distributed across the systems * with different locales and floating point representation shoudl be * considered as a part of file format. If the format uses "." as a delimiter * the same character must be used when parsing number regardless of actual * locale setting. * * @param nptr Pointer to string to convert. * * @return Converted value, if any. */double CPLAtof(const char *nptr){ return CPLStrtod(nptr, 0);}/************************************************************************//* CPLStrtodDelim() *//************************************************************************//** * Converts ASCII string to floating point number using specified delimiter. * * This function converts the initial portion of the string pointed to * by nptr to double floating point representation. This function does the * same as standard strtod(3), but does not take locale in account. Instead of * locale defined decimal delimiter you can specify your own one. Also see * notes for CPLAtof() function. * * @param nptr Pointer to string to convert. * @param endptr If is not NULL, a pointer to the character after the last * character used in the conversion is stored in the location referenced * by endptr. * @param point Decimal delimiter. * * @return Converted value, if any. */double CPLStrtodDelim(const char *nptr, char **endptr, char point){ double ld; char *nan_arg = 0; switch (_Stold(nptr, endptr, &ld, &nan_arg, point)) { case FP_NORMAL: default: return ld; case FP_ZERO: return 0.0; case FP_NAN: ld = copysign (nan (nan_arg), ld); if (nan_arg != 0) free (nan_arg); return ld; case FP_INFINITE: return ld < 0.0L ? -HUGE_VAL : HUGE_VAL; }}/************************************************************************//* CPLStrtod() *//************************************************************************//** * Converts ASCII string to floating point number. * * This function converts the initial portion of the string pointed to * by nptr to double floating point representation. This function does the * same as standard strtod(3), but does not take locale in account. That * means, the decimal delimiter is always '.' (decimal point). Use * CPLStrtodDelim() function if you want to specify custom delimiter. Also * see notes for CPLAtof() function. * * @param nptr Pointer to string to convert. * @param endptr If is not NULL, a pointer to the character after the last * character used in the conversion is stored in the location referenced * by endptr. * * @return Converted value, if any. */double CPLStrtod(const char *nptr, char **endptr){ return CPLStrtodDelim(nptr, endptr, '.');}/************************************************************************//* CPLStrtofDelim() *//************************************************************************//** * Converts ASCII string to floating point number using specified delimiter. * * This function converts the initial portion of the string pointed to * by nptr to single floating point representation. This function does the * same as standard strtof(3), but does not take locale in account. Instead of * locale defined decimal delimiter you can specify your own one. Also see * notes for CPLAtof() function. * * @param nptr Pointer to string to convert. * @param endptr If is not NULL, a pointer to the character after the last * character used in the conversion is stored in the location referenced * by endptr. * @param point Decimal delimiter. * * @return Converted value, if any. */float CPLStrtofDelim(const char *nptr, char **endptr, char point){ double ld; char *nan_arg = 0; float f; switch (_Stold(nptr, endptr, &ld, &nan_arg, point)) { case FP_NORMAL: default: if ((ld < 0.0L ? -ld : ld) > FLT_MAX) { errno = ERANGE; return (ld < 0.0L) ? -HUGE_VALF : HUGE_VALF; } else return (float) ld; case FP_ZERO: return 0.0F; case FP_NAN: f = copysignf (nanf (nan_arg), (float) ld); if (nan_arg != 0) free (nan_arg); return f; case FP_INFINITE: return ld < 0.0L ? -HUGE_VALF : HUGE_VALF; }}/************************************************************************//* CPLStrtof() *//************************************************************************//** * Converts ASCII string to floating point number. * * This function converts the initial portion of the string pointed to * by nptr to single floating point representation. This function does the * same as standard strtof(3), but does not take locale in account. That * means, the decimal delimiter is always '.' (decimal point). Use * CPLStrtofDelim() function if you want to specify custom delimiter. Also * see notes for CPLAtof() function. * * @param nptr Pointer to string to convert. * @param endptr If is not NULL, a pointer to the character after the last * character used in the conversion is stored in the location referenced * by endptr. * * @return Converted value, if any. */float CPLStrtof(const char *nptr, char **endptr){ return CPLStrtofDelim(nptr, endptr, '.');}/* END OF FILE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -