27 #if JUCE_WINDOWS && ! DOXYGEN
28 #define JUCE_NATIVE_WCHAR_IS_UTF8 0
29 #define JUCE_NATIVE_WCHAR_IS_UTF16 1
30 #define JUCE_NATIVE_WCHAR_IS_UTF32 0
33 #define JUCE_NATIVE_WCHAR_IS_UTF8 0
35 #define JUCE_NATIVE_WCHAR_IS_UTF16 0
37 #define JUCE_NATIVE_WCHAR_IS_UTF32 1
40 #if JUCE_NATIVE_WCHAR_IS_UTF32 || DOXYGEN
42 using juce_wchar = wchar_t;
44 using juce_wchar = uint32;
49 #define JUCE_T(stringLiteral) (L##stringLiteral)
52 #if JUCE_DEFINE_T_MACRO
60 #define T(stringLiteral) JUCE_T(stringLiteral)
69 template <
typename Type>
struct make_unsigned {
using type = Type; };
70 template <>
struct make_unsigned<signed char> {
using type =
unsigned char; };
71 template <>
struct make_unsigned<char> {
using type =
unsigned char; };
72 template <>
struct make_unsigned<short> {
using type =
unsigned short; };
73 template <>
struct make_unsigned<int> {
using type =
unsigned int; };
74 template <>
struct make_unsigned<long> {
using type =
unsigned long; };
75 template <>
struct make_unsigned<long long> {
using type =
unsigned long long; };
96 static juce_wchar toUpperCase (juce_wchar character) noexcept;
98 static juce_wchar toLowerCase (juce_wchar character) noexcept;
101 static bool isUpperCase (juce_wchar character) noexcept;
103 static bool isLowerCase (juce_wchar character) noexcept;
106 static bool isWhitespace (
char character) noexcept;
108 static bool isWhitespace (juce_wchar character) noexcept;
111 static bool isDigit (
char character) noexcept;
113 static bool isDigit (juce_wchar character) noexcept;
116 static bool isLetter (
char character) noexcept;
118 static bool isLetter (juce_wchar character) noexcept;
121 static bool isLetterOrDigit (
char character) noexcept;
123 static bool isLetterOrDigit (juce_wchar character) noexcept;
128 static bool isPrintable (
char character) noexcept;
133 static bool isPrintable (juce_wchar character) noexcept;
136 static int getHexDigitValue (juce_wchar digit) noexcept;
139 static juce_wchar getUnicodeCharFromWindows1252Codepage (uint8 windows1252Char) noexcept;
146 template <
typename CharPo
interType>
150 bool isNegative =
false;
152 JUCE_CONSTEXPR
const int maxSignificantDigits = 17 + 1;
153 JUCE_CONSTEXPR
const int bufferSize = maxSignificantDigits + 7 + 1;
154 char buffer[(size_t) bufferSize] = {};
155 char* currentCharacter = &(buffer[0]);
158 text = text.findEndOfWhitespace();
167 *currentCharacter++ =
'-';
178 if ((text[1] ==
'a' || text[1] ==
'A') && (text[2] ==
'n' || text[2] ==
'N'))
179 return std::numeric_limits<double>::quiet_NaN();
184 if ((text[1] ==
'n' || text[1] ==
'N') && (text[2] ==
'f' || text[2] ==
'F'))
185 return std::numeric_limits<double>::infinity();
192 double result[3] = { 0 }, accumulator[2] = { 0 };
193 int exponentAdjustment[2] = { 0 }, exponentAccumulator[2] = { -1, -1 };
194 int exponent = 0, decPointIndex = 0, digit = 0;
195 int lastDigit = 0, numSignificantDigits = 0;
196 bool digitsFound =
false;
197 JUCE_CONSTEXPR
const int maxSignificantDigits = 17 + 1;
204 digit = (int) text.getAndAdvance() -
'0';
207 if (decPointIndex != 0)
208 exponentAdjustment[1]++;
210 if (numSignificantDigits == 0 && digit == 0)
213 if (++numSignificantDigits > maxSignificantDigits)
216 ++accumulator [decPointIndex];
217 else if (digit == 5 && (lastDigit & 1) != 0)
218 ++accumulator [decPointIndex];
220 if (decPointIndex > 0)
221 exponentAdjustment[1]--;
223 exponentAdjustment[0]++;
225 while (text.isDigit())
228 if (decPointIndex == 0)
229 exponentAdjustment[0]++;
234 const auto maxAccumulatorValue = (double) ((std::numeric_limits<unsigned int>::max() - 9) / 10);
235 if (accumulator [decPointIndex] > maxAccumulatorValue)
237 result [decPointIndex] = mulexp10 (result [decPointIndex], exponentAccumulator [decPointIndex])
238 + accumulator [decPointIndex];
239 accumulator [decPointIndex] = 0;
240 exponentAccumulator [decPointIndex] = 0;
243 accumulator [decPointIndex] = accumulator[decPointIndex] * 10 + digit;
244 exponentAccumulator [decPointIndex]++;
247 else if (decPointIndex == 0 && *text ==
'.')
252 if (numSignificantDigits > maxSignificantDigits)
254 while (text.isDigit())
265 result[0] = mulexp10 (result[0], exponentAccumulator[0]) + accumulator[0];
267 if (decPointIndex != 0)
268 result[1] = mulexp10 (result[1], exponentAccumulator[1]) + accumulator[1];
271 if ((c ==
'e' || c ==
'E') && digitsFound)
273 auto negativeExponent =
false;
277 case '-': negativeExponent =
true;
281 while (text.isDigit())
282 exponent = (exponent * 10) + ((
int) text.getAndAdvance() -
'0');
284 if (negativeExponent)
285 exponent = -exponent;
288 auto r = mulexp10 (result[0], exponent + exponentAdjustment[0]);
289 if (decPointIndex != 0)
290 r += mulexp10 (result[1], exponent - exponentAdjustment[1]);
292 return isNegative ? -r : r;
297 bool decimalPointFound =
false;
298 int extraExponent = 0;
304 auto digit = (int) text.getAndAdvance() -
'0';
306 if (decimalPointFound)
308 if (numSigFigs >= maxSignificantDigits)
313 if (numSigFigs >= maxSignificantDigits)
319 if (numSigFigs == 0 && digit == 0)
323 *currentCharacter++ = (char) (
'0' + (
char) digit);
326 else if ((! decimalPointFound) && *text ==
'.')
329 *currentCharacter++ =
'.';
330 decimalPointFound =
true;
340 auto writeExponentDigits = [](
int exponent,
char* destination)
342 auto exponentDivisor = 100;
344 while (exponentDivisor > 1)
346 auto digit = exponent / exponentDivisor;
347 *destination++ = (char) (
'0' + (
char) digit);
348 exponent -= digit * exponentDivisor;
349 exponentDivisor /= 10;
352 *destination++ = (char) (
'0' + (
char) exponent);
355 if ((c ==
'e' || c ==
'E') && numSigFigs > 0)
357 *currentCharacter++ =
'e';
358 bool parsedExponentIsPositive =
true;
362 case '-': parsedExponentIsPositive =
false;
368 while (text.isDigit())
370 auto digit = (int) text.getAndAdvance() -
'0';
372 if (digit != 0 || exponent != 0)
373 exponent = (exponent * 10) + digit;
376 exponent = extraExponent + (parsedExponentIsPositive ? exponent : -exponent);
379 *currentCharacter++ =
'-';
381 exponent = std::abs (exponent);
383 if (exponent > std::numeric_limits<double>::max_exponent10)
384 return std::numeric_limits<double>::quiet_NaN();
386 writeExponentDigits (exponent, currentCharacter);
388 else if (extraExponent > 0)
390 *currentCharacter++ =
'e';
391 writeExponentDigits (extraExponent, currentCharacter);
395 static _locale_t locale = _create_locale (LC_ALL,
"C");
396 return _strtod_l (&buffer[0],
nullptr, locale);
398 static locale_t locale = newlocale (LC_ALL_MASK,
"C",
nullptr);
400 return (
double) strtold_l (&buffer[0],
nullptr, locale);
402 return strtod_l (&buffer[0],
nullptr, locale);
410 template <
typename CharPo
interType>
413 return readDoubleValue (text);
418 template <
typename IntType,
typename CharPo
interType>
421 using UIntType =
typename internal::make_unsigned<IntType>::type;
424 auto s = text.findEndOfWhitespace();
425 const bool isNeg = *s ==
'-';
432 auto c = s.getAndAdvance();
434 if (c >=
'0' && c <=
'9')
435 v = v * 10 + (UIntType) (c -
'0');
440 return isNeg ? - (IntType) v : (IntType) v;
444 template <
typename ResultType>
447 template <
typename CharPo
interType>
448 static ResultType parse (CharPointerType t) noexcept
450 ResultType result = 0;
452 while (! t.isEmpty())
457 result = (result << 4) | hexValue;
467 template <
typename CharPo
interType>
468 static size_t lengthUpTo (CharPointerType text,
const size_t maxCharsToCount) noexcept
472 while (len < maxCharsToCount && text.getAndAdvance() != 0)
480 template <
typename CharPo
interType>
481 static size_t lengthUpTo (CharPointerType start,
const CharPointerType end) noexcept
485 while (start < end && start.getAndAdvance() != 0)
492 template <
typename DestCharPo
interType,
typename SrcCharPo
interType>
493 static void copyAll (DestCharPointerType& dest, SrcCharPointerType src) noexcept
495 while (
auto c = src.getAndAdvance())
503 template <
typename DestCharPo
interType,
typename SrcCharPo
interType>
504 static size_t copyWithDestByteLimit (DestCharPointerType& dest, SrcCharPointerType src,
size_t maxBytesToWrite) noexcept
506 auto startAddress = dest.getAddress();
507 auto maxBytes = (ssize_t) maxBytesToWrite;
508 maxBytes -= (ssize_t)
sizeof (
typename DestCharPointerType::CharType);
512 auto c = src.getAndAdvance();
513 auto bytesNeeded = (ssize_t) DestCharPointerType::getBytesRequiredFor (c);
514 maxBytes -= bytesNeeded;
516 if (c == 0 || maxBytes < 0)
524 return (
size_t) getAddressDifference (dest.getAddress(), startAddress)
525 +
sizeof (
typename DestCharPointerType::CharType);
530 template <
typename DestCharPo
interType,
typename SrcCharPo
interType>
531 static void copyWithCharLimit (DestCharPointerType& dest, SrcCharPointerType src,
int maxChars) noexcept
533 while (--maxChars > 0)
535 auto c = src.getAndAdvance();
547 static inline int compare (juce_wchar char1, juce_wchar char2) noexcept
549 if (
auto diff =
static_cast<int> (char1) -
static_cast<int> (char2))
550 return diff < 0 ? -1 : 1;
556 template <
typename CharPo
interType1,
typename CharPo
interType2>
557 static int compare (CharPointerType1 s1, CharPointerType2 s2) noexcept
561 auto c1 = s1.getAndAdvance();
563 if (
auto diff = compare (c1, s2.getAndAdvance()))
574 template <
typename CharPo
interType1,
typename CharPo
interType2>
575 static int compareUpTo (CharPointerType1 s1, CharPointerType2 s2,
int maxChars) noexcept
577 while (--maxChars >= 0)
579 auto c1 = s1.getAndAdvance();
581 if (
auto diff = compare (c1, s2.getAndAdvance()))
594 return char1 != char2 ? compare (toUpperCase (char1), toUpperCase (char2)) : 0;
598 template <
typename CharPo
interType1,
typename CharPo
interType2>
603 auto c1 = s1.getAndAdvance();
605 if (
auto diff = compareIgnoreCase (c1, s2.getAndAdvance()))
616 template <
typename CharPo
interType1,
typename CharPo
interType2>
619 while (--maxChars >= 0)
621 auto c1 = s1.getAndAdvance();
623 if (
auto diff = compareIgnoreCase (c1, s2.getAndAdvance()))
636 template <
typename CharPo
interType1,
typename CharPo
interType2>
637 static int indexOf (CharPointerType1 textToSearch,
const CharPointerType2 substringToLookFor) noexcept
640 auto substringLength = (int) substringToLookFor.length();
644 if (textToSearch.compareUpTo (substringToLookFor, substringLength) == 0)
647 if (textToSearch.getAndAdvance() == 0)
658 template <
typename CharPo
interType1,
typename CharPo
interType2>
659 static CharPointerType1
find (CharPointerType1 textToSearch,
const CharPointerType2 substringToLookFor) noexcept
661 auto substringLength = (int) substringToLookFor.length();
663 while (textToSearch.compareUpTo (substringToLookFor, substringLength) != 0
664 && ! textToSearch.isEmpty())
674 template <
typename CharPo
interType>
675 static CharPointerType
find (CharPointerType textToSearch,
const juce_wchar charToLookFor) noexcept
677 for (;; ++textToSearch)
679 auto c = *textToSearch;
681 if (c == charToLookFor || c == 0)
692 template <
typename CharPo
interType1,
typename CharPo
interType2>
693 static int indexOfIgnoreCase (CharPointerType1 haystack,
const CharPointerType2 needle) noexcept
696 auto needleLength = (int) needle.length();
700 if (haystack.compareIgnoreCaseUpTo (needle, needleLength) == 0)
703 if (haystack.getAndAdvance() == 0)
713 template <
typename Type>
714 static int indexOfChar (Type text,
const juce_wchar charToFind) noexcept
718 while (! text.isEmpty())
720 if (text.getAndAdvance() == charToFind)
733 template <
typename Type>
739 while (! text.isEmpty())
741 if (text.toLowerCase() == charToFind)
755 template <
typename Type>
758 while (text.isWhitespace())
767 template <
typename Type,
typename BreakType>
768 static Type
findEndOfToken (Type text, BreakType breakCharacters, Type quoteCharacters)
770 juce_wchar currentQuoteChar = 0;
772 while (! text.isEmpty())
774 auto c = text.getAndAdvance();
776 if (currentQuoteChar == 0 && breakCharacters.indexOf (c) >= 0)
782 if (quoteCharacters.indexOf (c) >= 0)
784 if (currentQuoteChar == 0)
785 currentQuoteChar = c;
786 else if (currentQuoteChar == c)
787 currentQuoteChar = 0;
795 static double mulexp10 (
double value,
int exponent) noexcept;
static int indexOfIgnoreCase(CharPointerType1 haystack, const CharPointerType2 needle) noexcept
static int compare(juce_wchar char1, juce_wchar char2) noexcept
static juce_wchar toLowerCase(juce_wchar character) noexcept
static size_t copyWithDestByteLimit(DestCharPointerType &dest, SrcCharPointerType src, size_t maxBytesToWrite) noexcept
static int indexOfCharIgnoreCase(Type text, juce_wchar charToFind) noexcept
static IntType getIntValue(const CharPointerType text) noexcept
static int compareIgnoreCaseUpTo(CharPointerType1 s1, CharPointerType2 s2, int maxChars) noexcept
static int indexOfChar(Type text, const juce_wchar charToFind) noexcept
static int compare(CharPointerType1 s1, CharPointerType2 s2) noexcept
static int compareIgnoreCase(juce_wchar char1, juce_wchar char2) noexcept
static size_t lengthUpTo(CharPointerType start, const CharPointerType end) noexcept
static int indexOf(CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
static size_t lengthUpTo(CharPointerType text, const size_t maxCharsToCount) noexcept
static double readDoubleValue(CharPointerType &text) noexcept
static CharPointerType find(CharPointerType textToSearch, const juce_wchar charToLookFor) noexcept
static Type findEndOfWhitespace(Type text) noexcept
static void copyWithCharLimit(DestCharPointerType &dest, SrcCharPointerType src, int maxChars) noexcept
static int getHexDigitValue(juce_wchar digit) noexcept
static Type findEndOfToken(Type text, BreakType breakCharacters, Type quoteCharacters)
static CharPointerType1 find(CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
static int compareIgnoreCase(CharPointerType1 s1, CharPointerType2 s2) noexcept
static double getDoubleValue(CharPointerType text) noexcept
static void copyAll(DestCharPointerType &dest, SrcCharPointerType src) noexcept
static int compareUpTo(CharPointerType1 s1, CharPointerType2 s2, int maxChars) noexcept