Implement locale dependent float parser

closes #250
This commit is contained in:
Jason Turner 2016-03-04 15:18:12 -07:00
parent 457367ea7b
commit 2a8c248167
2 changed files with 70 additions and 3 deletions

View File

@ -93,6 +93,8 @@
#endif #endif
#include <memory> #include <memory>
#include <string>
#include <cmath>
namespace chaiscript { namespace chaiscript {
static const int version_major = 5; static const int version_major = 5;
@ -119,6 +121,71 @@ namespace chaiscript {
return iter; return iter;
} }
template<typename T>
auto parse_num(const char *t_str) -> typename std::enable_if<std::is_integral<T>::value, T>::type
{
T t = 0;
for (char c = *t_str; (c = *t_str); ++t_str) {
if (c < '0' || c > '9') {
return t;
}
t *= 10;
t += c - '0';
}
return t;
}
template<typename T>
auto parse_num(const char *t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type
{
T t = 0;
T base = 0;
T decimal_place = 0;
bool exponent = false;
bool neg_exponent = false;
const auto final_value = [](const T val, const T baseval, const bool hasexp, const bool negexp) -> T {
if (!hasexp) {
return val;
} else {
return baseval * std::pow(T(10), val*T(negexp?-1:1));
}
};
for(char c = *t_str; (c = *t_str); ++t_str) {
if (c == '.') {
decimal_place = 10;
} else if (c == 'e' || c == 'E') {
exponent = true;
decimal_place = 0;
base = t;
t = 0;
} else if (c == '-' && exponent) {
neg_exponent = true;
} else if (c == '+' && exponent) {
neg_exponent = false;
} else if (c < '0' || c > '9') {
return final_value(t, base, exponent, neg_exponent);
} else if (decimal_place == 0) {
t *= T(10);
t += T(c - '0');
} else {
t += (T(c - '0') / (T(decimal_place)));
decimal_place *= 10;
}
}
return final_value(t, base, exponent, neg_exponent);
}
template<typename T>
T parse_num(const std::string &t_str)
{
return parse_num<T>(t_str.c_str());
}
} }
#endif #endif

View File

@ -621,11 +621,11 @@ namespace chaiscript
if (float_) if (float_)
{ {
return const_var(std::stof(t_val.substr(0,i))); return const_var(parse_num<float>(t_val.substr(0,i)));
} else if (long_) { } else if (long_) {
return const_var(std::stold(t_val.substr(0,i))); return const_var(parse_num<long double>(t_val.substr(0,i)));
} else { } else {
return const_var(std::stod(t_val.substr(0,i))); return const_var(parse_num<double>(t_val.substr(0,i)));
} }
} }