31 #if JUCE_WINDOWS && ! DOXYGEN 32 #define JUCE_NATIVE_WCHAR_IS_UTF8 0 33 #define JUCE_NATIVE_WCHAR_IS_UTF16 1 34 #define JUCE_NATIVE_WCHAR_IS_UTF32 0 37 #define JUCE_NATIVE_WCHAR_IS_UTF8 0 39 #define JUCE_NATIVE_WCHAR_IS_UTF16 0 41 #define JUCE_NATIVE_WCHAR_IS_UTF32 1 44 #if JUCE_NATIVE_WCHAR_IS_UTF32 || DOXYGEN 46 using juce_wchar = wchar_t;
48 using juce_wchar = uint32;
53 #define JUCE_T(stringLiteral) (L##stringLiteral) 56 #if JUCE_DEFINE_T_MACRO 64 #define T(stringLiteral) JUCE_T(stringLiteral) 73 template <
typename Type>
struct make_unsigned {
using type = Type; };
74 template <>
struct make_unsigned<signed char> {
using type =
unsigned char; };
75 template <>
struct make_unsigned<char> {
using type =
unsigned char; };
76 template <>
struct make_unsigned<short> {
using type =
unsigned short; };
77 template <>
struct make_unsigned<int> {
using type =
unsigned int; };
78 template <>
struct make_unsigned<long> {
using type =
unsigned long; };
79 template <>
struct make_unsigned<long long> {
using type =
unsigned long long; };
100 static juce_wchar toUpperCase (juce_wchar character) noexcept;
102 static juce_wchar toLowerCase (juce_wchar character) noexcept;
105 static bool isUpperCase (juce_wchar character) noexcept;
107 static bool isLowerCase (juce_wchar character) noexcept;
110 static bool isWhitespace (
char character) noexcept;
112 static bool isWhitespace (juce_wchar character) noexcept;
115 static bool isDigit (
char character) noexcept;
117 static bool isDigit (juce_wchar character) noexcept;
120 static bool isLetter (
char character) noexcept;
122 static bool isLetter (juce_wchar character) noexcept;
125 static bool isLetterOrDigit (
char character) noexcept;
127 static bool isLetterOrDigit (juce_wchar character) noexcept;
132 static bool isPrintable (
char character) noexcept;
137 static bool isPrintable (juce_wchar character) noexcept;
140 static int getHexDigitValue (juce_wchar digit) noexcept;
143 static juce_wchar getUnicodeCharFromWindows1252Codepage (uint8 windows1252Char) noexcept;
150 template <
typename CharPo
interType>
154 bool isNegative =
false;
156 JUCE_CONSTEXPR
const int maxSignificantDigits = 17 + 1;
157 JUCE_CONSTEXPR
const int bufferSize = maxSignificantDigits + 7 + 1;
158 char buffer[(size_t) bufferSize] = {};
159 char* currentCharacter = &(buffer[0]);
162 text = text.findEndOfWhitespace();
171 *currentCharacter++ =
'-';
182 if ((text[1] ==
'a' || text[1] ==
'A') && (text[2] ==
'n' || text[2] ==
'N'))
183 return std::numeric_limits<double>::quiet_NaN();
188 if ((text[1] ==
'n' || text[1] ==
'N') && (text[2] ==
'f' || text[2] ==
'F'))
189 return std::numeric_limits<double>::infinity();
196 double result[3] = { 0 }, accumulator[2] = { 0 };
197 int exponentAdjustment[2] = { 0 }, exponentAccumulator[2] = { -1, -1 };
198 int exponent = 0, decPointIndex = 0, digit = 0;
199 int lastDigit = 0, numSignificantDigits = 0;
200 bool digitsFound =
false;
201 JUCE_CONSTEXPR
const int maxSignificantDigits = 17 + 1;
208 digit = (int) text.getAndAdvance() -
'0';
211 if (decPointIndex != 0)
212 exponentAdjustment[1]++;
214 if (numSignificantDigits == 0 && digit == 0)
217 if (++numSignificantDigits > maxSignificantDigits)
220 ++accumulator [decPointIndex];
221 else if (digit == 5 && (lastDigit & 1) != 0)
222 ++accumulator [decPointIndex];
224 if (decPointIndex > 0)
225 exponentAdjustment[1]--;
227 exponentAdjustment[0]++;
229 while (text.isDigit())
232 if (decPointIndex == 0)
233 exponentAdjustment[0]++;
238 const auto maxAccumulatorValue = (double) ((std::numeric_limits<unsigned int>::max() - 9) / 10);
239 if (accumulator [decPointIndex] > maxAccumulatorValue)
241 result [decPointIndex] = mulexp10 (result [decPointIndex], exponentAccumulator [decPointIndex])
242 + accumulator [decPointIndex];
243 accumulator [decPointIndex] = 0;
244 exponentAccumulator [decPointIndex] = 0;
247 accumulator [decPointIndex] = accumulator[decPointIndex] * 10 + digit;
248 exponentAccumulator [decPointIndex]++;
251 else if (decPointIndex == 0 && *text ==
'.')
256 if (numSignificantDigits > maxSignificantDigits)
258 while (text.isDigit())
269 result[0] = mulexp10 (result[0], exponentAccumulator[0]) + accumulator[0];
271 if (decPointIndex != 0)
272 result[1] = mulexp10 (result[1], exponentAccumulator[1]) + accumulator[1];
275 if ((c ==
'e' || c ==
'E') && digitsFound)
277 auto negativeExponent =
false;
281 case '-': negativeExponent =
true;
285 while (text.isDigit())
286 exponent = (exponent * 10) + ((int) text.getAndAdvance() -
'0');
288 if (negativeExponent)
289 exponent = -exponent;
292 auto r = mulexp10 (result[0], exponent + exponentAdjustment[0]);
293 if (decPointIndex != 0)
294 r += mulexp10 (result[1], exponent - exponentAdjustment[1]);
296 return isNegative ? -r : r;
298 #else // ! JUCE_MINGW 301 bool decimalPointFound =
false;
302 int extraExponent = 0;
308 auto digit = (int) text.getAndAdvance() -
'0';
310 if (decimalPointFound)
312 if (numSigFigs >= maxSignificantDigits)
317 if (numSigFigs >= maxSignificantDigits)
323 if (numSigFigs == 0 && digit == 0)
327 *currentCharacter++ = (char) (
'0' + (
char) digit);
330 else if ((! decimalPointFound) && *text ==
'.')
333 *currentCharacter++ =
'.';
334 decimalPointFound =
true;
344 auto writeExponentDigits = [](
int exponent,
char* destination)
346 auto exponentDivisor = 100;
348 while (exponentDivisor > 1)
350 auto digit = exponent / exponentDivisor;
351 *destination++ = (char) (
'0' + (
char) digit);
352 exponent -= digit * exponentDivisor;
353 exponentDivisor /= 10;
356 *destination++ = (char) (
'0' + (
char) exponent);
359 if ((c ==
'e' || c ==
'E') && numSigFigs > 0)
361 *currentCharacter++ =
'e';
362 bool parsedExponentIsPositive =
true;
366 case '-': parsedExponentIsPositive =
false;
372 while (text.isDigit())
374 auto digit = (int) text.getAndAdvance() -
'0';
376 if (digit != 0 || exponent != 0)
377 exponent = (exponent * 10) + digit;
380 exponent = extraExponent + (parsedExponentIsPositive ? exponent : -exponent);
383 *currentCharacter++ =
'-';
385 exponent = std::abs (exponent);
387 if (exponent > std::numeric_limits<double>::max_exponent10)
388 return std::numeric_limits<double>::quiet_NaN();
390 writeExponentDigits (exponent, currentCharacter);
392 else if (extraExponent > 0)
394 *currentCharacter++ =
'e';
395 writeExponentDigits (extraExponent, currentCharacter);
399 static _locale_t locale = _create_locale (LC_ALL,
"C");
400 return _strtod_l (&buffer[0],
nullptr, locale);
402 static locale_t locale = newlocale (LC_ALL_MASK,
"C",
nullptr);
404 return (
double) strtold_l (&buffer[0],
nullptr, locale);
406 return strtod_l (&buffer[0],
nullptr, locale);
414 template <
typename CharPo
interType>
417 return readDoubleValue (text);
422 template <
typename IntType,
typename CharPo
interType>
425 using UIntType =
typename internal::make_unsigned<IntType>::type;
428 auto s = text.findEndOfWhitespace();
429 const bool isNeg = *s ==
'-';
436 auto c = s.getAndAdvance();
438 if (c >=
'0' && c <=
'9')
439 v = v * 10 + (UIntType) (c -
'0');
444 return isNeg ? - (IntType) v : (IntType) v;
448 template <
typename ResultType>
451 template <
typename CharPo
interType>
452 static ResultType parse (CharPointerType t) noexcept
454 ResultType result = 0;
456 while (! t.isEmpty())
461 result = (result << 4) | hexValue;
471 template <
typename CharPo
interType>
472 static size_t lengthUpTo (CharPointerType text,
const size_t maxCharsToCount) noexcept
476 while (len < maxCharsToCount && text.getAndAdvance() != 0)
484 template <
typename CharPo
interType>
485 static size_t lengthUpTo (CharPointerType start,
const CharPointerType end) noexcept
489 while (start < end && start.getAndAdvance() != 0)
496 template <
typename DestCharPo
interType,
typename SrcCharPo
interType>
497 static void copyAll (DestCharPointerType& dest, SrcCharPointerType src) noexcept
499 while (
auto c = src.getAndAdvance())
507 template <
typename DestCharPo
interType,
typename SrcCharPo
interType>
508 static size_t copyWithDestByteLimit (DestCharPointerType& dest, SrcCharPointerType src,
size_t maxBytesToWrite) noexcept
510 auto startAddress = dest.getAddress();
511 auto maxBytes = (ssize_t) maxBytesToWrite;
512 maxBytes -= (ssize_t)
sizeof (
typename DestCharPointerType::CharType);
516 auto c = src.getAndAdvance();
517 auto bytesNeeded = (ssize_t) DestCharPointerType::getBytesRequiredFor (c);
518 maxBytes -= bytesNeeded;
520 if (c == 0 || maxBytes < 0)
528 return (
size_t) getAddressDifference (dest.getAddress(), startAddress)
529 +
sizeof (
typename DestCharPointerType::CharType);
534 template <
typename DestCharPo
interType,
typename SrcCharPo
interType>
535 static void copyWithCharLimit (DestCharPointerType& dest, SrcCharPointerType src,
int maxChars) noexcept
537 while (--maxChars > 0)
539 auto c = src.getAndAdvance();
551 static inline int compare (juce_wchar char1, juce_wchar char2) noexcept
553 if (
auto diff = static_cast<int> (char1) - static_cast<int> (char2))
554 return diff < 0 ? -1 : 1;
560 template <
typename CharPo
interType1,
typename CharPo
interType2>
561 static int compare (CharPointerType1 s1, CharPointerType2 s2) noexcept
565 auto c1 = s1.getAndAdvance();
567 if (
auto diff = compare (c1, s2.getAndAdvance()))
578 template <
typename CharPo
interType1,
typename CharPo
interType2>
579 static int compareUpTo (CharPointerType1 s1, CharPointerType2 s2,
int maxChars) noexcept
581 while (--maxChars >= 0)
583 auto c1 = s1.getAndAdvance();
585 if (
auto diff = compare (c1, s2.getAndAdvance()))
598 return char1 != char2 ? compare (toUpperCase (char1), toUpperCase (char2)) : 0;
602 template <
typename CharPo
interType1,
typename CharPo
interType2>
607 auto c1 = s1.getAndAdvance();
609 if (
auto diff = compareIgnoreCase (c1, s2.getAndAdvance()))
620 template <
typename CharPo
interType1,
typename CharPo
interType2>
623 while (--maxChars >= 0)
625 auto c1 = s1.getAndAdvance();
627 if (
auto diff = compareIgnoreCase (c1, s2.getAndAdvance()))
640 template <
typename CharPo
interType1,
typename CharPo
interType2>
641 static int indexOf (CharPointerType1 textToSearch,
const CharPointerType2 substringToLookFor) noexcept
644 auto substringLength = (int) substringToLookFor.length();
648 if (textToSearch.compareUpTo (substringToLookFor, substringLength) == 0)
651 if (textToSearch.getAndAdvance() == 0)
662 template <
typename CharPo
interType1,
typename CharPo
interType2>
663 static CharPointerType1
find (CharPointerType1 textToSearch,
const CharPointerType2 substringToLookFor) noexcept
665 auto substringLength = (int) substringToLookFor.length();
667 while (textToSearch.compareUpTo (substringToLookFor, substringLength) != 0
668 && ! textToSearch.isEmpty())
678 template <
typename CharPo
interType>
679 static CharPointerType
find (CharPointerType textToSearch,
const juce_wchar charToLookFor) noexcept
681 for (;; ++textToSearch)
683 auto c = *textToSearch;
685 if (c == charToLookFor || c == 0)
696 template <
typename CharPo
interType1,
typename CharPo
interType2>
697 static int indexOfIgnoreCase (CharPointerType1 haystack,
const CharPointerType2 needle) noexcept
700 auto needleLength = (int) needle.length();
704 if (haystack.compareIgnoreCaseUpTo (needle, needleLength) == 0)
707 if (haystack.getAndAdvance() == 0)
717 template <
typename Type>
718 static int indexOfChar (Type text,
const juce_wchar charToFind) noexcept
722 while (! text.isEmpty())
724 if (text.getAndAdvance() == charToFind)
737 template <
typename Type>
743 while (! text.isEmpty())
745 if (text.toLowerCase() == charToFind)
759 template <
typename Type>
762 while (text.isWhitespace())
771 template <
typename Type,
typename BreakType>
772 static Type
findEndOfToken (Type text, BreakType breakCharacters, Type quoteCharacters)
774 juce_wchar currentQuoteChar = 0;
776 while (! text.isEmpty())
778 auto c = text.getAndAdvance();
780 if (currentQuoteChar == 0 && breakCharacters.indexOf (c) >= 0)
786 if (quoteCharacters.indexOf (c) >= 0)
788 if (currentQuoteChar == 0)
789 currentQuoteChar = c;
790 else if (currentQuoteChar == c)
791 currentQuoteChar = 0;
799 static double mulexp10 (
double value,
int exponent) noexcept;
static double getDoubleValue(CharPointerType text) noexcept
Parses a character string, to read a floating-point value.
#define JUCE_API
This macro is added to all JUCE public class declarations.
static Type findEndOfToken(Type text, BreakType breakCharacters, Type quoteCharacters)
Returns a pointer to the first character in the string which is found in the breakCharacters string...
A collection of functions for manipulating characters and character strings.
static size_t lengthUpTo(CharPointerType start, const CharPointerType end) noexcept
Counts the number of characters in a given string, stopping if the count exceeds a specified end-poin...
static int indexOfCharIgnoreCase(Type text, juce_wchar charToFind) noexcept
Finds the character index of a given character in another string, using a case-independent match...
static void copyAll(DestCharPointerType &dest, SrcCharPointerType src) noexcept
Copies null-terminated characters from one string to another.
static int compareIgnoreCase(juce_wchar char1, juce_wchar char2) noexcept
Compares two characters, using a case-independant match.
static double readDoubleValue(CharPointerType &text) noexcept
Parses a character string to read a floating-point number.
static Type findEndOfWhitespace(Type text) noexcept
Returns a pointer to the first non-whitespace character in a string.
static int compare(CharPointerType1 s1, CharPointerType2 s2) noexcept
Compares two null-terminated character strings.
static IntType getIntValue(const CharPointerType text) noexcept
Parses a character string, to read an integer value.
static int indexOfChar(Type text, const juce_wchar charToFind) noexcept
Finds the character index of a given character in another string.
static int compareIgnoreCaseUpTo(CharPointerType1 s1, CharPointerType2 s2, int maxChars) noexcept
Compares two null-terminated character strings, using a case-independent match.
static CharPointerType1 find(CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
Returns a pointer to the first occurrence of a substring in a string.
static size_t lengthUpTo(CharPointerType text, const size_t maxCharsToCount) noexcept
Counts the number of characters in a given string, stopping if the count exceeds a specified limit...
static CharPointerType find(CharPointerType textToSearch, const juce_wchar charToLookFor) noexcept
Returns a pointer to the first occurrence of a substring in a string.
static size_t copyWithDestByteLimit(DestCharPointerType &dest, SrcCharPointerType src, size_t maxBytesToWrite) noexcept
Copies characters from one string to another, up to a null terminator or a given byte size limit...
static int getHexDigitValue(juce_wchar digit) noexcept
Returns 0 to 16 for '0' to 'F", or -1 for characters that aren't a legal hex digit.
static juce_wchar toLowerCase(juce_wchar character) noexcept
Converts a character to lower-case.
static int compareIgnoreCase(CharPointerType1 s1, CharPointerType2 s2) noexcept
Compares two null-terminated character strings, using a case-independant match.
static int indexOf(CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
Finds the character index of a given substring in another string.
Parses a character string, to read a hexadecimal value.
static int compareUpTo(CharPointerType1 s1, CharPointerType2 s2, int maxChars) noexcept
Compares two null-terminated character strings, up to a given number of characters.
static int indexOfIgnoreCase(CharPointerType1 haystack, const CharPointerType2 needle) noexcept
Finds the character index of a given substring in another string, using a case-independent match...
static void copyWithCharLimit(DestCharPointerType &dest, SrcCharPointerType src, int maxChars) noexcept
Copies characters from one string to another, up to a null terminator or a given maximum number of ch...
static int compare(juce_wchar char1, juce_wchar char2) noexcept
Compares two characters.