27 #pragma warning (push)
28 #pragma warning (disable: 4514 4996)
33#if defined (JUCE_STRINGS_ARE_UNICODE) && ! JUCE_STRINGS_ARE_UNICODE
34 #error "JUCE_STRINGS_ARE_UNICODE is deprecated! All strings are now unicode by default."
37#if JUCE_NATIVE_WCHAR_IS_UTF8
38 using CharPointer_wchar_t = CharPointer_UTF8;
39#elif JUCE_NATIVE_WCHAR_IS_UTF16
40 using CharPointer_wchar_t = CharPointer_UTF16;
42 using CharPointer_wchar_t = CharPointer_UTF32;
45static inline CharPointer_wchar_t castToCharPointer_wchar_t (
const void* t)
noexcept
47 return CharPointer_wchar_t (
static_cast<const CharPointer_wchar_t::CharType*
> (t));
55 size_t allocatedBytes;
56 String::CharPointerType::CharType text;
59static const EmptyString emptyString { 0x3fffffff,
sizeof (String::CharPointerType::CharType), 0 };
65 StringHolder() =
delete;
67 using CharPointerType = String::CharPointerType;
68 using CharType = String::CharPointerType::CharType;
71 static CharPointerType createUninitialisedBytes (
size_t numBytes)
73 numBytes = (numBytes + 3) & ~(
size_t) 3;
74 auto s =
reinterpret_cast<StringHolder*
> (
new char [
sizeof (StringHolder) -
sizeof (CharType) + numBytes]);
75 s->refCount.value = 0;
76 s->allocatedNumBytes = numBytes;
77 return CharPointerType (s->text);
80 template <
class CharPo
inter>
81 static CharPointerType createFromCharPointer (
const CharPointer text)
83 if (text.getAddress() ==
nullptr || text.isEmpty())
84 return CharPointerType (&(emptyString.text));
86 auto bytesNeeded =
sizeof (CharType) + CharPointerType::getBytesRequiredFor (text);
87 auto dest = createUninitialisedBytes (bytesNeeded);
88 CharPointerType (dest).writeAll (text);
92 template <
class CharPo
inter>
93 static CharPointerType createFromCharPointer (
const CharPointer text,
size_t maxChars)
95 if (text.getAddress() ==
nullptr || text.isEmpty() || maxChars == 0)
96 return CharPointerType (&(emptyString.text));
100 size_t bytesNeeded =
sizeof (CharType);
102 while (numChars < maxChars && ! end.isEmpty())
104 bytesNeeded += CharPointerType::getBytesRequiredFor (end.getAndAdvance());
108 auto dest = createUninitialisedBytes (bytesNeeded);
109 CharPointerType (dest).writeWithCharLimit (text, (
int) numChars + 1);
113 template <
class CharPo
inter>
114 static CharPointerType createFromCharPointer (
const CharPointer start,
const CharPointer end)
116 if (start.getAddress() ==
nullptr || start.isEmpty())
117 return CharPointerType (&(emptyString.text));
121 auto bytesNeeded =
sizeof (CharType);
123 while (e < end && ! e.isEmpty())
125 bytesNeeded += CharPointerType::getBytesRequiredFor (e.getAndAdvance());
129 auto dest = createUninitialisedBytes (bytesNeeded);
130 CharPointerType (dest).writeWithCharLimit (start, numChars + 1);
134 static CharPointerType createFromCharPointer (
const CharPointerType start,
const CharPointerType end)
136 if (start.getAddress() ==
nullptr || start.isEmpty())
137 return CharPointerType (&(emptyString.text));
139 auto numBytes = (size_t) (
reinterpret_cast<const char*
> (end.getAddress())
140 -
reinterpret_cast<const char*
> (start.getAddress()));
141 auto dest = createUninitialisedBytes (numBytes +
sizeof (CharType));
142 memcpy (dest.getAddress(), start, numBytes);
143 dest.getAddress()[numBytes /
sizeof (CharType)] = 0;
147 static CharPointerType createFromFixedLength (
const char*
const src,
const size_t numChars)
149 auto dest = createUninitialisedBytes (numChars *
sizeof (CharType) +
sizeof (CharType));
150 CharPointerType (dest).writeWithCharLimit (CharPointer_UTF8 (src), (
int) (numChars + 1));
155 static void retain (
const CharPointerType text)
noexcept
157 auto* b = bufferFromText (text);
159 if (! isEmptyString (b))
163 static inline void release (StringHolder*
const b)
noexcept
165 if (! isEmptyString (b))
166 if (--(b->refCount) == -1)
167 delete[]
reinterpret_cast<char*
> (b);
170 static void release (
const CharPointerType text)
noexcept
172 release (bufferFromText (text));
175 static inline int getReferenceCount (
const CharPointerType text)
noexcept
177 return bufferFromText (text)->refCount.
get() + 1;
181 static CharPointerType makeUniqueWithByteSize (
const CharPointerType text,
size_t numBytes)
183 auto* b = bufferFromText (text);
185 if (isEmptyString (b))
187 auto newText = createUninitialisedBytes (numBytes);
192 if (b->allocatedNumBytes >= numBytes && b->refCount.get() <= 0)
195 auto newText = createUninitialisedBytes (jmax (b->allocatedNumBytes, numBytes));
196 memcpy (newText.getAddress(), text.getAddress(), b->allocatedNumBytes);
202 static size_t getAllocatedNumBytes (
const CharPointerType text)
noexcept
204 return bufferFromText (text)->allocatedNumBytes;
208 Atomic<int> refCount;
209 size_t allocatedNumBytes;
213 static inline StringHolder* bufferFromText (
const CharPointerType text)
noexcept
216 return reinterpret_cast<StringHolder*
> (
reinterpret_cast<char*
> (text.getAddress())
217 - (
reinterpret_cast<size_t> (
reinterpret_cast<StringHolder*
> (128)->text) - 128));
220 static inline bool isEmptyString (StringHolder* other)
222 return (other->refCount.get() & 0x30000000) != 0;
225 void compileTimeChecks()
228 #if JUCE_NATIVE_WCHAR_IS_UTF8
229 static_assert (
sizeof (wchar_t) == 1,
"JUCE_NATIVE_WCHAR_IS_* macro has incorrect value");
230 #elif JUCE_NATIVE_WCHAR_IS_UTF16
231 static_assert (
sizeof (wchar_t) == 2,
"JUCE_NATIVE_WCHAR_IS_* macro has incorrect value");
232 #elif JUCE_NATIVE_WCHAR_IS_UTF32
233 static_assert (
sizeof (wchar_t) == 4,
"JUCE_NATIVE_WCHAR_IS_* macro has incorrect value");
235 #error "native wchar_t size is unknown"
238 static_assert (
sizeof (EmptyString) ==
sizeof (StringHolder),
239 "StringHolder is not large enough to hold an empty String");
243JUCE_DECLARE_DEPRECATED_STATIC (
const String String::empty;)
252 StringHolder::release (text);
257 StringHolder::retain (text);
262 std::swap (text, other.text);
267 StringHolder::release (text);
268 text = &(emptyString.text);
273 StringHolder::retain (other.text);
274 StringHolder::release (text.atomicSwap (other.text));
280 other.text = &(emptyString.text);
285 std::swap (text, other.text);
289inline String::PreallocationBytes::PreallocationBytes (
const size_t num) noexcept : numBytes (num) {}
292 : text (StringHolder::createUninitialisedBytes (preallocationSize.numBytes + sizeof (CharPointerType::CharType)))
298 text = StringHolder::makeUniqueWithByteSize (text, numBytesNeeded +
sizeof (CharPointerType::CharType));
303 return StringHolder::getReferenceCount (text);
353String::String (
const wchar_t*
const t) : text (StringHolder::createFromCharPointer (castToCharPointer_wchar_t (t))) {}
362String::String (
const wchar_t* t,
size_t maxChars) : text (StringHolder::createFromCharPointer (castToCharPointer_wchar_t (t), maxChars)) {}
368String::String (
const std::string& s) : text (StringHolder::createFromFixedLength (s.data(), s.size())) {}
373 String result (PreallocationBytes (CharPointerType::getBytesRequiredFor (character)));
374 CharPointerType t (result.text);
381namespace NumberToStringConverters
385 charsNeededForInt = 32,
386 charsNeededForDouble = 48
389 template <
typename Type>
390 static char* printDigits (
char* t, Type v)
noexcept
396 *--t =
'0' + (char) (v % 10);
405 static char* numberToString (
char* t, int64 n)
noexcept
408 return printDigits (t,
static_cast<uint64
> (n));
412 t = printDigits (t,
static_cast<uint64
> (-(n + 1)) + 1);
417 static char* numberToString (
char* t, uint64 v)
noexcept
419 return printDigits (t, v);
422 static char* numberToString (
char* t,
int n)
noexcept
425 return printDigits (t,
static_cast<unsigned int> (n));
429 t = printDigits (t,
static_cast<unsigned int> (-(n + 1)) + 1);
434 static char* numberToString (
char* t,
unsigned int v)
noexcept
436 return printDigits (t, v);
439 static char* numberToString (
char* t,
long n)
noexcept
442 return printDigits (t,
static_cast<unsigned long> (n));
444 t = printDigits (t,
static_cast<unsigned long> (-(n + 1)) + 1);
449 static char* numberToString (
char* t,
unsigned long v)
noexcept
451 return printDigits (t, v);
454 struct StackArrayStream :
public std::basic_streambuf<char, std::char_traits<char>>
456 explicit StackArrayStream (
char* d)
458 static const std::locale classicLocale (std::locale::classic());
459 imbue (classicLocale);
460 setp (d, d + charsNeededForDouble);
463 size_t writeDouble (
double n,
int numDecPlaces,
bool useScientificNotation)
466 std::ostream o (
this);
468 if (numDecPlaces > 0)
470 o.setf (useScientificNotation ? std::ios_base::scientific : std::ios_base::fixed);
471 o.precision ((std::streamsize) numDecPlaces);
477 return (
size_t) (pptr() - pbase());
481 static char* doubleToString (
char* buffer,
double n,
int numDecPlaces,
bool useScientificNotation,
size_t& len)
noexcept
483 StackArrayStream strm (buffer);
484 len = strm.writeDouble (n, numDecPlaces, useScientificNotation);
485 jassert (len <= charsNeededForDouble);
489 template <
typename IntegerType>
490 static String::CharPointerType createFromInteger (IntegerType number)
492 char buffer [charsNeededForInt];
493 auto* end = buffer + numElementsInArray (buffer);
494 auto* start = numberToString (end, number);
495 return StringHolder::createFromFixedLength (start, (
size_t) (end - start - 1));
498 static String::CharPointerType createFromDouble (
double number,
int numberOfDecimalPlaces,
bool useScientificNotation)
500 char buffer [charsNeededForDouble];
502 auto start = doubleToString (buffer, number, numberOfDecimalPlaces, useScientificNotation, len);
503 return StringHolder::createFromFixedLength (start, len);
508String::String (
int number) : text (NumberToStringConverters::createFromInteger (number)) {}
509String::String (
unsigned int number) : text (NumberToStringConverters::createFromInteger (number)) {}
510String::String (
short number) : text (NumberToStringConverters::createFromInteger ((int) number)) {}
511String::String (
unsigned short number) : text (NumberToStringConverters::createFromInteger ((unsigned int) number)) {}
512String::String (int64 number) : text (NumberToStringConverters::createFromInteger (number)) {}
513String::String (uint64 number) : text (NumberToStringConverters::createFromInteger (number)) {}
514String::String (
long number) : text (NumberToStringConverters::createFromInteger (number)) {}
515String::String (
unsigned long number) : text (NumberToStringConverters::createFromInteger (number)) {}
517String::String (
float number) : text (NumberToStringConverters::createFromDouble ((double) number, 0, false)) {}
518String::String (
double number) : text (NumberToStringConverters::createFromDouble ( number, 0, false)) {}
519String::String (
float number,
int numberOfDecimalPlaces,
bool useScientificNotation) : text (NumberToStringConverters::createFromDouble ((double) number, numberOfDecimalPlaces, useScientificNotation)) {}
520String::String (
double number,
int numberOfDecimalPlaces,
bool useScientificNotation) : text (NumberToStringConverters::createFromDouble ( number, numberOfDecimalPlaces, useScientificNotation)) {}
525 return (
int) text.length();
528static size_t findByteOffsetOfEnd (String::CharPointerType text)
noexcept
530 return (
size_t) (((
char*) text.findTerminatingNull().getAddress()) - (
char*) text.getAddress());
533size_t String::getByteOffsetOfEnd() const noexcept
535 return findByteOffsetOfEnd (text);
540 jassert (index == 0 || (index > 0 && index <= (
int) text.lengthUpTo ((
size_t) index + 1)));
544template <
typename Type>
547 template <
typename CharPo
inter>
548 static Type calculate (CharPointer t)
noexcept
552 while (! t.isEmpty())
553 result = ((Type) multiplier) * result + (Type) t.getAndAdvance();
558 enum { multiplier =
sizeof (Type) > 4 ? 101 : 31 };
561int String::hashCode() const noexcept {
return (
int) HashGenerator<uint32> ::calculate (text); }
562int64
String::hashCode64() const noexcept {
return (int64) HashGenerator<uint64> ::calculate (text); }
563size_t String::hash() const noexcept {
return HashGenerator<size_t> ::calculate (text); }
566JUCE_API
bool JUCE_CALLTYPE operator== (
const String& s1,
const String& s2)
noexcept {
return s1.compare (s2) == 0; }
567JUCE_API
bool JUCE_CALLTYPE operator!= (
const String& s1,
const String& s2)
noexcept {
return s1.compare (s2) != 0; }
568JUCE_API
bool JUCE_CALLTYPE operator== (
const String& s1,
const char* s2)
noexcept {
return s1.compare (s2) == 0; }
569JUCE_API
bool JUCE_CALLTYPE operator!= (
const String& s1,
const char* s2)
noexcept {
return s1.compare (s2) != 0; }
570JUCE_API
bool JUCE_CALLTYPE operator== (
const String& s1,
const wchar_t* s2)
noexcept {
return s1.compare (s2) == 0; }
571JUCE_API
bool JUCE_CALLTYPE operator!= (
const String& s1,
const wchar_t* s2)
noexcept {
return s1.compare (s2) != 0; }
572JUCE_API
bool JUCE_CALLTYPE operator== (
const String& s1, StringRef s2)
noexcept {
return s1.getCharPointer().compare (s2.text) == 0; }
573JUCE_API
bool JUCE_CALLTYPE operator!= (
const String& s1, StringRef s2)
noexcept {
return s1.getCharPointer().compare (s2.text) != 0; }
574JUCE_API
bool JUCE_CALLTYPE operator< (
const String& s1, StringRef s2)
noexcept {
return s1.getCharPointer().compare (s2.text) < 0; }
575JUCE_API
bool JUCE_CALLTYPE operator<= (
const String& s1, StringRef s2)
noexcept {
return s1.getCharPointer().compare (s2.text) <= 0; }
576JUCE_API
bool JUCE_CALLTYPE operator> (
const String& s1, StringRef s2)
noexcept {
return s1.getCharPointer().compare (s2.text) > 0; }
577JUCE_API
bool JUCE_CALLTYPE operator>= (
const String& s1, StringRef s2)
noexcept {
return s1.getCharPointer().compare (s2.text) >= 0; }
578JUCE_API
bool JUCE_CALLTYPE operator== (
const String& s1,
const CharPointer_UTF8 s2)
noexcept {
return s1.getCharPointer().compare (s2) == 0; }
579JUCE_API
bool JUCE_CALLTYPE operator!= (
const String& s1,
const CharPointer_UTF8 s2)
noexcept {
return s1.getCharPointer().compare (s2) != 0; }
580JUCE_API
bool JUCE_CALLTYPE operator== (
const String& s1,
const CharPointer_UTF16 s2)
noexcept {
return s1.getCharPointer().compare (s2) == 0; }
581JUCE_API
bool JUCE_CALLTYPE operator!= (
const String& s1,
const CharPointer_UTF16 s2)
noexcept {
return s1.getCharPointer().compare (s2) != 0; }
582JUCE_API
bool JUCE_CALLTYPE operator== (
const String& s1,
const CharPointer_UTF32 s2)
noexcept {
return s1.getCharPointer().compare (s2) == 0; }
583JUCE_API
bool JUCE_CALLTYPE operator!= (
const String& s1,
const CharPointer_UTF32 s2)
noexcept {
return s1.getCharPointer().compare (s2) != 0; }
587 return t !=
nullptr ? text.compareIgnoreCase (castToCharPointer_wchar_t (t)) == 0
599 return text.compareIgnoreCase (t.text) == 0;
604 return text == other.text
605 || text.compareIgnoreCase (other.text) == 0;
608int String::compare (
const String& other)
const noexcept {
return (text == other.text) ? 0 : text.compare (other.text); }
610int String::compare (
const wchar_t*
const other)
const noexcept {
return text.compare (castToCharPointer_wchar_t (other)); }
613static int stringCompareRight (String::CharPointerType s1, String::CharPointerType s2)
noexcept
617 auto c1 = s1.getAndAdvance();
620 auto c2 = s2.getAndAdvance();
623 if (! (isDigit1 || isDigit2))
return bias;
624 if (! isDigit1)
return -1;
625 if (! isDigit2)
return 1;
627 if (c1 != c2 && bias == 0)
628 bias = c1 < c2 ? -1 : 1;
630 jassert (c1 != 0 && c2 != 0);
634static int stringCompareLeft (String::CharPointerType s1, String::CharPointerType s2)
noexcept
638 auto c1 = s1.getAndAdvance();
641 auto c2 = s2.getAndAdvance();
644 if (! (isDigit1 || isDigit2))
return 0;
645 if (! isDigit1)
return -1;
646 if (! isDigit2)
return 1;
647 if (c1 < c2)
return -1;
648 if (c1 > c2)
return 1;
652static int naturalStringCompare (String::CharPointerType s1, String::CharPointerType s2,
bool isCaseSensitive)
noexcept
654 bool firstLoop =
true;
658 const bool hasSpace1 = s1.isWhitespace();
659 const bool hasSpace2 = s2.isWhitespace();
661 if ((! firstLoop) && (hasSpace1 ^ hasSpace2))
663 if (s1.isEmpty())
return -1;
664 if (s2.isEmpty())
return 1;
666 return hasSpace2 ? 1 : -1;
671 if (hasSpace1) s1 = s1.findEndOfWhitespace();
672 if (hasSpace2) s2 = s2.findEndOfWhitespace();
674 if (s1.isDigit() && s2.isDigit())
676 auto result = (*s1 ==
'0' || *s2 ==
'0') ? stringCompareLeft (s1, s2)
677 : stringCompareRight (s1, s2);
683 auto c1 = s1.getAndAdvance();
684 auto c2 = s2.getAndAdvance();
686 if (c1 != c2 && ! isCaseSensitive)
702 if (isAlphaNum2 && ! isAlphaNum1)
return -1;
703 if (isAlphaNum1 && ! isAlphaNum2)
return 1;
705 return c1 < c2 ? -1 : 1;
708 jassert (c1 != 0 && c2 != 0);
714 return naturalStringCompare (getCharPointer(), other.text, isCaseSensitive);
720 appendCharPointer (
this == &textToAppend ?
String (textToAppend).text
721 : textToAppend.text, maxCharsToTake);
726 appendCharPointer (textToAppend, textToAppend.findTerminatingNull());
730 const CharPointerType endOfTextToAppend)
732 jassert (startOfTextToAppend.getAddress() !=
nullptr && endOfTextToAppend.getAddress() !=
nullptr);
734 auto extraBytesNeeded = getAddressDifference (endOfTextToAppend.getAddress(),
735 startOfTextToAppend.getAddress());
736 jassert (extraBytesNeeded >= 0);
738 if (extraBytesNeeded > 0)
740 auto byteOffsetOfNull = getByteOffsetOfEnd();
741 preallocateBytes ((
size_t) extraBytesNeeded + byteOffsetOfNull);
743 auto* newStringStart = addBytesToPointer (text.getAddress(), (
int) byteOffsetOfNull);
744 memcpy (newStringStart, startOfTextToAppend.getAddress(), (
size_t) extraBytesNeeded);
745 CharPointerType (addBytesToPointer (newStringStart, extraBytesNeeded)).writeNull();
751 appendCharPointer (castToCharPointer_wchar_t (t));
764 return operator= (other);
767 return operator+= (
String (*
this));
769 appendCharPointer (other.text);
775 return operator+= (
String (other));
780 const char asString[] = { ch, 0 };
781 return operator+= (asString);
786 const wchar_t asString[] = { ch, 0 };
787 return operator+= (asString);
790#if ! JUCE_NATIVE_WCHAR_IS_UTF32
793 const juce_wchar asString[] = { ch, 0 };
794 appendCharPointer (CharPointer_UTF32 (asString));
799namespace StringHelpers
801 template <
typename T>
802 inline String& operationAddAssign (String& str,
const T number)
804 char buffer [(
sizeof(T) * 8) / 2];
805 auto* end = buffer + numElementsInArray (buffer);
806 auto* start = NumberToStringConverters::numberToString (end, number);
808 #if JUCE_STRING_UTF_TYPE == 8
809 str.appendCharPointer (String::CharPointerType (start), String::CharPointerType (end));
811 str.appendCharPointer (CharPointer_ASCII (start), CharPointer_ASCII (end));
823JUCE_API
String JUCE_CALLTYPE operator+ (
const char* s1,
const String& s2) {
String s (s1);
return s += s2; }
824JUCE_API String JUCE_CALLTYPE operator+ (
const wchar_t* s1,
const String& s2) { String s (s1);
return s += s2; }
826JUCE_API String JUCE_CALLTYPE operator+ (
char s1,
const String& s2) {
return String::charToString ((juce_wchar) (uint8) s1) + s2; }
827JUCE_API String JUCE_CALLTYPE operator+ (
wchar_t s1,
const String& s2) {
return String::charToString (s1) + s2; }
829JUCE_API String JUCE_CALLTYPE operator+ (String s1,
const String& s2) {
return s1 += s2; }
830JUCE_API String JUCE_CALLTYPE operator+ (String s1,
const char* s2) {
return s1 += s2; }
831JUCE_API String JUCE_CALLTYPE operator+ (String s1,
const wchar_t* s2) {
return s1 += s2; }
832JUCE_API String JUCE_CALLTYPE operator+ (String s1,
const std::string& s2) {
return s1 += s2.c_str(); }
834JUCE_API String JUCE_CALLTYPE operator+ (String s1,
char s2) {
return s1 += s2; }
835JUCE_API String JUCE_CALLTYPE operator+ (String s1,
wchar_t s2) {
return s1 += s2; }
837#if ! JUCE_NATIVE_WCHAR_IS_UTF32
838JUCE_API String JUCE_CALLTYPE operator+ (juce_wchar s1,
const String& s2) {
return String::charToString (s1) + s2; }
839JUCE_API String JUCE_CALLTYPE operator+ (String s1, juce_wchar s2) {
return s1 += s2; }
840JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, juce_wchar s2) {
return s1 += s2; }
843JUCE_API String& JUCE_CALLTYPE operator<< (String& s1,
char s2) {
return s1 += s2; }
844JUCE_API String& JUCE_CALLTYPE operator<< (String& s1,
wchar_t s2) {
return s1 += s2; }
846JUCE_API String& JUCE_CALLTYPE operator<< (String& s1,
const char* s2) {
return s1 += s2; }
847JUCE_API String& JUCE_CALLTYPE operator<< (String& s1,
const wchar_t* s2) {
return s1 += s2; }
848JUCE_API String& JUCE_CALLTYPE operator<< (String& s1,
const String& s2) {
return s1 += s2; }
849JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, StringRef s2) {
return s1 += s2; }
850JUCE_API String& JUCE_CALLTYPE operator<< (String& s1,
const std::string& s2) {
return s1 += s2.c_str(); }
852JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, uint8 number) {
return s1 += (int) number; }
853JUCE_API String& JUCE_CALLTYPE operator<< (String& s1,
short number) {
return s1 += (int) number; }
854JUCE_API String& JUCE_CALLTYPE operator<< (String& s1,
int number) {
return s1 += number; }
855JUCE_API String& JUCE_CALLTYPE operator<< (String& s1,
long number) {
return s1 += String (number); }
856JUCE_API String& JUCE_CALLTYPE operator<< (String& s1,
unsigned long number) {
return s1 += String (number); }
857JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, int64 number) {
return s1 += String (number); }
858JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, uint64 number) {
return s1 += String (number); }
859JUCE_API String& JUCE_CALLTYPE operator<< (String& s1,
float number) {
return s1 += String (number); }
860JUCE_API String& JUCE_CALLTYPE operator<< (String& s1,
double number) {
return s1 += String (number); }
862JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream,
const String& text)
864 return operator<< (stream, StringRef (text));
867JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, StringRef text)
871 #if (JUCE_STRING_UTF_TYPE == 8)
872 stream.write (text.text.getAddress(), numBytes);
876 HeapBlock<char> temp (numBytes + 1);
877 CharPointer_UTF8 (temp).writeAll (text.text);
878 stream.write (temp, numBytes);
887 return text.indexOf (character);
894 for (
int i = 0; ! t.isEmpty(); ++i)
898 if (t.getAndAdvance() == character)
915 for (
int i = 0; ! t.isEmpty(); ++i)
916 if (t.getAndAdvance() == character)
926 for (
int i = 0; ! t.isEmpty(); ++i)
930 if (charactersToLookFor.text.indexOf (t.getAndAdvance(), ignoreCase) >= 0)
944 return other.isEmpty() ? 0 : text.indexOf (other.text);
959 for (
int i = startIndex; --i >= 0;)
967 auto found = t.indexOf (other.text);
968 return found >= 0 ? found + startIndex : found;
978 for (
int i = startIndex; --i >= 0;)
987 return found >= 0 ? found + startIndex : found;
992 if (other.isNotEmpty())
994 auto len = other.length();
995 int i = length() - len;
999 for (
auto n = text + i; i >= 0; --i)
1001 if (n.compareUpTo (other.text, len) == 0)
1014 if (other.isNotEmpty())
1016 auto len = other.length();
1017 int i = length() - len;
1021 for (
auto n = text + i; i >= 0; --i)
1023 if (n.compareIgnoreCaseUpTo (other.text, len) == 0)
1039 for (
int i = 0; ! t.isEmpty(); ++i)
1040 if (charactersToLookFor.text.indexOf (t.getAndAdvance(), ignoreCase) >= 0)
1048 return indexOf (other) >= 0;
1053 return text.indexOf (character) >= 0;
1058 return indexOfIgnoreCase (t) >= 0;
1063 if (word.isNotEmpty())
1066 auto wordLen = word.length();
1067 auto end = (int) t.length() - wordLen;
1069 for (
int i = 0; i <= end; ++i)
1071 if (t.compareUpTo (word.text, wordLen) == 0
1072 && (i == 0 || ! (t - 1).isLetterOrDigit())
1073 && ! (t + wordLen).isLetterOrDigit())
1085 if (word.isNotEmpty())
1088 auto wordLen = word.length();
1089 auto end = (int) t.length() - wordLen;
1091 for (
int i = 0; i <= end; ++i)
1093 if (t.compareIgnoreCaseUpTo (word.text, wordLen) == 0
1094 && (i == 0 || ! (t - 1).isLetterOrDigit())
1095 && ! (t + wordLen).isLetterOrDigit())
1107 return indexOfWholeWord (wordToLookFor) >= 0;
1112 return indexOfWholeWordIgnoreCase (wordToLookFor) >= 0;
1116template <
typename CharPo
inter>
1117struct WildCardMatcher
1119 static bool matches (CharPointer wildcard, CharPointer test,
const bool ignoreCase)
noexcept
1123 auto wc = wildcard.getAndAdvance();
1126 return wildcard.isEmpty() || matchesAnywhere (wildcard, test, ignoreCase);
1128 if (! characterMatches (wc, test.getAndAdvance(), ignoreCase))
1136 static bool characterMatches (
const juce_wchar wc,
const juce_wchar tc,
const bool ignoreCase)
noexcept
1138 return (wc == tc) || (wc ==
'?' && tc != 0)
1139 || (ignoreCase && CharacterFunctions::toLowerCase (wc) == CharacterFunctions::toLowerCase (tc));
1142 static bool matchesAnywhere (
const CharPointer wildcard, CharPointer test,
const bool ignoreCase)
noexcept
1144 for (; ! test.isEmpty(); ++test)
1145 if (matches (wildcard, test, ignoreCase))
1154 return WildCardMatcher<CharPointerType>::matches (wildcard.text, text, ignoreCase);
1160 if (numberOfTimesToRepeat <= 0)
1163 String result (PreallocationBytes (findByteOffsetOfEnd (stringToRepeat) * (
size_t) numberOfTimesToRepeat));
1164 auto n = result.text;
1166 while (--numberOfTimesToRepeat >= 0)
1167 n.writeAll (stringToRepeat.
text);
1174 jassert (padCharacter != 0);
1176 auto extraChars = minimumLength;
1179 while (! end.isEmpty())
1185 if (extraChars <= 0 || padCharacter == 0)
1188 auto currentByteSize = (size_t) (((
char*) end.getAddress()) - (
char*) text.getAddress());
1189 String result (PreallocationBytes (currentByteSize + (
size_t) extraChars * CharPointerType::getBytesRequiredFor (padCharacter)));
1190 auto n = result.text;
1192 while (--extraChars >= 0)
1193 n.write (padCharacter);
1201 jassert (padCharacter != 0);
1203 auto extraChars = minimumLength;
1204 CharPointerType end (text);
1206 while (! end.isEmpty())
1212 if (extraChars <= 0 || padCharacter == 0)
1215 auto currentByteSize = (size_t) (((
char*) end.getAddress()) - (
char*) text.getAddress());
1216 String result (PreallocationBytes (currentByteSize + (
size_t) extraChars * CharPointerType::getBytesRequiredFor (padCharacter)));
1217 auto n = result.text;
1221 while (--extraChars >= 0)
1222 n.write (padCharacter);
1238 if (numCharsToReplace < 0)
1241 numCharsToReplace = 0;
1245 auto insertPoint = text;
1247 for (
int i = 0; i < index; ++i)
1249 if (insertPoint.isEmpty())
1253 return *
this + stringToInsert;
1259 auto startOfRemainder = insertPoint;
1261 for (
int i = 0; i < numCharsToReplace && ! startOfRemainder.isEmpty(); ++i)
1264 if (insertPoint == text && startOfRemainder.isEmpty())
1265 return stringToInsert.
text;
1267 auto initialBytes = (size_t) (((
char*) insertPoint.getAddress()) - (
char*) text.getAddress());
1268 auto newStringBytes = findByteOffsetOfEnd (stringToInsert);
1269 auto remainderBytes = (size_t) (((
char*) startOfRemainder.findTerminatingNull().getAddress()) - (
char*) startOfRemainder.getAddress());
1271 auto newTotalBytes = initialBytes + newStringBytes + remainderBytes;
1273 if (newTotalBytes <= 0)
1276 String result (PreallocationBytes ((
size_t) newTotalBytes));
1278 auto* dest = (
char*) result.text.getAddress();
1279 memcpy (dest, text.getAddress(), initialBytes);
1280 dest += initialBytes;
1281 memcpy (dest, stringToInsert.
text.getAddress(), newStringBytes);
1282 dest += newStringBytes;
1283 memcpy (dest, startOfRemainder.getAddress(), remainderBytes);
1284 dest += remainderBytes;
1285 CharPointerType ((CharPointerType::CharType*) dest).writeNull();
1292 auto stringToReplaceLen = stringToReplace.
length();
1293 auto stringToInsertLen = stringToInsert.
length();
1299 : result.
indexOf (i, stringToReplace))) >= 0)
1301 result = result.
replaceSection (i, stringToReplaceLen, stringToInsert);
1302 i += stringToInsertLen;
1310 auto stringToReplaceLen = stringToReplace.
length();
1311 auto index = ignoreCase ? indexOfIgnoreCase (stringToReplace)
1312 : indexOf (stringToReplace);
1315 return replaceSection (index, stringToReplaceLen, stringToInsert);
1320struct StringCreationHelper
1322 StringCreationHelper (
size_t initialBytes) : allocatedBytes (initialBytes)
1324 result.preallocateBytes (allocatedBytes);
1325 dest = result.getCharPointer();
1328 StringCreationHelper (
const String::CharPointerType s)
1329 : source (s), allocatedBytes (StringHolder::getAllocatedNumBytes (s))
1331 result.preallocateBytes (allocatedBytes);
1332 dest = result.getCharPointer();
1335 void write (juce_wchar c)
1337 bytesWritten += String::CharPointerType::getBytesRequiredFor (c);
1339 if (bytesWritten > allocatedBytes)
1341 allocatedBytes += jmax ((
size_t) 8, allocatedBytes / 16);
1342 auto destOffset = (size_t) (((
char*) dest.getAddress()) - (
char*) result.getCharPointer().getAddress());
1343 result.preallocateBytes (allocatedBytes);
1344 dest = addBytesToPointer (result.getCharPointer().getAddress(), (
int) destOffset);
1351 String::CharPointerType source {
nullptr }, dest {
nullptr };
1352 size_t allocatedBytes, bytesWritten = 0;
1357 if (! containsChar (charToReplace))
1360 StringCreationHelper builder (text);
1364 auto c = builder.source.getAndAdvance();
1366 if (c == charToReplace)
1375 return std::move (builder.result);
1382 jassert (charactersToReplace.
length() == charactersToInsertInstead.
length());
1384 StringCreationHelper builder (text);
1388 auto c = builder.source.getAndAdvance();
1389 auto index = charactersToReplace.
text.indexOf (c);
1392 c = charactersToInsertInstead [index];
1400 return std::move (builder.result);
1406 return text.compareUpTo (other.text, other.length()) == 0;
1411 return text.compareIgnoreCaseUpTo (other.text, other.length()) == 0;
1416 jassert (character != 0);
1418 return *text == character;
1423 jassert (character != 0);
1428 auto t = text.findTerminatingNull();
1429 return *--t == character;
1434 auto end = text.findTerminatingNull();
1435 auto otherEnd = other.text.findTerminatingNull();
1437 while (end > text && otherEnd > other.text)
1442 if (*end != *otherEnd)
1446 return otherEnd == other.text;
1451 auto end = text.findTerminatingNull();
1452 auto otherEnd = other.text.findTerminatingNull();
1454 while (end > text && otherEnd > other.text)
1459 if (end.toLowerCase() != otherEnd.toLowerCase())
1463 return otherEnd == other.text;
1469 StringCreationHelper builder (text);
1473 auto c = builder.source.toUpperCase();
1482 return std::move (builder.result);
1487 StringCreationHelper builder (text);
1491 auto c = builder.source.toLowerCase();
1500 return std::move (builder.result);
1506 return isEmpty() ? juce_wchar() : text [length() - 1];
1555 while (--start >= 0)
1568 return String (text, (
size_t) jmax (0, length() - numberToDrop));
1573 return String (text + jmax (0, length() - jmax (0, numCharacters)));
1578 auto i = ignoreCase ? indexOfIgnoreCase (sub)
1583 return substring (includeSubString ? i : i + sub.
length());
1588 auto i = ignoreCase ? lastIndexOfIgnoreCase (sub)
1589 : lastIndexOf (sub);
1593 return substring (includeSubString ? i : i + sub.
length());
1598 auto i = ignoreCase ? indexOfIgnoreCase (sub)
1603 return substring (0, includeSubString ? i + sub.
length() : i);
1608 auto i = ignoreCase ? lastIndexOfIgnoreCase (sub)
1609 : lastIndexOf (sub);
1613 return substring (0, includeSubString ? i + sub.
length() : i);
1616static bool isQuoteCharacter (juce_wchar c)
noexcept
1618 return c ==
'"' || c ==
'\'';
1623 return isQuoteCharacter (*text.findEndOfWhitespace());
1628 if (! isQuoteCharacter (*text))
1631 auto len = length();
1632 return substring (1, len - (isQuoteCharacter (text[len - 1]) ? 1 : 0));
1638 return charToString (quoteCharacter) + quoteCharacter;
1643 t = charToString (quoteCharacter) + t;
1646 t += quoteCharacter;
1652static String::CharPointerType findTrimmedEnd (
const String::CharPointerType start,
1653 String::CharPointerType end)
1657 if (! (--end).isWhitespace())
1671 auto start = text.findEndOfWhitespace();
1672 auto end = start.findTerminatingNull();
1673 auto trimmedEnd = findTrimmedEnd (start, end);
1675 if (trimmedEnd <= start)
1678 if (text < start || trimmedEnd < end)
1679 return String (start, trimmedEnd);
1689 auto t = text.findEndOfWhitespace();
1702 auto end = text.findTerminatingNull();
1703 auto trimmedEnd = findTrimmedEnd (text, end);
1705 if (trimmedEnd < end)
1706 return String (text, trimmedEnd);
1716 while (charactersToTrim.
text.indexOf (*t) >= 0)
1719 return t == text ? *this :
String (t);
1726 auto end = text.findTerminatingNull();
1727 auto trimmedEnd = end;
1729 while (trimmedEnd > text)
1731 if (charactersToTrim.
text.indexOf (*--trimmedEnd) < 0)
1738 if (trimmedEnd < end)
1739 return String (text, trimmedEnd);
1751 StringCreationHelper builder (text);
1755 auto c = builder.source.getAndAdvance();
1757 if (charactersToRetain.
text.indexOf (c) >= 0)
1765 return std::move (builder.result);
1773 StringCreationHelper builder (text);
1777 auto c = builder.source.getAndAdvance();
1779 if (charactersToRemove.
text.indexOf (c) < 0)
1786 return std::move (builder.result);
1791 for (
auto t = text; ! t.isEmpty(); ++t)
1792 if (permittedCharacters.
text.indexOf (*t) < 0)
1800 for (
auto t = text; ! t.isEmpty(); ++t)
1801 if (charactersToStopAt.
text.indexOf (*t) >= 0)
1809 for (
auto t = text; ! t.isEmpty();)
1810 if (chars.text.indexOf (t.getAndAdvance()) < 0)
1818 for (
auto t = text; ! t.isEmpty();)
1819 if (chars.text.indexOf (t.getAndAdvance()) >= 0)
1827 for (
auto t = text; ! t.isEmpty(); ++t)
1828 if (! t.isWhitespace())
1834String String::formattedRaw (
const char* pf, ...)
1836 size_t bufferSize = 256;
1841 va_start (args, pf);
1845 int num = (int) vsnprintf (temp.get(), bufferSize - 1, pf, args);
1846 if (num >=
static_cast<int> (bufferSize))
1849 String wideCharVersion (pf);
1851 const int num = (int)
1857 (temp.get(), bufferSize - 1, wideCharVersion.toWideCharPointer(), args);
1862 return String (temp.get());
1866 if (num == 0 || bufferSize > 65536)
1883 auto t = text.findTerminatingNull();
1895 n +=
static_cast<juce_wchar
> (mult) * (*t -
'0');
1902static const char hexDigits[] =
"0123456789abcdef";
1904template <
typename Type>
1905static String hexToString (Type v)
1907 String::CharPointerType::CharType buffer[32];
1908 auto* end = buffer + numElementsInArray (buffer) - 1;
1914 *--t = hexDigits [(int) (v & 15)];
1919 return String (String::CharPointerType (t),
1920 String::CharPointerType (end));
1923String String::createHex (uint8 n) {
return hexToString (n); }
1924String String::createHex (uint16 n) {
return hexToString (n); }
1925String String::createHex (uint32 n) {
return hexToString (n); }
1926String String::createHex (uint64 n) {
return hexToString (n); }
1933 int numChars = (size * 2) + 2;
1935 numChars += size / groupSize;
1937 String s (PreallocationBytes ((
size_t) numChars *
sizeof (CharPointerType::CharType)));
1939 auto* data =
static_cast<const unsigned char*
> (d);
1942 for (
int i = 0; i < size; ++i)
1944 const unsigned char nextByte = *data++;
1945 dest.write ((juce_wchar) hexDigits [nextByte >> 4]);
1946 dest.write ((juce_wchar) hexDigits [nextByte & 0xf]);
1948 if (groupSize > 0 && (i % groupSize) == (groupSize - 1) && i < (size - 1))
1949 dest.write ((juce_wchar)
' ');
1960static String getStringFromWindows1252Codepage (
const char* data,
size_t num)
1964 for (
size_t i = 0; i < num; ++i)
1973 auto* data =
static_cast<const uint8*
> (unknownData);
1975 if (size <= 0 || data ==
nullptr)
1979 return charToString ((juce_wchar) data[0]);
1984 const int numChars = size / 2 - 1;
1986 StringCreationHelper builder ((
size_t) numChars);
1988 auto src =
reinterpret_cast<const uint16*
> (data + 2);
1992 for (
int i = 0; i < numChars; ++i)
1997 for (
int i = 0; i < numChars; ++i)
2002 return std::move (builder.result);
2005 auto* start = (
const char*) data;
2017 return getStringFromWindows1252Codepage (start, (
size_t) size);
2021static const juce_wchar emptyChar = 0;
2023template <
class CharPo
interType_Src,
class CharPo
interType_Dest>
2024struct StringEncodingConverter
2026 static CharPointerType_Dest convert (
const String& s)
2028 auto& source =
const_cast<String&
> (s);
2030 using DestChar =
typename CharPointerType_Dest::CharType;
2032 if (source.isEmpty())
2033 return CharPointerType_Dest (
reinterpret_cast<const DestChar*
> (&emptyChar));
2035 CharPointerType_Src text (source.getCharPointer());
2036 auto extraBytesNeeded = CharPointerType_Dest::getBytesRequiredFor (text) +
sizeof (
typename CharPointerType_Dest::CharType);
2037 auto endOffset = (text.sizeInBytes() + 3) & ~3u;
2039 source.preallocateBytes (endOffset + extraBytesNeeded);
2040 text = source.getCharPointer();
2042 void*
const newSpace = addBytesToPointer (text.getAddress(), (
int) endOffset);
2043 const CharPointerType_Dest extraSpace (
static_cast<DestChar*
> (newSpace));
2046 auto bytesToClear = (size_t) jmin ((
int) extraBytesNeeded, 4);
2047 zeromem (addBytesToPointer (newSpace, extraBytesNeeded - bytesToClear), bytesToClear);
2050 CharPointerType_Dest (extraSpace).writeAll (text);
2056struct StringEncodingConverter<CharPointer_UTF8, CharPointer_UTF8>
2058 static CharPointer_UTF8 convert (
const String& source)
noexcept {
return CharPointer_UTF8 (
reinterpret_cast<CharPointer_UTF8::CharType*
> (source.getCharPointer().getAddress())); }
2062struct StringEncodingConverter<CharPointer_UTF16, CharPointer_UTF16>
2064 static CharPointer_UTF16 convert (
const String& source)
noexcept {
return CharPointer_UTF16 (
reinterpret_cast<CharPointer_UTF16::CharType*
> (source.getCharPointer().getAddress())); }
2068struct StringEncodingConverter<CharPointer_UTF32, CharPointer_UTF32>
2070 static CharPointer_UTF32 convert (
const String& source)
noexcept {
return CharPointer_UTF32 (
reinterpret_cast<CharPointer_UTF32::CharType*
> (source.getCharPointer().getAddress())); }
2079 return toUTF8().getAddress();
2084 return StringEncodingConverter<CharPointerType, CharPointer_wchar_t>::convert (*this).getAddress();
2087std::string String::toStdString()
const
2089 return std::string (toRawUTF8());
2093template <
class CharPo
interType_Src,
class CharPo
interType_Dest>
2096 static size_t copyToBuffer (
const CharPointerType_Src source,
typename CharPointerType_Dest::CharType*
const buffer,
const size_t maxBufferSizeBytes)
2098 jassert (((ssize_t) maxBufferSizeBytes) >= 0);
2100 if (buffer ==
nullptr)
2101 return CharPointerType_Dest::getBytesRequiredFor (source) +
sizeof (
typename CharPointerType_Dest::CharType);
2103 return CharPointerType_Dest (buffer).writeWithDestByteLimit (source, maxBufferSizeBytes);
2107size_t String::copyToUTF8 (CharPointer_UTF8::CharType*
const buffer,
size_t maxBufferSizeBytes)
const noexcept
2109 return StringCopier<CharPointerType, CharPointer_UTF8>::copyToBuffer (text, buffer, maxBufferSizeBytes);
2112size_t String::copyToUTF16 (CharPointer_UTF16::CharType*
const buffer,
size_t maxBufferSizeBytes)
const noexcept
2114 return StringCopier<CharPointerType, CharPointer_UTF16>::copyToBuffer (text, buffer, maxBufferSizeBytes);
2117size_t String::copyToUTF32 (CharPointer_UTF32::CharType*
const buffer,
size_t maxBufferSizeBytes)
const noexcept
2119 return StringCopier<CharPointerType, CharPointer_UTF32>::copyToBuffer (text, buffer, maxBufferSizeBytes);
2130 if (buffer !=
nullptr)
2132 if (bufferSizeBytes < 0)
2135 if (bufferSizeBytes > 0)
2146 #pragma warning (pop)
2155 #if JUCE_STRING_UTF_TYPE != 8
2156 : text (
nullptr), stringCopy (stringLiteral)
2158 : text (stringLiteral)
2161 #if JUCE_STRING_UTF_TYPE != 8
2162 text = stringCopy.getCharPointer();
2165 jassert (stringLiteral !=
nullptr);
2167 #if JUCE_NATIVE_WCHAR_IS_UTF8
2187 jassert (stringLiteral.getAddress() !=
nullptr);
2195static String reduceLengthOfFloatString (
const String& input)
2198 const auto end = start + (int) input.
length();
2199 auto trimStart = end;
2200 auto trimEnd = trimStart;
2201 auto exponentTrimStart = end;
2202 auto exponentTrimEnd = exponentTrimStart;
2204 decltype (*start) currentChar =
'\0';
2206 for (
auto c = end - 1; c > start; --c)
2210 if (currentChar ==
'0' && c + 1 == trimStart)
2214 else if (currentChar ==
'.')
2216 if (trimStart == c + 1 && trimStart != end && *trimStart ==
'0')
2221 else if (currentChar ==
'e' || currentChar ==
'E')
2230 exponentTrimStart = cNext;
2232 if (cNext != end && *cNext ==
'+')
2235 exponentTrimEnd = cNext;
2238 while (cNext != end && *cNext++ ==
'0')
2239 exponentTrimEnd = cNext;
2241 if (exponentTrimEnd == end)
2242 exponentTrimStart = c;
2245 trimEnd = trimStart;
2249 if ((trimStart != trimEnd && currentChar ==
'.') || exponentTrimStart != exponentTrimEnd)
2251 if (trimStart == trimEnd)
2252 return String (start, exponentTrimStart) + String (exponentTrimEnd, end);
2254 if (exponentTrimStart == exponentTrimEnd)
2255 return String (start, trimStart) + String (trimEnd, end);
2257 if (trimEnd == exponentTrimStart)
2258 return String (start, trimStart) + String (exponentTrimEnd, end);
2260 return String (start, trimStart) + String (trimEnd, exponentTrimStart) + String (exponentTrimEnd, end);
2266static String serialiseDouble (
double input)
2268 auto absInput = std::abs (input);
2270 if (absInput >= 1.0e6 || absInput <= 1.0e-5)
2271 return reduceLengthOfFloatString ({ input, 15,
true });
2273 int intInput = (int) input;
2275 if ((
double) intInput == input)
2276 return { input, 1 };
2278 auto numberOfDecimalPlaces = [absInput]
2282 if (absInput >= 1.0e-3)
2284 if (absInput >= 1.0e-1)
return 16;
2285 if (absInput >= 1.0e-2)
return 17;
2289 if (absInput >= 1.0e-4)
return 19;
2293 if (absInput < 1.0e3)
2295 if (absInput < 1.0e1)
return 15;
2296 if (absInput < 1.0e2)
return 14;
2300 if (absInput < 1.0e4)
return 12;
2301 if (absInput < 1.0e5)
return 11;
2305 return reduceLengthOfFloatString (String (input, numberOfDecimalPlaces));
2313#define STRINGIFY2(X) #X
2314#define STRINGIFY(X) STRINGIFY2(X)
2316class StringTests :
public UnitTest
2320 : UnitTest (
"String class", UnitTestCategories::text)
2323 template <
class CharPo
interType>
2324 struct TestUTFConversion
2326 static void test (UnitTest& test, Random& r)
2328 String s (createRandomWideCharString (r));
2330 typename CharPointerType::CharType buffer [300];
2332 memset (buffer, 0xff,
sizeof (buffer));
2333 CharPointerType (buffer).writeAll (s.
toUTF32());
2334 test.expectEquals (String (CharPointerType (buffer)), s);
2336 memset (buffer, 0xff,
sizeof (buffer));
2337 CharPointerType (buffer).writeAll (s.
toUTF16());
2338 test.expectEquals (String (CharPointerType (buffer)), s);
2340 memset (buffer, 0xff,
sizeof (buffer));
2341 CharPointerType (buffer).writeAll (s.
toUTF8());
2342 test.expectEquals (String (CharPointerType (buffer)), s);
2344 test.expect (CharPointerType::isValidString (buffer, (
int) strlen ((
const char*) buffer)));
2348 static String createRandomWideCharString (Random& r)
2350 juce_wchar buffer[50] = { 0 };
2352 for (
int i = 0; i < numElementsInArray (buffer) - 1; ++i)
2358 buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1));
2360 while (! CharPointer_UTF16::canRepresent (buffer[i]));
2363 buffer[i] = (juce_wchar) (1 + r.nextInt (0xff));
2366 return CharPointer_UTF32 (buffer);
2369 void runTest()
override
2371 Random r = getRandom();
2374 beginTest (
"Basics");
2376 expect (String().length() == 0);
2377 expect (String() == String());
2378 String s1, s2 (
"abcd");
2379 expect (s1.isEmpty() && ! s1.isNotEmpty());
2380 expect (s2.isNotEmpty() && ! s2.isEmpty());
2381 expect (s2.length() == 4);
2383 expect (s2 == s1 && s1 == s2);
2384 expect (s1 ==
"abcd" && s1 == L
"abcd");
2385 expect (String (
"abcd") == String (L
"abcd"));
2386 expect (String (
"abcdefg", 4) == L
"abcd");
2387 expect (String (
"abcdefg", 4) == String (L
"abcdefg", 4));
2388 expect (String::charToString (
'x') ==
"x");
2389 expect (String::charToString (0) == String());
2390 expect (s2 +
"e" ==
"abcde" && s2 +
'e' ==
"abcde");
2391 expect (s2 + L
'e' ==
"abcde" && s2 + L
"e" ==
"abcde");
2392 expect (s1.equalsIgnoreCase (
"abcD") && s1 < "abce" && s1 >
"abbb");
2393 expect (s1.startsWith (
"ab") && s1.startsWith (
"abcd") && ! s1.startsWith (
"abcde"));
2394 expect (s1.startsWithIgnoreCase (
"aB") && s1.endsWithIgnoreCase (
"CD"));
2395 expect (s1.endsWith (
"bcd") && ! s1.endsWith (
"aabcd"));
2396 expectEquals (s1.indexOf (String()), 0);
2397 expectEquals (s1.indexOfIgnoreCase (String()), 0);
2398 expect (s1.startsWith (String()) && s1.endsWith (String()) && s1.contains (String()));
2399 expect (s1.contains (
"cd") && s1.contains (
"ab") && s1.contains (
"abcd"));
2400 expect (s1.containsChar (
'a'));
2401 expect (! s1.containsChar (
'x'));
2402 expect (! s1.containsChar (0));
2403 expect (String (
"abc foo bar").containsWholeWord (
"abc") && String (
"abc foo bar").containsWholeWord (
"abc"));
2407 beginTest (
"Operations");
2409 String s (
"012345678");
2412 expect (s.
hashCode() != (s + s).hashCode());
2413 expect (s.
hashCode64() != (s + s).hashCode64());
2414 expect (s.
compare (String (
"012345678")) == 0);
2415 expect (s.
compare (String (
"012345679")) < 0);
2416 expect (s.
compare (String (
"012345676")) > 0);
2417 expect (String(
"a").compareNatural (
"A") == 0);
2418 expect (String(
"A").compareNatural (
"B") < 0);
2419 expect (String(
"a").compareNatural (
"B") < 0);
2420 expect (String(
"10").compareNatural (
"2") > 0);
2421 expect (String(
"Abc 10").compareNatural (
"aBC 2") > 0);
2422 expect (String(
"Abc 1").compareNatural (
"aBC 2") < 0);
2423 expect (s.
substring (2, 3) == String::charToString (s[2]));
2424 expect (s.
substring (0, 1) == String::charToString (s[0]));
2431 expect (s.
indexOf (String (L
"45")) == 4);
2432 expect (String (
"444445").indexOf (
"45") == 4);
2433 expect (String (
"444445").lastIndexOfChar (
'4') == 4);
2434 expect (String (
"45454545x").lastIndexOf (String (L
"45")) == 6);
2435 expect (String (
"45454545x").lastIndexOfAnyOf (
"456") == 7);
2436 expect (String (
"45454545x").lastIndexOfAnyOf (String (L
"456x")) == 8);
2437 expect (String (
"abABaBaBa").lastIndexOfIgnoreCase (
"aB") == 6);
2439 expect (s + s ==
"012345678012345678");
2449 expect (s [s.
length()] == 0);
2450 expect (String (
"abcdEFGH").toLowerCase() == String (
"abcdefgh"));
2451 expect (String (
"abcdEFGH").toUpperCase() == String (
"ABCDEFGH"));
2453 expect (String (StringRef (
"abc")) ==
"abc");
2454 expect (String (StringRef (
"abc")) == StringRef (
"abc"));
2455 expect (String (
"abc") + StringRef (
"def") ==
"abcdef");
2458 s2 << ((int) 4) << ((short) 5) <<
"678" << L
"9" <<
'0';
2460 expect (s2 ==
"1234567890xyz");
2462 expect (s2 ==
"1234567890xyz123");
2464 expect (s2 ==
"1234567890xyz123123");
2465 s2 << StringRef (
"def");
2466 expect (s2 ==
"1234567890xyz123123def");
2470 String numStr (std::numeric_limits<int16>::max());
2471 expect (numStr ==
"32767");
2474 String numStr (std::numeric_limits<int16>::min());
2475 expect (numStr ==
"-32768");
2479 numStr << std::numeric_limits<int16>::max();
2480 expect (numStr ==
"32767");
2484 numStr << std::numeric_limits<int16>::min();
2485 expect (numStr ==
"-32768");
2489 String numStr (std::numeric_limits<int32>::max());
2490 expect (numStr ==
"2147483647");
2493 String numStr (std::numeric_limits<int32>::min());
2494 expect (numStr ==
"-2147483648");
2498 numStr << std::numeric_limits<int32>::max();
2499 expect (numStr ==
"2147483647");
2503 numStr << std::numeric_limits<int32>::min();
2504 expect (numStr ==
"-2147483648");
2508 String numStr (std::numeric_limits<uint32>::max());
2509 expect (numStr ==
"4294967295");
2512 String numStr (std::numeric_limits<uint32>::min());
2513 expect (numStr ==
"0");
2517 String numStr (std::numeric_limits<int64>::max());
2518 expect (numStr ==
"9223372036854775807");
2521 String numStr (std::numeric_limits<int64>::min());
2522 expect (numStr ==
"-9223372036854775808");
2526 numStr << std::numeric_limits<int64>::max();
2527 expect (numStr ==
"9223372036854775807");
2531 numStr << std::numeric_limits<int64>::min();
2532 expect (numStr ==
"-9223372036854775808");
2536 String numStr (std::numeric_limits<uint64>::max());
2537 expect (numStr ==
"18446744073709551615");
2540 String numStr (std::numeric_limits<uint64>::min());
2541 expect (numStr ==
"0");
2545 numStr << std::numeric_limits<uint64>::max();
2546 expect (numStr ==
"18446744073709551615");
2550 numStr << std::numeric_limits<uint64>::min();
2551 expect (numStr ==
"0");
2555 String numStr (std::numeric_limits<size_t>::min());
2556 expect (numStr ==
"0");
2559 beginTest (
"Numeric conversions");
2560 expect (String().getIntValue() == 0);
2561 expect (String().getDoubleValue() == 0.0);
2562 expect (String().getFloatValue() == 0.0f);
2567 expect (String (-1234).getIntValue() == -1234);
2568 expect (String ((int64) -1234).getLargeIntValue() == -1234);
2569 expect (String (-1234.56).getDoubleValue() == -1234.56);
2570 expect (String (-1234.56f).getFloatValue() == -1234.56f);
2571 expect (String (std::numeric_limits<int>::max()).getIntValue() == std::numeric_limits<int>::max());
2572 expect (String (std::numeric_limits<int>::min()).getIntValue() == std::numeric_limits<int>::min());
2573 expect (String (std::numeric_limits<int64>::max()).getLargeIntValue() == std::numeric_limits<int64>::max());
2574 expect (String (std::numeric_limits<int64>::min()).getLargeIntValue() == std::numeric_limits<int64>::min());
2575 expect ((
"xyz" + s).getTrailingIntValue() == s.
getIntValue());
2578 expect (String::toHexString (0x1234abcd).equalsIgnoreCase (
"1234abcd"));
2579 expect (String::toHexString ((int64) 0x1234abcd).equalsIgnoreCase (
"1234abcd"));
2580 expect (String::toHexString ((
short) 0x12ab).equalsIgnoreCase (
"12ab"));
2581 expect (String::toHexString ((
size_t) 0x12ab).equalsIgnoreCase (
"12ab"));
2582 expect (String::toHexString ((
long) 0x12ab).equalsIgnoreCase (
"12ab"));
2583 expect (String::toHexString ((int8) -1).equalsIgnoreCase (
"ff"));
2584 expect (String::toHexString ((int16) -1).equalsIgnoreCase (
"ffff"));
2585 expect (String::toHexString ((int32) -1).equalsIgnoreCase (
"ffffffff"));
2586 expect (String::toHexString ((int64) -1).equalsIgnoreCase (
"ffffffffffffffff"));
2588 unsigned char data[] = { 1, 2, 3, 4, 0xa, 0xb, 0xc, 0xd };
2589 expect (String::toHexString (data, 8, 0).equalsIgnoreCase (
"010203040a0b0c0d"));
2590 expect (String::toHexString (data, 8, 1).equalsIgnoreCase (
"01 02 03 04 0a 0b 0c 0d"));
2591 expect (String::toHexString (data, 8, 2).equalsIgnoreCase (
"0102 0304 0a0b 0c0d"));
2593 expectEquals (String (12345.67, 4), String (
"12345.6700"));
2594 expectEquals (String (12345.67, 6), String (
"12345.670000"));
2595 expectEquals (String (2589410.5894, 7), String (
"2589410.5894000"));
2596 expectEquals (String (12345.67, 8), String (
"12345.67000000"));
2597 expectEquals (String (1e19, 4), String (
"10000000000000000000.0000"));
2598 expectEquals (String (1e-34, 36), String (
"0.000000000000000000000000000000000100"));
2599 expectEquals (String (1.39, 1), String (
"1.4"));
2601 expectEquals (String (12345.67, 4,
true), String (
"1.2346e+04"));
2602 expectEquals (String (12345.67, 6,
true), String (
"1.234567e+04"));
2603 expectEquals (String (2589410.5894, 7,
true), String (
"2.5894106e+06"));
2604 expectEquals (String (12345.67, 8,
true), String (
"1.23456700e+04"));
2605 expectEquals (String (1e19, 4,
true), String (
"1.0000e+19"));
2606 expectEquals (String (1e-34, 5,
true), String (
"1.00000e-34"));
2607 expectEquals (String (1.39, 1,
true), String (
"1.4e+00"));
2609 beginTest (
"Subsections");
2612 expect (s3.equalsIgnoreCase (
"ABCdeFGhiJ"));
2613 expect (s3.compareIgnoreCase (L
"ABCdeFGhiJ") == 0);
2614 expect (s3.containsIgnoreCase (s3.substring (3)));
2615 expect (s3.indexOfAnyOf (
"xyzf", 2,
true) == 5);
2616 expect (s3.indexOfAnyOf (String (L
"xyzf"), 2,
false) == -1);
2617 expect (s3.indexOfAnyOf (
"xyzF", 2,
false) == 5);
2618 expect (s3.containsAnyOf (String (L
"zzzFs")));
2619 expect (s3.startsWith (
"abcd"));
2620 expect (s3.startsWithIgnoreCase (String (L
"abCD")));
2621 expect (s3.startsWith (String()));
2622 expect (s3.startsWithChar (
'a'));
2623 expect (s3.endsWith (String (
"HIJ")));
2624 expect (s3.endsWithIgnoreCase (String (L
"Hij")));
2625 expect (s3.endsWith (String()));
2626 expect (s3.endsWithChar (L
'J'));
2627 expect (s3.indexOf (
"HIJ") == 7);
2628 expect (s3.indexOf (String (L
"HIJK")) == -1);
2629 expect (s3.indexOfIgnoreCase (
"hij") == 7);
2630 expect (s3.indexOfIgnoreCase (String (L
"hijk")) == -1);
2631 expect (s3.toStdString() == s3.toRawUTF8());
2634 s4.append (String (
"xyz123"), 3);
2635 expect (s4 == s3 +
"xyz");
2637 expect (String (1234) < String (1235));
2638 expect (String (1235) > String (1234));
2639 expect (String (1234) >= String (1234));
2640 expect (String (1234) <= String (1234));
2641 expect (String (1235) >= String (1234));
2642 expect (String (1234) <= String (1235));
2644 String s5 (
"word word2 word3");
2645 expect (s5.containsWholeWord (String (
"word2")));
2646 expect (s5.indexOfWholeWord (
"word2") == 5);
2647 expect (s5.containsWholeWord (String (L
"word")));
2648 expect (s5.containsWholeWord (
"word3"));
2649 expect (s5.containsWholeWord (s5));
2650 expect (s5.containsWholeWordIgnoreCase (String (L
"Word2")));
2651 expect (s5.indexOfWholeWordIgnoreCase (
"Word2") == 5);
2652 expect (s5.containsWholeWordIgnoreCase (String (L
"Word")));
2653 expect (s5.containsWholeWordIgnoreCase (
"Word3"));
2654 expect (! s5.containsWholeWordIgnoreCase (String (L
"Wordx")));
2655 expect (! s5.containsWholeWordIgnoreCase (
"xWord2"));
2656 expect (s5.containsNonWhitespaceChars());
2657 expect (s5.containsOnly (
"ordw23 "));
2658 expect (! String (
" \n\r\t").containsNonWhitespaceChars());
2660 expect (s5.matchesWildcard (String (L
"wor*"),
false));
2661 expect (s5.matchesWildcard (
"wOr*",
true));
2662 expect (s5.matchesWildcard (String (L
"*word3"),
true));
2663 expect (s5.matchesWildcard (
"*word?",
true));
2664 expect (s5.matchesWildcard (String (L
"Word*3"),
true));
2665 expect (! s5.matchesWildcard (String (L
"*34"),
true));
2666 expect (String (
"xx**y").matchesWildcard (
"*y",
true));
2667 expect (String (
"xx**y").matchesWildcard (
"x*y",
true));
2668 expect (String (
"xx**y").matchesWildcard (
"xx*y",
true));
2669 expect (String (
"xx**y").matchesWildcard (
"xx*",
true));
2670 expect (String (
"xx?y").matchesWildcard (
"x??y",
true));
2671 expect (String (
"xx?y").matchesWildcard (
"xx?y",
true));
2672 expect (! String (
"xx?y").matchesWildcard (
"xx?y?",
true));
2673 expect (String (
"xx?y").matchesWildcard (
"xx??",
true));
2675 expectEquals (s5.fromFirstOccurrenceOf (String(),
true,
false), s5);
2676 expectEquals (s5.fromFirstOccurrenceOf (
"xword2",
true,
false), s5.substring (100));
2677 expectEquals (s5.fromFirstOccurrenceOf (String (L
"word2"),
true,
false), s5.substring (5));
2678 expectEquals (s5.fromFirstOccurrenceOf (
"Word2",
true,
true), s5.substring (5));
2679 expectEquals (s5.fromFirstOccurrenceOf (
"word2",
false,
false), s5.getLastCharacters (6));
2680 expectEquals (s5.fromFirstOccurrenceOf (
"Word2",
false,
true), s5.getLastCharacters (6));
2682 expectEquals (s5.fromLastOccurrenceOf (String(),
true,
false), s5);
2683 expectEquals (s5.fromLastOccurrenceOf (
"wordx",
true,
false), s5);
2684 expectEquals (s5.fromLastOccurrenceOf (
"word",
true,
false), s5.getLastCharacters (5));
2685 expectEquals (s5.fromLastOccurrenceOf (
"worD",
true,
true), s5.getLastCharacters (5));
2686 expectEquals (s5.fromLastOccurrenceOf (
"word",
false,
false), s5.getLastCharacters (1));
2687 expectEquals (s5.fromLastOccurrenceOf (
"worD",
false,
true), s5.getLastCharacters (1));
2689 expect (s5.upToFirstOccurrenceOf (String(),
true,
false).isEmpty());
2690 expectEquals (s5.upToFirstOccurrenceOf (
"word4",
true,
false), s5);
2691 expectEquals (s5.upToFirstOccurrenceOf (
"word2",
true,
false), s5.substring (0, 10));
2692 expectEquals (s5.upToFirstOccurrenceOf (
"Word2",
true,
true), s5.substring (0, 10));
2693 expectEquals (s5.upToFirstOccurrenceOf (
"word2",
false,
false), s5.substring (0, 5));
2694 expectEquals (s5.upToFirstOccurrenceOf (
"Word2",
false,
true), s5.substring (0, 5));
2696 expectEquals (s5.upToLastOccurrenceOf (String(),
true,
false), s5);
2697 expectEquals (s5.upToLastOccurrenceOf (
"zword",
true,
false), s5);
2698 expectEquals (s5.upToLastOccurrenceOf (
"word",
true,
false), s5.dropLastCharacters (1));
2699 expectEquals (s5.dropLastCharacters(1).upToLastOccurrenceOf (
"word",
true,
false), s5.dropLastCharacters (1));
2700 expectEquals (s5.upToLastOccurrenceOf (
"Word",
true,
true), s5.dropLastCharacters (1));
2701 expectEquals (s5.upToLastOccurrenceOf (
"word",
false,
false), s5.dropLastCharacters (5));
2702 expectEquals (s5.upToLastOccurrenceOf (
"Word",
false,
true), s5.dropLastCharacters (5));
2704 expectEquals (s5.replace (
"word",
"xyz",
false), String (
"xyz xyz2 xyz3"));
2705 expect (s5.replace (
"Word",
"xyz",
true) ==
"xyz xyz2 xyz3");
2706 expect (s5.dropLastCharacters (1).replace (
"Word", String (
"xyz"),
true) == L
"xyz xyz2 xyz");
2707 expect (s5.replace (
"Word",
"",
true) ==
" 2 3");
2708 expectEquals (s5.replace (
"Word2",
"xyz",
true), String (
"word xyz word3"));
2709 expect (s5.replaceCharacter (L
'w',
'x') != s5);
2710 expectEquals (s5.replaceCharacter (
'w', L
'x').replaceCharacter (
'x',
'w'), s5);
2711 expect (s5.replaceCharacters (
"wo",
"xy") != s5);
2712 expectEquals (s5.replaceCharacters (
"wo",
"xy").replaceCharacters (
"xy",
"wo"), s5);
2713 expectEquals (s5.retainCharacters (
"1wordxya"), String (
"wordwordword"));
2714 expect (s5.retainCharacters (String()).isEmpty());
2715 expect (s5.removeCharacters (
"1wordxya") ==
" 2 3");
2716 expectEquals (s5.removeCharacters (String()), s5);
2717 expect (s5.initialSectionContainingOnly (
"word") == L
"word");
2718 expect (String (
"word").initialSectionContainingOnly (
"word") == L
"word");
2719 expectEquals (s5.initialSectionNotContaining (String (
"xyz ")), String (
"word"));
2720 expectEquals (s5.initialSectionNotContaining (String (
";[:'/")), s5);
2721 expect (! s5.isQuotedString());
2722 expect (s5.quoted().isQuotedString());
2723 expect (! s5.quoted().unquoted().isQuotedString());
2724 expect (! String (
"x'").isQuotedString());
2725 expect (String (
"'x").isQuotedString());
2727 String s6 (
" \t xyz \t\r\n");
2728 expectEquals (s6.trim(), String (
"xyz"));
2729 expect (s6.trim().trim() ==
"xyz");
2730 expectEquals (s5.trim(), s5);
2731 expectEquals (s6.trimStart().trimEnd(), s6.trim());
2732 expectEquals (s6.trimStart().trimEnd(), s6.trimEnd().trimStart());
2733 expectEquals (s6.trimStart().trimStart().trimEnd().trimEnd(), s6.trimEnd().trimStart());
2734 expect (s6.trimStart() != s6.trimEnd());
2735 expectEquals ((
"\t\r\n " + s6 +
"\t\n \r").trim(), s6.trim());
2736 expect (String::repeatedString (
"xyz", 3) == L
"xyzxyzxyz");
2740 beginTest (
"UTF conversions");
2742 TestUTFConversion <CharPointer_UTF32>::test (*
this, r);
2743 TestUTFConversion <CharPointer_UTF8>::test (*
this, r);
2744 TestUTFConversion <CharPointer_UTF16>::test (*
this, r);
2748 beginTest (
"StringArray");
2751 s.addTokens (
"4,3,2,1,0",
";,",
"x");
2752 expectEquals (s.size(), 5);
2754 expectEquals (s.joinIntoString (
"-"), String (
"4-3-2-1-0"));
2756 expectEquals (s.joinIntoString (
"--"), String (
"4--3--1--0"));
2757 expectEquals (s.joinIntoString (StringRef()), String (
"4310"));
2759 expectEquals (s.joinIntoString (
"x"), String());
2762 toks.addTokens (
"x,,",
";,",
"");
2763 expectEquals (toks.size(), 3);
2764 expectEquals (toks.joinIntoString (
"-"), String (
"x--"));
2767 toks.addTokens (
",x,",
";,",
"");
2768 expectEquals (toks.size(), 3);
2769 expectEquals (toks.joinIntoString (
"-"), String (
"-x-"));
2772 toks.addTokens (
"x,'y,z',",
";,",
"'");
2773 expectEquals (toks.size(), 3);
2774 expectEquals (toks.joinIntoString (
"-"), String (
"x-'y,z'-"));
2785 expect (! v2.equals (v1));
2786 expect (! v1.equals (v2));
2787 expect (v2.equals (v3));
2788 expect (! v3.equals (v1));
2789 expect (! v1.equals (v3));
2790 expect (v1.equals (v4));
2791 expect (v4.equals (v1));
2792 expect (v5.equals (v4));
2793 expect (v4.equals (v5));
2794 expect (! v2.equals (v4));
2795 expect (! v4.equals (v2));
2799 beginTest (
"Significant figures");
2803 expectEquals (String::toDecimalStringWithSignificantFigures (13, 1), String (
"10"));
2804 expectEquals (String::toDecimalStringWithSignificantFigures (13, 2), String (
"13"));
2805 expectEquals (String::toDecimalStringWithSignificantFigures (13, 3), String (
"13.0"));
2806 expectEquals (String::toDecimalStringWithSignificantFigures (13, 4), String (
"13.00"));
2808 expectEquals (String::toDecimalStringWithSignificantFigures (19368, 1), String (
"20000"));
2809 expectEquals (String::toDecimalStringWithSignificantFigures (19348, 3), String (
"19300"));
2811 expectEquals (String::toDecimalStringWithSignificantFigures (-5, 1), String (
"-5"));
2812 expectEquals (String::toDecimalStringWithSignificantFigures (-5, 3), String (
"-5.00"));
2816 expectEquals (String::toDecimalStringWithSignificantFigures (0, 1), String (
"0"));
2817 expectEquals (String::toDecimalStringWithSignificantFigures (0, 2), String (
"0.0"));
2818 expectEquals (String::toDecimalStringWithSignificantFigures (0, 3), String (
"0.00"));
2822 expectEquals (String::toDecimalStringWithSignificantFigures (19.0, 1), String (
"20"));
2823 expectEquals (String::toDecimalStringWithSignificantFigures (19.0, 2), String (
"19"));
2824 expectEquals (String::toDecimalStringWithSignificantFigures (19.0, 3), String (
"19.0"));
2825 expectEquals (String::toDecimalStringWithSignificantFigures (19.0, 4), String (
"19.00"));
2827 expectEquals (String::toDecimalStringWithSignificantFigures (-5.45, 1), String (
"-5"));
2828 expectEquals (String::toDecimalStringWithSignificantFigures (-5.45, 3), String (
"-5.45"));
2830 expectEquals (String::toDecimalStringWithSignificantFigures (12345.6789, 9), String (
"12345.6789"));
2831 expectEquals (String::toDecimalStringWithSignificantFigures (12345.6789, 8), String (
"12345.679"));
2832 expectEquals (String::toDecimalStringWithSignificantFigures (12345.6789, 5), String (
"12346"));
2834 expectEquals (String::toDecimalStringWithSignificantFigures (0.00028647, 6), String (
"0.000286470"));
2835 expectEquals (String::toDecimalStringWithSignificantFigures (0.0028647, 6), String (
"0.00286470"));
2836 expectEquals (String::toDecimalStringWithSignificantFigures (2.8647, 6), String (
"2.86470"));
2838 expectEquals (String::toDecimalStringWithSignificantFigures (-0.0000000000019, 1), String (
"-0.000000000002"));
2842 beginTest (
"Float trimming");
2845 StringPairArray tests;
2846 tests.set (
"1",
"1");
2847 tests.set (
"1.0",
"1.0");
2848 tests.set (
"-1",
"-1");
2849 tests.set (
"-100",
"-100");
2850 tests.set (
"110",
"110");
2851 tests.set (
"9090",
"9090");
2852 tests.set (
"1000.0",
"1000.0");
2853 tests.set (
"1.0",
"1.0");
2854 tests.set (
"-1.00",
"-1.0");
2855 tests.set (
"1.20",
"1.2");
2856 tests.set (
"1.300",
"1.3");
2857 tests.set (
"1.301",
"1.301");
2858 tests.set (
"1e",
"1");
2859 tests.set (
"-1e+",
"-1");
2860 tests.set (
"1e-",
"1");
2861 tests.set (
"1e0",
"1");
2862 tests.set (
"1e+0",
"1");
2863 tests.set (
"1e-0",
"1");
2864 tests.set (
"1e000",
"1");
2865 tests.set (
"1e+000",
"1");
2866 tests.set (
"-1e-000",
"-1");
2867 tests.set (
"1e100",
"1e100");
2868 tests.set (
"100e100",
"100e100");
2869 tests.set (
"100.0e0100",
"100.0e100");
2870 tests.set (
"-1e1",
"-1e1");
2871 tests.set (
"1e10",
"1e10");
2872 tests.set (
"-1e+10",
"-1e10");
2873 tests.set (
"1e-10",
"1e-10");
2874 tests.set (
"1e0010",
"1e10");
2875 tests.set (
"1e-0010",
"1e-10");
2876 tests.set (
"1e-1",
"1e-1");
2877 tests.set (
"-1.0e1",
"-1.0e1");
2878 tests.set (
"1.0e-1",
"1.0e-1");
2879 tests.set (
"1.00e-1",
"1.0e-1");
2880 tests.set (
"1.001e1",
"1.001e1");
2881 tests.set (
"1.010e+1",
"1.01e1");
2882 tests.set (
"-1.1000e1",
"-1.1e1");
2884 for (
auto& input : tests.getAllKeys())
2885 expectEquals (reduceLengthOfFloatString (input), tests[input]);
2889 std::map<double, String> tests;
2892 tests[1.01] =
"1.01";
2893 tests[0.76378] =
"7.6378e-1";
2894 tests[-10] =
"-1.0e1";
2895 tests[10.01] =
"1.001e1";
2896 tests[10691.01] =
"1.069101e4";
2897 tests[0.0123] =
"1.23e-2";
2898 tests[-3.7e-27] =
"-3.7e-27";
2899 tests[1e+40] =
"1.0e40";
2901 for (
auto& test : tests)
2902 expectEquals (reduceLengthOfFloatString (String (test.first, 15, true)), test.second);
2907 beginTest (
"Serialisation");
2909 std::map <double, String> tests;
2911 tests[364] =
"364.0";
2912 tests[1e7] =
"1.0e7";
2913 tests[12345678901] =
"1.2345678901e10";
2915 tests[1234567890123456.7] =
"1.234567890123457e15";
2916 tests[12345678.901234567] =
"1.234567890123457e7";
2917 tests[1234567.8901234567] =
"1.234567890123457e6";
2918 tests[123456.78901234567] =
"123456.7890123457";
2919 tests[12345.678901234567] =
"12345.67890123457";
2920 tests[1234.5678901234567] =
"1234.567890123457";
2921 tests[123.45678901234567] =
"123.4567890123457";
2922 tests[12.345678901234567] =
"12.34567890123457";
2923 tests[1.2345678901234567] =
"1.234567890123457";
2924 tests[0.12345678901234567] =
"0.1234567890123457";
2925 tests[0.012345678901234567] =
"0.01234567890123457";
2926 tests[0.0012345678901234567] =
"0.001234567890123457";
2927 tests[0.00012345678901234567] =
"0.0001234567890123457";
2928 tests[0.000012345678901234567] =
"0.00001234567890123457";
2929 tests[0.0000012345678901234567] =
"1.234567890123457e-6";
2930 tests[0.00000012345678901234567] =
"1.234567890123457e-7";
2932 for (
auto& test : tests)
2934 expectEquals (serialiseDouble (test.first), test.second);
2935 expectEquals (serialiseDouble (-test.first),
"-" + test.second);
2941static StringTests stringUnitTests;
static Type swapIfLittleEndian(Type value) noexcept
static Type swapIfBigEndian(Type value) noexcept
static bool isValidString(const CharType *dataToTest, int maxBytesToRead)
static bool isByteOrderMarkBigEndian(const void *possibleByteOrder) noexcept
static bool isByteOrderMarkLittleEndian(const void *possibleByteOrder) noexcept
static size_t getBytesRequiredFor(const juce_wchar charToWrite) noexcept
static bool isByteOrderMark(const void *possibleByteOrder) noexcept
static bool isValidString(const CharType *dataToTest, int maxBytesToRead)
static int indexOfIgnoreCase(CharPointerType1 haystack, const CharPointerType2 needle) noexcept
static bool isDigit(char character) noexcept
static bool isLetterOrDigit(char character) noexcept
static juce_wchar toUpperCase(juce_wchar character) noexcept
static juce_wchar getUnicodeCharFromWindows1252Codepage(uint8 windows1252Char) noexcept
int length() const noexcept
String::CharPointerType text
CharPointerType getCharPointer() const noexcept
bool equalsIgnoreCase(const String &other) const noexcept
static String repeatedString(StringRef stringToRepeat, int numberOfTimesToRepeat)
int indexOfChar(juce_wchar characterToLookFor) const noexcept
String upToFirstOccurrenceOf(StringRef substringToEndWith, bool includeSubStringInResult, bool ignoreCase) const
int length() const noexcept
int compareNatural(StringRef other, bool isCaseSensitive=false) const noexcept
bool endsWithChar(juce_wchar character) const noexcept
String trimCharactersAtStart(StringRef charactersToTrim) const
String toUpperCase() const
CharPointer_UTF16 toUTF16() const
bool isQuotedString() const
void append(const String &textToAppend, size_t maxCharsToTake)
float getFloatValue() const noexcept
const char * toRawUTF8() const
bool containsIgnoreCase(StringRef text) const noexcept
bool startsWithChar(juce_wchar character) const noexcept
bool startsWith(StringRef text) const noexcept
int64 hashCode64() const noexcept
bool containsChar(juce_wchar character) const noexcept
String paddedLeft(juce_wchar padCharacter, int minimumLength) const
bool startsWithIgnoreCase(StringRef text) const noexcept
int compareIgnoreCase(const String &other) const noexcept
String removeCharacters(StringRef charactersToRemove) const
bool endsWithIgnoreCase(StringRef text) const noexcept
bool matchesWildcard(StringRef wildcard, bool ignoreCase) const noexcept
void appendCharPointer(CharPointerType startOfTextToAppend, CharPointerType endOfTextToAppend)
String quoted(juce_wchar quoteCharacter='"') const
String & operator+=(const String &stringToAppend)
int indexOf(StringRef textToLookFor) const noexcept
size_t getNumBytesAsUTF8() const noexcept
String initialSectionContainingOnly(StringRef permittedCharacters) const
static String createStringFromData(const void *data, int size)
int lastIndexOf(StringRef textToLookFor) const noexcept
String retainCharacters(StringRef charactersToRetain) const
int indexOfAnyOf(StringRef charactersToLookFor, int startIndex=0, bool ignoreCase=false) const noexcept
size_t copyToUTF16(CharPointer_UTF16::CharType *destBuffer, size_t maxBufferSizeBytes) const noexcept
void preallocateBytes(size_t numBytesNeeded)
int lastIndexOfAnyOf(StringRef charactersToLookFor, bool ignoreCase=false) const noexcept
size_t hash() const noexcept
String dropLastCharacters(int numberToDrop) const
juce_wchar operator[](int index) const noexcept
bool contains(StringRef text) const noexcept
String toLowerCase() const
String replaceFirstOccurrenceOf(StringRef stringToReplace, StringRef stringToInsertInstead, bool ignoreCase=false) const
double getDoubleValue() const noexcept
int getTrailingIntValue() const noexcept
static String toHexString(IntegerType number)
int indexOfWholeWord(StringRef wordToLookFor) const noexcept
int lastIndexOfChar(juce_wchar character) const noexcept
size_t copyToUTF32(CharPointer_UTF32::CharType *destBuffer, size_t maxBufferSizeBytes) const noexcept
const wchar_t * toWideCharPointer() const
size_t copyToUTF8(CharPointer_UTF8::CharType *destBuffer, size_t maxBufferSizeBytes) const noexcept
String replace(StringRef stringToReplace, StringRef stringToInsertInstead, bool ignoreCase=false) const
int lastIndexOfIgnoreCase(StringRef textToLookFor) const noexcept
String getLastCharacters(int numCharacters) const
String replaceCharacters(StringRef charactersToReplace, StringRef charactersToInsertInstead) const
String upToLastOccurrenceOf(StringRef substringToFind, bool includeSubStringInResult, bool ignoreCase) const
String trimCharactersAtEnd(StringRef charactersToTrim) const
bool containsWholeWord(StringRef wordToLookFor) const noexcept
static String charToString(juce_wchar character)
String paddedRight(juce_wchar padCharacter, int minimumLength) const
String replaceCharacter(juce_wchar characterToReplace, juce_wchar characterToInsertInstead) const
juce_wchar getLastCharacter() const noexcept
String substring(int startIndex, int endIndex) const
String fromLastOccurrenceOf(StringRef substringToFind, bool includeSubStringInResult, bool ignoreCase) const
int hashCode() const noexcept
bool containsNonWhitespaceChars() const noexcept
String replaceSection(int startIndex, int numCharactersToReplace, StringRef stringToInsert) const
String & operator=(const String &other) noexcept
String initialSectionNotContaining(StringRef charactersToStopAt) const
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)
int64 getLargeIntValue() const noexcept
int64 getHexValue64() const noexcept
bool containsAnyOf(StringRef charactersItMightContain) const noexcept
bool endsWith(StringRef text) const noexcept
int indexOfIgnoreCase(StringRef textToLookFor) const noexcept
bool containsWholeWordIgnoreCase(StringRef wordToLookFor) const noexcept
CharPointer_UTF8 toUTF8() const
int getReferenceCount() const noexcept
int indexOfWholeWordIgnoreCase(StringRef wordToLookFor) const noexcept
int compare(const String &other) const noexcept
int getIntValue() const noexcept
bool containsOnly(StringRef charactersItMightContain) const noexcept
CharPointer_UTF32 toUTF32() const
String fromFirstOccurrenceOf(StringRef substringToStartFrom, bool includeSubStringInResult, bool ignoreCase) const
void swapWith(String &other) noexcept
int getHexValue32() const noexcept
Type get() const noexcept