Use std::ostream for double to String conversions

This commit is contained in:
Vinnie Falco
2013-08-10 03:12:14 -07:00
parent b202b82f5a
commit 1f59e38dc7

View File

@@ -358,8 +358,14 @@ String String::charToString (const beast_wchar character)
//==============================================================================
namespace NumberToStringConverters
{
enum
{
charsNeededForInt = 32,
charsNeededForDouble = 48
};
template <typename Type>
static inline char* printDigits (char* t, Type v) noexcept
static char* printDigits (char* t, Type v) noexcept
{
*--t = 0;
@@ -408,6 +414,29 @@ namespace NumberToStringConverters
return printDigits (t, v);
}
struct StackArrayStream : public std::basic_streambuf<char, std::char_traits<char> >
{
explicit StackArrayStream (char* d)
{
imbue (std::locale::classic());
setp (d, d + charsNeededForDouble);
}
size_t writeDouble (double n, int numDecPlaces)
{
{
std::ostream o (this);
if (numDecPlaces > 0)
o.precision ((std::streamsize) numDecPlaces);
o << n;
}
return (size_t) (pptr() - pbase());
}
};
static char* doubleToString (char* buffer, const int numChars, double n, int numDecPlaces, size_t& len) noexcept
{
if (numDecPlaces > 0 && numDecPlaces < 7 && n > -1.0e20 && n < 1.0e20)
@@ -435,27 +464,16 @@ namespace NumberToStringConverters
return t;
}
// Use a locale-free sprintf where possible (not available on linux AFAICT)
#if BEAST_MSVC
static _locale_t cLocale = _create_locale (LC_NUMERIC, "C");
len = (size_t) (numDecPlaces > 0 ? _sprintf_l (buffer, "%.*f", cLocale, numDecPlaces, n)
: _sprintf_l (buffer, "%.9g", cLocale, n));
#elif BEAST_MAC || BEAST_IOS
len = (size_t) (numDecPlaces > 0 ? sprintf_l (buffer, nullptr, "%.*f", numDecPlaces, n)
: sprintf_l (buffer, nullptr, "%.9g", n));
#else
len = (size_t) (numDecPlaces > 0 ? sprintf (buffer, "%.*f", numDecPlaces, n)
: sprintf (buffer, "%.9g", n));
#endif
StackArrayStream strm (buffer);
len = strm.writeDouble (n, numDecPlaces);
bassert (len <= charsNeededForDouble);
return buffer;
}
template <typename IntegerType>
static String::CharPointerType createFromInteger (const IntegerType number)
{
char buffer [32];
char buffer [charsNeededForInt];
char* const end = buffer + numElementsInArray (buffer);
char* const start = numberToString (end, number);
return StringHolder::createFromFixedLength (start, (size_t) (end - start - 1));
@@ -463,7 +481,7 @@ namespace NumberToStringConverters
static String::CharPointerType createFromDouble (const double number, const int numberOfDecimalPlaces)
{
char buffer [48];
char buffer [charsNeededForDouble];
size_t len;
char* const start = doubleToString (buffer, numElementsInArray (buffer), (double) number, numberOfDecimalPlaces, len);
return StringHolder::createFromFixedLength (start, len);