diff --git a/.gitignore b/.gitignore index 629e360a22..a92b770d60 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ profile **/doxygen/doc **/doxygen/build **/.idea +**/out/build extras/Projucer/JUCECompileEngine.dylib .idea diff --git a/modules/juce_core/text/juce_String.cpp b/modules/juce_core/text/juce_String.cpp index 8ac68ea1f1..5c2b3c98fa 100644 --- a/modules/juce_core/text/juce_String.cpp +++ b/modules/juce_core/text/juce_String.cpp @@ -255,6 +255,8 @@ String::~String() noexcept String::String (const String& other) noexcept : text (other.text) { StringHolderUtils::retain (text); + size_t num = getNumBytesAsUTF8(); + preallocateBytes (num); } void String::swapWith (String& other) noexcept @@ -749,19 +751,30 @@ void String::appendCharPointer (const CharPointerType startOfTextToAppend, { jassert (startOfTextToAppend.getAddress() != nullptr && endOfTextToAppend.getAddress() != nullptr); - auto extraBytesNeeded = getAddressDifference (endOfTextToAppend.getAddress(), - startOfTextToAppend.getAddress()); - jassert (extraBytesNeeded >= 0); + auto bytesNeededForNewPart = getAddressDifference (endOfTextToAppend.getAddress(), + startOfTextToAppend.getAddress()); + jassert (bytesNeededForNewPart >= 0); + if (bytesNeededForNewPart == 0) return; + + + auto allocatedNumBytes = StringHolderUtils::getAllocatedNumBytes (text); + auto usedBytes = CharPointerType::getBytesRequiredFor (text) + 1; + auto currentlyUnusedBytes = allocatedNumBytes - usedBytes; + + size_t extraBytesNeeded = 0; + if (bytesNeededForNewPart > currentlyUnusedBytes) + extraBytesNeeded = bytesNeededForNewPart - currentlyUnusedBytes; + + auto byteOffsetOfNull = getByteOffsetOfEnd(); if (extraBytesNeeded > 0) { - auto byteOffsetOfNull = getByteOffsetOfEnd(); - preallocateBytes ((size_t) extraBytesNeeded + byteOffsetOfNull); - - auto* newStringStart = addBytesToPointer (text.getAddress(), (int) byteOffsetOfNull); - memcpy (newStringStart, startOfTextToAppend.getAddress(), (size_t) extraBytesNeeded); - CharPointerType (addBytesToPointer (newStringStart, extraBytesNeeded)).writeNull(); + preallocateBytes(extraBytesNeeded + allocatedNumBytes + 1); } + + auto* newStringStart = addBytesToPointer (text.getAddress(), (int)byteOffsetOfNull); + memcpy (newStringStart, startOfTextToAppend.getAddress(), (size_t) bytesNeededForNewPart); + CharPointerType (addBytesToPointer (newStringStart, bytesNeededForNewPart)).writeNull(); } String& String::operator+= (const wchar_t* t) @@ -845,17 +858,17 @@ JUCE_API String JUCE_CALLTYPE operator+ (const wchar_t* s1, const String& s2) { JUCE_API String JUCE_CALLTYPE operator+ (char s1, const String& s2) { return String::charToString ((juce_wchar) (uint8) s1) + s2; } JUCE_API String JUCE_CALLTYPE operator+ (wchar_t s1, const String& s2) { return String::charToString (s1) + s2; } -JUCE_API String JUCE_CALLTYPE operator+ (String s1, const String& s2) { return s1 += s2; } -JUCE_API String JUCE_CALLTYPE operator+ (String s1, const char* s2) { return s1 += s2; } -JUCE_API String JUCE_CALLTYPE operator+ (String s1, const wchar_t* s2) { return s1 += s2; } -JUCE_API String JUCE_CALLTYPE operator+ (String s1, const std::string& s2) { return s1 += s2.c_str(); } +JUCE_API String JUCE_CALLTYPE operator+ (String s1, const String& s2) { String s(s1); return s += s2; } +JUCE_API String JUCE_CALLTYPE operator+ (String s1, const char* s2) { String s(s1); return s += s2; } +JUCE_API String JUCE_CALLTYPE operator+ (String s1, const wchar_t* s2) { String s(s1); return s += s2; } +JUCE_API String JUCE_CALLTYPE operator+ (String s1, const std::string& s2) { String s(s1); return s += s2.c_str(); } -JUCE_API String JUCE_CALLTYPE operator+ (String s1, char s2) { return s1 += s2; } -JUCE_API String JUCE_CALLTYPE operator+ (String s1, wchar_t s2) { return s1 += s2; } +JUCE_API String JUCE_CALLTYPE operator+ (String s1, char s2) { String s(s1); return s += s2; } +JUCE_API String JUCE_CALLTYPE operator+ (String s1, wchar_t s2) { String s(s1); return s += s2; } #if ! JUCE_NATIVE_WCHAR_IS_UTF32 JUCE_API String JUCE_CALLTYPE operator+ (juce_wchar s1, const String& s2) { return String::charToString (s1) + s2; } -JUCE_API String JUCE_CALLTYPE operator+ (String s1, juce_wchar s2) { return s1 += s2; } +JUCE_API String JUCE_CALLTYPE operator+ (String s1, juce_wchar s2) { String s(s1); return s += s2; } JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, juce_wchar s2) { return s1 += s2; } #endif @@ -2509,6 +2522,11 @@ public: s2 << StringRef ("def"); expect (s2 == "1234567890xyz123123def"); + String sPrealloc ("a"); + sPrealloc.preallocateBytes (10); + sPrealloc += "bcd"; + expect (sPrealloc == "abcd"); + // int16 { String numStr (std::numeric_limits::max());