6 #ifndef DMLC_STRTONUM_H_ 7 #define DMLC_STRTONUM_H_ 10 #include <type_traits> 17 #include "./logging.h" 27 return (c ==
' ' || c ==
'\t' || c ==
'\r' || c ==
'\n' || c ==
'\f');
37 return (c ==
' ' || c ==
'\t');
47 return (c >=
'0' && c <=
'9');
58 static_cast<int>(
'A') == 65 && static_cast<int>(
'Z' -
'A') == 25,
59 "Only system with ASCII character set is supported");
60 return (c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z');
71 return (c >=
'0' && c <=
'9')
72 || c ==
'+' || c ==
'-' 74 || c ==
'e' || c ==
'E';
98 template <
typename FloatType,
bool CheckRange = false>
99 inline FloatType
ParseFloat(
const char* nptr,
char** endptr) {
101 static_assert(std::is_same<FloatType, double>::value
102 || std::is_same<FloatType, float>::value,
103 "ParseFloat is defined only for 'float' and 'double' types");
104 constexpr
unsigned kMaxExponent
105 = (std::is_same<FloatType, double>::value ? 308U : 38U);
106 constexpr FloatType kMaxSignificandForMaxExponent
107 =
static_cast<FloatType
>(std::is_same<FloatType, double>::value
108 ? 1.79769313486231570 : 3.402823466);
111 constexpr FloatType kMaxSignificandForNegMaxExponent
112 =
static_cast<FloatType
>(std::is_same<FloatType, double>::value
113 ? 2.22507385850720139 : 1.175494351);
117 const unsigned kMaxExponent
118 = (
sizeof(FloatType) ==
sizeof(
double) ? 308U : 38U);
119 const FloatType kMaxSignificandForMaxExponent
120 =
static_cast<FloatType
>(
sizeof(FloatType) ==
sizeof(
double)
121 ? 1.79769313486231570 : 3.402823466);
122 const FloatType kMaxSignificandForNegMaxExponent
123 =
static_cast<FloatType
>(
sizeof(FloatType) ==
sizeof(
double)
124 ? 2.22507385850720139 : 1.175494351);
127 const char *p = nptr;
135 }
else if (*p ==
'+') {
143 while (i < 8 && static_cast<char>((*p) | 32) ==
"infinity"[i]) {
146 if (i == 3 || i == 8) {
147 if (endptr) *endptr = (
char*)p;
148 return sign ? std::numeric_limits<FloatType>::infinity()
149 : -std::numeric_limits<FloatType>::infinity();
156 while (i < 3 && static_cast<char>((*p) | 32) ==
"nan"[i]) {
164 CHECK_EQ(*p,
')') <<
"Invalid NAN literal";
167 static_assert(std::numeric_limits<FloatType>::has_quiet_NaN,
168 "Only system with quiet NaN is supported");
169 if (endptr) *endptr = (
char*)p;
170 return std::numeric_limits<FloatType>::quiet_NaN();
178 for (predec = 0;
isdigit(*p); ++p) {
179 predec = predec * 10ULL +
static_cast<uint64_t
>(*p -
'0');
181 FloatType value =
static_cast<FloatType
>(predec);
190 if (digit_cnt < kStrtofMaxDigits) {
191 val2 = val2 * 10ULL +
static_cast<uint64_t
>(*p -
'0');
197 value +=
static_cast<FloatType
>(
198 static_cast<double>(val2) / static_cast<double>(pow10));
202 if ((*p ==
'e') || (*p ==
'E')) {
205 FloatType scale =
static_cast<FloatType
>(1.0f);
211 }
else if (*p ==
'+') {
215 for (expon = 0;
isdigit(*p); ++p) {
216 expon = expon * 10U +
static_cast<unsigned>(*p -
'0');
218 if (expon > kMaxExponent) {
221 if (endptr) *endptr = (
char*)p;
222 return std::numeric_limits<FloatType>::infinity();
224 expon = kMaxExponent;
228 if (expon == kMaxExponent
229 && ((!frac && value > kMaxSignificandForMaxExponent)
230 || (frac && value < kMaxSignificandForNegMaxExponent))) {
233 if (endptr) *endptr = (
char*)p;
234 return std::numeric_limits<FloatType>::infinity();
236 value = (frac ? kMaxSignificandForNegMaxExponent
237 : kMaxSignificandForMaxExponent);
241 while (expon >= 8U) { scale *=
static_cast<FloatType
>(1E8f); expon -= 8U; }
242 while (expon > 0U) { scale *=
static_cast<FloatType
>(10.0f); expon -= 1U; }
244 value = frac ? (value / scale) : (value * scale);
247 if (*p ==
'f' || *p ==
'F') {
251 if (endptr) *endptr = (
char*)p;
252 return sign ? value : - value;
268 inline float strtof(
const char* nptr,
char** endptr) {
269 return ParseFloat<float>(nptr, endptr);
287 return ParseFloat<float, true>(nptr, endptr);
303 inline double strtod(
const char* nptr,
char** endptr) {
304 return ParseFloat<double>(nptr, endptr);
322 return ParseFloat<double, true>(nptr, endptr);
336 template <
typename SignedIntType>
338 #ifdef DMLC_USE_CXX11 339 static_assert(std::is_signed<SignedIntType>::value
340 && std::is_integral<SignedIntType>::value,
341 "ParseSignedInt is defined for signed integers only");
343 CHECK(base <= 10 && base >= 2);
344 const char* p = nptr;
352 }
else if (*p ==
'+') {
357 const SignedIntType base_val =
static_cast<SignedIntType
>(base);
358 for (value = 0;
isdigit(*p); ++p) {
359 value = value * base_val +
static_cast<SignedIntType
>(*p -
'0');
362 if (endptr) *endptr = (
char*)p;
363 return sign ? value : - value;
377 template <
typename Un
signedIntType>
379 #ifdef DMLC_USE_CXX11 380 static_assert(std::is_unsigned<UnsignedIntType>::value
381 && std::is_integral<UnsignedIntType>::value,
382 "ParseUnsignedInt is defined for unsigned integers only");
384 CHECK(base <= 10 && base >= 2);
385 const char *p = nptr;
393 }
else if (*p ==
'+') {
398 CHECK_EQ(sign,
true);
400 UnsignedIntType value;
401 const UnsignedIntType base_val =
static_cast<UnsignedIntType
>(base);
402 for (value = 0;
isdigit(*p); ++p) {
403 value = value * base_val +
static_cast<UnsignedIntType
>(*p -
'0');
406 if (endptr) *endptr = (
char*)p;
422 inline uint64_t
strtoull(
const char* nptr,
char **endptr,
int base) {
423 return ParseUnsignedInt<uint64_t>(nptr, endptr, base);
434 inline long atol(
const char* p) {
435 return ParseSignedInt<long>(p, 0, 10);
448 inline float atof(
const char* nptr) {
467 inline float stof(
const std::string& value,
size_t* pos =
nullptr) {
468 const char* str_source = value.c_str();
471 if (errno == ERANGE && parsed_value == std::numeric_limits<float>::infinity()) {
472 throw std::out_of_range(
"Out of range value");
473 }
else if (const_cast<const char*>(endptr) == str_source) {
474 throw std::invalid_argument(
"No conversion could be performed");
477 *pos =
static_cast<size_t>(
const_cast<const char*
>(endptr) - str_source);
497 inline double stod(
const std::string& value,
size_t* pos =
nullptr) {
498 const char* str_source = value.c_str();
501 if (errno == ERANGE && parsed_value == std::numeric_limits<double>::infinity()) {
502 throw std::out_of_range(
"Out of range value");
503 }
else if (const_cast<const char*>(endptr) == str_source) {
504 throw std::invalid_argument(
"No conversion could be performed");
507 *pos =
static_cast<size_t>(
const_cast<const char*
>(endptr) - str_source);
527 static inline T
get(
const char * begin,
const char * end);
538 inline T
Str2Type(
const char * begin,
const char * end) {
554 static inline int32_t
get(
const char * begin,
const char * end) {
555 return ParseSignedInt<int32_t>(begin, NULL, 10);
571 static inline uint32_t
get(
const char* begin,
const char* end) {
572 return ParseUnsignedInt<uint32_t>(begin, NULL, 10);
588 static inline int64_t
get(
const char * begin,
const char * end) {
589 return ParseSignedInt<int64_t>(begin, NULL, 10);
605 static inline uint64_t
get(
const char * begin,
const char * end) {
606 return ParseUnsignedInt<uint64_t>(begin, NULL, 10);
622 static inline float get(
const char * begin,
const char * end) {
639 static inline double get(
const char * begin,
const char * end) {
655 template<
typename T1,
typename T2>
656 inline int ParsePair(
const char * begin,
const char * end,
657 const char ** endptr, T1 &v1, T2 &v2) {
658 const char * p = begin;
666 v1 = Str2Type<T1>(p, q);
668 while (p != end &&
isblank(*p)) ++p;
669 if (p == end || *p !=
':') {
679 v2 = Str2Type<T2>(p, q);
696 template<
typename T1,
typename T2,
typename T3>
698 const char ** endptr, T1 &v1, T2 &v2, T3 &v3) {
699 const char * p = begin;
707 v1 = Str2Type<T1>(p, q);
709 while (p != end &&
isblank(*p)) ++p;
710 if (p == end || *p !=
':') {
719 v2 = Str2Type<T2>(p, q);
721 while (p != end &&
isblank(*p)) ++p;
722 if (p == end || *p !=
':') {
732 v3 = Str2Type<T3>(p, q);
737 #endif // DMLC_STRTONUM_H_ FloatType ParseFloat(const char *nptr, char **endptr)
Common implementation for dmlc::strtof() and dmlc::strtod() TODO: the current version does not suppor...
Definition: strtonum.h:99
double strtod_check_range(const char *nptr, char **endptr)
A faster implementation of strtod(). See documentation of std::strtod() for more information. This function will check for overflow. If the converted value is outside the range for the double type, errno is set to ERANGE and HUGE_VAL is returned. TODO: the current version does not support hex number TODO: the current version does not handle long decimals: you may only have up to 19 digits after the decimal point, and you cannot have too many digits before the decimal point either.
Definition: strtonum.h:321
double stod(const std::string &value, size_t *pos=nullptr)
A faster implementation of stod(). See documentation of std::stod() for more information. This function will test for overflow and invalid arguments. TODO: the current version does not support hex number TODO: the current version does not handle long decimals: you may only have up to 19 digits after the decimal point, and you cannot have too many digits before the decimal point either.
Definition: strtonum.h:497
UnsignedIntType ParseUnsignedInt(const char *nptr, char **endptr, int base)
A fast string-to-integer convertor, for unsigned integers TODO: the current version supports only bas...
Definition: strtonum.h:378
Interface class that defines a single method get() to convert a string into type T. Define template specialization of this class to define the conversion method for a particular type.
Definition: strtonum.h:519
bool isspace(char c)
Inline implementation of isspace(). Tests whether the given character is a whitespace letter...
Definition: strtonum.h:26
namespace for dmlc
Definition: array_view.h:12
SignedIntType ParseSignedInt(const char *nptr, char **endptr, int base)
A fast string-to-integer convertor, for signed integers TODO: the current version supports only base ...
Definition: strtonum.h:337
float stof(const std::string &value, size_t *pos=nullptr)
A faster implementation of stof(). See documentation of std::stof() for more information. This function will test for overflow and invalid arguments. TODO: the current version does not support hex number TODO: the current version does not handle long decimals: you may only have up to 19 digits after the decimal point, and you cannot have too many digits before the decimal point either.
Definition: strtonum.h:467
float strtof_check_range(const char *nptr, char **endptr)
A faster implementation of strtof(). See documentation of std::strtof() for more information. This function will check for overflow. If the converted value is outside the range for the float type, errno is set to ERANGE and HUGE_VALF is returned. TODO: the current version does not support hex number TODO: the current version does not handle long decimals: you may only have up to 19 digits after the decimal point, and you cannot have too many digits before the decimal point either.
Definition: strtonum.h:286
uint64_t strtoull(const char *nptr, char **endptr, int base)
A faster implementation of strtoull(). See documentation of std::strtoull() for more information...
Definition: strtonum.h:422
bool isdigitchars(char c)
Tests whether the given character is a valid letter in the string representation of a floating-point ...
Definition: strtonum.h:70
const int kStrtofMaxDigits
Maximum number of decimal digits dmlc::strtof() / dmlc::strtod() will process. Trailing digits will b...
Definition: strtonum.h:81
int ParsePair(const char *begin, const char *end, const char **endptr, T1 &v1, T2 &v2)
Parse colon seperated pair v1[:v2].
Definition: strtonum.h:656
bool isblank(char c)
Inline implementation of isblank(). Tests whether the given character is a space or tab character...
Definition: strtonum.h:36
int ParseTriple(const char *begin, const char *end, const char **endptr, T1 &v1, T2 &v2, T3 &v3)
Parse colon seperated triple v1:v2[:v3].
Definition: strtonum.h:697
long atol(const char *p)
A faster implementation of atol(). See documentation of std::atol() for more information. This function will use base 10. Note that this function does not check for overflow.
Definition: strtonum.h:434
float atof(const char *nptr)
A faster implementation of atof(). Unlike std::atof(), this function returns float type...
Definition: strtonum.h:448
float strtof(const char *nptr, char **endptr)
A faster implementation of strtof(). See documentation of std::strtof() for more information. Note that this function does not check for overflow. Use strtof_check_range() to check for overflow. TODO: the current version does not support hex number TODO: the current version does not handle long decimals: you may only have up to 19 digits after the decimal point, and you cannot have too many digits before the decimal point either.
Definition: strtonum.h:268
bool isalpha(char c)
Inline implementation of isalpha(). Tests whether the given character is an alphabet letter...
Definition: strtonum.h:56
T Str2Type(const char *begin, const char *end)
Convenience function for converting string into type T.
Definition: strtonum.h:538
static T get(const char *begin, const char *end)
Convert a string into type T.
bool isdigit(char c)
Inline implementation of isdigit(). Tests whether the given character is a decimal digit...
Definition: strtonum.h:46
double strtod(const char *nptr, char **endptr)
A faster implementation of strtod(). See documentation of std::strtof() for more information. Note that this function does not check for overflow. Use strtod_check_range() to check for overflow. TODO: the current version does not support hex number TODO: the current version does not handle long decimals: you may only have up to 19 digits after the decimal point, and you cannot have too many digits before the decimal point either.
Definition: strtonum.h:303