Add a version of std::stod which takes locale.

We need a string-to-double conversion function which acts the same on
all computers, irrespective of which locale is running. We need to
guarantee that the function expects '.' as the decimal point, and not
','. The choice of en-US is more or less arbitrary.
pull/86/head
Andreas Jönsson 10 years ago
parent 0e42d3348a
commit be230c1a29

@ -761,4 +761,20 @@ generic_string stringTakeWhileAdmissable(const generic_string& input, const gene
{
return input.substr(0, idx);
}
}
double stodLocale(const generic_string& str, _locale_t loc, size_t* idx)
{
// Copied from the std::stod implementation but uses _wcstod_l instead of wcstod.
const wchar_t* ptr = str.c_str();
errno = 0;
wchar_t* eptr;
double ans = ::_wcstod_l(ptr, &eptr, loc);
if (ptr == eptr)
throw new std::invalid_argument("invalid stod argument");
if (errno == ERANGE)
throw new std::out_of_range("stod argument out of range");
if (idx != NULL)
*idx = (size_t)(eptr - ptr);
return ans;
}

@ -191,5 +191,6 @@ generic_string stringReplace(generic_string subject, const generic_string& searc
std::vector<generic_string> stringSplit(const generic_string& input, const generic_string& delimiter);
generic_string stringJoin(const std::vector<generic_string>& strings, const generic_string& separator);
generic_string stringTakeWhileAdmissable(const generic_string& input, const generic_string& admissable);
double stodLocale(const generic_string& str, _locale_t loc, size_t* idx = NULL);
#endif //M30_IDE_COMMUN_H

@ -79,7 +79,15 @@ template<typename T_Num>
class NumericSorter : public ISorter
{
public:
NumericSorter(bool isDescending) : ISorter(isDescending) { };
NumericSorter(bool isDescending) : ISorter(isDescending)
{
_usLocale = ::_wcreate_locale(LC_NUMERIC, TEXT("en-US"));
};
~NumericSorter()
{
::_free_locale(_usLocale);
}
std::vector<generic_string> sort(std::vector<generic_string> lines) override
{
@ -151,6 +159,10 @@ protected:
// Should convert the input string to a number of the correct type.
// If unable to convert, throw either std::invalid_argument or std::out_of_range.
virtual T_Num convertStringToNumber(const generic_string& input) = 0;
// We need a fixed locale so we get the same string-to-double behavior across all computers.
// This is the "enUS" locale.
_locale_t _usLocale;
};
// Converts lines to long long before sorting.
@ -186,7 +198,7 @@ protected:
double convertStringToNumber(const generic_string& input) override
{
return std::stod(input);
return stodLocale(input, _usLocale);
}
};
@ -204,7 +216,7 @@ protected:
double convertStringToNumber(const generic_string& input) override
{
return std::stod(input);
return stodLocale(input, _usLocale);
}
};

Loading…
Cancel
Save