upgrade to JUCE 5.4.3. Remove (probably) unused JUCE modules. Remove VST2 target (it's been end-of-life'd by Steinberg and by JUCE)
This commit is contained in:
		@ -44,10 +44,7 @@ public:
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline CharPointer_ASCII (const CharPointer_ASCII& other) noexcept
 | 
			
		||||
        : data (other.data)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    inline CharPointer_ASCII (const CharPointer_ASCII& other) = default;
 | 
			
		||||
 | 
			
		||||
    inline CharPointer_ASCII operator= (const CharPointer_ASCII other) noexcept
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
@ -45,10 +45,7 @@ public:
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline CharPointer_UTF16 (const CharPointer_UTF16& other) noexcept
 | 
			
		||||
        : data (other.data)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    inline CharPointer_UTF16 (const CharPointer_UTF16& other) = default;
 | 
			
		||||
 | 
			
		||||
    inline CharPointer_UTF16 operator= (CharPointer_UTF16 other) noexcept
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
@ -41,10 +41,7 @@ public:
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline CharPointer_UTF32 (const CharPointer_UTF32& other) noexcept
 | 
			
		||||
        : data (other.data)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    inline CharPointer_UTF32 (const CharPointer_UTF32& other) = default;
 | 
			
		||||
 | 
			
		||||
    inline CharPointer_UTF32 operator= (CharPointer_UTF32 other) noexcept
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
@ -41,10 +41,7 @@ public:
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline CharPointer_UTF8 (const CharPointer_UTF8& other) noexcept
 | 
			
		||||
        : data (other.data)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    inline CharPointer_UTF8 (const CharPointer_UTF8& other) = default;
 | 
			
		||||
 | 
			
		||||
    inline CharPointer_UTF8 operator= (CharPointer_UTF8 other) noexcept
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
@ -236,13 +236,23 @@ public:
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (10e10),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (1.4962e+2),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (3198693.0973e4),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (10973097.2087e-4),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (10973097.2087E-4),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (1.3986e00006),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (2087.3087e+00006),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (6.0872e-00006),
 | 
			
		||||
 | 
			
		||||
            // Too many sig figs. The parsing routine on MinGW gets the last
 | 
			
		||||
            // significant figure wrong.
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (17654321098765432.9),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (183456789012345678.9),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (1934567890123456789.9),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (20345678901234567891.9),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752.000000),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752e3),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752e100),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752.000000e-5),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752.000000e-40),
 | 
			
		||||
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (1.23456789012345678901234567890),
 | 
			
		||||
            STRING_DOUBLE_PAIR_COMBOS (1.23456789012345678901234567890e-111)
 | 
			
		||||
 | 
			
		||||
