}
UnicodeString::UnicodeString(UnicodeString &&src) U_NOEXCEPT {
- fUnion.fFields.fLengthAndFlags = kShortString;
- moveFrom(src);
+ copyFieldsFrom(src, TRUE);
}
UnicodeString::UnicodeString(const UnicodeString& that,
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();
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) {
}
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
}
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
}
// 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);
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))) {
// 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);
}