Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(326)

Side by Side Diff: source/common/unistr.cpp

Issue 1621843002: ICU 56 update step 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@561
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « source/common/uniset.cpp ('k') | source/common/unistr_case.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 ****************************************************************************** 2 ******************************************************************************
3 * Copyright (C) 1999-2014, International Business Machines Corporation and 3 * Copyright (C) 1999-2015, International Business Machines Corporation and
4 * others. All Rights Reserved. 4 * others. All Rights Reserved.
5 ****************************************************************************** 5 ******************************************************************************
6 * 6 *
7 * File unistr.cpp 7 * File unistr.cpp
8 * 8 *
9 * Modification History: 9 * Modification History:
10 * 10 *
11 * Date Name Description 11 * Date Name Description
12 * 09/25/98 stephen Creation. 12 * 09/25/98 stephen Creation.
13 * 04/20/99 stephen Overhauled per 4/16 code review. 13 * 04/20/99 stephen Overhauled per 4/16 code review.
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 return umtx_atomic_dec((u_atomic_int32_t *)fUnion.fFields.fArray - 1); 126 return umtx_atomic_dec((u_atomic_int32_t *)fUnion.fFields.fArray - 1);
127 } 127 }
128 128
129 int32_t 129 int32_t
130 UnicodeString::refCount() const { 130 UnicodeString::refCount() const {
131 return umtx_loadAcquire(*((u_atomic_int32_t *)fUnion.fFields.fArray - 1)); 131 return umtx_loadAcquire(*((u_atomic_int32_t *)fUnion.fFields.fArray - 1));
132 } 132 }
133 133
134 void 134 void
135 UnicodeString::releaseArray() { 135 UnicodeString::releaseArray() {
136 if((fFlags & kRefCounted) && removeRef() == 0) { 136 if((fUnion.fFields.fLengthAndFlags & kRefCounted) && removeRef() == 0) {
137 uprv_free((int32_t *)fUnion.fFields.fArray - 1); 137 uprv_free((int32_t *)fUnion.fFields.fArray - 1);
138 } 138 }
139 } 139 }
140 140
141 141
142 142
143 //======================================== 143 //========================================
144 // Constructors 144 // Constructors
145 //======================================== 145 //========================================
146 146
147 // The default constructor is inline in unistr.h. 147 // The default constructor is inline in unistr.h.
148 148
149 UnicodeString::UnicodeString(int32_t capacity, UChar32 c, int32_t count) 149 UnicodeString::UnicodeString(int32_t capacity, UChar32 c, int32_t count) {
150 : fShortLength(0), 150 fUnion.fFields.fLengthAndFlags = 0;
151 fFlags(0)
152 {
153 if(count <= 0 || (uint32_t)c > 0x10ffff) { 151 if(count <= 0 || (uint32_t)c > 0x10ffff) {
154 // just allocate and do not do anything else 152 // just allocate and do not do anything else
155 allocate(capacity); 153 allocate(capacity);
156 } else { 154 } else {
157 // count > 0, allocate and fill the new string with count c's 155 // count > 0, allocate and fill the new string with count c's
158 int32_t unitCount = U16_LENGTH(c), length = count * unitCount; 156 int32_t unitCount = U16_LENGTH(c), length = count * unitCount;
159 if(capacity < length) { 157 if(capacity < length) {
160 capacity = length; 158 capacity = length;
161 } 159 }
162 if(allocate(capacity)) { 160 if(allocate(capacity)) {
(...skipping 21 matching lines...) Expand all
184 while(unitIdx < unitCount) { 182 while(unitIdx < unitCount) {
185 array[i++]=units[unitIdx++]; 183 array[i++]=units[unitIdx++];
186 } 184 }
187 } 185 }
188 } 186 }
189 } 187 }
190 setLength(length); 188 setLength(length);
191 } 189 }
192 } 190 }
193 191
194 UnicodeString::UnicodeString(UChar ch) 192 UnicodeString::UnicodeString(UChar ch) {
195 : fShortLength(1), 193 fUnion.fFields.fLengthAndFlags = kLength1 | kShortString;
196 fFlags(kShortString) 194 fUnion.fStackFields.fBuffer[0] = ch;
197 {
198 fUnion.fStackBuffer[0] = ch;
199 } 195 }
200 196
201 UnicodeString::UnicodeString(UChar32 ch) 197 UnicodeString::UnicodeString(UChar32 ch) {
202 : fShortLength(0), 198 fUnion.fFields.fLengthAndFlags = kShortString;
203 fFlags(kShortString)
204 {
205 int32_t i = 0; 199 int32_t i = 0;
206 UBool isError = FALSE; 200 UBool isError = FALSE;
207 U16_APPEND(fUnion.fStackBuffer, i, US_STACKBUF_SIZE, ch, isError); 201 U16_APPEND(fUnion.fStackFields.fBuffer, i, US_STACKBUF_SIZE, ch, isError);
208 // We test isError so that the compiler does not complain that we don't. 202 // We test isError so that the compiler does not complain that we don't.
209 // If isError then i==0 which is what we want anyway. 203 // If isError then i==0 which is what we want anyway.
210 if(!isError) { 204 if(!isError) {
211 fShortLength = (int8_t)i; 205 setShortLength(i);
212 } 206 }
213 } 207 }
214 208
215 UnicodeString::UnicodeString(const UChar *text) 209 UnicodeString::UnicodeString(const UChar *text) {
216 : fShortLength(0), 210 fUnion.fFields.fLengthAndFlags = kShortString;
217 fFlags(kShortString) 211 doAppend(text, 0, -1);
218 {
219 doReplace(0, 0, text, 0, -1);
220 } 212 }
221 213
222 UnicodeString::UnicodeString(const UChar *text, 214 UnicodeString::UnicodeString(const UChar *text,
223 int32_t textLength) 215 int32_t textLength) {
224 : fShortLength(0), 216 fUnion.fFields.fLengthAndFlags = kShortString;
225 fFlags(kShortString) 217 doAppend(text, 0, textLength);
226 {
227 doReplace(0, 0, text, 0, textLength);
228 } 218 }
229 219
230 UnicodeString::UnicodeString(UBool isTerminated, 220 UnicodeString::UnicodeString(UBool isTerminated,
231 const UChar *text, 221 const UChar *text,
232 int32_t textLength) 222 int32_t textLength) {
233 : fShortLength(0), 223 fUnion.fFields.fLengthAndFlags = kReadonlyAlias;
234 fFlags(kReadonlyAlias)
235 {
236 if(text == NULL) { 224 if(text == NULL) {
237 // treat as an empty string, do not alias 225 // treat as an empty string, do not alias
238 setToEmpty(); 226 setToEmpty();
239 } else if(textLength < -1 || 227 } else if(textLength < -1 ||
240 (textLength == -1 && !isTerminated) || 228 (textLength == -1 && !isTerminated) ||
241 (textLength >= 0 && isTerminated && text[textLength] != 0) 229 (textLength >= 0 && isTerminated && text[textLength] != 0)
242 ) { 230 ) {
243 setToBogus(); 231 setToBogus();
244 } else { 232 } else {
245 if(textLength == -1) { 233 if(textLength == -1) {
246 // text is terminated, or else it would have failed the above test 234 // text is terminated, or else it would have failed the above test
247 textLength = u_strlen(text); 235 textLength = u_strlen(text);
248 } 236 }
249 setArray((UChar *)text, textLength, isTerminated ? textLength + 1 : textLeng th); 237 setArray((UChar *)text, textLength, isTerminated ? textLength + 1 : textLeng th);
250 } 238 }
251 } 239 }
252 240
253 UnicodeString::UnicodeString(UChar *buff, 241 UnicodeString::UnicodeString(UChar *buff,
254 int32_t buffLength, 242 int32_t buffLength,
255 int32_t buffCapacity) 243 int32_t buffCapacity) {
256 : fShortLength(0), 244 fUnion.fFields.fLengthAndFlags = kWritableAlias;
257 fFlags(kWritableAlias)
258 {
259 if(buff == NULL) { 245 if(buff == NULL) {
260 // treat as an empty string, do not alias 246 // treat as an empty string, do not alias
261 setToEmpty(); 247 setToEmpty();
262 } else if(buffLength < -1 || buffCapacity < 0 || buffLength > buffCapacity) { 248 } else if(buffLength < -1 || buffCapacity < 0 || buffLength > buffCapacity) {
263 setToBogus(); 249 setToBogus();
264 } else { 250 } else {
265 if(buffLength == -1) { 251 if(buffLength == -1) {
266 // fLength = u_strlen(buff); but do not look beyond buffCapacity 252 // fLength = u_strlen(buff); but do not look beyond buffCapacity
267 const UChar *p = buff, *limit = buff + buffCapacity; 253 const UChar *p = buff, *limit = buff + buffCapacity;
268 while(p != limit && *p != 0) { 254 while(p != limit && *p != 0) {
269 ++p; 255 ++p;
270 } 256 }
271 buffLength = (int32_t)(p - buff); 257 buffLength = (int32_t)(p - buff);
272 } 258 }
273 setArray(buff, buffLength, buffCapacity); 259 setArray(buff, buffLength, buffCapacity);
274 } 260 }
275 } 261 }
276 262
277 UnicodeString::UnicodeString(const char *src, int32_t length, EInvariant) 263 UnicodeString::UnicodeString(const char *src, int32_t length, EInvariant) {
278 : fShortLength(0), 264 fUnion.fFields.fLengthAndFlags = kShortString;
279 fFlags(kShortString)
280 {
281 if(src==NULL) { 265 if(src==NULL) {
282 // treat as an empty string 266 // treat as an empty string
283 } else { 267 } else {
284 if(length<0) { 268 if(length<0) {
285 length=(int32_t)uprv_strlen(src); 269 length=(int32_t)uprv_strlen(src);
286 } 270 }
287 if(cloneArrayIfNeeded(length, length, FALSE)) { 271 if(cloneArrayIfNeeded(length, length, FALSE)) {
288 u_charsToUChars(src, getArrayStart(), length); 272 u_charsToUChars(src, getArrayStart(), length);
289 setLength(length); 273 setLength(length);
290 } else { 274 } else {
291 setToBogus(); 275 setToBogus();
292 } 276 }
293 } 277 }
294 } 278 }
295 279
296 #if U_CHARSET_IS_UTF8 280 #if U_CHARSET_IS_UTF8
297 281
298 UnicodeString::UnicodeString(const char *codepageData) 282 UnicodeString::UnicodeString(const char *codepageData) {
299 : fShortLength(0), 283 fUnion.fFields.fLengthAndFlags = kShortString;
300 fFlags(kShortString) {
301 if(codepageData != 0) { 284 if(codepageData != 0) {
302 setToUTF8(codepageData); 285 setToUTF8(codepageData);
303 } 286 }
304 } 287 }
305 288
306 UnicodeString::UnicodeString(const char *codepageData, int32_t dataLength) 289 UnicodeString::UnicodeString(const char *codepageData, int32_t dataLength) {
307 : fShortLength(0), 290 fUnion.fFields.fLengthAndFlags = kShortString;
308 fFlags(kShortString) {
309 // if there's nothing to convert, do nothing 291 // if there's nothing to convert, do nothing
310 if(codepageData == 0 || dataLength == 0 || dataLength < -1) { 292 if(codepageData == 0 || dataLength == 0 || dataLength < -1) {
311 return; 293 return;
312 } 294 }
313 if(dataLength == -1) { 295 if(dataLength == -1) {
314 dataLength = (int32_t)uprv_strlen(codepageData); 296 dataLength = (int32_t)uprv_strlen(codepageData);
315 } 297 }
316 setToUTF8(StringPiece(codepageData, dataLength)); 298 setToUTF8(StringPiece(codepageData, dataLength));
317 } 299 }
318 300
319 // else see unistr_cnv.cpp 301 // else see unistr_cnv.cpp
320 #endif 302 #endif
321 303
322 UnicodeString::UnicodeString(const UnicodeString& that) 304 UnicodeString::UnicodeString(const UnicodeString& that) {
323 : Replaceable(), 305 fUnion.fFields.fLengthAndFlags = kShortString;
324 fShortLength(0),
325 fFlags(kShortString)
326 {
327 copyFrom(that); 306 copyFrom(that);
328 } 307 }
329 308
309 #if U_HAVE_RVALUE_REFERENCES
310 UnicodeString::UnicodeString(UnicodeString &&src) U_NOEXCEPT {
311 fUnion.fFields.fLengthAndFlags = kShortString;
312 moveFrom(src);
313 }
314 #endif
315
330 UnicodeString::UnicodeString(const UnicodeString& that, 316 UnicodeString::UnicodeString(const UnicodeString& that,
331 int32_t srcStart) 317 int32_t srcStart) {
332 : Replaceable(), 318 fUnion.fFields.fLengthAndFlags = kShortString;
333 fShortLength(0),
334 fFlags(kShortString)
335 {
336 setTo(that, srcStart); 319 setTo(that, srcStart);
337 } 320 }
338 321
339 UnicodeString::UnicodeString(const UnicodeString& that, 322 UnicodeString::UnicodeString(const UnicodeString& that,
340 int32_t srcStart, 323 int32_t srcStart,
341 int32_t srcLength) 324 int32_t srcLength) {
342 : Replaceable(), 325 fUnion.fFields.fLengthAndFlags = kShortString;
343 fShortLength(0),
344 fFlags(kShortString)
345 {
346 setTo(that, srcStart, srcLength); 326 setTo(that, srcStart, srcLength);
347 } 327 }
348 328
349 // Replaceable base class clone() default implementation, does not clone 329 // Replaceable base class clone() default implementation, does not clone
350 Replaceable * 330 Replaceable *
351 Replaceable::clone() const { 331 Replaceable::clone() const {
352 return NULL; 332 return NULL;
353 } 333 }
354 334
355 // UnicodeString overrides clone() with a real implementation 335 // UnicodeString overrides clone() with a real implementation
356 Replaceable * 336 Replaceable *
357 UnicodeString::clone() const { 337 UnicodeString::clone() const {
358 return new UnicodeString(*this); 338 return new UnicodeString(*this);
359 } 339 }
360 340
361 //======================================== 341 //========================================
362 // array allocation 342 // array allocation
363 //======================================== 343 //========================================
364 344
365 UBool 345 UBool
366 UnicodeString::allocate(int32_t capacity) { 346 UnicodeString::allocate(int32_t capacity) {
367 if(capacity <= US_STACKBUF_SIZE) { 347 if(capacity <= US_STACKBUF_SIZE) {
368 fFlags = kShortString; 348 fUnion.fFields.fLengthAndFlags = kShortString;
369 } else { 349 } else {
370 // count bytes for the refCounter and the string capacity, and 350 // count bytes for the refCounter and the string capacity, and
371 // round up to a multiple of 16; then divide by 4 and allocate int32_t's 351 // round up to a multiple of 16; then divide by 4 and allocate int32_t's
372 // to be safely aligned for the refCount 352 // to be safely aligned for the refCount
373 // the +1 is for the NUL terminator, to avoid reallocation in getTerminatedB uffer() 353 // the +1 is for the NUL terminator, to avoid reallocation in getTerminatedB uffer()
374 int32_t words = (int32_t)(((sizeof(int32_t) + (capacity + 1) * U_SIZEOF_UCHA R + 15) & ~15) >> 2); 354 int32_t words = (int32_t)(((sizeof(int32_t) + (capacity + 1) * U_SIZEOF_UCHA R + 15) & ~15) >> 2);
375 int32_t *array = (int32_t*) uprv_malloc( sizeof(int32_t) * words ); 355 int32_t *array = (int32_t*) uprv_malloc( sizeof(int32_t) * words );
376 if(array != 0) { 356 if(array != 0) {
377 // set initial refCount and point behind the refCount 357 // set initial refCount and point behind the refCount
378 *array++ = 1; 358 *array++ = 1;
379 359
380 // have fArray point to the first UChar 360 // have fArray point to the first UChar
381 fUnion.fFields.fArray = (UChar *)array; 361 fUnion.fFields.fArray = (UChar *)array;
382 fUnion.fFields.fCapacity = (int32_t)((words - 1) * (sizeof(int32_t) / U_SI ZEOF_UCHAR)); 362 fUnion.fFields.fCapacity = (int32_t)((words - 1) * (sizeof(int32_t) / U_SI ZEOF_UCHAR));
383 fFlags = kLongString; 363 fUnion.fFields.fLengthAndFlags = kLongString;
384 } else { 364 } else {
385 fShortLength = 0; 365 fUnion.fFields.fLengthAndFlags = kIsBogus;
386 fUnion.fFields.fArray = 0; 366 fUnion.fFields.fArray = 0;
387 fUnion.fFields.fCapacity = 0; 367 fUnion.fFields.fCapacity = 0;
388 fFlags = kIsBogus;
389 return FALSE; 368 return FALSE;
390 } 369 }
391 } 370 }
392 return TRUE; 371 return TRUE;
393 } 372 }
394 373
395 //======================================== 374 //========================================
396 // Destructor 375 // Destructor
397 //======================================== 376 //========================================
377
378 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
379 static u_atomic_int32_t finalLengthCounts[0x400]; // UnicodeString::kMaxShortLe ngth+1
380 static u_atomic_int32_t beyondCount(0);
381
382 U_CAPI void unistr_printLengths() {
383 int32_t i;
384 for(i = 0; i <= 59; ++i) {
385 printf("%2d, %9d\n", i, (int32_t)finalLengthCounts[i]);
386 }
387 int32_t beyond = beyondCount;
388 for(; i < UPRV_LENGTHOF(finalLengthCounts); ++i) {
389 beyond += finalLengthCounts[i];
390 }
391 printf(">59, %9d\n", beyond);
392 }
393 #endif
394
398 UnicodeString::~UnicodeString() 395 UnicodeString::~UnicodeString()
399 { 396 {
397 #ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
398 // Count lengths of strings at the end of their lifetime.
399 // Useful for discussion of a desirable stack buffer size.
400 // Count the contents length, not the optional NUL terminator nor further capa city.
401 // Ignore open-buffer strings and strings which alias external storage.
402 if((fUnion.fFields.fLengthAndFlags&(kOpenGetBuffer|kReadonlyAlias|kWritableAli as)) == 0) {
403 if(hasShortLength()) {
404 umtx_atomic_inc(finalLengthCounts + getShortLength());
405 } else {
406 umtx_atomic_inc(&beyondCount);
407 }
408 }
409 #endif
410
400 releaseArray(); 411 releaseArray();
401 } 412 }
402 413
403 //======================================== 414 //========================================
404 // Factory methods 415 // Factory methods
405 //======================================== 416 //========================================
406 417
407 UnicodeString UnicodeString::fromUTF8(const StringPiece &utf8) { 418 UnicodeString UnicodeString::fromUTF8(const StringPiece &utf8) {
408 UnicodeString result; 419 UnicodeString result;
409 result.setToUTF8(utf8); 420 result.setToUTF8(utf8);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 482
472 // delete the current contents 483 // delete the current contents
473 releaseArray(); 484 releaseArray();
474 485
475 if(src.isEmpty()) { 486 if(src.isEmpty()) {
476 // empty string - use the stack buffer 487 // empty string - use the stack buffer
477 setToEmpty(); 488 setToEmpty();
478 return *this; 489 return *this;
479 } 490 }
480 491
481 // we always copy the length
482 int32_t srcLength = src.length();
483 setLength(srcLength);
484
485 // fLength>0 and not an "open" src.getBuffer(minCapacity) 492 // fLength>0 and not an "open" src.getBuffer(minCapacity)
486 switch(src.fFlags) { 493 fUnion.fFields.fLengthAndFlags = src.fUnion.fFields.fLengthAndFlags;
494 switch(src.fUnion.fFields.fLengthAndFlags & kAllStorageFlags) {
487 case kShortString: 495 case kShortString:
488 // short string using the stack buffer, do the same 496 // short string using the stack buffer, do the same
489 fFlags = kShortString; 497 uprv_memcpy(fUnion.fStackFields.fBuffer, src.fUnion.fStackFields.fBuffer,
490 uprv_memcpy(fUnion.fStackBuffer, src.fUnion.fStackBuffer, srcLength * U_SIZE OF_UCHAR); 498 getShortLength() * U_SIZEOF_UCHAR);
491 break; 499 break;
492 case kLongString: 500 case kLongString:
493 // src uses a refCounted string buffer, use that buffer with refCount 501 // src uses a refCounted string buffer, use that buffer with refCount
494 // src is const, use a cast - we don't really change it 502 // src is const, use a cast - we don't actually change it
495 ((UnicodeString &)src).addRef(); 503 ((UnicodeString &)src).addRef();
496 // copy all fields, share the reference-counted buffer 504 // copy all fields, share the reference-counted buffer
497 fUnion.fFields.fArray = src.fUnion.fFields.fArray; 505 fUnion.fFields.fArray = src.fUnion.fFields.fArray;
498 fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity; 506 fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
499 fFlags = src.fFlags; 507 if(!hasShortLength()) {
508 fUnion.fFields.fLength = src.fUnion.fFields.fLength;
509 }
500 break; 510 break;
501 case kReadonlyAlias: 511 case kReadonlyAlias:
502 if(fastCopy) { 512 if(fastCopy) {
503 // src is a readonly alias, do the same 513 // src is a readonly alias, do the same
504 // -> maintain the readonly alias as such 514 // -> maintain the readonly alias as such
505 fUnion.fFields.fArray = src.fUnion.fFields.fArray; 515 fUnion.fFields.fArray = src.fUnion.fFields.fArray;
506 fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity; 516 fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
507 fFlags = src.fFlags; 517 if(!hasShortLength()) {
518 fUnion.fFields.fLength = src.fUnion.fFields.fLength;
519 }
508 break; 520 break;
509 } 521 }
510 // else if(!fastCopy) fall through to case kWritableAlias 522 // else if(!fastCopy) fall through to case kWritableAlias
511 // -> allocate a new buffer and copy the contents 523 // -> allocate a new buffer and copy the contents
512 case kWritableAlias: 524 case kWritableAlias: {
513 // src is a writable alias; we make a copy of that instead 525 // src is a writable alias; we make a copy of that instead
526 int32_t srcLength = src.length();
514 if(allocate(srcLength)) { 527 if(allocate(srcLength)) {
515 uprv_memcpy(getArrayStart(), src.getArrayStart(), srcLength * U_SIZEOF_UCH AR); 528 uprv_memcpy(getArrayStart(), src.getArrayStart(), srcLength * U_SIZEOF_UCH AR);
529 setLength(srcLength);
516 break; 530 break;
517 } 531 }
518 // if there is not enough memory, then fall through to setting to bogus 532 // if there is not enough memory, then fall through to setting to bogus
533 }
519 default: 534 default:
520 // if src is bogus, set ourselves to bogus 535 // if src is bogus, set ourselves to bogus
521 // do not call setToBogus() here because fArray and fFlags are not consisten t here 536 // do not call setToBogus() here because fArray and flags are not consistent here
522 fShortLength = 0; 537 fUnion.fFields.fLengthAndFlags = kIsBogus;
523 fUnion.fFields.fArray = 0; 538 fUnion.fFields.fArray = 0;
524 fUnion.fFields.fCapacity = 0; 539 fUnion.fFields.fCapacity = 0;
525 fFlags = kIsBogus;
526 break; 540 break;
527 } 541 }
528 542
529 return *this; 543 return *this;
530 } 544 }
531 545
546 UnicodeString &UnicodeString::moveFrom(UnicodeString &src) U_NOEXCEPT {
547 // No explicit check for self move assignment, consistent with standard librar y.
548 // Self move assignment causes no crash nor leak but might make the object bog us.
549 releaseArray();
550 copyFieldsFrom(src, TRUE);
551 return *this;
552 }
553
554 // Same as moveFrom() except without memory management.
555 void UnicodeString::copyFieldsFrom(UnicodeString &src, UBool setSrcToBogus) U_NO EXCEPT {
556 int16_t lengthAndFlags = fUnion.fFields.fLengthAndFlags = src.fUnion.fFields.f LengthAndFlags;
557 if(lengthAndFlags & kUsingStackBuffer) {
558 // Short string using the stack buffer, copy the contents.
559 // Check for self assignment to prevent "overlap in memcpy" warnings,
560 // although it should be harmless to copy a buffer to itself exactly.
561 if(this != &src) {
562 uprv_memcpy(fUnion.fStackFields.fBuffer, src.fUnion.fStackFields.fBuffer,
563 getShortLength() * U_SIZEOF_UCHAR);
564 }
565 } else {
566 // In all other cases, copy all fields.
567 fUnion.fFields.fArray = src.fUnion.fFields.fArray;
568 fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
569 if(!hasShortLength()) {
570 fUnion.fFields.fLength = src.fUnion.fFields.fLength;
571 }
572 if(setSrcToBogus) {
573 // Set src to bogus without releasing any memory.
574 src.fUnion.fFields.fLengthAndFlags = kIsBogus;
575 src.fUnion.fFields.fArray = NULL;
576 src.fUnion.fFields.fCapacity = 0;
577 }
578 }
579 }
580
581 void UnicodeString::swap(UnicodeString &other) U_NOEXCEPT {
582 UnicodeString temp; // Empty short string: Known not to need releaseArray().
583 // Copy fields without resetting source values in between.
584 temp.copyFieldsFrom(*this, FALSE);
585 this->copyFieldsFrom(other, FALSE);
586 other.copyFieldsFrom(temp, FALSE);
587 // Set temp to an empty string so that other's memory is not released twice.
588 temp.fUnion.fFields.fLengthAndFlags = kShortString;
589 }
590
532 //======================================== 591 //========================================
533 // Miscellaneous operations 592 // Miscellaneous operations
534 //======================================== 593 //========================================
535 594
536 UnicodeString UnicodeString::unescape() const { 595 UnicodeString UnicodeString::unescape() const {
537 UnicodeString result(length(), (UChar32)0, (int32_t)0); // construct with ca pacity 596 UnicodeString result(length(), (UChar32)0, (int32_t)0); // construct with ca pacity
597 if (result.isBogus()) {
598 return result;
599 }
538 const UChar *array = getBuffer(); 600 const UChar *array = getBuffer();
539 int32_t len = length(); 601 int32_t len = length();
540 int32_t prev = 0; 602 int32_t prev = 0;
541 for (int32_t i=0;;) { 603 for (int32_t i=0;;) {
542 if (i == len) { 604 if (i == len) {
543 result.append(array, prev, len - prev); 605 result.append(array, prev, len - prev);
544 break; 606 break;
545 } 607 }
546 if (array[i++] == 0x5C /*'\\'*/) { 608 if (array[i++] == 0x5C /*'\\'*/) {
547 result.append(array, prev, (i - 1) - prev); 609 result.append(array, prev, (i - 1) - prev);
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 } 882 }
821 UErrorCode status = U_ZERO_ERROR; 883 UErrorCode status = U_ZERO_ERROR;
822 return u_terminateChars(target, targetCapacity, length, &status); 884 return u_terminateChars(target, targetCapacity, length, &status);
823 } 885 }
824 886
825 UnicodeString 887 UnicodeString
826 UnicodeString::tempSubString(int32_t start, int32_t len) const { 888 UnicodeString::tempSubString(int32_t start, int32_t len) const {
827 pinIndices(start, len); 889 pinIndices(start, len);
828 const UChar *array = getBuffer(); // not getArrayStart() to check kIsBogus & kOpenGetBuffer 890 const UChar *array = getBuffer(); // not getArrayStart() to check kIsBogus & kOpenGetBuffer
829 if(array==NULL) { 891 if(array==NULL) {
830 array=fUnion.fStackBuffer; // anything not NULL because that would make an empty string 892 array=fUnion.fStackFields.fBuffer; // anything not NULL because that would make an empty string
831 len=-2; // bogus result string 893 len=-2; // bogus result string
832 } 894 }
833 return UnicodeString(FALSE, array + start, len); 895 return UnicodeString(FALSE, array + start, len);
834 } 896 }
835 897
836 int32_t 898 int32_t
837 UnicodeString::toUTF8(int32_t start, int32_t len, 899 UnicodeString::toUTF8(int32_t start, int32_t len,
838 char *target, int32_t capacity) const { 900 char *target, int32_t capacity) const {
839 pinIndices(start, len); 901 pinIndices(start, len);
840 int32_t length8; 902 int32_t length8;
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1104 1166
1105 return *this; 1167 return *this;
1106 } 1168 }
1107 1169
1108 1170
1109 void 1171 void
1110 UnicodeString::setToBogus() 1172 UnicodeString::setToBogus()
1111 { 1173 {
1112 releaseArray(); 1174 releaseArray();
1113 1175
1114 fShortLength = 0; 1176 fUnion.fFields.fLengthAndFlags = kIsBogus;
1115 fUnion.fFields.fArray = 0; 1177 fUnion.fFields.fArray = 0;
1116 fUnion.fFields.fCapacity = 0; 1178 fUnion.fFields.fCapacity = 0;
1117 fFlags = kIsBogus;
1118 } 1179 }
1119 1180
1120 // turn a bogus string into an empty one 1181 // turn a bogus string into an empty one
1121 void 1182 void
1122 UnicodeString::unBogus() { 1183 UnicodeString::unBogus() {
1123 if(fFlags & kIsBogus) { 1184 if(fUnion.fFields.fLengthAndFlags & kIsBogus) {
1124 setToEmpty(); 1185 setToEmpty();
1125 } 1186 }
1126 } 1187 }
1127 1188
1128 const UChar * 1189 const UChar *
1129 UnicodeString::getTerminatedBuffer() { 1190 UnicodeString::getTerminatedBuffer() {
1130 if(!isWritable()) { 1191 if(!isWritable()) {
1131 return 0; 1192 return 0;
1132 } 1193 }
1133 UChar *array = getArrayStart(); 1194 UChar *array = getArrayStart();
1134 int32_t len = length(); 1195 int32_t len = length();
1135 if(len < getCapacity()) { 1196 if(len < getCapacity()) {
1136 if(fFlags & kBufferIsReadonly) { 1197 if(fUnion.fFields.fLengthAndFlags & kBufferIsReadonly) {
1137 // If len<capacity on a read-only alias, then array[len] is 1198 // If len<capacity on a read-only alias, then array[len] is
1138 // either the original NUL (if constructed with (TRUE, s, length)) 1199 // either the original NUL (if constructed with (TRUE, s, length))
1139 // or one of the original string contents characters (if later truncated), 1200 // or one of the original string contents characters (if later truncated),
1140 // therefore we can assume that array[len] is initialized memory. 1201 // therefore we can assume that array[len] is initialized memory.
1141 if(array[len] == 0) { 1202 if(array[len] == 0) {
1142 return array; 1203 return array;
1143 } 1204 }
1144 } else if(((fFlags & kRefCounted) == 0 || refCount() == 1)) { 1205 } else if(((fUnion.fFields.fLengthAndFlags & kRefCounted) == 0 || refCount() == 1)) {
1145 // kRefCounted: Do not write the NUL if the buffer is shared. 1206 // kRefCounted: Do not write the NUL if the buffer is shared.
1146 // That is mostly safe, except when the length of one copy was modified 1207 // That is mostly safe, except when the length of one copy was modified
1147 // without copy-on-write, e.g., via truncate(newLength) or remove(void). 1208 // without copy-on-write, e.g., via truncate(newLength) or remove(void).
1148 // Then the NUL would be written into the middle of another copy's string. 1209 // Then the NUL would be written into the middle of another copy's string.
1149 1210
1150 // Otherwise, the buffer is fully writable and it is anyway safe to write the NUL. 1211 // Otherwise, the buffer is fully writable and it is anyway safe to write the NUL.
1151 // Do not test if there is a NUL already because it might be uninitialized memory. 1212 // Do not test if there is a NUL already because it might be uninitialized memory.
1152 // (That would be safe, but tools like valgrind & Purify would complain.) 1213 // (That would be safe, but tools like valgrind & Purify would complain.)
1153 array[len] = 0; 1214 array[len] = 0;
1154 return array; 1215 return array;
1155 } 1216 }
1156 } 1217 }
1157 if(cloneArrayIfNeeded(len+1)) { 1218 if(cloneArrayIfNeeded(len+1)) {
1158 array = getArrayStart(); 1219 array = getArrayStart();
1159 array[len] = 0; 1220 array[len] = 0;
1160 return array; 1221 return array;
1161 } else { 1222 } else {
1162 return NULL; 1223 return NULL;
1163 } 1224 }
1164 } 1225 }
1165 1226
1166 // setTo() analogous to the readonly-aliasing constructor with the same signatur e 1227 // setTo() analogous to the readonly-aliasing constructor with the same signatur e
1167 UnicodeString & 1228 UnicodeString &
1168 UnicodeString::setTo(UBool isTerminated, 1229 UnicodeString::setTo(UBool isTerminated,
1169 const UChar *text, 1230 const UChar *text,
1170 int32_t textLength) 1231 int32_t textLength)
1171 { 1232 {
1172 if(fFlags & kOpenGetBuffer) { 1233 if(fUnion.fFields.fLengthAndFlags & kOpenGetBuffer) {
1173 // do not modify a string that has an "open" getBuffer(minCapacity) 1234 // do not modify a string that has an "open" getBuffer(minCapacity)
1174 return *this; 1235 return *this;
1175 } 1236 }
1176 1237
1177 if(text == NULL) { 1238 if(text == NULL) {
1178 // treat as an empty string, do not alias 1239 // treat as an empty string, do not alias
1179 releaseArray(); 1240 releaseArray();
1180 setToEmpty(); 1241 setToEmpty();
1181 return *this; 1242 return *this;
1182 } 1243 }
1183 1244
1184 if( textLength < -1 || 1245 if( textLength < -1 ||
1185 (textLength == -1 && !isTerminated) || 1246 (textLength == -1 && !isTerminated) ||
1186 (textLength >= 0 && isTerminated && text[textLength] != 0) 1247 (textLength >= 0 && isTerminated && text[textLength] != 0)
1187 ) { 1248 ) {
1188 setToBogus(); 1249 setToBogus();
1189 return *this; 1250 return *this;
1190 } 1251 }
1191 1252
1192 releaseArray(); 1253 releaseArray();
1193 1254
1194 if(textLength == -1) { 1255 if(textLength == -1) {
1195 // text is terminated, or else it would have failed the above test 1256 // text is terminated, or else it would have failed the above test
1196 textLength = u_strlen(text); 1257 textLength = u_strlen(text);
1197 } 1258 }
1259 fUnion.fFields.fLengthAndFlags = kReadonlyAlias;
1198 setArray((UChar *)text, textLength, isTerminated ? textLength + 1 : textLength ); 1260 setArray((UChar *)text, textLength, isTerminated ? textLength + 1 : textLength );
1199
1200 fFlags = kReadonlyAlias;
1201 return *this; 1261 return *this;
1202 } 1262 }
1203 1263
1204 // setTo() analogous to the writable-aliasing constructor with the same signatur e 1264 // setTo() analogous to the writable-aliasing constructor with the same signatur e
1205 UnicodeString & 1265 UnicodeString &
1206 UnicodeString::setTo(UChar *buffer, 1266 UnicodeString::setTo(UChar *buffer,
1207 int32_t buffLength, 1267 int32_t buffLength,
1208 int32_t buffCapacity) { 1268 int32_t buffCapacity) {
1209 if(fFlags & kOpenGetBuffer) { 1269 if(fUnion.fFields.fLengthAndFlags & kOpenGetBuffer) {
1210 // do not modify a string that has an "open" getBuffer(minCapacity) 1270 // do not modify a string that has an "open" getBuffer(minCapacity)
1211 return *this; 1271 return *this;
1212 } 1272 }
1213 1273
1214 if(buffer == NULL) { 1274 if(buffer == NULL) {
1215 // treat as an empty string, do not alias 1275 // treat as an empty string, do not alias
1216 releaseArray(); 1276 releaseArray();
1217 setToEmpty(); 1277 setToEmpty();
1218 return *this; 1278 return *this;
1219 } 1279 }
1220 1280
1221 if(buffLength < -1 || buffCapacity < 0 || buffLength > buffCapacity) { 1281 if(buffLength < -1 || buffCapacity < 0 || buffLength > buffCapacity) {
1222 setToBogus(); 1282 setToBogus();
1223 return *this; 1283 return *this;
1224 } else if(buffLength == -1) { 1284 } else if(buffLength == -1) {
1225 // buffLength = u_strlen(buff); but do not look beyond buffCapacity 1285 // buffLength = u_strlen(buff); but do not look beyond buffCapacity
1226 const UChar *p = buffer, *limit = buffer + buffCapacity; 1286 const UChar *p = buffer, *limit = buffer + buffCapacity;
1227 while(p != limit && *p != 0) { 1287 while(p != limit && *p != 0) {
1228 ++p; 1288 ++p;
1229 } 1289 }
1230 buffLength = (int32_t)(p - buffer); 1290 buffLength = (int32_t)(p - buffer);
1231 } 1291 }
1232 1292
1233 releaseArray(); 1293 releaseArray();
1234 1294
1295 fUnion.fFields.fLengthAndFlags = kWritableAlias;
1235 setArray(buffer, buffLength, buffCapacity); 1296 setArray(buffer, buffLength, buffCapacity);
1236 fFlags = kWritableAlias;
1237 return *this; 1297 return *this;
1238 } 1298 }
1239 1299
1240 UnicodeString &UnicodeString::setToUTF8(const StringPiece &utf8) { 1300 UnicodeString &UnicodeString::setToUTF8(const StringPiece &utf8) {
1241 unBogus(); 1301 unBogus();
1242 int32_t length = utf8.length(); 1302 int32_t length = utf8.length();
1243 int32_t capacity; 1303 int32_t capacity;
1244 // The UTF-16 string will be at most as long as the UTF-8 string. 1304 // The UTF-16 string will be at most as long as the UTF-8 string.
1245 if(length <= US_STACKBUF_SIZE) { 1305 if(length <= US_STACKBUF_SIZE) {
1246 capacity = US_STACKBUF_SIZE; 1306 capacity = US_STACKBUF_SIZE;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1293 return doReplace(start, _length, buffer, 0, isError ? 0 : count); 1353 return doReplace(start, _length, buffer, 0, isError ? 0 : count);
1294 } 1354 }
1295 1355
1296 UnicodeString& 1356 UnicodeString&
1297 UnicodeString::append(UChar32 srcChar) { 1357 UnicodeString::append(UChar32 srcChar) {
1298 UChar buffer[U16_MAX_LENGTH]; 1358 UChar buffer[U16_MAX_LENGTH];
1299 int32_t _length = 0; 1359 int32_t _length = 0;
1300 UBool isError = FALSE; 1360 UBool isError = FALSE;
1301 U16_APPEND(buffer, _length, U16_MAX_LENGTH, srcChar, isError); 1361 U16_APPEND(buffer, _length, U16_MAX_LENGTH, srcChar, isError);
1302 // We test isError so that the compiler does not complain that we don't. 1362 // We test isError so that the compiler does not complain that we don't.
1303 // If isError then _length==0 which turns the doReplace() into a no-op anyway. 1363 // If isError then _length==0 which turns the doAppend() into a no-op anyway.
1304 return isError ? *this : doReplace(length(), 0, buffer, 0, _length); 1364 return isError ? *this : doAppend(buffer, 0, _length);
1305 } 1365 }
1306 1366
1307 UnicodeString& 1367 UnicodeString&
1308 UnicodeString::doReplace( int32_t start, 1368 UnicodeString::doReplace( int32_t start,
1309 int32_t length, 1369 int32_t length,
1310 const UnicodeString& src, 1370 const UnicodeString& src,
1311 int32_t srcStart, 1371 int32_t srcStart,
1312 int32_t srcLength) 1372 int32_t srcLength)
1313 { 1373 {
1314 if(!src.isBogus()) { 1374 // pin the indices to legal values
1315 // pin the indices to legal values 1375 src.pinIndices(srcStart, srcLength);
1316 src.pinIndices(srcStart, srcLength);
1317 1376
1318 // get the characters from src 1377 // get the characters from src
1319 // and replace the range in ourselves with them 1378 // and replace the range in ourselves with them
1320 return doReplace(start, length, src.getArrayStart(), srcStart, srcLength); 1379 return doReplace(start, length, src.getArrayStart(), srcStart, srcLength);
1321 } else {
1322 // remove the range
1323 return doReplace(start, length, 0, 0, 0);
1324 }
1325 } 1380 }
1326 1381
1327 UnicodeString& 1382 UnicodeString&
1328 UnicodeString::doReplace(int32_t start, 1383 UnicodeString::doReplace(int32_t start,
1329 int32_t length, 1384 int32_t length,
1330 const UChar *srcChars, 1385 const UChar *srcChars,
1331 int32_t srcStart, 1386 int32_t srcStart,
1332 int32_t srcLength) 1387 int32_t srcLength)
1333 { 1388 {
1334 if(!isWritable()) { 1389 if(!isWritable()) {
1335 return *this; 1390 return *this;
1336 } 1391 }
1337 1392
1338 int32_t oldLength = this->length(); 1393 int32_t oldLength = this->length();
1339 1394
1340 // optimize (read-only alias).remove(0, start) and .remove(start, end) 1395 // optimize (read-only alias).remove(0, start) and .remove(start, end)
1341 if((fFlags&kBufferIsReadonly) && srcLength == 0) { 1396 if((fUnion.fFields.fLengthAndFlags&kBufferIsReadonly) && srcLength == 0) {
1342 if(start == 0) { 1397 if(start == 0) {
1343 // remove prefix by adjusting the array pointer 1398 // remove prefix by adjusting the array pointer
1344 pinIndex(length); 1399 pinIndex(length);
1345 fUnion.fFields.fArray += length; 1400 fUnion.fFields.fArray += length;
1346 fUnion.fFields.fCapacity -= length; 1401 fUnion.fFields.fCapacity -= length;
1347 setLength(oldLength - length); 1402 setLength(oldLength - length);
1348 return *this; 1403 return *this;
1349 } else { 1404 } else {
1350 pinIndex(start); 1405 pinIndex(start);
1351 if(length >= (oldLength - start)) { 1406 if(length >= (oldLength - start)) {
1352 // remove suffix by reducing the length (like truncate()) 1407 // remove suffix by reducing the length (like truncate())
1353 setLength(start); 1408 setLength(start);
1354 fUnion.fFields.fCapacity = start; // not NUL-terminated any more 1409 fUnion.fFields.fCapacity = start; // not NUL-terminated any more
1355 return *this; 1410 return *this;
1356 } 1411 }
1357 } 1412 }
1358 } 1413 }
1359 1414
1415 if(start == oldLength) {
1416 return doAppend(srcChars, srcStart, srcLength);
1417 }
1418
1360 if(srcChars == 0) { 1419 if(srcChars == 0) {
1361 srcStart = srcLength = 0; 1420 srcStart = srcLength = 0;
1362 } else if(srcLength < 0) { 1421 } else if(srcLength < 0) {
1363 // get the srcLength if necessary 1422 // get the srcLength if necessary
1364 srcLength = u_strlen(srcChars + srcStart); 1423 srcLength = u_strlen(srcChars + srcStart);
1365 } 1424 }
1366 1425
1426 // pin the indices to legal values
1427 pinIndices(start, length);
1428
1367 // calculate the size of the string after the replace 1429 // calculate the size of the string after the replace
1368 int32_t newLength; 1430 int32_t newLength = oldLength - length + srcLength;
1369 1431
1370 // optimize append() onto a large-enough, owned string 1432 // cloneArrayIfNeeded(doCopyArray=FALSE) may change fArray but will not copy t he current contents;
1371 if(start >= oldLength) {
1372 if(srcLength == 0) {
1373 return *this;
1374 }
1375 newLength = oldLength + srcLength;
1376 if(newLength <= getCapacity() && isBufferWritable()) {
1377 UChar *oldArray = getArrayStart();
1378 // Do not copy characters when
1379 // UChar *buffer=str.getAppendBuffer(...);
1380 // is followed by
1381 // str.append(buffer, length);
1382 // or
1383 // str.appendString(buffer, length)
1384 // or similar.
1385 if(srcChars + srcStart != oldArray + start || start > oldLength) {
1386 us_arrayCopy(srcChars, srcStart, oldArray, oldLength, srcLength);
1387 }
1388 setLength(newLength);
1389 return *this;
1390 } else {
1391 // pin the indices to legal values
1392 start = oldLength;
1393 length = 0;
1394 }
1395 } else {
1396 // pin the indices to legal values
1397 pinIndices(start, length);
1398
1399 newLength = oldLength - length + srcLength;
1400 }
1401
1402 // the following may change fArray but will not copy the current contents;
1403 // therefore we need to keep the current fArray 1433 // therefore we need to keep the current fArray
1404 UChar oldStackBuffer[US_STACKBUF_SIZE]; 1434 UChar oldStackBuffer[US_STACKBUF_SIZE];
1405 UChar *oldArray; 1435 UChar *oldArray;
1406 if((fFlags&kUsingStackBuffer) && (newLength > US_STACKBUF_SIZE)) { 1436 if((fUnion.fFields.fLengthAndFlags&kUsingStackBuffer) && (newLength > US_STACK BUF_SIZE)) {
1407 // copy the stack buffer contents because it will be overwritten with 1437 // copy the stack buffer contents because it will be overwritten with
1408 // fUnion.fFields values 1438 // fUnion.fFields values
1409 u_memcpy(oldStackBuffer, fUnion.fStackBuffer, oldLength); 1439 u_memcpy(oldStackBuffer, fUnion.fStackFields.fBuffer, oldLength);
1410 oldArray = oldStackBuffer; 1440 oldArray = oldStackBuffer;
1411 } else { 1441 } else {
1412 oldArray = getArrayStart(); 1442 oldArray = getArrayStart();
1413 } 1443 }
1414 1444
1415 // clone our array and allocate a bigger array if needed 1445 // clone our array and allocate a bigger array if needed
1416 int32_t *bufferToDelete = 0; 1446 int32_t *bufferToDelete = 0;
1417 if(!cloneArrayIfNeeded(newLength, newLength + (newLength >> 2) + kGrowSize, 1447 if(!cloneArrayIfNeeded(newLength, newLength + (newLength >> 2) + kGrowSize,
1418 FALSE, &bufferToDelete) 1448 FALSE, &bufferToDelete)
1419 ) { 1449 ) {
(...skipping 23 matching lines...) Expand all
1443 1473
1444 // delayed delete in case srcChars == fArray when we started, and 1474 // delayed delete in case srcChars == fArray when we started, and
1445 // to keep oldArray alive for the above operations 1475 // to keep oldArray alive for the above operations
1446 if (bufferToDelete) { 1476 if (bufferToDelete) {
1447 uprv_free(bufferToDelete); 1477 uprv_free(bufferToDelete);
1448 } 1478 }
1449 1479
1450 return *this; 1480 return *this;
1451 } 1481 }
1452 1482
1483 // Versions of doReplace() only for append() variants.
1484 // doReplace() and doAppend() optimize for different cases.
1485
1486 UnicodeString&
1487 UnicodeString::doAppend(const UnicodeString& src, int32_t srcStart, int32_t srcL ength) {
1488 if(srcLength == 0) {
1489 return *this;
1490 }
1491
1492 // pin the indices to legal values
1493 src.pinIndices(srcStart, srcLength);
1494 return doAppend(src.getArrayStart(), srcStart, srcLength);
1495 }
1496
1497 UnicodeString&
1498 UnicodeString::doAppend(const UChar *srcChars, int32_t srcStart, int32_t srcLeng th) {
1499 if(!isWritable() || srcLength == 0 || srcChars == NULL) {
1500 return *this;
1501 }
1502
1503 if(srcLength < 0) {
1504 // get the srcLength if necessary
1505 if((srcLength = u_strlen(srcChars + srcStart)) == 0) {
1506 return *this;
1507 }
1508 }
1509
1510 int32_t oldLength = length();
1511 int32_t newLength = oldLength + srcLength;
1512 // optimize append() onto a large-enough, owned string
1513 if((newLength <= getCapacity() && isBufferWritable()) ||
1514 cloneArrayIfNeeded(newLength, newLength + (newLength >> 2) + kGrowSize)) {
1515 UChar *newArray = getArrayStart();
1516 // Do not copy characters when
1517 // UChar *buffer=str.getAppendBuffer(...);
1518 // is followed by
1519 // str.append(buffer, length);
1520 // or
1521 // str.appendString(buffer, length)
1522 // or similar.
1523 if(srcChars + srcStart != newArray + oldLength) {
1524 us_arrayCopy(srcChars, srcStart, newArray, oldLength, srcLength);
1525 }
1526 setLength(newLength);
1527 }
1528 return *this;
1529 }
1530
1453 /** 1531 /**
1454 * Replaceable API 1532 * Replaceable API
1455 */ 1533 */
1456 void 1534 void
1457 UnicodeString::handleReplaceBetween(int32_t start, 1535 UnicodeString::handleReplaceBetween(int32_t start,
1458 int32_t limit, 1536 int32_t limit,
1459 const UnicodeString& text) { 1537 const UnicodeString& text) {
1460 replaceBetween(start, limit, text); 1538 replaceBetween(start, limit, text);
1461 } 1539 }
1462 1540
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1596 return hashCode; 1674 return hashCode;
1597 } 1675 }
1598 1676
1599 //======================================== 1677 //========================================
1600 // External Buffer 1678 // External Buffer
1601 //======================================== 1679 //========================================
1602 1680
1603 UChar * 1681 UChar *
1604 UnicodeString::getBuffer(int32_t minCapacity) { 1682 UnicodeString::getBuffer(int32_t minCapacity) {
1605 if(minCapacity>=-1 && cloneArrayIfNeeded(minCapacity)) { 1683 if(minCapacity>=-1 && cloneArrayIfNeeded(minCapacity)) {
1606 fFlags|=kOpenGetBuffer; 1684 fUnion.fFields.fLengthAndFlags|=kOpenGetBuffer;
1607 fShortLength=0; 1685 setZeroLength();
1608 return getArrayStart(); 1686 return getArrayStart();
1609 } else { 1687 } else {
1610 return 0; 1688 return 0;
1611 } 1689 }
1612 } 1690 }
1613 1691
1614 void 1692 void
1615 UnicodeString::releaseBuffer(int32_t newLength) { 1693 UnicodeString::releaseBuffer(int32_t newLength) {
1616 if(fFlags&kOpenGetBuffer && newLength>=-1) { 1694 if(fUnion.fFields.fLengthAndFlags&kOpenGetBuffer && newLength>=-1) {
1617 // set the new fLength 1695 // set the new fLength
1618 int32_t capacity=getCapacity(); 1696 int32_t capacity=getCapacity();
1619 if(newLength==-1) { 1697 if(newLength==-1) {
1620 // the new length is the string length, capped by fCapacity 1698 // the new length is the string length, capped by fCapacity
1621 const UChar *array=getArrayStart(), *p=array, *limit=array+capacity; 1699 const UChar *array=getArrayStart(), *p=array, *limit=array+capacity;
1622 while(p<limit && *p!=0) { 1700 while(p<limit && *p!=0) {
1623 ++p; 1701 ++p;
1624 } 1702 }
1625 newLength=(int32_t)(p-array); 1703 newLength=(int32_t)(p-array);
1626 } else if(newLength>capacity) { 1704 } else if(newLength>capacity) {
1627 newLength=capacity; 1705 newLength=capacity;
1628 } 1706 }
1629 setLength(newLength); 1707 setLength(newLength);
1630 fFlags&=~kOpenGetBuffer; 1708 fUnion.fFields.fLengthAndFlags&=~kOpenGetBuffer;
1631 } 1709 }
1632 } 1710 }
1633 1711
1634 //======================================== 1712 //========================================
1635 // Miscellaneous 1713 // Miscellaneous
1636 //======================================== 1714 //========================================
1637 UBool 1715 UBool
1638 UnicodeString::cloneArrayIfNeeded(int32_t newCapacity, 1716 UnicodeString::cloneArrayIfNeeded(int32_t newCapacity,
1639 int32_t growCapacity, 1717 int32_t growCapacity,
1640 UBool doCopyArray, 1718 UBool doCopyArray,
(...skipping 13 matching lines...) Expand all
1654 } 1732 }
1655 1733
1656 /* 1734 /*
1657 * We need to make a copy of the array if 1735 * We need to make a copy of the array if
1658 * the buffer is read-only, or 1736 * the buffer is read-only, or
1659 * the buffer is refCounted (shared), and refCount>1, or 1737 * the buffer is refCounted (shared), and refCount>1, or
1660 * the buffer is too small. 1738 * the buffer is too small.
1661 * Return FALSE if memory could not be allocated. 1739 * Return FALSE if memory could not be allocated.
1662 */ 1740 */
1663 if(forceClone || 1741 if(forceClone ||
1664 fFlags & kBufferIsReadonly || 1742 fUnion.fFields.fLengthAndFlags & kBufferIsReadonly ||
1665 (fFlags & kRefCounted && refCount() > 1) || 1743 (fUnion.fFields.fLengthAndFlags & kRefCounted && refCount() > 1) ||
1666 newCapacity > getCapacity() 1744 newCapacity > getCapacity()
1667 ) { 1745 ) {
1668 // check growCapacity for default value and use of the stack buffer 1746 // check growCapacity for default value and use of the stack buffer
1669 if(growCapacity < 0) { 1747 if(growCapacity < 0) {
1670 growCapacity = newCapacity; 1748 growCapacity = newCapacity;
1671 } else if(newCapacity <= US_STACKBUF_SIZE && growCapacity > US_STACKBUF_SIZE ) { 1749 } else if(newCapacity <= US_STACKBUF_SIZE && growCapacity > US_STACKBUF_SIZE ) {
1672 growCapacity = US_STACKBUF_SIZE; 1750 growCapacity = US_STACKBUF_SIZE;
1673 } 1751 }
1674 1752
1675 // save old values 1753 // save old values
1676 UChar oldStackBuffer[US_STACKBUF_SIZE]; 1754 UChar oldStackBuffer[US_STACKBUF_SIZE];
1677 UChar *oldArray; 1755 UChar *oldArray;
1678 uint8_t flags = fFlags; 1756 int32_t oldLength = length();
1757 int16_t flags = fUnion.fFields.fLengthAndFlags;
1679 1758
1680 if(flags&kUsingStackBuffer) { 1759 if(flags&kUsingStackBuffer) {
1681 U_ASSERT(!(flags&kRefCounted)); /* kRefCounted and kUsingStackBuffer are m utally exclusive */ 1760 U_ASSERT(!(flags&kRefCounted)); /* kRefCounted and kUsingStackBuffer are m utally exclusive */
1682 if(doCopyArray && growCapacity > US_STACKBUF_SIZE) { 1761 if(doCopyArray && growCapacity > US_STACKBUF_SIZE) {
1683 // copy the stack buffer contents because it will be overwritten with 1762 // copy the stack buffer contents because it will be overwritten with
1684 // fUnion.fFields values 1763 // fUnion.fFields values
1685 us_arrayCopy(fUnion.fStackBuffer, 0, oldStackBuffer, 0, fShortLength); 1764 us_arrayCopy(fUnion.fStackFields.fBuffer, 0, oldStackBuffer, 0, oldLengt h);
1686 oldArray = oldStackBuffer; 1765 oldArray = oldStackBuffer;
1687 } else { 1766 } else {
1688 oldArray = 0; // no need to copy from stack buffer to itself 1767 oldArray = NULL; // no need to copy from the stack buffer to itself
1689 } 1768 }
1690 } else { 1769 } else {
1691 oldArray = fUnion.fFields.fArray; 1770 oldArray = fUnion.fFields.fArray;
1692 U_ASSERT(oldArray!=NULL); /* when stack buffer is not used, oldArray must have a non-NULL reference */ 1771 U_ASSERT(oldArray!=NULL); /* when stack buffer is not used, oldArray must have a non-NULL reference */
1693 } 1772 }
1694 1773
1695 // allocate a new array 1774 // allocate a new array
1696 if(allocate(growCapacity) || 1775 if(allocate(growCapacity) ||
1697 (newCapacity < growCapacity && allocate(newCapacity)) 1776 (newCapacity < growCapacity && allocate(newCapacity))
1698 ) { 1777 ) {
1699 if(doCopyArray && oldArray != 0) { 1778 if(doCopyArray) {
1700 // copy the contents 1779 // copy the contents
1701 // do not copy more than what fits - it may be smaller than before 1780 // do not copy more than what fits - it may be smaller than before
1702 int32_t minLength = length(); 1781 int32_t minLength = oldLength;
1703 newCapacity = getCapacity(); 1782 newCapacity = getCapacity();
1704 if(newCapacity < minLength) { 1783 if(newCapacity < minLength) {
1705 minLength = newCapacity; 1784 minLength = newCapacity;
1706 setLength(minLength);
1707 } 1785 }
1708 us_arrayCopy(oldArray, 0, getArrayStart(), 0, minLength); 1786 if(oldArray != NULL) {
1787 us_arrayCopy(oldArray, 0, getArrayStart(), 0, minLength);
1788 }
1789 setLength(minLength);
1709 } else { 1790 } else {
1710 fShortLength = 0; 1791 setZeroLength();
1711 } 1792 }
1712 1793
1713 // release the old array 1794 // release the old array
1714 if(flags & kRefCounted) { 1795 if(flags & kRefCounted) {
1715 // the array is refCounted; decrement and release if 0 1796 // the array is refCounted; decrement and release if 0
1716 u_atomic_int32_t *pRefCount = ((u_atomic_int32_t *)oldArray - 1); 1797 u_atomic_int32_t *pRefCount = ((u_atomic_int32_t *)oldArray - 1);
1717 if(umtx_atomic_dec(pRefCount) == 0) { 1798 if(umtx_atomic_dec(pRefCount) == 0) {
1718 if(pBufferToDelete == 0) { 1799 if(pBufferToDelete == 0) {
1719 // Note: cast to (void *) is needed with MSVC, where u_atomic_int3 2_t 1800 // Note: cast to (void *) is needed with MSVC, where u_atomic_int3 2_t
1720 // is defined as volatile. (Volatile has useful non-standard behav ior 1801 // is defined as volatile. (Volatile has useful non-standard behav ior
1721 // with this compiler.) 1802 // with this compiler.)
1722 uprv_free((void *)pRefCount); 1803 uprv_free((void *)pRefCount);
1723 } else { 1804 } else {
1724 // the caller requested to delete it himself 1805 // the caller requested to delete it himself
1725 *pBufferToDelete = (int32_t *)pRefCount; 1806 *pBufferToDelete = (int32_t *)pRefCount;
1726 } 1807 }
1727 } 1808 }
1728 } 1809 }
1729 } else { 1810 } else {
1730 // not enough memory for growCapacity and not even for the smaller newCapa city 1811 // not enough memory for growCapacity and not even for the smaller newCapa city
1731 // reset the old values for setToBogus() to release the array 1812 // reset the old values for setToBogus() to release the array
1732 if(!(flags&kUsingStackBuffer)) { 1813 if(!(flags&kUsingStackBuffer)) {
1733 fUnion.fFields.fArray = oldArray; 1814 fUnion.fFields.fArray = oldArray;
1734 } 1815 }
1735 fFlags = flags; 1816 fUnion.fFields.fLengthAndFlags = flags;
1736 setToBogus(); 1817 setToBogus();
1737 return FALSE; 1818 return FALSE;
1738 } 1819 }
1739 } 1820 }
1740 return TRUE; 1821 return TRUE;
1741 } 1822 }
1742 1823
1743 // UnicodeStringAppendable ------------------------------------------------- *** 1824 // UnicodeStringAppendable ------------------------------------------------- ***
1744 1825
1745 UnicodeStringAppendable::~UnicodeStringAppendable() {} 1826 UnicodeStringAppendable::~UnicodeStringAppendable() {}
1746 1827
1747 UBool 1828 UBool
1748 UnicodeStringAppendable::appendCodeUnit(UChar c) { 1829 UnicodeStringAppendable::appendCodeUnit(UChar c) {
1749 return str.doReplace(str.length(), 0, &c, 0, 1).isWritable(); 1830 return str.doAppend(&c, 0, 1).isWritable();
1750 } 1831 }
1751 1832
1752 UBool 1833 UBool
1753 UnicodeStringAppendable::appendCodePoint(UChar32 c) { 1834 UnicodeStringAppendable::appendCodePoint(UChar32 c) {
1754 UChar buffer[U16_MAX_LENGTH]; 1835 UChar buffer[U16_MAX_LENGTH];
1755 int32_t cLength = 0; 1836 int32_t cLength = 0;
1756 UBool isError = FALSE; 1837 UBool isError = FALSE;
1757 U16_APPEND(buffer, cLength, U16_MAX_LENGTH, c, isError); 1838 U16_APPEND(buffer, cLength, U16_MAX_LENGTH, c, isError);
1758 return !isError && str.doReplace(str.length(), 0, buffer, 0, cLength).isWritab le(); 1839 return !isError && str.doAppend(buffer, 0, cLength).isWritable();
1759 } 1840 }
1760 1841
1761 UBool 1842 UBool
1762 UnicodeStringAppendable::appendString(const UChar *s, int32_t length) { 1843 UnicodeStringAppendable::appendString(const UChar *s, int32_t length) {
1763 return str.doReplace(str.length(), 0, s, 0, length).isWritable(); 1844 return str.doAppend(s, 0, length).isWritable();
1764 } 1845 }
1765 1846
1766 UBool 1847 UBool
1767 UnicodeStringAppendable::reserveAppendCapacity(int32_t appendCapacity) { 1848 UnicodeStringAppendable::reserveAppendCapacity(int32_t appendCapacity) {
1768 return str.cloneArrayIfNeeded(str.length() + appendCapacity); 1849 return str.cloneArrayIfNeeded(str.length() + appendCapacity);
1769 } 1850 }
1770 1851
1771 UChar * 1852 UChar *
1772 UnicodeStringAppendable::getAppendBuffer(int32_t minCapacity, 1853 UnicodeStringAppendable::getAppendBuffer(int32_t minCapacity,
1773 int32_t desiredCapacityHint, 1854 int32_t desiredCapacityHint,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1816 This should never be called. It is defined here to make sure that the 1897 This should never be called. It is defined here to make sure that the
1817 virtual vector deleting destructor is defined within unistr.cpp. 1898 virtual vector deleting destructor is defined within unistr.cpp.
1818 The vector deleting destructor is already a part of UObject, 1899 The vector deleting destructor is already a part of UObject,
1819 but defining it here makes sure that it is included with this object file. 1900 but defining it here makes sure that it is included with this object file.
1820 This makes sure that static library dependencies are kept to a minimum. 1901 This makes sure that static library dependencies are kept to a minimum.
1821 */ 1902 */
1822 static void uprv_UnicodeStringDummy(void) { 1903 static void uprv_UnicodeStringDummy(void) {
1823 delete [] (new UnicodeString[2]); 1904 delete [] (new UnicodeString[2]);
1824 } 1905 }
1825 #endif 1906 #endif
OLDNEW
« no previous file with comments | « source/common/uniset.cpp ('k') | source/common/unistr_case.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698