| @@ -363,6 +363,12 @@ String String::charToString (const juce_wchar character) | |||||
| //============================================================================== | //============================================================================== | ||||
| namespace NumberToStringConverters | namespace NumberToStringConverters | ||||
| { | { | ||||
| enum | |||||
| { | |||||
| charsNeededForInt = 32, | |||||
| charsNeededForDouble = 48 | |||||
| }; | |||||
| template <typename Type> | template <typename Type> | ||||
| static char* printDigits (char* t, Type v) noexcept | static char* printDigits (char* t, Type v) noexcept | ||||
| { | { | ||||
| @@ -413,6 +419,26 @@ namespace NumberToStringConverters | |||||
| return printDigits (t, v); | 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 | 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) | if (numDecPlaces > 0 && numDecPlaces < 7 && n > -1.0e20 && n < 1.0e20) | ||||
| @@ -440,27 +466,16 @@ namespace NumberToStringConverters | |||||
| return t; | 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; | return buffer; | ||||
| } | } | ||||
| template <typename IntegerType> | template <typename IntegerType> | ||||
| static String::CharPointerType createFromInteger (const IntegerType number) | static String::CharPointerType createFromInteger (const IntegerType number) | ||||
| { | { | ||||
| char buffer [32]; | |||||
| char buffer [charsNeededForInt]; | |||||
| char* const end = buffer + numElementsInArray (buffer); | char* const end = buffer + numElementsInArray (buffer); | ||||
| char* const start = numberToString (end, number); | char* const start = numberToString (end, number); | ||||
| return StringHolder::createFromFixedLength (start, (size_t) (end - start - 1)); | 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) | static String::CharPointerType createFromDouble (const double number, const int numberOfDecimalPlaces) | ||||
| { | { | ||||
| char buffer [48]; | |||||
| char buffer [charsNeededForDouble]; | |||||
| size_t len; | size_t len; | ||||
| char* const start = doubleToString (buffer, numElementsInArray (buffer), (double) number, numberOfDecimalPlaces, len); | char* const start = doubleToString (buffer, numElementsInArray (buffer), (double) number, numberOfDecimalPlaces, len); | ||||
| return StringHolder::createFromFixedLength (start, len); | return StringHolder::createFromFixedLength (start, len); | ||||