| @@ -363,6 +363,12 @@ String String::charToString (const juce_wchar character) | |||
| //============================================================================== | |||
| namespace NumberToStringConverters | |||
| { | |||
| enum | |||
| { | |||
| charsNeededForInt = 32, | |||
| charsNeededForDouble = 48 | |||
| }; | |||
| template <typename Type> | |||
| static char* printDigits (char* t, Type v) noexcept | |||
| { | |||
| @@ -413,6 +419,26 @@ 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); | |||
| 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) | |||
| @@ -440,27 +466,16 @@ namespace NumberToStringConverters | |||
| return t; | |||
| } | |||
| // Use a locale-free sprintf where possible (not available on linux AFAICT) | |||
| #if JUCE_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 JUCE_MAC || JUCE_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 <= 0 ? 20 : numDecPlaces); | |||
| jassert (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)); | |||
| @@ -468,7 +483,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); | |||