diff --git a/src/graph/str_repr.hh b/src/graph/str_repr.hh index 4a49e12d7524b508d55ba3dc66f271ba9fcf6d5c..e7ca6758b9b35e87f33c0d9fc4ee5e8aceca53a8 100644 --- a/src/graph/str_repr.hh +++ b/src/graph/str_repr.hh @@ -19,6 +19,7 @@ #define STR_REPR_HH #include +#include #include #include @@ -51,13 +52,64 @@ uint8_t lexical_cast(const string& val) } // float, double and long double should be printed in hexadecimal format to -// preserve internal representation +// preserve internal representation. (we also need to make sure the +// representation is locale-independent). + +template +int print_float(char*& str, Val val) +{ + char* locale = setlocale(LC_NUMERIC, NULL); + setlocale(LC_NUMERIC, "C"); + int retval = print_float_dispatch(str, val); + setlocale(LC_NUMERIC, locale); + return retval; +} + +int print_float_dispatch(char*& str, float val) +{ + return asprintf(&str, "%a", val); +} + +int print_float_dispatch(char*& str, double val) +{ + return asprintf(&str, "%la", val); +} + +int print_float_dispatch(char*& str, long double val) +{ + return asprintf(&str, "%La", val); +} + +template +int scan_float(const char* str, Val& val) +{ + char* locale = setlocale(LC_NUMERIC, NULL); + setlocale(LC_NUMERIC, "C"); + int retval = scan_float_dispatch(str, val); + setlocale(LC_NUMERIC, locale); + return retval; +} + +int scan_float_dispatch(const char* str, float& val) +{ + return sscanf(str, "%a", &val); +} + +int scan_float_dispatch(const char* str, double& val) +{ + return sscanf(str, "%la", &val); +} + +int scan_float_dispatch(const char* str, long double& val) +{ + return sscanf(str, "%La", &val); +} template <> string lexical_cast(const float& val) { char* str = 0; - int retval = asprintf(&str, "%a", val); + int retval = print_float(str, val); if (retval == -1) throw bad_lexical_cast(); std::string ret = str; @@ -69,7 +121,7 @@ template <> float lexical_cast(const string& val) { float ret; - int nc = sscanf(val.c_str(), "%a", &ret); + int nc = scan_float(val.c_str(), ret); if (nc != 1) throw bad_lexical_cast(); return ret; @@ -79,7 +131,7 @@ template <> string lexical_cast(const double& val) { char* str = 0; - int retval = asprintf(&str, "%la", val); + int retval = print_float(str, val); if (retval == -1) throw bad_lexical_cast(); std::string ret = str; @@ -91,7 +143,7 @@ template <> double lexical_cast(const string& val) { double ret; - int nc = sscanf(val.c_str(), "%la", &ret); + int nc = scan_float(val.c_str(), ret); if (nc != 1) throw bad_lexical_cast(); return ret; @@ -101,7 +153,7 @@ template <> string lexical_cast(const long double& val) { char* str = 0; - int retval = asprintf(&str, "%La", val); + int retval = print_float(str, val); if (retval == -1) throw bad_lexical_cast(); std::string ret = str; @@ -113,7 +165,7 @@ template <> long double lexical_cast(const string& val) { long double ret; - int nc = sscanf(val.c_str(), "%La", &ret); + int nc = scan_float(val.c_str(), ret); if (nc != 1) throw bad_lexical_cast(); return ret;