@ -262,6 +272,7 @@ public:
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            String nans[] = { "NaN", "-nan", "+NAN", "1.0E1024", "-1.0E-999", "1.23456789012345678901234567890e123456789"};
 | 
			
		||||
 | 
			
		||||
            for (auto nan : nans)
 | 
			
		||||
            {
 | 
			
		||||
                auto charPtr = nan.getCharPointer();
 | 
			
		||||
@ -271,6 +282,7 @@ public:
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            String infs[] = { "Inf", "-inf",  "INF"};
 | 
			
		||||
 | 
			
		||||
            for (auto inf : infs)
 | 
			
		||||
            {
 | 
			
		||||
                auto charPtr = inf.getCharPointer();
 | 
			
		||||
 | 
			
		||||
@ -295,6 +295,7 @@ public:
 | 
			
		||||
 | 
			
		||||
        int numSigFigs = 0;
 | 
			
		||||
        bool decimalPointFound = false;
 | 
			
		||||
        int extraExponent = 0;
 | 
			
		||||
 | 
			
		||||
        for (;;)
 | 
			
		||||
        {
 | 
			
		||||
@ -302,9 +303,22 @@ public:
 | 
			
		||||
            {
 | 
			
		||||
                auto digit = (int) text.getAndAdvance() - '0';
 | 
			
		||||
 | 
			
		||||
                if (numSigFigs >= maxSignificantDigits
 | 
			
		||||
                     || ((numSigFigs == 0 && (! decimalPointFound)) && digit == 0))
 | 
			
		||||
                    continue;
 | 
			
		||||
                if (decimalPointFound)
 | 
			
		||||
                {
 | 
			
		||||
                    if (numSigFigs >= maxSignificantDigits)
 | 
			
		||||
                        continue;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    if (numSigFigs >= maxSignificantDigits)
 | 
			
		||||
                    {
 | 
			
		||||
                        ++extraExponent;
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (numSigFigs == 0 && digit == 0)
 | 
			
		||||
                        continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                *currentCharacter++ = (char) ('0' + (char) digit);
 | 
			
		||||
                numSigFigs++;
 | 
			
		||||
@ -323,37 +337,58 @@ public:
 | 
			
		||||
 | 
			
		||||
        c = *text;
 | 
			
		||||
 | 
			
		||||
        auto writeExponentDigits = [](int exponent, char* destination)
 | 
			
		||||
        {
 | 
			
		||||
            auto exponentDivisor = 100;
 | 
			
		||||
 | 
			
		||||
            while (exponentDivisor > 1)
 | 
			
		||||
            {
 | 
			
		||||
                auto digit = exponent / exponentDivisor;
 | 
			
		||||
                *destination++ = (char) ('0' + (char) digit);
 | 
			
		||||
                exponent -= digit * exponentDivisor;
 | 
			
		||||
                exponentDivisor /= 10;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            *destination++ = (char) ('0' + (char) exponent);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        if ((c == 'e' || c == 'E') && numSigFigs > 0)
 | 
			
		||||
        {
 | 
			
		||||
            *currentCharacter++ = 'e';
 | 
			
		||||
            bool parsedExponentIsPositive = true;
 | 
			
		||||
 | 
			
		||||
            switch (*++text)
 | 
			
		||||
            {
 | 
			
		||||
                case '-':   *currentCharacter++ = '-'; // Fall-through..
 | 
			
		||||
                case '-':   parsedExponentIsPositive = false; // Fall-through..
 | 
			
		||||
                case '+':   ++text;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int exponentMagnitude = 0;
 | 
			
		||||
            int exponent = 0;
 | 
			
		||||
 | 
			
		||||
            while (text.isDigit())
 | 
			
		||||
            {
 | 
			
		||||
                if (currentCharacter == &buffer[bufferSize - 1])
 | 
			
		||||
                    return std::numeric_limits<double>::quiet_NaN();
 | 
			
		||||
 | 
			
		||||
                auto digit = (int) text.getAndAdvance() - '0';
 | 
			
		||||
 | 
			
		||||
                if (digit != 0 || exponentMagnitude != 0)
 | 
			
		||||
                {
 | 
			
		||||
                    *currentCharacter++ = (char) ('0' + (char) digit);
 | 
			
		||||
                    exponentMagnitude = (exponentMagnitude * 10) + digit;
 | 
			
		||||
                }
 | 
			
		||||
                if (digit != 0 || exponent != 0)
 | 
			
		||||
                    exponent = (exponent * 10) + digit;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (exponentMagnitude > std::numeric_limits<double>::max_exponent10)
 | 
			
		||||
            exponent = extraExponent + (parsedExponentIsPositive ? exponent : -exponent);
 | 
			
		||||
 | 
			
		||||
            if (exponent < 0)
 | 
			
		||||
                *currentCharacter++ = '-';
 | 
			
		||||
 | 
			
		||||
            exponent = std::abs (exponent);
 | 
			
		||||
 | 
			
		||||
            if (exponent > std::numeric_limits<double>::max_exponent10)
 | 
			
		||||
                return std::numeric_limits<double>::quiet_NaN();
 | 
			
		||||
 | 
			
		||||
            if (exponentMagnitude == 0)
 | 
			
		||||
                *currentCharacter++ = '0';
 | 
			
		||||
            writeExponentDigits (exponent, currentCharacter);
 | 
			
		||||
        }
 | 
			
		||||
        else if (extraExponent > 0)
 | 
			
		||||
        {
 | 
			
		||||
            *currentCharacter++ = 'e';
 | 
			
		||||
            writeExponentDigits (extraExponent, currentCharacter);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
       #if JUCE_WINDOWS
 | 
			
		||||
 | 
			
		||||
@ -28,11 +28,11 @@ Identifier::~Identifier() noexcept {}
 | 
			
		||||
 | 
			
		||||
Identifier::Identifier (const Identifier& other) noexcept  : name (other.name) {}
 | 
			
		||||
 | 
			
		||||
Identifier::Identifier (Identifier&& other) noexcept : name (static_cast<String&&> (other.name)) {}
 | 
			
		||||
Identifier::Identifier (Identifier&& other) noexcept : name (std::move (other.name)) {}
 | 
			
		||||
 | 
			
		||||
Identifier& Identifier::operator= (Identifier&& other) noexcept
 | 
			
		||||
{
 | 
			
		||||
    name = static_cast<String&&> (other.name);
 | 
			
		||||
    name = std::move (other.name);
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -191,7 +191,6 @@ private:
 | 
			
		||||
    StringArray countryCodes;
 | 
			
		||||
    StringPairArray translations;
 | 
			
		||||
    std::unique_ptr<LocalisedStrings> fallback;
 | 
			
		||||
    friend struct ContainerDeletePolicy<LocalisedStrings>;
 | 
			
		||||
 | 
			
		||||
    void loadFromText (const String&, bool ignoreCase);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -351,19 +351,19 @@ String::String (const CharPointer_UTF16 t)   : text (StringHolder::createFromCha
 | 
			
		||||
String::String (const CharPointer_UTF32 t)   : text (StringHolder::createFromCharPointer (t)) {}
 | 
			
		||||
String::String (const CharPointer_ASCII t)   : text (StringHolder::createFromCharPointer (t)) {}
 | 
			
		||||
 | 
			
		||||
String::String (const CharPointer_UTF8  t, const size_t maxChars)   : text (StringHolder::createFromCharPointer (t, maxChars)) {}
 | 
			
		||||
String::String (const CharPointer_UTF16 t, const size_t maxChars)   : text (StringHolder::createFromCharPointer (t, maxChars)) {}
 | 
			
		||||
String::String (const CharPointer_UTF32 t, const size_t maxChars)   : text (StringHolder::createFromCharPointer (t, maxChars)) {}
 | 
			
		||||
String::String (const wchar_t* const t, size_t maxChars)            : text (StringHolder::createFromCharPointer (castToCharPointer_wchar_t (t), maxChars)) {}
 | 
			
		||||
String::String (CharPointer_UTF8  t, size_t maxChars)   : text (StringHolder::createFromCharPointer (t, maxChars)) {}
 | 
			
		||||
String::String (CharPointer_UTF16 t, size_t maxChars)   : text (StringHolder::createFromCharPointer (t, maxChars)) {}
 | 
			
		||||
String::String (CharPointer_UTF32 t, size_t maxChars)   : text (StringHolder::createFromCharPointer (t, maxChars)) {}
 | 
			
		||||
String::String (const wchar_t* t, size_t maxChars)      : text (StringHolder::createFromCharPointer (castToCharPointer_wchar_t (t), maxChars)) {}
 | 
			
		||||
 | 
			
		||||
String::String (const CharPointer_UTF8  start, const CharPointer_UTF8  end)  : text (StringHolder::createFromCharPointer (start, end)) {}
 | 
			
		||||
String::String (const CharPointer_UTF16 start, const CharPointer_UTF16 end)  : text (StringHolder::createFromCharPointer (start, end)) {}
 | 
			
		||||
String::String (const CharPointer_UTF32 start, const CharPointer_UTF32 end)  : text (StringHolder::createFromCharPointer (start, end)) {}
 | 
			
		||||
String::String (CharPointer_UTF8  start, CharPointer_UTF8  end)  : text (StringHolder::createFromCharPointer (start, end)) {}
 | 
			
		||||
String::String (CharPointer_UTF16 start, CharPointer_UTF16 end)  : text (StringHolder::createFromCharPointer (start, end)) {}
 | 
			
		||||
String::String (CharPointer_UTF32 start, CharPointer_UTF32 end)  : text (StringHolder::createFromCharPointer (start, end)) {}
 | 
			
		||||
 | 
			
		||||
String::String (const std::string& s) : text (StringHolder::createFromFixedLength (s.data(), s.size())) {}
 | 
			
		||||
String::String (StringRef s)          : text (StringHolder::createFromCharPointer (s.text)) {}
 | 
			
		||||
 | 
			
		||||
String String::charToString (const juce_wchar character)
 | 
			
		||||
String String::charToString (juce_wchar character)
 | 
			
		||||
{
 | 
			
		||||
    String result (PreallocationBytes (CharPointerType::getBytesRequiredFor (character)));
 | 
			
		||||
    CharPointerType t (result.text);
 | 
			
		||||
@ -397,7 +397,7 @@ namespace NumberToStringConverters
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // pass in a pointer to the END of a buffer..
 | 
			
		||||
    static char* numberToString (char* t, const int64 n) noexcept
 | 
			
		||||
    static char* numberToString (char* t, int64 n) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        if (n >= 0)
 | 
			
		||||
            return printDigits (t, static_cast<uint64> (n));
 | 
			
		||||
@ -414,7 +414,7 @@ namespace NumberToStringConverters
 | 
			
		||||
        return printDigits (t, v);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static char* numberToString (char* t, const int n) noexcept
 | 
			
		||||
    static char* numberToString (char* t, int n) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        if (n >= 0)
 | 
			
		||||
            return printDigits (t, static_cast<unsigned int> (n));
 | 
			
		||||
@ -426,12 +426,12 @@ namespace NumberToStringConverters
 | 
			
		||||
        return t;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static char* numberToString (char* t, const unsigned int v) noexcept
 | 
			
		||||
    static char* numberToString (char* t, unsigned int v) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return printDigits (t, v);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static char* numberToString (char* t, const long n) noexcept
 | 
			
		||||
    static char* numberToString (char* t, long n) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        if (n >= 0)
 | 
			
		||||
            return printDigits (t, static_cast<unsigned long> (n));
 | 
			
		||||
@ -441,7 +441,7 @@ namespace NumberToStringConverters
 | 
			
		||||
        return t;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static char* numberToString (char* t, const unsigned long v) noexcept
 | 
			
		||||
    static char* numberToString (char* t, unsigned long v) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return printDigits (t, v);
 | 
			
		||||
    }
 | 
			
		||||
@ -455,14 +455,14 @@ namespace NumberToStringConverters
 | 
			
		||||
            setp (d, d + charsNeededForDouble);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        size_t writeDouble (double n, int numDecPlaces)
 | 
			
		||||
        size_t writeDouble (double n, int numDecPlaces, bool useScientificNotation)
 | 
			
		||||
        {
 | 
			
		||||
            {
 | 
			
		||||
                std::ostream o (this);
 | 
			
		||||
 | 
			
		||||
                if (numDecPlaces > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    o.setf (std::ios_base::fixed);
 | 
			
		||||
                    o.setf (useScientificNotation ? std::ios_base::scientific : std::ios_base::fixed);
 | 
			
		||||
                    o.precision ((std::streamsize) numDecPlaces);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -473,41 +473,16 @@ namespace NumberToStringConverters
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static char* doubleToString (char* buffer, const int numChars, double n, int numDecPlaces, size_t& len) noexcept
 | 
			
		||||
    static char* doubleToString (char* buffer, double n, int numDecPlaces, bool useScientificNotation, size_t& len) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        if (numDecPlaces > 0 && numDecPlaces < 7 && n > -1.0e20 && n < 1.0e20)
 | 
			
		||||
        {
 | 
			
		||||
            auto* end = buffer + numChars;
 | 
			
		||||
            auto* t = end;
 | 
			
		||||
            auto v = (int64) (std::pow (10.0, numDecPlaces) * std::abs (n) + 0.5);
 | 
			
		||||
            *--t = (char) 0;
 | 
			
		||||
 | 
			
		||||
            while (numDecPlaces >= 0 || v > 0)
 | 
			
		||||
            {
 | 
			
		||||
                if (numDecPlaces == 0)
 | 
			
		||||
                    *--t = '.';
 | 
			
		||||
 | 
			
		||||
                *--t = (char) ('0' + (v % 10));
 | 
			
		||||
 | 
			
		||||
                v /= 10;
 | 
			
		||||
                --numDecPlaces;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (n < 0)
 | 
			
		||||
                *--t = '-';
 | 
			
		||||
 | 
			
		||||
            len = (size_t) (end - t - 1);
 | 
			
		||||
            return t;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        StackArrayStream strm (buffer);
 | 
			
		||||
        len = strm.writeDouble (n, numDecPlaces);
 | 
			
		||||
        len = strm.writeDouble (n, numDecPlaces, useScientificNotation);
 | 
			
		||||
        jassert (len <= charsNeededForDouble);
 | 
			
		||||
        return buffer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename IntegerType>
 | 
			
		||||
    static String::CharPointerType createFromInteger (const IntegerType number)
 | 
			
		||||
    static String::CharPointerType createFromInteger (IntegerType number)
 | 
			
		||||
    {
 | 
			
		||||
        char buffer [charsNeededForInt];
 | 
			
		||||
        auto* end = buffer + numElementsInArray (buffer);
 | 
			
		||||
@ -515,11 +490,11 @@ namespace NumberToStringConverters
 | 
			
		||||
        return StringHolder::createFromFixedLength (start, (size_t) (end - start - 1));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static String::CharPointerType createFromDouble (const double number, const int numberOfDecimalPlaces)
 | 
			
		||||
    static String::CharPointerType createFromDouble (double number, int numberOfDecimalPlaces, bool useScientificNotation)
 | 
			
		||||
    {
 | 
			
		||||
        char buffer [charsNeededForDouble];
 | 
			
		||||
        size_t len;
 | 
			
		||||
        auto start = doubleToString (buffer, numElementsInArray (buffer), (double) number, numberOfDecimalPlaces, len);
 | 
			
		||||
        auto start = doubleToString (buffer, number, numberOfDecimalPlaces, useScientificNotation, len);
 | 
			
		||||
        return StringHolder::createFromFixedLength (start, len);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -534,10 +509,10 @@ String::String (uint64 number)         : text (NumberToStringConverters::createF
 | 
			
		||||
String::String (long number)           : text (NumberToStringConverters::createFromInteger (number)) {}
 | 
			
		||||
String::String (unsigned long number)  : text (NumberToStringConverters::createFromInteger (number)) {}
 | 
			
		||||
 | 
			
		||||
String::String (float  number)         : text (NumberToStringConverters::createFromDouble ((double) number, 0)) {}
 | 
			
		||||
String::String (double number)         : text (NumberToStringConverters::createFromDouble (number, 0)) {}
 | 
			
		||||
String::String (float  number, int numberOfDecimalPlaces)  : text (NumberToStringConverters::createFromDouble ((double) number, numberOfDecimalPlaces)) {}
 | 
			
		||||
String::String (double number, int numberOfDecimalPlaces)  : text (NumberToStringConverters::createFromDouble (number, numberOfDecimalPlaces)) {}
 | 
			
		||||
String::String (float  number)         : text (NumberToStringConverters::createFromDouble ((double) number, 0, false)) {}
 | 
			
		||||
String::String (double number)         : text (NumberToStringConverters::createFromDouble (         number, 0, false)) {}
 | 
			
		||||
String::String (float  number, int numberOfDecimalPlaces, bool useScientificNotation)  : text (NumberToStringConverters::createFromDouble ((double) number, numberOfDecimalPlaces, useScientificNotation)) {}
 | 
			
		||||
String::String (double number, int numberOfDecimalPlaces, bool useScientificNotation)  : text (NumberToStringConverters::createFromDouble (         number, numberOfDecimalPlaces, useScientificNotation)) {}
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
int String::length() const noexcept
 | 
			
		||||
@ -1392,7 +1367,7 @@ String String::replaceCharacter (const juce_wchar charToReplace, const juce_wcha
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return static_cast<String&&> (builder.result);
 | 
			
		||||
    return std::move (builder.result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
String String::replaceCharacters (StringRef charactersToReplace, StringRef charactersToInsertInstead) const
 | 
			
		||||
@ -1417,7 +1392,7 @@ String String::replaceCharacters (StringRef charactersToReplace, StringRef chara
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return static_cast<String&&> (builder.result);
 | 
			
		||||
    return std::move (builder.result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
@ -1499,7 +1474,7 @@ String String::toUpperCase() const
 | 
			
		||||
        ++(builder.source);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return static_cast<String&&> (builder.result);
 | 
			
		||||
    return std::move (builder.result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
String String::toLowerCase() const
 | 
			
		||||
@ -1517,7 +1492,7 @@ String String::toLowerCase() const
 | 
			
		||||
        ++(builder.source);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return static_cast<String&&> (builder.result);
 | 
			
		||||
    return std::move (builder.result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
@ -1782,7 +1757,7 @@ String String::retainCharacters (StringRef charactersToRetain) const
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    builder.write (0);
 | 
			
		||||
    return static_cast<String&&> (builder.result);
 | 
			
		||||
    return std::move (builder.result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
String String::removeCharacters (StringRef charactersToRemove) const
 | 
			
		||||
@ -1803,7 +1778,7 @@ String String::removeCharacters (StringRef charactersToRemove) const
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return static_cast<String&&> (builder.result);
 | 
			
		||||
    return std::move (builder.result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
String String::initialSectionContainingOnly (StringRef permittedCharacters) const
 | 
			
		||||
@ -2005,7 +1980,7 @@ String String::createStringFromData (const void* const unknownData, int size)
 | 
			
		||||
 | 
			
		||||
        StringCreationHelper builder ((size_t) numChars);
 | 
			
		||||
 | 
			
		||||
        auto src = (const uint16*) (data + 2);
 | 
			
		||||
        auto src = reinterpret_cast<const uint16*> (data + 2);
 | 
			
		||||
 | 
			
		||||
        if (CharPointer_UTF16::isByteOrderMarkBigEndian (data))
 | 
			
		||||
        {
 | 
			
		||||
@ -2019,7 +1994,7 @@ String String::createStringFromData (const void* const unknownData, int size)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        builder.write (0);
 | 
			
		||||
        return static_cast<String&&> (builder.result);
 | 
			
		||||
        return std::move (builder.result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto* start = (const char*) data;
 | 
			
		||||
@ -2047,7 +2022,7 @@ struct StringEncodingConverter
 | 
			
		||||
    {
 | 
			
		||||
        auto& source = const_cast<String&> (s);
 | 
			
		||||
 | 
			
		||||
        typedef typename CharPointerType_Dest::CharType DestChar;
 | 
			
		||||
        using DestChar = typename CharPointerType_Dest::CharType;
 | 
			
		||||
 | 
			
		||||
        if (source.isEmpty())
 | 
			
		||||
            return CharPointerType_Dest (reinterpret_cast<const DestChar*> (&emptyChar));
 | 
			
		||||
@ -2075,19 +2050,19 @@ struct StringEncodingConverter
 | 
			
		||||
template <>
 | 
			
		||||
struct StringEncodingConverter<CharPointer_UTF8, CharPointer_UTF8>
 | 
			
		||||
{
 | 
			
		||||
    static CharPointer_UTF8 convert (const String& source) noexcept   { return CharPointer_UTF8 ((CharPointer_UTF8::CharType*) source.getCharPointer().getAddress()); }
 | 
			
		||||
    static CharPointer_UTF8 convert (const String& source) noexcept   { return CharPointer_UTF8 (reinterpret_cast<CharPointer_UTF8::CharType*> (source.getCharPointer().getAddress())); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct StringEncodingConverter<CharPointer_UTF16, CharPointer_UTF16>
 | 
			
		||||
{
 | 
			
		||||
    static CharPointer_UTF16 convert (const String& source) noexcept  { return CharPointer_UTF16 ((CharPointer_UTF16::CharType*) source.getCharPointer().getAddress()); }
 | 
			
		||||
    static CharPointer_UTF16 convert (const String& source) noexcept  { return CharPointer_UTF16 (reinterpret_cast<CharPointer_UTF16::CharType*> (source.getCharPointer().getAddress())); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct StringEncodingConverter<CharPointer_UTF32, CharPointer_UTF32>
 | 
			
		||||
{
 | 
			
		||||
    static CharPointer_UTF32 convert (const String& source) noexcept  { return CharPointer_UTF32 ((CharPointer_UTF32::CharType*) source.getCharPointer().getAddress()); }
 | 
			
		||||
    static CharPointer_UTF32 convert (const String& source) noexcept  { return CharPointer_UTF32 (reinterpret_cast<CharPointer_UTF32::CharType*> (source.getCharPointer().getAddress())); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
CharPointer_UTF8  String::toUTF8()  const { return StringEncodingConverter<CharPointerType, CharPointer_UTF8 >::convert (*this); }
 | 
			
		||||
@ -2210,12 +2185,128 @@ StringRef::StringRef (String::CharPointerType stringLiteral) noexcept  : text (s
 | 
			
		||||
StringRef::StringRef (const String& string) noexcept   : text (string.getCharPointer()) {}
 | 
			
		||||
StringRef::StringRef (const std::string& string)       : StringRef (string.c_str()) {}
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
static String reduceLengthOfFloatString (const String& input)
 | 
			
		||||
{
 | 
			
		||||
    const auto start = input.getCharPointer();
 | 
			
		||||
    const auto end = start + (int) input.length();
 | 
			
		||||
    auto trimStart = end;
 | 
			
		||||
    auto trimEnd = trimStart;
 | 
			
		||||
    auto exponentTrimStart = end;
 | 
			
		||||
    auto exponentTrimEnd = exponentTrimStart;
 | 
			
		||||
 | 
			
		||||
    decltype (*start) currentChar = '\0';
 | 
			
		||||
 | 
			
		||||
    for (auto c = end - 1; c > start; --c)
 | 
			
		||||
    {
 | 
			
		||||
        currentChar = *c;
 | 
			
		||||
 | 
			
		||||
        if (currentChar == '0' && c + 1 == trimStart)
 | 
			
		||||
        {
 | 
			
		||||
            --trimStart;
 | 
			
		||||
        }
 | 
			
		||||
        else if (currentChar == '.')
 | 
			
		||||
        {
 | 
			
		||||
            if (trimStart == c + 1 && trimStart != end && *trimStart == '0')
 | 
			
		||||
                ++trimStart;
 | 
			
		||||
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        else if (currentChar == 'e' || currentChar == 'E')
 | 
			
		||||
        {
 | 
			
		||||
            auto cNext = c + 1;
 | 
			
		||||
 | 
			
		||||
            if (cNext != end)
 | 
			
		||||
            {
 | 
			
		||||
                if (*cNext == '-')
 | 
			
		||||
                    ++cNext;
 | 
			
		||||
 | 
			
		||||
                exponentTrimStart = cNext;
 | 
			
		||||
 | 
			
		||||
                if (cNext != end && *cNext == '+')
 | 
			
		||||
                    ++cNext;
 | 
			
		||||
 | 
			
		||||
                exponentTrimEnd = cNext;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            while (cNext != end && *cNext++ == '0')
 | 
			
		||||
                exponentTrimEnd = cNext;
 | 
			
		||||
 | 
			
		||||
            if (exponentTrimEnd == end)
 | 
			
		||||
                exponentTrimStart = c;
 | 
			
		||||
 | 
			
		||||
            trimStart = c;
 | 
			
		||||
            trimEnd = trimStart;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((trimStart != trimEnd && currentChar == '.') || exponentTrimStart != exponentTrimEnd)
 | 
			
		||||
    {
 | 
			
		||||
        if (trimStart == trimEnd)
 | 
			
		||||
            return String (start, exponentTrimStart) + String (exponentTrimEnd, end);
 | 
			
		||||
 | 
			
		||||
        if (exponentTrimStart == exponentTrimEnd)
 | 
			
		||||
            return String (start, trimStart) + String (trimEnd, end);
 | 
			
		||||
 | 
			
		||||
        if (trimEnd == exponentTrimStart)
 | 
			
		||||
            return String (start, trimStart) + String (exponentTrimEnd, end);
 | 
			
		||||
 | 
			
		||||
        return String (start, trimStart) + String (trimEnd, exponentTrimStart) + String (exponentTrimEnd, end);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return input;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static String serialiseDouble (double input)
 | 
			
		||||
{
 | 
			
		||||
    auto absInput = std::abs (input);
 | 
			
		||||
 | 
			
		||||
    if (absInput >= 1.0e6 || absInput <= 1.0e-5)
 | 
			
		||||
        return reduceLengthOfFloatString ({ input, 15, true });
 | 
			
		||||
 | 
			
		||||
    int intInput = (int) input;
 | 
			
		||||
 | 
			
		||||
    if ((double) intInput == input)
 | 
			
		||||
        return { input, 1 };
 | 
			
		||||
 | 
			
		||||
    auto numberOfDecimalPlaces = [absInput]
 | 
			
		||||
    {
 | 
			
		||||
        if (absInput < 1.0)
 | 
			
		||||
        {
 | 
			
		||||
            if (absInput >= 1.0e-3)
 | 
			
		||||
            {
 | 
			
		||||
                if (absInput >= 1.0e-1) return 16;
 | 
			
		||||
                if (absInput >= 1.0e-2) return 17;
 | 
			
		||||
                return 18;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (absInput >= 1.0e-4) return 19;
 | 
			
		||||
            return 20;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (absInput < 1.0e3)
 | 
			
		||||
        {
 | 
			
		||||
            if (absInput < 1.0e1) return 15;
 | 
			
		||||
            if (absInput < 1.0e2) return 14;
 | 
			
		||||
            return 13;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (absInput < 1.0e4) return 12;
 | 
			
		||||
        if (absInput < 1.0e5) return 11;
 | 
			
		||||
        return 10;
 | 
			
		||||
    }();
 | 
			
		||||
 | 
			
		||||
    return reduceLengthOfFloatString (String (input, numberOfDecimalPlaces));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
//==============================================================================
 | 
			
		||||
#if JUCE_UNIT_TESTS
 | 
			
		||||
 #define STRINGIFY2(X) #X
 | 
			
		||||
 #define STRINGIFY(X) STRINGIFY2(X)
 | 
			
		||||
 | 
			
		||||
#define STRINGIFY2(X) #X
 | 
			
		||||
#define STRINGIFY(X) STRINGIFY2(X)
 | 
			
		||||
 | 
			
		||||
class StringTests  : public UnitTest
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
@ -2491,7 +2582,21 @@ public:
 | 
			
		||||
            expect (String::toHexString (data, 8, 1).equalsIgnoreCase ("01 02 03 04 0a 0b 0c 0d"));
 | 
			
		||||
            expect (String::toHexString (data, 8, 2).equalsIgnoreCase ("0102 0304 0a0b 0c0d"));
 | 
			
		||||
 | 
			
		||||
            expectEquals (String (12345.67, 4),     String ("12345.6700"));
 | 
			
		||||
            expectEquals (String (12345.67, 6),     String ("12345.670000"));
 | 
			
		||||
            expectEquals (String (2589410.5894, 7), String ("2589410.5894000"));
 | 
			
		||||
            expectEquals (String (12345.67, 8),     String ("12345.67000000"));
 | 
			
		||||
            expectEquals (String (1e19, 4),         String ("10000000000000000000.0000"));
 | 
			
		||||
            expectEquals (String (1e-34, 36),       String ("0.000000000000000000000000000000000100"));
 | 
			
		||||
            expectEquals (String (1.39, 1),         String ("1.4"));
 | 
			
		||||
 | 
			
		||||
            expectEquals (String (12345.67, 4,     true), String ("1.2346e+04"));
 | 
			
		||||
            expectEquals (String (12345.67, 6,     true), String ("1.234567e+04"));
 | 
			
		||||
            expectEquals (String (2589410.5894, 7, true), String ("2.5894106e+06"));
 | 
			
		||||
            expectEquals (String (12345.67, 8,     true), String ("1.23456700e+04"));
 | 
			
		||||
            expectEquals (String (1e19, 4,         true), String ("1.0000e+19"));
 | 
			
		||||
            expectEquals (String (1e-34, 5,        true), String ("1.00000e-34"));
 | 
			
		||||
            expectEquals (String (1.39, 1,         true), String ("1.4e+00"));
 | 
			
		||||
 | 
			
		||||
            beginTest ("Subsections");
 | 
			
		||||
            String s3;
 | 
			
		||||
@ -2681,6 +2786,147 @@ public:
 | 
			
		||||
            expect (! v2.equals (v4));
 | 
			
		||||
            expect (! v4.equals (v2));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            beginTest ("Significant figures");
 | 
			
		||||
 | 
			
		||||
            // Integers
 | 
			
		||||
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (13, 1), String ("10"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (13, 2), String ("13"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (13, 3), String ("13.0"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (13, 4), String ("13.00"));
 | 
			
		||||
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (19368, 1), String ("20000"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (19348, 3), String ("19300"));
 | 
			
		||||
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (-5, 1), String ("-5"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (-5, 3), String ("-5.00"));
 | 
			
		||||
 | 
			
		||||
            // Zero
 | 
			
		||||
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (0, 1), String ("0"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (0, 2), String ("0.0"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (0, 3), String ("0.00"));
 | 
			
		||||
 | 
			
		||||
            // Floating point
 | 
			
		||||
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (19.0, 1), String ("20"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (19.0, 2), String ("19"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (19.0, 3), String ("19.0"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (19.0, 4), String ("19.00"));
 | 
			
		||||
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (-5.45, 1), String ("-5"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (-5.45, 3), String ("-5.45"));
 | 
			
		||||
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (12345.6789, 9), String ("12345.6789"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (12345.6789, 8), String ("12345.679"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (12345.6789, 5), String ("12346"));
 | 
			
		||||
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (0.00028647, 6), String ("0.000286470"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (0.0028647,  6), String ("0.00286470"));
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (2.8647,     6), String ("2.86470"));
 | 
			
		||||
 | 
			
		||||
            expectEquals (String::toDecimalStringWithSignificantFigures (-0.0000000000019, 1), String ("-0.000000000002"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            beginTest ("Float trimming");
 | 
			
		||||
 | 
			
		||||
            {
 | 
			
		||||
                StringPairArray tests;
 | 
			
		||||
                tests.set ("1", "1");
 | 
			
		||||
                tests.set ("1.0", "1.0");
 | 
			
		||||
                tests.set ("-1", "-1");
 | 
			
		||||
                tests.set ("-100", "-100");
 | 
			
		||||
                tests.set ("110", "110");
 | 
			
		||||
                tests.set ("9090", "9090");
 | 
			
		||||
                tests.set ("1000.0", "1000.0");
 | 
			
		||||
                tests.set ("1.0", "1.0");
 | 
			
		||||
                tests.set ("-1.00", "-1.0");
 | 
			
		||||
                tests.set ("1.20", "1.2");
 | 
			
		||||
                tests.set ("1.300", "1.3");
 | 
			
		||||
                tests.set ("1.301", "1.301");
 | 
			
		||||
                tests.set ("1e", "1");
 | 
			
		||||
                tests.set ("-1e+", "-1");
 | 
			
		||||
                tests.set ("1e-", "1");
 | 
			
		||||
                tests.set ("1e0", "1");
 | 
			
		||||
                tests.set ("1e+0", "1");
 | 
			
		||||
                tests.set ("1e-0", "1");
 | 
			
		||||
                tests.set ("1e000", "1");
 | 
			
		||||
                tests.set ("1e+000", "1");
 | 
			
		||||
                tests.set ("-1e-000", "-1");
 | 
			
		||||
                tests.set ("1e100", "1e100");
 | 
			
		||||
                tests.set ("100e100", "100e100");
 | 
			
		||||
                tests.set ("100.0e0100", "100.0e100");
 | 
			
		||||
                tests.set ("-1e1", "-1e1");
 | 
			
		||||
                tests.set ("1e10", "1e10");
 | 
			
		||||
                tests.set ("-1e+10", "-1e10");
 | 
			
		||||
                tests.set ("1e-10", "1e-10");
 | 
			
		||||
                tests.set ("1e0010", "1e10");
 | 
			
		||||
                tests.set ("1e-0010", "1e-10");
 | 
			
		||||
                tests.set ("1e-1", "1e-1");
 | 
			
		||||
                tests.set ("-1.0e1", "-1.0e1");
 | 
			
		||||
                tests.set ("1.0e-1", "1.0e-1");
 | 
			
		||||
                tests.set ("1.00e-1", "1.0e-1");
 | 
			
		||||
                tests.set ("1.001e1", "1.001e1");
 | 
			
		||||
                tests.set ("1.010e+1", "1.01e1");
 | 
			
		||||
                tests.set ("-1.1000e1", "-1.1e1");
 | 
			
		||||
 | 
			
		||||
                for (auto& input : tests.getAllKeys())
 | 
			
		||||
                    expectEquals (reduceLengthOfFloatString (input), tests[input]);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            {
 | 
			
		||||
                std::map<double, String> tests;
 | 
			
		||||
                tests[1] = "1.0";
 | 
			
		||||
                tests[1.1] = "1.1";
 | 
			
		||||
                tests[1.01] = "1.01";
 | 
			
		||||
                tests[0.76378] = "7.6378e-1";
 | 
			
		||||
                tests[-10] = "-1.0e1";
 | 
			
		||||
                tests[10.01] = "1.001e1";
 | 
			
		||||
                tests[10691.01] = "1.069101e4";
 | 
			
		||||
                tests[0.0123] = "1.23e-2";
 | 
			
		||||
                tests[-3.7e-27] = "-3.7e-27";
 | 
			
		||||
                tests[1e+40] = "1.0e40";
 | 
			
		||||
 | 
			
		||||
                for (auto& test : tests)
 | 
			
		||||
                    expectEquals (reduceLengthOfFloatString (String (test.first, 15, true)), test.second);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            beginTest ("Serialisation");
 | 
			
		||||
 | 
			
		||||
            std::map <double, String> tests;
 | 
			
		||||
 | 
			
		||||
            tests[364] = "364.0";
 | 
			
		||||
            tests[1e7] = "1.0e7";
 | 
			
		||||
            tests[12345678901] = "1.2345678901e10";
 | 
			
		||||
 | 
			
		||||
            tests[1234567890123456.7] = "1.234567890123457e15";
 | 
			
		||||
            tests[12345678.901234567] = "1.234567890123457e7";
 | 
			
		||||
            tests[1234567.8901234567] = "1.234567890123457e6";
 | 
			
		||||
            tests[123456.78901234567] = "123456.7890123457";
 | 
			
		||||
            tests[12345.678901234567] = "12345.67890123457";
 | 
			
		||||
            tests[1234.5678901234567] = "1234.567890123457";
 | 
			
		||||
            tests[123.45678901234567] = "123.4567890123457";
 | 
			
		||||
            tests[12.345678901234567] = "12.34567890123457";
 | 
			
		||||
            tests[1.2345678901234567] = "1.234567890123457";
 | 
			
		||||
            tests[0.12345678901234567] = "0.1234567890123457";
 | 
			
		||||
            tests[0.012345678901234567] = "0.01234567890123457";
 | 
			
		||||
            tests[0.0012345678901234567] = "0.001234567890123457";
 | 
			
		||||
            tests[0.00012345678901234567] = "0.0001234567890123457";
 | 
			
		||||
            tests[0.000012345678901234567] = "0.00001234567890123457";
 | 
			
		||||
            tests[0.0000012345678901234567] = "1.234567890123457e-6";
 | 
			
		||||
            tests[0.00000012345678901234567] = "1.234567890123457e-7";
 | 
			
		||||
 | 
			
		||||
            for (auto& test : tests)
 | 
			
		||||
            {
 | 
			
		||||
                expectEquals (serialiseDouble (test.first), test.second);
 | 
			
		||||
                expectEquals (serialiseDouble (-test.first), "-" + test.second);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -153,11 +153,11 @@ public:
 | 
			
		||||
        toUTF32() methods let you access the string's content in any of the other formats.
 | 
			
		||||
    */
 | 
			
		||||
   #if (JUCE_STRING_UTF_TYPE == 32)
 | 
			
		||||
    typedef CharPointer_UTF32 CharPointerType;
 | 
			
		||||
    using CharPointerType = CharPointer_UTF32;
 | 
			
		||||
   #elif (JUCE_STRING_UTF_TYPE == 16)
 | 
			
		||||
    typedef CharPointer_UTF16 CharPointerType;
 | 
			
		||||
    using CharPointerType = CharPointer_UTF16;
 | 
			
		||||
   #elif (DOXYGEN || JUCE_STRING_UTF_TYPE == 8)
 | 
			
		||||
    typedef CharPointer_UTF8  CharPointerType;
 | 
			
		||||
    using CharPointerType = CharPointer_UTF8;
 | 
			
		||||
   #else
 | 
			
		||||
    #error "You must set the value of JUCE_STRING_UTF_TYPE to be either 8, 16, or 32!"
 | 
			
		||||
   #endif
 | 
			
		||||
@ -962,21 +962,26 @@ public:
 | 
			
		||||
 | 
			
		||||
    /** Creates a string representing this floating-point number.
 | 
			
		||||
        @param floatValue               the value to convert to a string
 | 
			
		||||
        @param numberOfDecimalPlaces    if this is > 0, it will format the number using that many
 | 
			
		||||
                                        decimal places, and will not use exponent notation. If 0 or
 | 
			
		||||
                                        less, it will use exponent notation if necessary.
 | 
			
		||||
        @param numberOfDecimalPlaces    if this is > 0 the number will be formatted using that many
 | 
			
		||||
                                        decimal places, adding trailing zeros as required. If 0 or
 | 
			
		||||
                                        less the number will be formatted using the C++ standard
 | 
			
		||||
                                        library default format, which uses scientific notation for
 | 
			
		||||
                                        large and small numbers.
 | 
			
		||||
        @param useScientificNotation    if the number should be formatted using scientific notation
 | 
			
		||||
        @see getDoubleValue, getIntValue
 | 
			
		||||
    */
 | 
			
		||||
    String (float floatValue, int numberOfDecimalPlaces);
 | 
			
		||||
    String (float floatValue, int numberOfDecimalPlaces, bool useScientificNotation = false);
 | 
			
		||||
 | 
			
		||||
    /** Creates a string representing this floating-point number.
 | 
			
		||||
        @param doubleValue              the value to convert to a string
 | 
			
		||||
        @param numberOfDecimalPlaces    if this is > 0, it will format the number using that many
 | 
			
		||||
                                        decimal places, and will not use exponent notation. If 0 or
 | 
			
		||||
                                        less, it will use exponent notation if necessary.
 | 
			
		||||
                                        decimal places, adding trailing zeros as required, and
 | 
			
		||||
                                        will not use exponent notation. If 0 or less, it will use
 | 
			
		||||
                                        exponent notation if necessary.
 | 
			
		||||
        @param useScientificNotation    if the number should be formatted using scientific notation
 | 
			
		||||
        @see getFloatValue, getIntValue
 | 
			
		||||
    */
 | 
			
		||||
    String (double doubleValue, int numberOfDecimalPlaces);
 | 
			
		||||
    String (double doubleValue, int numberOfDecimalPlaces, bool useScientificNotation = false);
 | 
			
		||||
 | 
			
		||||
    // Automatically creating a String from a bool opens up lots of nasty type conversion edge cases.
 | 
			
		||||
    // If you want a String representation of a bool you can cast the bool to an int first.
 | 
			
		||||
@ -1056,6 +1061,131 @@ public:
 | 
			
		||||
    */
 | 
			
		||||
    static String toHexString (const void* data, int size, int groupSize = 1);
 | 
			
		||||
 | 
			
		||||
    /** Returns a string containing a decimal with a set number of significant figures.
 | 
			
		||||
 | 
			
		||||
        @param number                         the intput number
 | 
			
		||||
        @param numberOfSignificantFigures     the number of significant figures to use
 | 
			
		||||
    */
 | 
			
		||||
    template <typename DecimalType>
 | 
			
		||||
    static String toDecimalStringWithSignificantFigures (DecimalType number, int numberOfSignificantFigures)
 | 
			
		||||
    {
 | 
			
		||||
        jassert (numberOfSignificantFigures > 0);
 | 
			
		||||
 | 
			
		||||
        if (number == 0)
 | 
			
		||||
        {
 | 
			
		||||
            if (numberOfSignificantFigures > 1)
 | 
			
		||||
            {
 | 
			
		||||
                String result ("0.0");
 | 
			
		||||
 | 
			
		||||
                for (int i = 2; i < numberOfSignificantFigures; ++i)
 | 
			
		||||
                    result += "0";
 | 
			
		||||
 | 
			
		||||
                return result;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return "0";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auto numDigitsBeforePoint = (int) std::ceil (std::log10 (number < 0 ? -number : number));
 | 
			
		||||
 | 
			
		||||
       #if JUCE_PROJUCER_LIVE_BUILD
 | 
			
		||||
        auto doubleNumber = (double) number;
 | 
			
		||||
        constexpr int bufferSize = 311;
 | 
			
		||||
        char buffer[bufferSize];
 | 
			
		||||
        auto* ptr = &(buffer[0]);
 | 
			
		||||
        auto* const safeEnd = ptr + (bufferSize - 1);
 | 
			
		||||
        auto numSigFigsParsed = 0;
 | 
			
		||||
 | 
			
		||||
        auto writeToBuffer = [safeEnd] (char* destination, char data)
 | 
			
		||||
        {
 | 
			
		||||
            *destination++ = data;
 | 
			
		||||
 | 
			
		||||
            if (destination == safeEnd)
 | 
			
		||||
            {
 | 
			
		||||
                *destination = '\0';
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        auto truncateOrRound = [numberOfSignificantFigures] (double fractional, int sigFigsParsed)
 | 
			
		||||
        {
 | 
			
		||||
            return (sigFigsParsed == numberOfSignificantFigures - 1) ? (int) std::round (fractional)
 | 
			
		||||
                                                                     : (int) fractional;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        if (doubleNumber < 0)
 | 
			
		||||
        {
 | 
			
		||||
            doubleNumber *= -1;
 | 
			
		||||
            *ptr++ = '-';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (numDigitsBeforePoint > 0)
 | 
			
		||||
        {
 | 
			
		||||
            doubleNumber /= std::pow (10.0, numDigitsBeforePoint);
 | 
			
		||||
 | 
			
		||||
            while (numDigitsBeforePoint-- > 0)
 | 
			
		||||
            {
 | 
			
		||||
                if (numSigFigsParsed == numberOfSignificantFigures)
 | 
			
		||||
                {
 | 
			
		||||
                    if (writeToBuffer (ptr++, '0'))
 | 
			
		||||
                        return buffer;
 | 
			
		||||
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                doubleNumber *= 10;
 | 
			
		||||
                auto digit = truncateOrRound (doubleNumber, numSigFigsParsed);
 | 
			
		||||
 | 
			
		||||
                if (writeToBuffer (ptr++, (char) ('0' + digit)))
 | 
			
		||||
                    return buffer;
 | 
			
		||||
 | 
			
		||||
                ++numSigFigsParsed;
 | 
			
		||||
                doubleNumber -= digit;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (numSigFigsParsed == numberOfSignificantFigures)
 | 
			
		||||
            {
 | 
			
		||||
                *ptr++ = '\0';
 | 
			
		||||
                return buffer;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            *ptr++ = '0';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (writeToBuffer (ptr++, '.'))
 | 
			
		||||
            return buffer;
 | 
			
		||||
 | 
			
		||||
        while (numSigFigsParsed < numberOfSignificantFigures)
 | 
			
		||||
        {
 | 
			
		||||
            doubleNumber *= 10;
 | 
			
		||||
            auto digit = truncateOrRound (doubleNumber, numSigFigsParsed);
 | 
			
		||||
 | 
			
		||||
            if (writeToBuffer (ptr++, (char) ('0' + digit)))
 | 
			
		||||
                return buffer;
 | 
			
		||||
 | 
			
		||||
            if (numSigFigsParsed != 0 || digit != 0)
 | 
			
		||||
                ++numSigFigsParsed;
 | 
			
		||||
 | 
			
		||||
            doubleNumber -= digit;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        *ptr++ = '\0';
 | 
			
		||||
        return buffer;
 | 
			
		||||
       #else
 | 
			
		||||
        auto shift = numberOfSignificantFigures - numDigitsBeforePoint;
 | 
			
		||||
        auto factor = std::pow (10.0, shift);
 | 
			
		||||
        auto rounded = std::round (number * factor) / factor;
 | 
			
		||||
 | 
			
		||||
        std::stringstream ss;
 | 
			
		||||
        ss << std::fixed << std::setprecision (std::max (shift, 0)) << rounded;
 | 
			
		||||
        return ss.str();
 | 
			
		||||
       #endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    /** Returns the character pointer currently being used to store this string.
 | 
			
		||||
 | 
			
		||||
@ -1278,7 +1408,7 @@ private:
 | 
			
		||||
    static String createHex (uint64);
 | 
			
		||||
 | 
			
		||||
    template <typename Type>
 | 
			
		||||
    static String createHex (Type n)  { return createHex (static_cast<typename TypeHelpers::UnsignedTypeWithSize<sizeof (n)>::type> (n)); }
 | 
			
		||||
    static String createHex (Type n)  { return createHex (static_cast<typename TypeHelpers::UnsignedTypeWithSize<(int) sizeof (n)>::type> (n)); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,12 @@ StringArray::StringArray (const StringArray& other)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
StringArray::StringArray (StringArray&& other) noexcept
 | 
			
		||||
    : strings (static_cast<Array<String>&&> (other.strings))
 | 
			
		||||
    : strings (std::move (other.strings))
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
StringArray::StringArray (Array<String>&& other) noexcept
 | 
			
		||||
    : strings (std::move (other))
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -80,7 +85,7 @@ StringArray& StringArray::operator= (const StringArray& other)
 | 
			
		||||
 | 
			
		||||
StringArray& StringArray::operator= (StringArray&& other) noexcept
 | 
			
		||||
{
 | 
			
		||||
    strings = static_cast<Array<String>&&> (other.strings);
 | 
			
		||||
    strings = std::move (other.strings);
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -127,19 +132,18 @@ String& StringArray::getReference (int index) noexcept
 | 
			
		||||
    return strings.getReference (index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void StringArray::add (const String& newString)
 | 
			
		||||
void StringArray::add (String newString)
 | 
			
		||||
{
 | 
			
		||||
    strings.add (newString);
 | 
			
		||||
    // NB: the local temp copy is to avoid a dangling pointer if the
 | 
			
		||||
    // argument being passed-in is a reference into this array.
 | 
			
		||||
    strings.add (std::move (newString));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void StringArray::add (String&& stringToAdd)
 | 
			
		||||
void StringArray::insert (int index, String newString)
 | 
			
		||||
{
 | 
			
		||||
    strings.add (static_cast<String&&> (stringToAdd));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void StringArray::insert (int index, const String& newString)
 | 
			
		||||
{
 | 
			
		||||
    strings.insert (index, newString);
 | 
			
		||||
    // NB: the local temp copy is to avoid a dangling pointer if the
 | 
			
		||||
    // argument being passed-in is a reference into this array.
 | 
			
		||||
    strings.insert (index, std::move (newString));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool StringArray::addIfNotAlreadyThere (const String& newString, bool ignoreCase)
 | 
			
		||||
@ -153,6 +157,8 @@ bool StringArray::addIfNotAlreadyThere (const String& newString, bool ignoreCase
 | 
			
		||||
 | 
			
		||||
void StringArray::addArray (const StringArray& otherArray, int startIndex, int numElementsToAdd)
 | 
			
		||||
{
 | 
			
		||||
    jassert (this != &otherArray); // can't add from our own elements!
 | 
			
		||||
 | 
			
		||||
    if (startIndex < 0)
 | 
			
		||||
    {
 | 
			
		||||
        jassertfalse;
 | 
			
		||||
@ -168,13 +174,15 @@ void StringArray::addArray (const StringArray& otherArray, int startIndex, int n
 | 
			
		||||
 | 
			
		||||
void StringArray::mergeArray (const StringArray& otherArray, bool ignoreCase)
 | 
			
		||||
{
 | 
			
		||||
    jassert (this != &otherArray); // can't add from our own elements!
 | 
			
		||||
 | 
			
		||||
    for (auto& s : otherArray)
 | 
			
		||||
        addIfNotAlreadyThere (s, ignoreCase);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void StringArray::set (int index, const String& newString)
 | 
			
		||||
void StringArray::set (int index, String newString)
 | 
			
		||||
{
 | 
			
		||||
    strings.set (index, newString);
 | 
			
		||||
    strings.set (index, std::move (newString));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool StringArray::contains (StringRef stringToLookFor, bool ignoreCase) const
 | 
			
		||||
 | 
			
		||||
@ -54,6 +54,16 @@ public:
 | 
			
		||||
    /** Creates an array containing a list of strings. */
 | 
			
		||||
    StringArray (const std::initializer_list<const char*>& strings);
 | 
			
		||||
 | 
			
		||||
    /** Creates a StringArray by moving from an Array<String> */
 | 
			
		||||
    StringArray (Array<String>&&) noexcept;
 | 
			
		||||
 | 
			
		||||
    /** Creates a StringArray from an array of objects which can be implicitly converted to Strings. */
 | 
			
		||||
    template <typename Type>
 | 
			
		||||
    StringArray (const Array<Type>& stringArray)
 | 
			
		||||
    {
 | 
			
		||||
        addArray (stringArray.begin(), stringArray.end());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Creates an array from a raw array of strings.
 | 
			
		||||
        @param strings          an array of strings to add
 | 
			
		||||
        @param numberOfStrings  how many items there are in the array
 | 
			
		||||
@ -96,6 +106,14 @@ public:
 | 
			
		||||
    /** Move assignment operator */
 | 
			
		||||
    StringArray& operator= (StringArray&&) noexcept;
 | 
			
		||||
 | 
			
		||||
    /** Copies a StringArray from an array of objects which can be implicitly converted to Strings. */
 | 
			
		||||
    template <typename Type>
 | 
			
		||||
    StringArray& operator= (const Array<Type>& stringArray)
 | 
			
		||||
    {
 | 
			
		||||
        addArray (stringArray.begin(), stringArray.end());
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Swaps the contents of this and another StringArray. */
 | 
			
		||||
    void swapWith (StringArray&) noexcept;
 | 
			
		||||
 | 
			
		||||
@ -169,10 +187,7 @@ public:
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    /** Appends a string at the end of the array. */
 | 
			
		||||
    void add (const String& stringToAdd);
 | 
			
		||||
 | 
			
		||||
    /** Appends a string at the end of the array. */
 | 
			
		||||
    void add (String&& stringToAdd);
 | 
			
		||||
    void add (String stringToAdd);
 | 
			
		||||
 | 
			
		||||
    /** Inserts a string into the array.
 | 
			
		||||
 | 
			
		||||
@ -181,7 +196,7 @@ public:
 | 
			
		||||
        If the index is less than zero or greater than the size of the array,
 | 
			
		||||
        the new string will be added to the end of the array.
 | 
			
		||||
    */
 | 
			
		||||
    void insert (int index, const String& stringToAdd);
 | 
			
		||||
    void insert (int index, String stringToAdd);
 | 
			
		||||
 | 
			
		||||
    /** Adds a string to the array as long as it's not already in there.
 | 
			
		||||
        The search can optionally be case-insensitive.
 | 
			
		||||
@ -195,7 +210,7 @@ public:
 | 
			
		||||
        If the index is higher than the array's size, the new string will be
 | 
			
		||||
        added to the end of the array; if it's less than zero nothing happens.
 | 
			
		||||
    */
 | 
			
		||||
    void set (int index, const String& newString);
 | 
			
		||||
    void set (int index, String newString);
 | 
			
		||||
 | 
			
		||||
    /** Appends some strings from another array to the end of this one.
 | 
			
		||||
 | 
			
		||||
@ -208,6 +223,18 @@ public:
 | 
			
		||||
                   int startIndex = 0,
 | 
			
		||||
                   int numElementsToAdd = -1);
 | 
			
		||||
 | 
			
		||||
    /** Adds items from a range of start/end iterators of some kind of objects which
 | 
			
		||||
        can be implicitly converted to Strings.
 | 
			
		||||
    */
 | 
			
		||||
    template <typename Iterator>
 | 
			
		||||
    void addArray (Iterator&& start, Iterator&& end)
 | 
			
		||||
    {
 | 
			
		||||
        ensureStorageAllocated (size() + (int) static_cast<size_t> (end - start));
 | 
			
		||||
 | 
			
		||||
        while (start != end)
 | 
			
		||||
            strings.add (*start++);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Merges the strings from another array into this one.
 | 
			
		||||
        This will not add a string that already exists.
 | 
			
		||||
 | 
			
		||||
@ -393,7 +420,7 @@ public:
 | 
			
		||||
 | 
			
		||||
    //==============================================================================
 | 
			
		||||
    /** Sorts the array into alphabetical order.
 | 
			
		||||
        @param ignoreCase       if true, the comparisons used will be case-sensitive.
 | 
			
		||||
        @param ignoreCase       if true, the comparisons used will not be case-sensitive.
 | 
			
		||||
    */
 | 
			
		||||
    void sort (bool ignoreCase);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user