diff options
Diffstat (limited to 'deps/icu-small/source/common/unistr.cpp')
-rw-r--r-- | deps/icu-small/source/common/unistr.cpp | 59 |
1 files changed, 47 insertions, 12 deletions
diff --git a/deps/icu-small/source/common/unistr.cpp b/deps/icu-small/source/common/unistr.cpp index 48ad929e85a..ff85734d615 100644 --- a/deps/icu-small/source/common/unistr.cpp +++ b/deps/icu-small/source/common/unistr.cpp @@ -1447,10 +1447,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 +1470,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 +1519,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 +1552,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 +1591,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); } |