| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2022 - Raw Material Software Limited
 - 
 -    JUCE is an open source library subject to commercial or open-source
 -    licensing.
 - 
 -    The code included in this file is provided under the terms of the ISC license
 -    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
 -    To use, copy, modify, and/or distribute this software for any purpose with or
 -    without fee is hereby granted provided that the above copyright notice and
 -    this permission notice appear in all copies.
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - namespace juce
 - {
 - 
 - JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4514 4996)
 - 
 - juce_wchar CharacterFunctions::toUpperCase (const juce_wchar character) noexcept
 - {
 -     return (juce_wchar) towupper ((wint_t) character);
 - }
 - 
 - juce_wchar CharacterFunctions::toLowerCase (const juce_wchar character) noexcept
 - {
 -     return (juce_wchar) towlower ((wint_t) character);
 - }
 - 
 - bool CharacterFunctions::isUpperCase (const juce_wchar character) noexcept
 - {
 -    #if JUCE_WINDOWS
 -     return iswupper ((wint_t) character) != 0;
 -    #else
 -     return toLowerCase (character) != character;
 -    #endif
 - }
 - 
 - bool CharacterFunctions::isLowerCase (const juce_wchar character) noexcept
 - {
 -    #if JUCE_WINDOWS
 -     return iswlower ((wint_t) character) != 0;
 -    #else
 -     return toUpperCase (character) != character;
 -    #endif
 - }
 - 
 - JUCE_END_IGNORE_WARNINGS_MSVC
 - 
 - //==============================================================================
 - bool CharacterFunctions::isWhitespace (const char character) noexcept
 - {
 -     return character == ' ' || (character <= 13 && character >= 9);
 - }
 - 
 - bool CharacterFunctions::isWhitespace (const juce_wchar character) noexcept
 - {
 -     return iswspace ((wint_t) character) != 0;
 - }
 - 
 - bool CharacterFunctions::isDigit (const char character) noexcept
 - {
 -     return (character >= '0' && character <= '9');
 - }
 - 
 - bool CharacterFunctions::isDigit (const juce_wchar character) noexcept
 - {
 -     return iswdigit ((wint_t) character) != 0;
 - }
 - 
 - bool CharacterFunctions::isLetter (const char character) noexcept
 - {
 -     return (character >= 'a' && character <= 'z')
 -         || (character >= 'A' && character <= 'Z');
 - }
 - 
 - bool CharacterFunctions::isLetter (const juce_wchar character) noexcept
 - {
 -     return iswalpha ((wint_t) character) != 0;
 - }
 - 
 - bool CharacterFunctions::isLetterOrDigit (const char character) noexcept
 - {
 -     return (character >= 'a' && character <= 'z')
 -         || (character >= 'A' && character <= 'Z')
 -         || (character >= '0' && character <= '9');
 - }
 - 
 - bool CharacterFunctions::isLetterOrDigit (const juce_wchar character) noexcept
 - {
 -     return iswalnum ((wint_t) character) != 0;
 - }
 - 
 - bool CharacterFunctions::isPrintable (const char character) noexcept
 - {
 -     return (character >= ' ' && character <= '~');
 - }
 - 
 - bool CharacterFunctions::isPrintable (const juce_wchar character) noexcept
 - {
 -     return iswprint ((wint_t) character) != 0;
 - }
 - 
 - int CharacterFunctions::getHexDigitValue (const juce_wchar digit) noexcept
 - {
 -     auto d = (unsigned int) (digit - '0');
 - 
 -     if (d < (unsigned int) 10)
 -         return (int) d;
 - 
 -     d += (unsigned int) ('0' - 'a');
 - 
 -     if (d < (unsigned int) 6)
 -         return (int) d + 10;
 - 
 -     d += (unsigned int) ('a' - 'A');
 - 
 -     if (d < (unsigned int) 6)
 -         return (int) d + 10;
 - 
 -     return -1;
 - }
 - 
 - double CharacterFunctions::mulexp10 (const double value, int exponent) noexcept
 - {
 -     if (exponent == 0)
 -         return value;
 - 
 -     if (exactlyEqual (value, 0.0))
 -         return 0;
 - 
 -     const bool negative = (exponent < 0);
 - 
 -     if (negative)
 -         exponent = -exponent;
 - 
 -     double result = 1.0, power = 10.0;
 - 
 -     for (int bit = 1; exponent != 0; bit <<= 1)
 -     {
 -         if ((exponent & bit) != 0)
 -         {
 -             exponent ^= bit;
 -             result *= power;
 - 
 -             if (exponent == 0)
 -                 break;
 -         }
 - 
 -         power *= power;
 -     }
 - 
 -     return negative ? (value / result) : (value * result);
 - }
 - 
 - juce_wchar CharacterFunctions::getUnicodeCharFromWindows1252Codepage (const uint8 c) noexcept
 - {
 -     if (c < 0x80 || c >= 0xa0)
 -         return (juce_wchar) c;
 - 
 -     static const uint16 lookup[] = { 0x20AC, 0x0007, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
 -                                      0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0007, 0x017D, 0x0007,
 -                                      0x0007, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
 -                                      0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0007, 0x017E, 0x0178 };
 - 
 -     return (juce_wchar) lookup[c - 0x80];
 - }
 - 
 - 
 - //==============================================================================
 - //==============================================================================
 - #if JUCE_UNIT_TESTS
 - 
 - #define QUOTE(x) #x
 - #define STR(value) QUOTE(value)
 - #define ASYM_CHARPTR_DOUBLE_PAIR(str, value) std::pair<const char*, double> (STR(str), value)
 - #define CHARPTR_DOUBLE_PAIR(value) ASYM_CHARPTR_DOUBLE_PAIR(value, value)
 - #define CHARPTR_DOUBLE_PAIR_COMBOS(value) \
 -     CHARPTR_DOUBLE_PAIR(value), \
 -     CHARPTR_DOUBLE_PAIR(-value), \
 -     ASYM_CHARPTR_DOUBLE_PAIR(+value, value), \
 -     ASYM_CHARPTR_DOUBLE_PAIR(000000 ## value, value), \
 -     ASYM_CHARPTR_DOUBLE_PAIR(+000 ## value, value), \
 -     ASYM_CHARPTR_DOUBLE_PAIR(-0 ## value, -value)
 - 
 - namespace characterFunctionsTests
 - {
 - 
 - template <typename CharPointerType>
 - MemoryBlock memoryBlockFromCharPtr (const typename CharPointerType::CharType* charPtr)
 - {
 -     using CharType = typename CharPointerType::CharType;
 - 
 -     MemoryBlock result;
 -     CharPointerType source (charPtr);
 - 
 -     result.setSize (CharPointerType::getBytesRequiredFor (source) + sizeof (CharType));
 -     CharPointerType dest { (CharType*) result.getData() };
 -     dest.writeAll (source);
 -     return result;
 - }
 - 
 - template <typename FromCharPointerType, typename ToCharPointerType>
 - MemoryBlock convert (const MemoryBlock& source, bool removeNullTerminator = false)
 - {
 -     using ToCharType   = typename ToCharPointerType  ::CharType;
 -     using FromCharType = typename FromCharPointerType::CharType;
 - 
 -     FromCharPointerType sourcePtr { (FromCharType*) source.getData() };
 - 
 -     std::vector<juce_wchar> sourceChars;
 -     size_t requiredSize = 0;
 -     juce_wchar c;
 - 
 -     while ((c = sourcePtr.getAndAdvance()) != '\0')
 -     {
 -         requiredSize += ToCharPointerType::getBytesRequiredFor (c);
 -         sourceChars.push_back (c);
 -     }
 - 
 -     if (! removeNullTerminator)
 -         requiredSize += sizeof (ToCharType);
 - 
 -     MemoryBlock result;
 -     result.setSize (requiredSize);
 - 
 -     ToCharPointerType dest { (ToCharType*) result.getData() };
 - 
 -     for (auto wc : sourceChars)
 -         dest.write (wc);
 - 
 -     if (! removeNullTerminator)
 -         dest.writeNull();
 - 
 -     return result;
 - }
 - 
 - struct SeparatorStrings
 - {
 -     std::vector<MemoryBlock> terminals, nulls;
 - };
 - 
 - template <typename CharPointerType>
 - SeparatorStrings getSeparators()
 - {
 -     jassertfalse;
 -     return {};
 - }
 - 
 - template <>
 - SeparatorStrings getSeparators<CharPointer_ASCII>()
 - {
 -     SeparatorStrings result;
 - 
 -     const CharPointer_ASCII::CharType* terminalCharPtrs[] = {
 -         "", "-", "+", "e", "e+", "E-", "f", " ", ",", ";", "<", "'", "\"", "_", "k",
 -         " +", " -", " -e", "-In ", " +n", "n", "  r"
 -     };
 - 
 -     for (auto ptr : terminalCharPtrs)
 -         result.terminals.push_back (memoryBlockFromCharPtr<CharPointer_ASCII> (ptr));
 - 
 -     const CharPointer_ASCII::CharType* nullCharPtrs[] = { "." };
 - 
 -     result.nulls = result.terminals;
 - 
 -     for (auto ptr : nullCharPtrs)
 -         result.nulls.push_back (memoryBlockFromCharPtr<CharPointer_ASCII> (ptr));
 - 
 -     return result;
 - }
 - 
 - template <>
 - SeparatorStrings getSeparators<CharPointer_UTF8>()
 - {
 -     auto result = getSeparators<CharPointer_ASCII>();
 - 
 -     const CharPointer_UTF8::CharType* terminalCharPtrs[] = {
 -         "\xe2\x82\xac",                      // €
 -         "\xf0\x90\x90\xB7",                  // 𐐷
 -         "\xf0\x9f\x98\x83",                  // 😃
 -         "\xf0\x9f\x8f\x81\xF0\x9F\x9A\x97"   // 🏁🚗
 -     };
 - 
 -     for (auto ptr : terminalCharPtrs)
 -     {
 -         auto block = memoryBlockFromCharPtr<CharPointer_UTF8> (ptr);
 - 
 -         for (auto vec : { &result.terminals, &result.nulls })
 -             vec->push_back (block);
 -     }
 - 
 -     return result;
 - }
 - 
 - template <typename CharPointerType, typename StorageType>
 - SeparatorStrings prefixWithAsciiSeparators (const std::vector<std::vector<StorageType>>& terminalCharPtrs)
 - {
 -     auto asciiSeparators = getSeparators<CharPointer_ASCII>();
 - 
 -     SeparatorStrings result;
 - 
 -     for (const auto& block : asciiSeparators.terminals)
 -         result.terminals.push_back (convert<CharPointer_ASCII, CharPointerType> (block));
 - 
 -     for (const auto& block : asciiSeparators.nulls)
 -         result.nulls.push_back (convert<CharPointer_ASCII, CharPointerType> (block));
 - 
 -     for (auto& t : terminalCharPtrs)
 -     {
 -         const auto block = memoryBlockFromCharPtr<CharPointerType> ((typename CharPointerType::CharType*) t.data());
 - 
 -         for (auto vec : { &result.terminals, &result.nulls })
 -             vec->push_back (block);
 -     }
 - 
 -     return result;
 - }
 - 
 - template <>
 - SeparatorStrings getSeparators<CharPointer_UTF16>()
 - {
 -     const std::vector<std::vector<char16_t>> terminalCharPtrs {
 -         { 0x0                                 },
 -         { 0x0076, 0x0                         },   // v
 -         { 0x20ac, 0x0                         },   // €
 -         { 0xd801, 0xdc37, 0x0                 },   // 𐐷
 -         { 0x0065, 0xd83d, 0xde03, 0x0         },   // e😃
 -         { 0xd83c, 0xdfc1, 0xd83d, 0xde97, 0x0 }    // 🏁🚗
 -     };
 - 
 -     return prefixWithAsciiSeparators<CharPointer_UTF16> (terminalCharPtrs);
 - }
 - 
 - template <>
 - SeparatorStrings getSeparators<CharPointer_UTF32>()
 - {
 -     const std::vector<std::vector<char32_t>> terminalCharPtrs = {
 -         { 0x00000076, 0x0             },   // v
 -         { 0x000020aC, 0x0             },   // €
 -         { 0x00010437, 0x0             },   // 𐐷
 -         { 0x00000065, 0x0001f603, 0x0 },   // e😃
 -         { 0x0001f3c1, 0x0001f697, 0x0 }    // 🏁🚗
 -     };
 - 
 -     return prefixWithAsciiSeparators<CharPointer_UTF32> (terminalCharPtrs);
 - }
 - 
 - template <typename TestFunction>
 - void withAllPrefixesAndSuffixes (const std::vector<MemoryBlock>& prefixes,
 -                                  const std::vector<MemoryBlock>& suffixes,
 -                                  const std::vector<MemoryBlock>& testValues,
 -                                  TestFunction&& test)
 - {
 -     for (const auto& prefix : prefixes)
 -     {
 -         for (const auto& testValue : testValues)
 -         {
 -             MemoryBlock testBlock = prefix;
 -             testBlock.append (testValue.getData(), testValue.getSize());
 - 
 -             for (const auto& suffix : suffixes)
 -             {
 -                 MemoryBlock data = testBlock;
 -                 data.append (suffix.getData(), suffix.getSize());
 - 
 -                 test (data, suffix);
 -             }
 -         }
 -     }
 - }
 - 
 - template <typename CharPointerType>
 - class CharacterFunctionsTests  : public UnitTest
 - {
 - public:
 -     using CharType = typename CharPointerType::CharType;
 - 
 -     CharacterFunctionsTests()
 -         : UnitTest ("CharacterFunctions", UnitTestCategories::text)
 -     {}
 - 
 -     void runTest() override
 -     {
 -         beginTest ("readDoubleValue");
 - 
 -         const std::pair<const char*, double> trials[] =
 -         {
 -             // Integers
 -             CHARPTR_DOUBLE_PAIR_COMBOS (0),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (3),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (4931),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (5000),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (9862097),
 - 
 -             // Floating point numbers
 -             CHARPTR_DOUBLE_PAIR_COMBOS (0.),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (9.),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (7.000),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (0.2),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (.298630),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (1.118),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (0.9000),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (0.0000001),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (500.0000001),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (9862098.2398604),
 - 
 -             // Exponents
 -             CHARPTR_DOUBLE_PAIR_COMBOS (0e0),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (0.e0),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (0.00000e0),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (.0e7),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (0e-5),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (2E0),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (4.E0),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (1.2000000E0),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (1.2000000E6),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (.398e3),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (10e10),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (1.4962e+2),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (3198693.0973e4),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (10973097.2087E-4),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (1.3986e00006),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (2087.3087e+00006),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (6.0872e-00006),
 - 
 -             CHARPTR_DOUBLE_PAIR_COMBOS (1.7976931348623157e+308),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (2.2250738585072014e-308),
 - 
 -             // Too many sig figs. The parsing routine on MinGW gets the last
 -             // significant figure wrong.
 -             CHARPTR_DOUBLE_PAIR_COMBOS (17654321098765432.9),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (183456789012345678.9),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (1934567890123456789.9),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (20345678901234567891.9),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752.000000),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752e3),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752e100),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752.000000e-5),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752.000005e-40),
 - 
 -             CHARPTR_DOUBLE_PAIR_COMBOS (1.23456789012345678901234567890),
 -             CHARPTR_DOUBLE_PAIR_COMBOS (1.23456789012345678901234567890e-111),
 -         };
 - 
 -         auto asciiToMemoryBlock = [] (const char* asciiPtr, bool removeNullTerminator)
 -         {
 -             auto block = memoryBlockFromCharPtr<CharPointer_ASCII> (asciiPtr);
 -             return convert<CharPointer_ASCII, CharPointerType> (block, removeNullTerminator);
 -         };
 - 
 -         const auto separators = getSeparators<CharPointerType>();
 - 
 -         for (const auto& trial : trials)
 -         {
 -             for (const auto& terminal : separators.terminals)
 -             {
 -                 MemoryBlock data { asciiToMemoryBlock (trial.first, true) };
 -                 data.append (terminal.getData(), terminal.getSize());
 - 
 -                 CharPointerType charPtr { (CharType*) data.getData() };
 -                 expectEquals (CharacterFunctions::readDoubleValue (charPtr), trial.second);
 -                 expect (*charPtr == *(CharPointerType ((CharType*) terminal.getData())));
 -             }
 -         }
 - 
 -         auto asciiToMemoryBlocks = [&] (const std::vector<const char*>& asciiPtrs, bool removeNullTerminator)
 -         {
 -             std::vector<MemoryBlock> result;
 - 
 -             for (auto* ptr : asciiPtrs)
 -                 result.push_back (asciiToMemoryBlock (ptr, removeNullTerminator));
 - 
 -             return result;
 -         };
 - 
 -         std::vector<const char*> prefixCharPtrs = { "" , "+", "-" };
 -         const auto prefixes = asciiToMemoryBlocks (prefixCharPtrs, true);
 - 
 -         {
 -             std::vector<const char*> nanCharPtrs = { "NaN", "nan", "NAN", "naN" };
 -             auto nans = asciiToMemoryBlocks (nanCharPtrs, true);
 - 
 -             withAllPrefixesAndSuffixes (prefixes, separators.terminals, nans, [this] (const MemoryBlock& data,
 -                                                                                       const MemoryBlock& suffix)
 -             {
 -                 CharPointerType charPtr { (CharType*) data.getData() };
 -                 expect (std::isnan (CharacterFunctions::readDoubleValue (charPtr)));
 -                 expect (*charPtr == *(CharPointerType ((CharType*) suffix.getData())));
 -             });
 -         }
 - 
 -         {
 -             std::vector<const char*> infCharPtrs = { "Inf", "inf", "INF", "InF", "1.0E1024", "1.23456789012345678901234567890e123456789" };
 -             auto infs = asciiToMemoryBlocks (infCharPtrs, true);
 - 
 -             withAllPrefixesAndSuffixes (prefixes, separators.terminals, infs, [this] (const MemoryBlock& data,
 -                                                                                       const MemoryBlock& suffix)
 -             {
 -                 CharPointerType charPtr { (CharType*) data.getData() };
 -                 auto expected = charPtr[0] == '-' ? -std::numeric_limits<double>::infinity()
 -                                                   :  std::numeric_limits<double>::infinity();
 -                 expectEquals (CharacterFunctions::readDoubleValue (charPtr), expected);
 -                 expect (*charPtr == *(CharPointerType ((CharType*) suffix.getData())));
 -             });
 -         }
 - 
 -         {
 -             std::vector<const char*> zeroCharPtrs = { "1.0E-400", "1.23456789012345678901234567890e-123456789" };
 -             auto zeros = asciiToMemoryBlocks (zeroCharPtrs, true);
 - 
 -             withAllPrefixesAndSuffixes (prefixes, separators.terminals, zeros, [this] (const MemoryBlock& data,
 -                                                                                        const MemoryBlock& suffix)
 -             {
 -                 CharPointerType charPtr { (CharType*) data.getData() };
 -                 auto expected = charPtr[0] == '-' ? -0.0 : 0.0;
 -                 expectEquals (CharacterFunctions::readDoubleValue (charPtr), expected);
 -                 expect (*charPtr == *(CharPointerType ((CharType*) suffix.getData())));
 -             });
 -         }
 - 
 -         {
 -             for (const auto& n : separators.nulls)
 -             {
 -                 MemoryBlock data { n.getData(), n.getSize() };
 -                 CharPointerType charPtr { (CharType*) data.getData() };
 -                 expectEquals (CharacterFunctions::readDoubleValue (charPtr), 0.0);
 -                 expect (charPtr == CharPointerType { (CharType*) data.getData() }.findEndOfWhitespace());
 -             }
 -         }
 -     }
 - };
 - 
 - static CharacterFunctionsTests<CharPointer_ASCII> characterFunctionsTestsAscii;
 - static CharacterFunctionsTests<CharPointer_UTF8>  characterFunctionsTestsUtf8;
 - static CharacterFunctionsTests<CharPointer_UTF16> characterFunctionsTestsUtf16;
 - static CharacterFunctionsTests<CharPointer_UTF32> characterFunctionsTestsUtf32;
 - 
 - }
 - 
 - #endif
 - 
 - } // namespace juce
 
 
  |