1 #ifndef ROSE_StringUtility_StringToNumber_H
2 #define ROSE_StringUtility_StringToNumber_H
4 #include <Rose/StringUtility/NumberToString.h>
6 #include <Rose/StringUtility/Diagnostics.h>
7 #include <Rose/Exception.h>
12 #include <type_traits>
14 #include <Sawyer/Optional.h>
15 #include <Sawyer/Result.h>
18 namespace StringUtility {
59 template<
class Container,
class Stringifier>
63 template<
class Iterator,
class Stringifier>
65 std::vector<std::string> retval;
66 for (; begin!=end; ++begin)
67 retval.push_back(stringifier(*begin));
76 template<
class IntegralType>
78 toDigit(
char ch, IntegralType radix = 10) {
80 assert(!std::numeric_limits<IntegralType>::is_signed || radix >= 0);
82 if (ch >=
'0' && ch <=
'9') {
84 }
else if (ch >=
'a' && ch <=
'f') {
85 digit = ch -
'a' + 10;
86 }
else if (ch >=
'A' && ch <=
'F') {
87 digit = ch -
'A' + 10;
110 template<
class IntegralType>
113 using UnsignedType =
typename std::make_unsigned<IntegralType>::type;
119 const char *sptr = s.c_str();
122 if (
'-' == *sptr ||
'+' == *sptr) {
123 if (std::numeric_limits<IntegralType>::is_signed) {
126 return Error(
"syntax error: sign not allowed for unsigned types");
130 return Error(
"syntax error: separator not allowed before first digit");
133 UnsignedType radix = 10;
134 if (strncmp(
"0x", sptr, 2) == 0 || strncmp(
"0X", sptr, 2) == 0) {
137 }
else if (strncmp(
"0b", sptr, 2) == 0) {
143 if (radix != 10 &&
'_' == *sptr)
149 for (
size_t i = 0; sptr[i]; ++i) {
150 if (
'_' == sptr[i]) {
151 if (0 == i ||
'_' == sptr[i-1] || !sptr[i+1])
152 return Error(
"syntax error: invalid use of digit separator");
158 const UnsignedType shifted = n * radix;
159 if ((n != 0 && shifted / n != radix) || *digit > std::numeric_limits<UnsignedType>::max() - shifted) {
161 return Error(
"overflow error: less than minimum value for type");
163 return Error(
"overflow error: greater than maximum value for type");
167 n = shifted + *digit;
169 return Error(
"syntax error: invalid digit after parsing " +
plural(nDigits,
"digits"));
173 return Error(
"syntax error: digits expected");
176 if (std::numeric_limits<IntegralType>::is_signed) {
177 const UnsignedType signBit = (UnsignedType)1 << (8*
sizeof(IntegralType) - 1);
179 if (n & signBit && n != signBit)
180 return Error(
"overflow error: less than minimum value for type");
181 return Ok((IntegralType)(~n + 1));
182 }
else if (n & signBit) {
183 return Error(
"overflow error: greater than maximum value for type");
185 return Ok((IntegralType)n);
188 return Ok((IntegralType)n);
196 template<
class IntegralType>
197 typename std::enable_if<std::is_integral<IntegralType>::value, IntegralType>::type
199 return toNumber<IntegralType>(s).template orThrow<Exception>();