X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/0f5d89e82340278ed3d7d50029f37cab2c41a57e..1a147d096ae81f4c8262f7bfc56bd19fc2dee932:/icuSources/common/unistr.cpp?ds=inline diff --git a/icuSources/common/unistr.cpp b/icuSources/common/unistr.cpp index 5d7cab2e..8f065158 100644 --- a/icuSources/common/unistr.cpp +++ b/icuSources/common/unistr.cpp @@ -309,8 +309,7 @@ UnicodeString::UnicodeString(const UnicodeString& that) { } UnicodeString::UnicodeString(UnicodeString &&src) U_NOEXCEPT { - fUnion.fFields.fLengthAndFlags = kShortString; - moveFrom(src); + copyFieldsFrom(src, TRUE); } UnicodeString::UnicodeString(const UnicodeString& that, @@ -572,7 +571,7 @@ UnicodeString::copyFrom(const UnicodeString &src, UBool fastCopy) { return *this; } -UnicodeString &UnicodeString::moveFrom(UnicodeString &src) U_NOEXCEPT { +UnicodeString &UnicodeString::operator=(UnicodeString &&src) U_NOEXCEPT { // No explicit check for self move assignment, consistent with standard library. // Self move assignment causes no crash nor leak but might make the object bogus. releaseArray(); @@ -580,7 +579,7 @@ UnicodeString &UnicodeString::moveFrom(UnicodeString &src) U_NOEXCEPT { return *this; } -// Same as moveFrom() except without memory management. +// Same as move assignment except without memory management. void UnicodeString::copyFieldsFrom(UnicodeString &src, UBool setSrcToBogus) U_NOEXCEPT { int16_t lengthAndFlags = fUnion.fFields.fLengthAndFlags = src.fUnion.fFields.fLengthAndFlags; if(lengthAndFlags & kUsingStackBuffer) { @@ -1447,10 +1446,15 @@ UnicodeString::doReplace(int32_t start, } if(srcChars == 0) { - srcStart = srcLength = 0; - } else if(srcLength < 0) { - // get the srcLength if necessary - srcLength = u_strlen(srcChars + srcStart); + srcLength = 0; + } else { + // Perform all remaining operations relative to srcChars + srcStart. + // From this point forward, do not use srcStart. + srcChars += srcStart; + if (srcLength < 0) { + // get the srcLength if necessary + srcLength = u_strlen(srcChars); + } } // pin the indices to legal values @@ -1465,17 +1469,28 @@ UnicodeString::doReplace(int32_t start, } newLength += srcLength; + // Check for insertion into ourself + const UChar *oldArray = getArrayStart(); + if (isBufferWritable() && + oldArray < srcChars + srcLength && + srcChars < oldArray + oldLength) { + // Copy into a new UnicodeString and start over + UnicodeString copy(srcChars, srcLength); + if (copy.isBogus()) { + setToBogus(); + return *this; + } + return doReplace(start, length, copy.getArrayStart(), 0, srcLength); + } + // cloneArrayIfNeeded(doCopyArray=FALSE) may change fArray but will not copy the current contents; // therefore we need to keep the current fArray UChar oldStackBuffer[US_STACKBUF_SIZE]; - UChar *oldArray; if((fUnion.fFields.fLengthAndFlags&kUsingStackBuffer) && (newLength > US_STACKBUF_SIZE)) { // copy the stack buffer contents because it will be overwritten with // fUnion.fFields values - u_memcpy(oldStackBuffer, fUnion.fStackFields.fBuffer, oldLength); + u_memcpy(oldStackBuffer, oldArray, oldLength); oldArray = oldStackBuffer; - } else { - oldArray = getArrayStart(); } // clone our array and allocate a bigger array if needed @@ -1503,7 +1518,7 @@ UnicodeString::doReplace(int32_t start, } // now fill in the hole with the new string - us_arrayCopy(srcChars, srcStart, newArray, start, srcLength); + us_arrayCopy(srcChars, 0, newArray, start, srcLength); setLength(newLength); @@ -1536,15 +1551,34 @@ UnicodeString::doAppend(const UChar *srcChars, int32_t srcStart, int32_t srcLeng return *this; } + // Perform all remaining operations relative to srcChars + srcStart. + // From this point forward, do not use srcStart. + srcChars += srcStart; + if(srcLength < 0) { // get the srcLength if necessary - if((srcLength = u_strlen(srcChars + srcStart)) == 0) { + if((srcLength = u_strlen(srcChars)) == 0) { return *this; } } int32_t oldLength = length(); int32_t newLength = oldLength + srcLength; + + // Check for append onto ourself + const UChar* oldArray = getArrayStart(); + if (isBufferWritable() && + oldArray < srcChars + srcLength && + srcChars < oldArray + oldLength) { + // Copy into a new UnicodeString and start over + UnicodeString copy(srcChars, srcLength); + if (copy.isBogus()) { + setToBogus(); + return *this; + } + return doAppend(copy.getArrayStart(), 0, srcLength); + } + // optimize append() onto a large-enough, owned string if((newLength <= getCapacity() && isBufferWritable()) || cloneArrayIfNeeded(newLength, getGrowCapacity(newLength))) { @@ -1556,8 +1590,8 @@ UnicodeString::doAppend(const UChar *srcChars, int32_t srcStart, int32_t srcLeng // or // str.appendString(buffer, length) // or similar. - if(srcChars + srcStart != newArray + oldLength) { - us_arrayCopy(srcChars, srcStart, newArray, oldLength, srcLength); + if(srcChars != newArray + oldLength) { + us_arrayCopy(srcChars, 0, newArray, oldLength, srcLength); } setLength(newLength); }