Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/intl/icu/source/common/unistr.cpp
Line
Count
Source (jump to first uncovered line)
1
// © 2016 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
/*
4
******************************************************************************
5
* Copyright (C) 1999-2016, International Business Machines Corporation and
6
* others. All Rights Reserved.
7
******************************************************************************
8
*
9
* File unistr.cpp
10
*
11
* Modification History:
12
*
13
*   Date        Name        Description
14
*   09/25/98    stephen     Creation.
15
*   04/20/99    stephen     Overhauled per 4/16 code review.
16
*   07/09/99    stephen     Renamed {hi,lo},{byte,word} to icu_X for HP/UX
17
*   11/18/99    aliu        Added handleReplaceBetween() to make inherit from
18
*                           Replaceable.
19
*   06/25/01    grhoten     Removed the dependency on iostream
20
******************************************************************************
21
*/
22
23
#include "unicode/utypes.h"
24
#include "unicode/appendable.h"
25
#include "unicode/putil.h"
26
#include "cstring.h"
27
#include "cmemory.h"
28
#include "unicode/ustring.h"
29
#include "unicode/unistr.h"
30
#include "unicode/utf.h"
31
#include "unicode/utf16.h"
32
#include "uelement.h"
33
#include "ustr_imp.h"
34
#include "umutex.h"
35
#include "uassert.h"
36
37
#if 0
38
39
#include <iostream>
40
using namespace std;
41
42
//DEBUGGING
43
void
44
print(const UnicodeString& s,
45
      const char *name)
46
{
47
  UChar c;
48
  cout << name << ":|";
49
  for(int i = 0; i < s.length(); ++i) {
50
    c = s[i];
51
    if(c>= 0x007E || c < 0x0020)
52
      cout << "[0x" << hex << s[i] << "]";
53
    else
54
      cout << (char) s[i];
55
  }
56
  cout << '|' << endl;
57
}
58
59
void
60
print(const UChar *s,
61
      int32_t len,
62
      const char *name)
63
{
64
  UChar c;
65
  cout << name << ":|";
66
  for(int i = 0; i < len; ++i) {
67
    c = s[i];
68
    if(c>= 0x007E || c < 0x0020)
69
      cout << "[0x" << hex << s[i] << "]";
70
    else
71
      cout << (char) s[i];
72
  }
73
  cout << '|' << endl;
74
}
75
// END DEBUGGING
76
#endif
77
78
// Local function definitions for now
79
80
// need to copy areas that may overlap
81
static
82
inline void
83
us_arrayCopy(const UChar *src, int32_t srcStart,
84
         UChar *dst, int32_t dstStart, int32_t count)
85
17.1k
{
86
17.1k
  if(count>0) {
87
10.0k
    uprv_memmove(dst+dstStart, src+srcStart, (size_t)count*sizeof(*src));
88
10.0k
  }
89
17.1k
}
90
91
// u_unescapeAt() callback to get a UChar from a UnicodeString
92
U_CDECL_BEGIN
93
static UChar U_CALLCONV
94
0
UnicodeString_charAt(int32_t offset, void *context) {
95
0
    return ((icu::UnicodeString*) context)->charAt(offset);
96
0
}
97
U_CDECL_END
98
99
U_NAMESPACE_BEGIN
100
101
/* The Replaceable virtual destructor can't be defined in the header
102
   due to how AIX works with multiple definitions of virtual functions.
103
*/
104
379k
Replaceable::~Replaceable() {}
105
106
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UnicodeString)
107
108
UnicodeString U_EXPORT2
109
0
operator+ (const UnicodeString &s1, const UnicodeString &s2) {
110
0
    return
111
0
        UnicodeString(s1.length()+s2.length()+1, (UChar32)0, 0).
112
0
            append(s1).
113
0
                append(s2);
114
0
}
115
116
//========================================
117
// Reference Counting functions, put at top of file so that optimizing compilers
118
//                               have a chance to automatically inline.
119
//========================================
120
121
void
122
0
UnicodeString::addRef() {
123
0
  umtx_atomic_inc((u_atomic_int32_t *)fUnion.fFields.fArray - 1);
124
0
}
125
126
int32_t
127
2.44k
UnicodeString::removeRef() {
128
2.44k
  return umtx_atomic_dec((u_atomic_int32_t *)fUnion.fFields.fArray - 1);
129
2.44k
}
130
131
int32_t
132
639
UnicodeString::refCount() const {
133
639
  return umtx_loadAcquire(*((u_atomic_int32_t *)fUnion.fFields.fArray - 1));
134
639
}
135
136
void
137
380k
UnicodeString::releaseArray() {
138
380k
  if((fUnion.fFields.fLengthAndFlags & kRefCounted) && removeRef() == 0) {
139
2.44k
    uprv_free((int32_t *)fUnion.fFields.fArray - 1);
140
2.44k
  }
141
380k
}
142
143
144
145
//========================================
146
// Constructors
147
//========================================
148
149
// The default constructor is inline in unistr.h.
150
151
0
UnicodeString::UnicodeString(int32_t capacity, UChar32 c, int32_t count) {
152
0
  fUnion.fFields.fLengthAndFlags = 0;
153
0
  if(count <= 0 || (uint32_t)c > 0x10ffff) {
154
0
    // just allocate and do not do anything else
155
0
    allocate(capacity);
156
0
  } else if(c <= 0xffff) {
157
0
    int32_t length = count;
158
0
    if(capacity < length) {
159
0
      capacity = length;
160
0
    }
161
0
    if(allocate(capacity)) {
162
0
      UChar *array = getArrayStart();
163
0
      UChar unit = (UChar)c;
164
0
      for(int32_t i = 0; i < length; ++i) {
165
0
        array[i] = unit;
166
0
      }
167
0
      setLength(length);
168
0
    }
169
0
  } else {  // supplementary code point, write surrogate pairs
170
0
    if(count > (INT32_MAX / 2)) {
171
0
      // We would get more than 2G UChars.
172
0
      allocate(capacity);
173
0
      return;
174
0
    }
175
0
    int32_t length = count * 2;
176
0
    if(capacity < length) {
177
0
      capacity = length;
178
0
    }
179
0
    if(allocate(capacity)) {
180
0
      UChar *array = getArrayStart();
181
0
      UChar lead = U16_LEAD(c);
182
0
      UChar trail = U16_TRAIL(c);
183
0
      for(int32_t i = 0; i < length; i += 2) {
184
0
        array[i] = lead;
185
0
        array[i + 1] = trail;
186
0
      }
187
0
      setLength(length);
188
0
    }
189
0
  }
190
0
}
191
192
0
UnicodeString::UnicodeString(UChar ch) {
193
0
  fUnion.fFields.fLengthAndFlags = kLength1 | kShortString;
194
0
  fUnion.fStackFields.fBuffer[0] = ch;
195
0
}
196
197
0
UnicodeString::UnicodeString(UChar32 ch) {
198
0
  fUnion.fFields.fLengthAndFlags = kShortString;
199
0
  int32_t i = 0;
200
0
  UBool isError = FALSE;
201
0
  U16_APPEND(fUnion.fStackFields.fBuffer, i, US_STACKBUF_SIZE, ch, isError);
202
0
  // We test isError so that the compiler does not complain that we don't.
203
0
  // If isError then i==0 which is what we want anyway.
204
0
  if(!isError) {
205
0
    setShortLength(i);
206
0
  }
207
0
}
208
209
0
UnicodeString::UnicodeString(const UChar *text) {
210
0
  fUnion.fFields.fLengthAndFlags = kShortString;
211
0
  doAppend(text, 0, -1);
212
0
}
213
214
UnicodeString::UnicodeString(const UChar *text,
215
1.10k
                             int32_t textLength) {
216
1.10k
  fUnion.fFields.fLengthAndFlags = kShortString;
217
1.10k
  doAppend(text, 0, textLength);
218
1.10k
}
219
220
UnicodeString::UnicodeString(UBool isTerminated,
221
                             ConstChar16Ptr textPtr,
222
143k
                             int32_t textLength) {
223
143k
  fUnion.fFields.fLengthAndFlags = kReadonlyAlias;
224
143k
  const UChar *text = textPtr;
225
143k
  if(text == NULL) {
226
0
    // treat as an empty string, do not alias
227
0
    setToEmpty();
228
143k
  } else if(textLength < -1 ||
229
143k
            (textLength == -1 && !isTerminated) ||
230
143k
            (textLength >= 0 && isTerminated && text[textLength] != 0)
231
0
  ) {
232
0
    setToBogus();
233
143k
  } else {
234
143k
    if(textLength == -1) {
235
0
      // text is terminated, or else it would have failed the above test
236
0
      textLength = u_strlen(text);
237
0
    }
238
143k
    setArray(const_cast<UChar *>(text), textLength,
239
143k
             isTerminated ? textLength + 1 : textLength);
240
143k
  }
241
143k
}
242
243
UnicodeString::UnicodeString(UChar *buff,
244
                             int32_t buffLength,
245
89.6k
                             int32_t buffCapacity) {
246
89.6k
  fUnion.fFields.fLengthAndFlags = kWritableAlias;
247
89.6k
  if(buff == NULL) {
248
0
    // treat as an empty string, do not alias
249
0
    setToEmpty();
250
89.6k
  } else if(buffLength < -1 || buffCapacity < 0 || buffLength > buffCapacity) {
251
0
    setToBogus();
252
89.6k
  } else {
253
89.6k
    if(buffLength == -1) {
254
0
      // fLength = u_strlen(buff); but do not look beyond buffCapacity
255
0
      const UChar *p = buff, *limit = buff + buffCapacity;
256
0
      while(p != limit && *p != 0) {
257
0
        ++p;
258
0
      }
259
0
      buffLength = (int32_t)(p - buff);
260
0
    }
261
89.6k
    setArray(buff, buffLength, buffCapacity);
262
89.6k
  }
263
89.6k
}
264
265
0
UnicodeString::UnicodeString(const char *src, int32_t length, EInvariant) {
266
0
  fUnion.fFields.fLengthAndFlags = kShortString;
267
0
  if(src==NULL) {
268
0
    // treat as an empty string
269
0
  } else {
270
0
    if(length<0) {
271
0
      length=(int32_t)uprv_strlen(src);
272
0
    }
273
0
    if(cloneArrayIfNeeded(length, length, FALSE)) {
274
0
      u_charsToUChars(src, getArrayStart(), length);
275
0
      setLength(length);
276
0
    } else {
277
0
      setToBogus();
278
0
    }
279
0
  }
280
0
}
281
282
#if U_CHARSET_IS_UTF8
283
284
0
UnicodeString::UnicodeString(const char *codepageData) {
285
0
  fUnion.fFields.fLengthAndFlags = kShortString;
286
0
  if(codepageData != 0) {
287
0
    setToUTF8(codepageData);
288
0
  }
289
0
}
290
291
0
UnicodeString::UnicodeString(const char *codepageData, int32_t dataLength) {
292
0
  fUnion.fFields.fLengthAndFlags = kShortString;
293
0
  // if there's nothing to convert, do nothing
294
0
  if(codepageData == 0 || dataLength == 0 || dataLength < -1) {
295
0
    return;
296
0
  }
297
0
  if(dataLength == -1) {
298
0
    dataLength = (int32_t)uprv_strlen(codepageData);
299
0
  }
300
0
  setToUTF8(StringPiece(codepageData, dataLength));
301
0
}
302
303
// else see unistr_cnv.cpp
304
#endif
305
306
0
UnicodeString::UnicodeString(const UnicodeString& that) {
307
0
  fUnion.fFields.fLengthAndFlags = kShortString;
308
0
  copyFrom(that);
309
0
}
310
311
0
UnicodeString::UnicodeString(UnicodeString &&src) U_NOEXCEPT {
312
0
  fUnion.fFields.fLengthAndFlags = kShortString;
313
0
  moveFrom(src);
314
0
}
315
316
UnicodeString::UnicodeString(const UnicodeString& that,
317
0
                             int32_t srcStart) {
318
0
  fUnion.fFields.fLengthAndFlags = kShortString;
319
0
  setTo(that, srcStart);
320
0
}
321
322
UnicodeString::UnicodeString(const UnicodeString& that,
323
                             int32_t srcStart,
324
0
                             int32_t srcLength) {
325
0
  fUnion.fFields.fLengthAndFlags = kShortString;
326
0
  setTo(that, srcStart, srcLength);
327
0
}
328
329
// Replaceable base class clone() default implementation, does not clone
330
Replaceable *
331
0
Replaceable::clone() const {
332
0
  return NULL;
333
0
}
334
335
// UnicodeString overrides clone() with a real implementation
336
Replaceable *
337
0
UnicodeString::clone() const {
338
0
  return new UnicodeString(*this);
339
0
}
340
341
//========================================
342
// array allocation
343
//========================================
344
345
namespace {
346
347
const int32_t kGrowSize = 128;
348
349
// The number of bytes for one int32_t reference counter and capacity UChars
350
// must fit into a 32-bit size_t (at least when on a 32-bit platform).
351
// We also add one for the NUL terminator, to avoid reallocation in getTerminatedBuffer(),
352
// and round up to a multiple of 16 bytes.
353
// This means that capacity must be at most (0xfffffff0 - 4) / 2 - 1 = 0x7ffffff5.
354
// (With more complicated checks we could go up to 0x7ffffffd without rounding up,
355
// but that does not seem worth it.)
356
const int32_t kMaxCapacity = 0x7ffffff5;
357
358
6.44k
int32_t getGrowCapacity(int32_t newLength) {
359
6.44k
  int32_t growSize = (newLength >> 2) + kGrowSize;
360
6.44k
  if(growSize <= (kMaxCapacity - newLength)) {
361
6.44k
    return newLength + growSize;
362
6.44k
  } else {
363
0
    return kMaxCapacity;
364
0
  }
365
6.44k
}
366
367
}  // namespace
368
369
UBool
370
2.46k
UnicodeString::allocate(int32_t capacity) {
371
2.46k
  if(capacity <= US_STACKBUF_SIZE) {
372
0
    fUnion.fFields.fLengthAndFlags = kShortString;
373
0
    return TRUE;
374
0
  }
375
2.46k
  if(capacity <= kMaxCapacity) {
376
2.46k
    ++capacity;  // for the NUL
377
2.46k
    // Switch to size_t which is unsigned so that we can allocate up to 4GB.
378
2.46k
    // Reference counter + UChars.
379
2.46k
    size_t numBytes = sizeof(int32_t) + (size_t)capacity * U_SIZEOF_UCHAR;
380
2.46k
    // Round up to a multiple of 16.
381
2.46k
    numBytes = (numBytes + 15) & ~15;
382
2.46k
    int32_t *array = (int32_t *) uprv_malloc(numBytes);
383
2.46k
    if(array != NULL) {
384
2.46k
      // set initial refCount and point behind the refCount
385
2.46k
      *array++ = 1;
386
2.46k
      numBytes -= sizeof(int32_t);
387
2.46k
388
2.46k
      // have fArray point to the first UChar
389
2.46k
      fUnion.fFields.fArray = (UChar *)array;
390
2.46k
      fUnion.fFields.fCapacity = (int32_t)(numBytes / U_SIZEOF_UCHAR);
391
2.46k
      fUnion.fFields.fLengthAndFlags = kLongString;
392
2.46k
      return TRUE;
393
2.46k
    }
394
0
  }
395
0
  fUnion.fFields.fLengthAndFlags = kIsBogus;
396
0
  fUnion.fFields.fArray = 0;
397
0
  fUnion.fFields.fCapacity = 0;
398
0
  return FALSE;
399
0
}
400
401
//========================================
402
// Destructor
403
//========================================
404
405
#ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
406
static u_atomic_int32_t finalLengthCounts[0x400];  // UnicodeString::kMaxShortLength+1
407
static u_atomic_int32_t beyondCount(0);
408
409
U_CAPI void unistr_printLengths() {
410
  int32_t i;
411
  for(i = 0; i <= 59; ++i) {
412
    printf("%2d,  %9d\n", i, (int32_t)finalLengthCounts[i]);
413
  }
414
  int32_t beyond = beyondCount;
415
  for(; i < UPRV_LENGTHOF(finalLengthCounts); ++i) {
416
    beyond += finalLengthCounts[i];
417
  }
418
  printf(">59, %9d\n", beyond);
419
}
420
#endif
421
422
UnicodeString::~UnicodeString()
423
379k
{
424
#ifdef UNISTR_COUNT_FINAL_STRING_LENGTHS
425
  // Count lengths of strings at the end of their lifetime.
426
  // Useful for discussion of a desirable stack buffer size.
427
  // Count the contents length, not the optional NUL terminator nor further capacity.
428
  // Ignore open-buffer strings and strings which alias external storage.
429
  if((fUnion.fFields.fLengthAndFlags&(kOpenGetBuffer|kReadonlyAlias|kWritableAlias)) == 0) {
430
    if(hasShortLength()) {
431
      umtx_atomic_inc(finalLengthCounts + getShortLength());
432
    } else {
433
      umtx_atomic_inc(&beyondCount);
434
    }
435
  }
436
#endif
437
438
379k
  releaseArray();
439
379k
}
440
441
//========================================
442
// Factory methods
443
//========================================
444
445
0
UnicodeString UnicodeString::fromUTF8(StringPiece utf8) {
446
0
  UnicodeString result;
447
0
  result.setToUTF8(utf8);
448
0
  return result;
449
0
}
450
451
0
UnicodeString UnicodeString::fromUTF32(const UChar32 *utf32, int32_t length) {
452
0
  UnicodeString result;
453
0
  int32_t capacity;
454
0
  // Most UTF-32 strings will be BMP-only and result in a same-length
455
0
  // UTF-16 string. We overestimate the capacity just slightly,
456
0
  // just in case there are a few supplementary characters.
457
0
  if(length <= US_STACKBUF_SIZE) {
458
0
    capacity = US_STACKBUF_SIZE;
459
0
  } else {
460
0
    capacity = length + (length >> 4) + 4;
461
0
  }
462
0
  do {
463
0
    UChar *utf16 = result.getBuffer(capacity);
464
0
    int32_t length16;
465
0
    UErrorCode errorCode = U_ZERO_ERROR;
466
0
    u_strFromUTF32WithSub(utf16, result.getCapacity(), &length16,
467
0
        utf32, length,
468
0
        0xfffd,  // Substitution character.
469
0
        NULL,    // Don't care about number of substitutions.
470
0
        &errorCode);
471
0
    result.releaseBuffer(length16);
472
0
    if(errorCode == U_BUFFER_OVERFLOW_ERROR) {
473
0
      capacity = length16 + 1;  // +1 for the terminating NUL.
474
0
      continue;
475
0
    } else if(U_FAILURE(errorCode)) {
476
0
      result.setToBogus();
477
0
    }
478
0
    break;
479
0
  } while(TRUE);
480
0
  return result;
481
0
}
482
483
//========================================
484
// Assignment
485
//========================================
486
487
UnicodeString &
488
1.10k
UnicodeString::operator=(const UnicodeString &src) {
489
1.10k
  return copyFrom(src);
490
1.10k
}
491
492
UnicodeString &
493
0
UnicodeString::fastCopyFrom(const UnicodeString &src) {
494
0
  return copyFrom(src, TRUE);
495
0
}
496
497
UnicodeString &
498
1.10k
UnicodeString::copyFrom(const UnicodeString &src, UBool fastCopy) {
499
1.10k
  // if assigning to ourselves, do nothing
500
1.10k
  if(this == &src) {
501
0
    return *this;
502
0
  }
503
1.10k
504
1.10k
  // is the right side bogus?
505
1.10k
  if(src.isBogus()) {
506
0
    setToBogus();
507
0
    return *this;
508
0
  }
509
1.10k
510
1.10k
  // delete the current contents
511
1.10k
  releaseArray();
512
1.10k
513
1.10k
  if(src.isEmpty()) {
514
1.09k
    // empty string - use the stack buffer
515
1.09k
    setToEmpty();
516
1.09k
    return *this;
517
1.09k
  }
518
12
519
12
  // fLength>0 and not an "open" src.getBuffer(minCapacity)
520
12
  fUnion.fFields.fLengthAndFlags = src.fUnion.fFields.fLengthAndFlags;
521
12
  switch(src.fUnion.fFields.fLengthAndFlags & kAllStorageFlags) {
522
12
  case kShortString:
523
12
    // short string using the stack buffer, do the same
524
12
    uprv_memcpy(fUnion.fStackFields.fBuffer, src.fUnion.fStackFields.fBuffer,
525
12
                getShortLength() * U_SIZEOF_UCHAR);
526
12
    break;
527
12
  case kLongString:
528
0
    // src uses a refCounted string buffer, use that buffer with refCount
529
0
    // src is const, use a cast - we don't actually change it
530
0
    ((UnicodeString &)src).addRef();
531
0
    // copy all fields, share the reference-counted buffer
532
0
    fUnion.fFields.fArray = src.fUnion.fFields.fArray;
533
0
    fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
534
0
    if(!hasShortLength()) {
535
0
      fUnion.fFields.fLength = src.fUnion.fFields.fLength;
536
0
    }
537
0
    break;
538
12
  case kReadonlyAlias:
539
0
    if(fastCopy) {
540
0
      // src is a readonly alias, do the same
541
0
      // -> maintain the readonly alias as such
542
0
      fUnion.fFields.fArray = src.fUnion.fFields.fArray;
543
0
      fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
544
0
      if(!hasShortLength()) {
545
0
        fUnion.fFields.fLength = src.fUnion.fFields.fLength;
546
0
      }
547
0
      break;
548
0
    }
549
0
    // else if(!fastCopy) fall through to case kWritableAlias
550
0
    // -> allocate a new buffer and copy the contents
551
0
    U_FALLTHROUGH;
552
0
  case kWritableAlias: {
553
0
    // src is a writable alias; we make a copy of that instead
554
0
    int32_t srcLength = src.length();
555
0
    if(allocate(srcLength)) {
556
0
      u_memcpy(getArrayStart(), src.getArrayStart(), srcLength);
557
0
      setLength(srcLength);
558
0
      break;
559
0
    }
560
0
    // if there is not enough memory, then fall through to setting to bogus
561
0
    U_FALLTHROUGH;
562
0
  }
563
0
  default:
564
0
    // if src is bogus, set ourselves to bogus
565
0
    // do not call setToBogus() here because fArray and flags are not consistent here
566
0
    fUnion.fFields.fLengthAndFlags = kIsBogus;
567
0
    fUnion.fFields.fArray = 0;
568
0
    fUnion.fFields.fCapacity = 0;
569
0
    break;
570
12
  }
571
12
572
12
  return *this;
573
12
}
574
575
0
UnicodeString &UnicodeString::moveFrom(UnicodeString &src) U_NOEXCEPT {
576
0
  // No explicit check for self move assignment, consistent with standard library.
577
0
  // Self move assignment causes no crash nor leak but might make the object bogus.
578
0
  releaseArray();
579
0
  copyFieldsFrom(src, TRUE);
580
0
  return *this;
581
0
}
582
583
// Same as moveFrom() except without memory management.
584
0
void UnicodeString::copyFieldsFrom(UnicodeString &src, UBool setSrcToBogus) U_NOEXCEPT {
585
0
  int16_t lengthAndFlags = fUnion.fFields.fLengthAndFlags = src.fUnion.fFields.fLengthAndFlags;
586
0
  if(lengthAndFlags & kUsingStackBuffer) {
587
0
    // Short string using the stack buffer, copy the contents.
588
0
    // Check for self assignment to prevent "overlap in memcpy" warnings,
589
0
    // although it should be harmless to copy a buffer to itself exactly.
590
0
    if(this != &src) {
591
0
      uprv_memcpy(fUnion.fStackFields.fBuffer, src.fUnion.fStackFields.fBuffer,
592
0
                  getShortLength() * U_SIZEOF_UCHAR);
593
0
    }
594
0
  } else {
595
0
    // In all other cases, copy all fields.
596
0
    fUnion.fFields.fArray = src.fUnion.fFields.fArray;
597
0
    fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
598
0
    if(!hasShortLength()) {
599
0
      fUnion.fFields.fLength = src.fUnion.fFields.fLength;
600
0
    }
601
0
    if(setSrcToBogus) {
602
0
      // Set src to bogus without releasing any memory.
603
0
      src.fUnion.fFields.fLengthAndFlags = kIsBogus;
604
0
      src.fUnion.fFields.fArray = NULL;
605
0
      src.fUnion.fFields.fCapacity = 0;
606
0
    }
607
0
  }
608
0
}
609
610
0
void UnicodeString::swap(UnicodeString &other) U_NOEXCEPT {
611
0
  UnicodeString temp;  // Empty short string: Known not to need releaseArray().
612
0
  // Copy fields without resetting source values in between.
613
0
  temp.copyFieldsFrom(*this, FALSE);
614
0
  this->copyFieldsFrom(other, FALSE);
615
0
  other.copyFieldsFrom(temp, FALSE);
616
0
  // Set temp to an empty string so that other's memory is not released twice.
617
0
  temp.fUnion.fFields.fLengthAndFlags = kShortString;
618
0
}
619
620
//========================================
621
// Miscellaneous operations
622
//========================================
623
624
0
UnicodeString UnicodeString::unescape() const {
625
0
    UnicodeString result(length(), (UChar32)0, (int32_t)0); // construct with capacity
626
0
    if (result.isBogus()) {
627
0
        return result;
628
0
    }
629
0
    const UChar *array = getBuffer();
630
0
    int32_t len = length();
631
0
    int32_t prev = 0;
632
0
    for (int32_t i=0;;) {
633
0
        if (i == len) {
634
0
            result.append(array, prev, len - prev);
635
0
            break;
636
0
        }
637
0
        if (array[i++] == 0x5C /*'\\'*/) {
638
0
            result.append(array, prev, (i - 1) - prev);
639
0
            UChar32 c = unescapeAt(i); // advances i
640
0
            if (c < 0) {
641
0
                result.remove(); // return empty string
642
0
                break; // invalid escape sequence
643
0
            }
644
0
            result.append(c);
645
0
            prev = i;
646
0
        }
647
0
    }
648
0
    return result;
649
0
}
650
651
0
UChar32 UnicodeString::unescapeAt(int32_t &offset) const {
652
0
    return u_unescapeAt(UnicodeString_charAt, &offset, length(), (void*)this);
653
0
}
654
655
//========================================
656
// Read-only implementation
657
//========================================
658
UBool
659
0
UnicodeString::doEquals(const UnicodeString &text, int32_t len) const {
660
0
  // Requires: this & text not bogus and have same lengths.
661
0
  // Byte-wise comparison works for equality regardless of endianness.
662
0
  return uprv_memcmp(getArrayStart(), text.getArrayStart(), len * U_SIZEOF_UCHAR) == 0;
663
0
}
664
665
int8_t
666
UnicodeString::doCompare( int32_t start,
667
              int32_t length,
668
              const UChar *srcChars,
669
              int32_t srcStart,
670
              int32_t srcLength) const
671
0
{
672
0
  // compare illegal string values
673
0
  if(isBogus()) {
674
0
    return -1;
675
0
  }
676
0
  
677
0
  // pin indices to legal values
678
0
  pinIndices(start, length);
679
0
680
0
  if(srcChars == NULL) {
681
0
    // treat const UChar *srcChars==NULL as an empty string
682
0
    return length == 0 ? 0 : 1;
683
0
  }
684
0
685
0
  // get the correct pointer
686
0
  const UChar *chars = getArrayStart();
687
0
688
0
  chars += start;
689
0
  srcChars += srcStart;
690
0
691
0
  int32_t minLength;
692
0
  int8_t lengthResult;
693
0
694
0
  // get the srcLength if necessary
695
0
  if(srcLength < 0) {
696
0
    srcLength = u_strlen(srcChars + srcStart);
697
0
  }
698
0
699
0
  // are we comparing different lengths?
700
0
  if(length != srcLength) {
701
0
    if(length < srcLength) {
702
0
      minLength = length;
703
0
      lengthResult = -1;
704
0
    } else {
705
0
      minLength = srcLength;
706
0
      lengthResult = 1;
707
0
    }
708
0
  } else {
709
0
    minLength = length;
710
0
    lengthResult = 0;
711
0
  }
712
0
713
0
  /*
714
0
   * note that uprv_memcmp() returns an int but we return an int8_t;
715
0
   * we need to take care not to truncate the result -
716
0
   * one way to do this is to right-shift the value to
717
0
   * move the sign bit into the lower 8 bits and making sure that this
718
0
   * does not become 0 itself
719
0
   */
720
0
721
0
  if(minLength > 0 && chars != srcChars) {
722
0
    int32_t result;
723
0
724
#   if U_IS_BIG_ENDIAN 
725
      // big-endian: byte comparison works
726
      result = uprv_memcmp(chars, srcChars, minLength * sizeof(UChar));
727
      if(result != 0) {
728
        return (int8_t)(result >> 15 | 1);
729
      }
730
#   else
731
      // little-endian: compare UChar units
732
0
      do {
733
0
        result = ((int32_t)*(chars++) - (int32_t)*(srcChars++));
734
0
        if(result != 0) {
735
0
          return (int8_t)(result >> 15 | 1);
736
0
        }
737
0
      } while(--minLength > 0);
738
0
#   endif
739
0
  }
740
0
  return lengthResult;
741
0
}
742
743
/* String compare in code point order - doCompare() compares in code unit order. */
744
int8_t
745
UnicodeString::doCompareCodePointOrder(int32_t start,
746
                                       int32_t length,
747
                                       const UChar *srcChars,
748
                                       int32_t srcStart,
749
                                       int32_t srcLength) const
750
0
{
751
0
  // compare illegal string values
752
0
  // treat const UChar *srcChars==NULL as an empty string
753
0
  if(isBogus()) {
754
0
    return -1;
755
0
  }
756
0
757
0
  // pin indices to legal values
758
0
  pinIndices(start, length);
759
0
760
0
  if(srcChars == NULL) {
761
0
    srcStart = srcLength = 0;
762
0
  }
763
0
764
0
  int32_t diff = uprv_strCompare(getArrayStart() + start, length, (srcChars!=NULL)?(srcChars + srcStart):NULL, srcLength, FALSE, TRUE);
765
0
  /* translate the 32-bit result into an 8-bit one */
766
0
  if(diff!=0) {
767
0
    return (int8_t)(diff >> 15 | 1);
768
0
  } else {
769
0
    return 0;
770
0
  }
771
0
}
772
773
int32_t
774
0
UnicodeString::getLength() const {
775
0
    return length();
776
0
}
777
778
UChar
779
0
UnicodeString::getCharAt(int32_t offset) const {
780
0
  return charAt(offset);
781
0
}
782
783
UChar32
784
0
UnicodeString::getChar32At(int32_t offset) const {
785
0
  return char32At(offset);
786
0
}
787
788
UChar32
789
UnicodeString::char32At(int32_t offset) const
790
0
{
791
0
  int32_t len = length();
792
0
  if((uint32_t)offset < (uint32_t)len) {
793
0
    const UChar *array = getArrayStart();
794
0
    UChar32 c;
795
0
    U16_GET(array, 0, offset, len, c);
796
0
    return c;
797
0
  } else {
798
0
    return kInvalidUChar;
799
0
  }
800
0
}
801
802
int32_t
803
0
UnicodeString::getChar32Start(int32_t offset) const {
804
0
  if((uint32_t)offset < (uint32_t)length()) {
805
0
    const UChar *array = getArrayStart();
806
0
    U16_SET_CP_START(array, 0, offset);
807
0
    return offset;
808
0
  } else {
809
0
    return 0;
810
0
  }
811
0
}
812
813
int32_t
814
0
UnicodeString::getChar32Limit(int32_t offset) const {
815
0
  int32_t len = length();
816
0
  if((uint32_t)offset < (uint32_t)len) {
817
0
    const UChar *array = getArrayStart();
818
0
    U16_SET_CP_LIMIT(array, 0, offset, len);
819
0
    return offset;
820
0
  } else {
821
0
    return len;
822
0
  }
823
0
}
824
825
int32_t
826
0
UnicodeString::countChar32(int32_t start, int32_t length) const {
827
0
  pinIndices(start, length);
828
0
  // if(isBogus()) then fArray==0 and start==0 - u_countChar32() checks for NULL
829
0
  return u_countChar32(getArrayStart()+start, length);
830
0
}
831
832
UBool
833
0
UnicodeString::hasMoreChar32Than(int32_t start, int32_t length, int32_t number) const {
834
0
  pinIndices(start, length);
835
0
  // if(isBogus()) then fArray==0 and start==0 - u_strHasMoreChar32Than() checks for NULL
836
0
  return u_strHasMoreChar32Than(getArrayStart()+start, length, number);
837
0
}
838
839
int32_t
840
0
UnicodeString::moveIndex32(int32_t index, int32_t delta) const {
841
0
  // pin index
842
0
  int32_t len = length();
843
0
  if(index<0) {
844
0
    index=0;
845
0
  } else if(index>len) {
846
0
    index=len;
847
0
  }
848
0
849
0
  const UChar *array = getArrayStart();
850
0
  if(delta>0) {
851
0
    U16_FWD_N(array, index, len, delta);
852
0
  } else {
853
0
    U16_BACK_N(array, 0, index, -delta);
854
0
  }
855
0
856
0
  return index;
857
0
}
858
859
void
860
UnicodeString::doExtract(int32_t start,
861
             int32_t length,
862
             UChar *dst,
863
             int32_t dstStart) const
864
0
{
865
0
  // pin indices to legal values
866
0
  pinIndices(start, length);
867
0
868
0
  // do not copy anything if we alias dst itself
869
0
  const UChar *array = getArrayStart();
870
0
  if(array + start != dst + dstStart) {
871
0
    us_arrayCopy(array, start, dst, dstStart, length);
872
0
  }
873
0
}
874
875
int32_t
876
UnicodeString::extract(Char16Ptr dest, int32_t destCapacity,
877
89.6k
                       UErrorCode &errorCode) const {
878
89.6k
  int32_t len = length();
879
89.6k
  if(U_SUCCESS(errorCode)) {
880
89.6k
    if(isBogus() || destCapacity<0 || (destCapacity>0 && dest==0)) {
881
0
      errorCode=U_ILLEGAL_ARGUMENT_ERROR;
882
89.6k
    } else {
883
89.6k
      const UChar *array = getArrayStart();
884
89.6k
      if(len>0 && len<=destCapacity && array!=dest) {
885
1
        u_memcpy(dest, array, len);
886
1
      }
887
89.6k
      return u_terminateUChars(dest, destCapacity, len, &errorCode);
888
89.6k
    }
889
0
  }
890
0
891
0
  return len;
892
0
}
893
894
int32_t
895
UnicodeString::extract(int32_t start,
896
                       int32_t length,
897
                       char *target,
898
                       int32_t targetCapacity,
899
                       enum EInvariant) const
900
0
{
901
0
  // if the arguments are illegal, then do nothing
902
0
  if(targetCapacity < 0 || (targetCapacity > 0 && target == NULL)) {
903
0
    return 0;
904
0
  }
905
0
906
0
  // pin the indices to legal values
907
0
  pinIndices(start, length);
908
0
909
0
  if(length <= targetCapacity) {
910
0
    u_UCharsToChars(getArrayStart() + start, target, length);
911
0
  }
912
0
  UErrorCode status = U_ZERO_ERROR;
913
0
  return u_terminateChars(target, targetCapacity, length, &status);
914
0
}
915
916
UnicodeString
917
53.8k
UnicodeString::tempSubString(int32_t start, int32_t len) const {
918
53.8k
  pinIndices(start, len);
919
53.8k
  const UChar *array = getBuffer();  // not getArrayStart() to check kIsBogus & kOpenGetBuffer
920
53.8k
  if(array==NULL) {
921
0
    array=fUnion.fStackFields.fBuffer;  // anything not NULL because that would make an empty string
922
0
    len=-2;  // bogus result string
923
0
  }
924
53.8k
  return UnicodeString(FALSE, array + start, len);
925
53.8k
}
926
927
int32_t
928
UnicodeString::toUTF8(int32_t start, int32_t len,
929
0
                      char *target, int32_t capacity) const {
930
0
  pinIndices(start, len);
931
0
  int32_t length8;
932
0
  UErrorCode errorCode = U_ZERO_ERROR;
933
0
  u_strToUTF8WithSub(target, capacity, &length8,
934
0
                     getBuffer() + start, len,
935
0
                     0xFFFD,  // Standard substitution character.
936
0
                     NULL,    // Don't care about number of substitutions.
937
0
                     &errorCode);
938
0
  return length8;
939
0
}
940
941
#if U_CHARSET_IS_UTF8
942
943
int32_t
944
UnicodeString::extract(int32_t start, int32_t len,
945
0
                       char *target, uint32_t dstSize) const {
946
0
  // if the arguments are illegal, then do nothing
947
0
  if(/*dstSize < 0 || */(dstSize > 0 && target == 0)) {
948
0
    return 0;
949
0
  }
950
0
  return toUTF8(start, len, target, dstSize <= 0x7fffffff ? (int32_t)dstSize : 0x7fffffff);
951
0
}
952
953
// else see unistr_cnv.cpp
954
#endif
955
956
void 
957
UnicodeString::extractBetween(int32_t start,
958
                  int32_t limit,
959
0
                  UnicodeString& target) const {
960
0
  pinIndex(start);
961
0
  pinIndex(limit);
962
0
  doExtract(start, limit - start, target);
963
0
}
964
965
// When converting from UTF-16 to UTF-8, the result will have at most 3 times
966
// as many bytes as the source has UChars.
967
// The "worst cases" are writing systems like Indic, Thai and CJK with
968
// 3:1 bytes:UChars.
969
void
970
0
UnicodeString::toUTF8(ByteSink &sink) const {
971
0
  int32_t length16 = length();
972
0
  if(length16 != 0) {
973
0
    char stackBuffer[1024];
974
0
    int32_t capacity = (int32_t)sizeof(stackBuffer);
975
0
    UBool utf8IsOwned = FALSE;
976
0
    char *utf8 = sink.GetAppendBuffer(length16 < capacity ? length16 : capacity,
977
0
                                      3*length16,
978
0
                                      stackBuffer, capacity,
979
0
                                      &capacity);
980
0
    int32_t length8 = 0;
981
0
    UErrorCode errorCode = U_ZERO_ERROR;
982
0
    u_strToUTF8WithSub(utf8, capacity, &length8,
983
0
                       getBuffer(), length16,
984
0
                       0xFFFD,  // Standard substitution character.
985
0
                       NULL,    // Don't care about number of substitutions.
986
0
                       &errorCode);
987
0
    if(errorCode == U_BUFFER_OVERFLOW_ERROR) {
988
0
      utf8 = (char *)uprv_malloc(length8);
989
0
      if(utf8 != NULL) {
990
0
        utf8IsOwned = TRUE;
991
0
        errorCode = U_ZERO_ERROR;
992
0
        u_strToUTF8WithSub(utf8, length8, &length8,
993
0
                           getBuffer(), length16,
994
0
                           0xFFFD,  // Standard substitution character.
995
0
                           NULL,    // Don't care about number of substitutions.
996
0
                           &errorCode);
997
0
      } else {
998
0
        errorCode = U_MEMORY_ALLOCATION_ERROR;
999
0
      }
1000
0
    }
1001
0
    if(U_SUCCESS(errorCode)) {
1002
0
      sink.Append(utf8, length8);
1003
0
      sink.Flush();
1004
0
    }
1005
0
    if(utf8IsOwned) {
1006
0
      uprv_free(utf8);
1007
0
    }
1008
0
  }
1009
0
}
1010
1011
int32_t
1012
0
UnicodeString::toUTF32(UChar32 *utf32, int32_t capacity, UErrorCode &errorCode) const {
1013
0
  int32_t length32=0;
1014
0
  if(U_SUCCESS(errorCode)) {
1015
0
    // getBuffer() and u_strToUTF32WithSub() check for illegal arguments.
1016
0
    u_strToUTF32WithSub(utf32, capacity, &length32,
1017
0
        getBuffer(), length(),
1018
0
        0xfffd,  // Substitution character.
1019
0
        NULL,    // Don't care about number of substitutions.
1020
0
        &errorCode);
1021
0
  }
1022
0
  return length32;
1023
0
}
1024
1025
int32_t 
1026
UnicodeString::indexOf(const UChar *srcChars,
1027
               int32_t srcStart,
1028
               int32_t srcLength,
1029
               int32_t start,
1030
               int32_t length) const
1031
0
{
1032
0
  if(isBogus() || srcChars == 0 || srcStart < 0 || srcLength == 0) {
1033
0
    return -1;
1034
0
  }
1035
0
1036
0
  // UnicodeString does not find empty substrings
1037
0
  if(srcLength < 0 && srcChars[srcStart] == 0) {
1038
0
    return -1;
1039
0
  }
1040
0
1041
0
  // get the indices within bounds
1042
0
  pinIndices(start, length);
1043
0
1044
0
  // find the first occurrence of the substring
1045
0
  const UChar *array = getArrayStart();
1046
0
  const UChar *match = u_strFindFirst(array + start, length, srcChars + srcStart, srcLength);
1047
0
  if(match == NULL) {
1048
0
    return -1;
1049
0
  } else {
1050
0
    return (int32_t)(match - array);
1051
0
  }
1052
0
}
1053
1054
int32_t
1055
UnicodeString::doIndexOf(UChar c,
1056
             int32_t start,
1057
             int32_t length) const
1058
0
{
1059
0
  // pin indices
1060
0
  pinIndices(start, length);
1061
0
1062
0
  // find the first occurrence of c
1063
0
  const UChar *array = getArrayStart();
1064
0
  const UChar *match = u_memchr(array + start, c, length);
1065
0
  if(match == NULL) {
1066
0
    return -1;
1067
0
  } else {
1068
0
    return (int32_t)(match - array);
1069
0
  }
1070
0
}
1071
1072
int32_t
1073
UnicodeString::doIndexOf(UChar32 c,
1074
                         int32_t start,
1075
0
                         int32_t length) const {
1076
0
  // pin indices
1077
0
  pinIndices(start, length);
1078
0
1079
0
  // find the first occurrence of c
1080
0
  const UChar *array = getArrayStart();
1081
0
  const UChar *match = u_memchr32(array + start, c, length);
1082
0
  if(match == NULL) {
1083
0
    return -1;
1084
0
  } else {
1085
0
    return (int32_t)(match - array);
1086
0
  }
1087
0
}
1088
1089
int32_t 
1090
UnicodeString::lastIndexOf(const UChar *srcChars,
1091
               int32_t srcStart,
1092
               int32_t srcLength,
1093
               int32_t start,
1094
               int32_t length) const
1095
0
{
1096
0
  if(isBogus() || srcChars == 0 || srcStart < 0 || srcLength == 0) {
1097
0
    return -1;
1098
0
  }
1099
0
1100
0
  // UnicodeString does not find empty substrings
1101
0
  if(srcLength < 0 && srcChars[srcStart] == 0) {
1102
0
    return -1;
1103
0
  }
1104
0
1105
0
  // get the indices within bounds
1106
0
  pinIndices(start, length);
1107
0
1108
0
  // find the last occurrence of the substring
1109
0
  const UChar *array = getArrayStart();
1110
0
  const UChar *match = u_strFindLast(array + start, length, srcChars + srcStart, srcLength);
1111
0
  if(match == NULL) {
1112
0
    return -1;
1113
0
  } else {
1114
0
    return (int32_t)(match - array);
1115
0
  }
1116
0
}
1117
1118
int32_t
1119
UnicodeString::doLastIndexOf(UChar c,
1120
                 int32_t start,
1121
                 int32_t length) const
1122
0
{
1123
0
  if(isBogus()) {
1124
0
    return -1;
1125
0
  }
1126
0
1127
0
  // pin indices
1128
0
  pinIndices(start, length);
1129
0
1130
0
  // find the last occurrence of c
1131
0
  const UChar *array = getArrayStart();
1132
0
  const UChar *match = u_memrchr(array + start, c, length);
1133
0
  if(match == NULL) {
1134
0
    return -1;
1135
0
  } else {
1136
0
    return (int32_t)(match - array);
1137
0
  }
1138
0
}
1139
1140
int32_t
1141
UnicodeString::doLastIndexOf(UChar32 c,
1142
                             int32_t start,
1143
0
                             int32_t length) const {
1144
0
  // pin indices
1145
0
  pinIndices(start, length);
1146
0
1147
0
  // find the last occurrence of c
1148
0
  const UChar *array = getArrayStart();
1149
0
  const UChar *match = u_memrchr32(array + start, c, length);
1150
0
  if(match == NULL) {
1151
0
    return -1;
1152
0
  } else {
1153
0
    return (int32_t)(match - array);
1154
0
  }
1155
0
}
1156
1157
//========================================
1158
// Write implementation
1159
//========================================
1160
1161
UnicodeString& 
1162
UnicodeString::findAndReplace(int32_t start,
1163
                  int32_t length,
1164
                  const UnicodeString& oldText,
1165
                  int32_t oldStart,
1166
                  int32_t oldLength,
1167
                  const UnicodeString& newText,
1168
                  int32_t newStart,
1169
                  int32_t newLength)
1170
0
{
1171
0
  if(isBogus() || oldText.isBogus() || newText.isBogus()) {
1172
0
    return *this;
1173
0
  }
1174
0
1175
0
  pinIndices(start, length);
1176
0
  oldText.pinIndices(oldStart, oldLength);
1177
0
  newText.pinIndices(newStart, newLength);
1178
0
1179
0
  if(oldLength == 0) {
1180
0
    return *this;
1181
0
  }
1182
0
1183
0
  while(length > 0 && length >= oldLength) {
1184
0
    int32_t pos = indexOf(oldText, oldStart, oldLength, start, length);
1185
0
    if(pos < 0) {
1186
0
      // no more oldText's here: done
1187
0
      break;
1188
0
    } else {
1189
0
      // we found oldText, replace it by newText and go beyond it
1190
0
      replace(pos, oldLength, newText, newStart, newLength);
1191
0
      length -= pos + oldLength - start;
1192
0
      start = pos + newLength;
1193
0
    }
1194
0
  }
1195
0
1196
0
  return *this;
1197
0
}
1198
1199
1200
void
1201
UnicodeString::setToBogus()
1202
0
{
1203
0
  releaseArray();
1204
0
1205
0
  fUnion.fFields.fLengthAndFlags = kIsBogus;
1206
0
  fUnion.fFields.fArray = 0;
1207
0
  fUnion.fFields.fCapacity = 0;
1208
0
}
1209
1210
// turn a bogus string into an empty one
1211
void
1212
0
UnicodeString::unBogus() {
1213
0
  if(fUnion.fFields.fLengthAndFlags & kIsBogus) {
1214
0
    setToEmpty();
1215
0
  }
1216
0
}
1217
1218
const char16_t *
1219
0
UnicodeString::getTerminatedBuffer() {
1220
0
  if(!isWritable()) {
1221
0
    return nullptr;
1222
0
  }
1223
0
  UChar *array = getArrayStart();
1224
0
  int32_t len = length();
1225
0
  if(len < getCapacity()) {
1226
0
    if(fUnion.fFields.fLengthAndFlags & kBufferIsReadonly) {
1227
0
      // If len<capacity on a read-only alias, then array[len] is
1228
0
      // either the original NUL (if constructed with (TRUE, s, length))
1229
0
      // or one of the original string contents characters (if later truncated),
1230
0
      // therefore we can assume that array[len] is initialized memory.
1231
0
      if(array[len] == 0) {
1232
0
        return array;
1233
0
      }
1234
0
    } else if(((fUnion.fFields.fLengthAndFlags & kRefCounted) == 0 || refCount() == 1)) {
1235
0
      // kRefCounted: Do not write the NUL if the buffer is shared.
1236
0
      // That is mostly safe, except when the length of one copy was modified
1237
0
      // without copy-on-write, e.g., via truncate(newLength) or remove(void).
1238
0
      // Then the NUL would be written into the middle of another copy's string.
1239
0
1240
0
      // Otherwise, the buffer is fully writable and it is anyway safe to write the NUL.
1241
0
      // Do not test if there is a NUL already because it might be uninitialized memory.
1242
0
      // (That would be safe, but tools like valgrind & Purify would complain.)
1243
0
      array[len] = 0;
1244
0
      return array;
1245
0
    }
1246
0
  }
1247
0
  if(len<INT32_MAX && cloneArrayIfNeeded(len+1)) {
1248
0
    array = getArrayStart();
1249
0
    array[len] = 0;
1250
0
    return array;
1251
0
  } else {
1252
0
    return nullptr;
1253
0
  }
1254
0
}
1255
1256
// setTo() analogous to the readonly-aliasing constructor with the same signature
1257
UnicodeString &
1258
UnicodeString::setTo(UBool isTerminated,
1259
                     ConstChar16Ptr textPtr,
1260
                     int32_t textLength)
1261
0
{
1262
0
  if(fUnion.fFields.fLengthAndFlags & kOpenGetBuffer) {
1263
0
    // do not modify a string that has an "open" getBuffer(minCapacity)
1264
0
    return *this;
1265
0
  }
1266
0
1267
0
  const UChar *text = textPtr;
1268
0
  if(text == NULL) {
1269
0
    // treat as an empty string, do not alias
1270
0
    releaseArray();
1271
0
    setToEmpty();
1272
0
    return *this;
1273
0
  }
1274
0
1275
0
  if( textLength < -1 ||
1276
0
      (textLength == -1 && !isTerminated) ||
1277
0
      (textLength >= 0 && isTerminated && text[textLength] != 0)
1278
0
  ) {
1279
0
    setToBogus();
1280
0
    return *this;
1281
0
  }
1282
0
1283
0
  releaseArray();
1284
0
1285
0
  if(textLength == -1) {
1286
0
    // text is terminated, or else it would have failed the above test
1287
0
    textLength = u_strlen(text);
1288
0
  }
1289
0
  fUnion.fFields.fLengthAndFlags = kReadonlyAlias;
1290
0
  setArray((UChar *)text, textLength, isTerminated ? textLength + 1 : textLength);
1291
0
  return *this;
1292
0
}
1293
1294
// setTo() analogous to the writable-aliasing constructor with the same signature
1295
UnicodeString &
1296
UnicodeString::setTo(UChar *buffer,
1297
                     int32_t buffLength,
1298
0
                     int32_t buffCapacity) {
1299
0
  if(fUnion.fFields.fLengthAndFlags & kOpenGetBuffer) {
1300
0
    // do not modify a string that has an "open" getBuffer(minCapacity)
1301
0
    return *this;
1302
0
  }
1303
0
1304
0
  if(buffer == NULL) {
1305
0
    // treat as an empty string, do not alias
1306
0
    releaseArray();
1307
0
    setToEmpty();
1308
0
    return *this;
1309
0
  }
1310
0
1311
0
  if(buffLength < -1 || buffCapacity < 0 || buffLength > buffCapacity) {
1312
0
    setToBogus();
1313
0
    return *this;
1314
0
  } else if(buffLength == -1) {
1315
0
    // buffLength = u_strlen(buff); but do not look beyond buffCapacity
1316
0
    const UChar *p = buffer, *limit = buffer + buffCapacity;
1317
0
    while(p != limit && *p != 0) {
1318
0
      ++p;
1319
0
    }
1320
0
    buffLength = (int32_t)(p - buffer);
1321
0
  }
1322
0
1323
0
  releaseArray();
1324
0
1325
0
  fUnion.fFields.fLengthAndFlags = kWritableAlias;
1326
0
  setArray(buffer, buffLength, buffCapacity);
1327
0
  return *this;
1328
0
}
1329
1330
0
UnicodeString &UnicodeString::setToUTF8(StringPiece utf8) {
1331
0
  unBogus();
1332
0
  int32_t length = utf8.length();
1333
0
  int32_t capacity;
1334
0
  // The UTF-16 string will be at most as long as the UTF-8 string.
1335
0
  if(length <= US_STACKBUF_SIZE) {
1336
0
    capacity = US_STACKBUF_SIZE;
1337
0
  } else {
1338
0
    capacity = length + 1;  // +1 for the terminating NUL.
1339
0
  }
1340
0
  UChar *utf16 = getBuffer(capacity);
1341
0
  int32_t length16;
1342
0
  UErrorCode errorCode = U_ZERO_ERROR;
1343
0
  u_strFromUTF8WithSub(utf16, getCapacity(), &length16,
1344
0
      utf8.data(), length,
1345
0
      0xfffd,  // Substitution character.
1346
0
      NULL,    // Don't care about number of substitutions.
1347
0
      &errorCode);
1348
0
  releaseBuffer(length16);
1349
0
  if(U_FAILURE(errorCode)) {
1350
0
    setToBogus();
1351
0
  }
1352
0
  return *this;
1353
0
}
1354
1355
UnicodeString&
1356
UnicodeString::setCharAt(int32_t offset,
1357
             UChar c)
1358
0
{
1359
0
  int32_t len = length();
1360
0
  if(cloneArrayIfNeeded() && len > 0) {
1361
0
    if(offset < 0) {
1362
0
      offset = 0;
1363
0
    } else if(offset >= len) {
1364
0
      offset = len - 1;
1365
0
    }
1366
0
1367
0
    getArrayStart()[offset] = c;
1368
0
  }
1369
0
  return *this;
1370
0
}
1371
1372
UnicodeString&
1373
UnicodeString::replace(int32_t start,
1374
               int32_t _length,
1375
0
               UChar32 srcChar) {
1376
0
  UChar buffer[U16_MAX_LENGTH];
1377
0
  int32_t count = 0;
1378
0
  UBool isError = FALSE;
1379
0
  U16_APPEND(buffer, count, U16_MAX_LENGTH, srcChar, isError);
1380
0
  // We test isError so that the compiler does not complain that we don't.
1381
0
  // If isError (srcChar is not a valid code point) then count==0 which means
1382
0
  // we remove the source segment rather than replacing it with srcChar.
1383
0
  return doReplace(start, _length, buffer, 0, isError ? 0 : count);
1384
0
}
1385
1386
UnicodeString&
1387
0
UnicodeString::append(UChar32 srcChar) {
1388
0
  UChar buffer[U16_MAX_LENGTH];
1389
0
  int32_t _length = 0;
1390
0
  UBool isError = FALSE;
1391
0
  U16_APPEND(buffer, _length, U16_MAX_LENGTH, srcChar, isError);
1392
0
  // We test isError so that the compiler does not complain that we don't.
1393
0
  // If isError then _length==0 which turns the doAppend() into a no-op anyway.
1394
0
  return isError ? *this : doAppend(buffer, 0, _length);
1395
0
}
1396
1397
UnicodeString&
1398
UnicodeString::doReplace( int32_t start,
1399
              int32_t length,
1400
              const UnicodeString& src,
1401
              int32_t srcStart,
1402
              int32_t srcLength)
1403
6.44k
{
1404
6.44k
  // pin the indices to legal values
1405
6.44k
  src.pinIndices(srcStart, srcLength);
1406
6.44k
1407
6.44k
  // get the characters from src
1408
6.44k
  // and replace the range in ourselves with them
1409
6.44k
  return doReplace(start, length, src.getArrayStart(), srcStart, srcLength);
1410
6.44k
}
1411
1412
UnicodeString&
1413
UnicodeString::doReplace(int32_t start,
1414
             int32_t length,
1415
             const UChar *srcChars,
1416
             int32_t srcStart,
1417
             int32_t srcLength)
1418
7.11k
{
1419
7.11k
  if(!isWritable()) {
1420
0
    return *this;
1421
0
  }
1422
7.11k
1423
7.11k
  int32_t oldLength = this->length();
1424
7.11k
1425
7.11k
  // optimize (read-only alias).remove(0, start) and .remove(start, end)
1426
7.11k
  if((fUnion.fFields.fLengthAndFlags&kBufferIsReadonly) && srcLength == 0) {
1427
0
    if(start == 0) {
1428
0
      // remove prefix by adjusting the array pointer
1429
0
      pinIndex(length);
1430
0
      fUnion.fFields.fArray += length;
1431
0
      fUnion.fFields.fCapacity -= length;
1432
0
      setLength(oldLength - length);
1433
0
      return *this;
1434
0
    } else {
1435
0
      pinIndex(start);
1436
0
      if(length >= (oldLength - start)) {
1437
0
        // remove suffix by reducing the length (like truncate())
1438
0
        setLength(start);
1439
0
        fUnion.fFields.fCapacity = start;  // not NUL-terminated any more
1440
0
        return *this;
1441
0
      }
1442
7.11k
    }
1443
0
  }
1444
7.11k
1445
7.11k
  if(start == oldLength) {
1446
668
    return doAppend(srcChars, srcStart, srcLength);
1447
668
  }
1448
6.44k
1449
6.44k
  if(srcChars == 0) {
1450
0
    srcStart = srcLength = 0;
1451
6.44k
  } else if(srcLength < 0) {
1452
0
    // get the srcLength if necessary
1453
0
    srcLength = u_strlen(srcChars + srcStart);
1454
0
  }
1455
6.44k
1456
6.44k
  // pin the indices to legal values
1457
6.44k
  pinIndices(start, length);
1458
6.44k
1459
6.44k
  // Calculate the size of the string after the replace.
1460
6.44k
  // Avoid int32_t overflow.
1461
6.44k
  int32_t newLength = oldLength - length;
1462
6.44k
  if(srcLength > (INT32_MAX - newLength)) {
1463
0
    setToBogus();
1464
0
    return *this;
1465
0
  }
1466
6.44k
  newLength += srcLength;
1467
6.44k
1468
6.44k
  // cloneArrayIfNeeded(doCopyArray=FALSE) may change fArray but will not copy the current contents;
1469
6.44k
  // therefore we need to keep the current fArray
1470
6.44k
  UChar oldStackBuffer[US_STACKBUF_SIZE];
1471
6.44k
  UChar *oldArray;
1472
6.44k
  if((fUnion.fFields.fLengthAndFlags&kUsingStackBuffer) && (newLength > US_STACKBUF_SIZE)) {
1473
0
    // copy the stack buffer contents because it will be overwritten with
1474
0
    // fUnion.fFields values
1475
0
    u_memcpy(oldStackBuffer, fUnion.fStackFields.fBuffer, oldLength);
1476
0
    oldArray = oldStackBuffer;
1477
6.44k
  } else {
1478
6.44k
    oldArray = getArrayStart();
1479
6.44k
  }
1480
6.44k
1481
6.44k
  // clone our array and allocate a bigger array if needed
1482
6.44k
  int32_t *bufferToDelete = 0;
1483
6.44k
  if(!cloneArrayIfNeeded(newLength, getGrowCapacity(newLength),
1484
6.44k
                         FALSE, &bufferToDelete)
1485
0
  ) {
1486
0
    return *this;
1487
0
  }
1488
6.44k
1489
6.44k
  // now do the replace
1490
6.44k
1491
6.44k
  UChar *newArray = getArrayStart();
1492
6.44k
  if(newArray != oldArray) {
1493
0
    // if fArray changed, then we need to copy everything except what will change
1494
0
    us_arrayCopy(oldArray, 0, newArray, 0, start);
1495
0
    us_arrayCopy(oldArray, start + length,
1496
0
                 newArray, start + srcLength,
1497
0
                 oldLength - (start + length));
1498
6.44k
  } else if(length != srcLength) {
1499
6.44k
    // fArray did not change; copy only the portion that isn't changing, leaving a hole
1500
6.44k
    us_arrayCopy(oldArray, start + length,
1501
6.44k
                 newArray, start + srcLength,
1502
6.44k
                 oldLength - (start + length));
1503
6.44k
  }
1504
6.44k
1505
6.44k
  // now fill in the hole with the new string
1506
6.44k
  us_arrayCopy(srcChars, srcStart, newArray, start, srcLength);
1507
6.44k
1508
6.44k
  setLength(newLength);
1509
6.44k
1510
6.44k
  // delayed delete in case srcChars == fArray when we started, and
1511
6.44k
  // to keep oldArray alive for the above operations
1512
6.44k
  if (bufferToDelete) {
1513
0
    uprv_free(bufferToDelete);
1514
0
  }
1515
6.44k
1516
6.44k
  return *this;
1517
6.44k
}
1518
1519
// Versions of doReplace() only for append() variants.
1520
// doReplace() and doAppend() optimize for different cases.
1521
1522
UnicodeString&
1523
0
UnicodeString::doAppend(const UnicodeString& src, int32_t srcStart, int32_t srcLength) {
1524
0
  if(srcLength == 0) {
1525
0
    return *this;
1526
0
  }
1527
0
1528
0
  // pin the indices to legal values
1529
0
  src.pinIndices(srcStart, srcLength);
1530
0
  return doAppend(src.getArrayStart(), srcStart, srcLength);
1531
0
}
1532
1533
UnicodeString&
1534
2.87k
UnicodeString::doAppend(const UChar *srcChars, int32_t srcStart, int32_t srcLength) {
1535
2.87k
  if(!isWritable() || srcLength == 0 || srcChars == NULL) {
1536
1.09k
    return *this;
1537
1.09k
  }
1538
1.78k
1539
1.78k
  if(srcLength < 0) {
1540
0
    // get the srcLength if necessary
1541
0
    if((srcLength = u_strlen(srcChars + srcStart)) == 0) {
1542
0
      return *this;
1543
0
    }
1544
1.78k
  }
1545
1.78k
1546
1.78k
  int32_t oldLength = length();
1547
1.78k
  int32_t newLength = oldLength + srcLength;
1548
1.78k
  // optimize append() onto a large-enough, owned string
1549
1.78k
  if((newLength <= getCapacity() && isBufferWritable()) ||
1550
1.78k
      cloneArrayIfNeeded(newLength, getGrowCapacity(newLength))) {
1551
1.78k
    UChar *newArray = getArrayStart();
1552
1.78k
    // Do not copy characters when
1553
1.78k
    //   UChar *buffer=str.getAppendBuffer(...);
1554
1.78k
    // is followed by
1555
1.78k
    //   str.append(buffer, length);
1556
1.78k
    // or
1557
1.78k
    //   str.appendString(buffer, length)
1558
1.78k
    // or similar.
1559
1.78k
    if(srcChars + srcStart != newArray + oldLength) {
1560
1.78k
      us_arrayCopy(srcChars, srcStart, newArray, oldLength, srcLength);
1561
1.78k
    }
1562
1.78k
    setLength(newLength);
1563
1.78k
  }
1564
1.78k
  return *this;
1565
1.78k
}
1566
1567
/**
1568
 * Replaceable API
1569
 */
1570
void
1571
UnicodeString::handleReplaceBetween(int32_t start,
1572
                                    int32_t limit,
1573
0
                                    const UnicodeString& text) {
1574
0
    replaceBetween(start, limit, text);
1575
0
}
1576
1577
/**
1578
 * Replaceable API
1579
 */
1580
void 
1581
0
UnicodeString::copy(int32_t start, int32_t limit, int32_t dest) {
1582
0
    if (limit <= start) {
1583
0
        return; // Nothing to do; avoid bogus malloc call
1584
0
    }
1585
0
    UChar* text = (UChar*) uprv_malloc( sizeof(UChar) * (limit - start) );
1586
0
    // Check to make sure text is not null.
1587
0
    if (text != NULL) {
1588
0
      extractBetween(start, limit, text, 0);
1589
0
      insert(dest, text, 0, limit - start);    
1590
0
      uprv_free(text);
1591
0
    }
1592
0
}
1593
1594
/**
1595
 * Replaceable API
1596
 *
1597
 * NOTE: This is for the Replaceable class.  There is no rep.cpp,
1598
 * so we implement this function here.
1599
 */
1600
0
UBool Replaceable::hasMetaData() const {
1601
0
    return TRUE;
1602
0
}
1603
1604
/**
1605
 * Replaceable API
1606
 */
1607
0
UBool UnicodeString::hasMetaData() const {
1608
0
    return FALSE;
1609
0
}
1610
1611
UnicodeString&
1612
0
UnicodeString::doReverse(int32_t start, int32_t length) {
1613
0
  if(length <= 1 || !cloneArrayIfNeeded()) {
1614
0
    return *this;
1615
0
  }
1616
0
1617
0
  // pin the indices to legal values
1618
0
  pinIndices(start, length);
1619
0
  if(length <= 1) {  // pinIndices() might have shrunk the length
1620
0
    return *this;
1621
0
  }
1622
0
1623
0
  UChar *left = getArrayStart() + start;
1624
0
  UChar *right = left + length - 1;  // -1 for inclusive boundary (length>=2)
1625
0
  UChar swap;
1626
0
  UBool hasSupplementary = FALSE;
1627
0
1628
0
  // Before the loop we know left<right because length>=2.
1629
0
  do {
1630
0
    hasSupplementary |= (UBool)U16_IS_LEAD(swap = *left);
1631
0
    hasSupplementary |= (UBool)U16_IS_LEAD(*left++ = *right);
1632
0
    *right-- = swap;
1633
0
  } while(left < right);
1634
0
  // Make sure to test the middle code unit of an odd-length string.
1635
0
  // Redundant if the length is even.
1636
0
  hasSupplementary |= (UBool)U16_IS_LEAD(*left);
1637
0
1638
0
  /* if there are supplementary code points in the reversed range, then re-swap their surrogates */
1639
0
  if(hasSupplementary) {
1640
0
    UChar swap2;
1641
0
1642
0
    left = getArrayStart() + start;
1643
0
    right = left + length - 1; // -1 so that we can look at *(left+1) if left<right
1644
0
    while(left < right) {
1645
0
      if(U16_IS_TRAIL(swap = *left) && U16_IS_LEAD(swap2 = *(left + 1))) {
1646
0
        *left++ = swap2;
1647
0
        *left++ = swap;
1648
0
      } else {
1649
0
        ++left;
1650
0
      }
1651
0
    }
1652
0
  }
1653
0
1654
0
  return *this;
1655
0
}
1656
1657
UBool 
1658
UnicodeString::padLeading(int32_t targetLength,
1659
                          UChar padChar)
1660
0
{
1661
0
  int32_t oldLength = length();
1662
0
  if(oldLength >= targetLength || !cloneArrayIfNeeded(targetLength)) {
1663
0
    return FALSE;
1664
0
  } else {
1665
0
    // move contents up by padding width
1666
0
    UChar *array = getArrayStart();
1667
0
    int32_t start = targetLength - oldLength;
1668
0
    us_arrayCopy(array, 0, array, start, oldLength);
1669
0
1670
0
    // fill in padding character
1671
0
    while(--start >= 0) {
1672
0
      array[start] = padChar;
1673
0
    }
1674
0
    setLength(targetLength);
1675
0
    return TRUE;
1676
0
  }
1677
0
}
1678
1679
UBool 
1680
UnicodeString::padTrailing(int32_t targetLength,
1681
                           UChar padChar)
1682
0
{
1683
0
  int32_t oldLength = length();
1684
0
  if(oldLength >= targetLength || !cloneArrayIfNeeded(targetLength)) {
1685
0
    return FALSE;
1686
0
  } else {
1687
0
    // fill in padding character
1688
0
    UChar *array = getArrayStart();
1689
0
    int32_t length = targetLength;
1690
0
    while(--length >= oldLength) {
1691
0
      array[length] = padChar;
1692
0
    }
1693
0
    setLength(targetLength);
1694
0
    return TRUE;
1695
0
  }
1696
0
}
1697
1698
//========================================
1699
// Hashing
1700
//========================================
1701
int32_t
1702
UnicodeString::doHashCode() const
1703
0
{
1704
0
    /* Delegate hash computation to uhash.  This makes UnicodeString
1705
0
     * hashing consistent with UChar* hashing.  */
1706
0
    int32_t hashCode = ustr_hashUCharsN(getArrayStart(), length());
1707
0
    if (hashCode == kInvalidHashCode) {
1708
0
        hashCode = kEmptyHashCode;
1709
0
    }
1710
0
    return hashCode;
1711
0
}
1712
1713
//========================================
1714
// External Buffer
1715
//========================================
1716
1717
char16_t *
1718
188k
UnicodeString::getBuffer(int32_t minCapacity) {
1719
188k
  if(minCapacity>=-1 && cloneArrayIfNeeded(minCapacity)) {
1720
188k
    fUnion.fFields.fLengthAndFlags|=kOpenGetBuffer;
1721
188k
    setZeroLength();
1722
188k
    return getArrayStart();
1723
188k
  } else {
1724
0
    return nullptr;
1725
0
  }
1726
188k
}
1727
1728
void
1729
188k
UnicodeString::releaseBuffer(int32_t newLength) {
1730
188k
  if(fUnion.fFields.fLengthAndFlags&kOpenGetBuffer && newLength>=-1) {
1731
188k
    // set the new fLength
1732
188k
    int32_t capacity=getCapacity();
1733
188k
    if(newLength==-1) {
1734
0
      // the new length is the string length, capped by fCapacity
1735
0
      const UChar *array=getArrayStart(), *p=array, *limit=array+capacity;
1736
0
      while(p<limit && *p!=0) {
1737
0
        ++p;
1738
0
      }
1739
0
      newLength=(int32_t)(p-array);
1740
188k
    } else if(newLength>capacity) {
1741
0
      newLength=capacity;
1742
0
    }
1743
188k
    setLength(newLength);
1744
188k
    fUnion.fFields.fLengthAndFlags&=~kOpenGetBuffer;
1745
188k
  }
1746
188k
}
1747
1748
//========================================
1749
// Miscellaneous
1750
//========================================
1751
UBool
1752
UnicodeString::cloneArrayIfNeeded(int32_t newCapacity,
1753
                                  int32_t growCapacity,
1754
                                  UBool doCopyArray,
1755
                                  int32_t **pBufferToDelete,
1756
194k
                                  UBool forceClone) {
1757
194k
  // default parameters need to be static, therefore
1758
194k
  // the defaults are -1 to have convenience defaults
1759
194k
  if(newCapacity == -1) {
1760
7.68k
    newCapacity = getCapacity();
1761
7.68k
  }
1762
194k
1763
194k
  // while a getBuffer(minCapacity) is "open",
1764
194k
  // prevent any modifications of the string by returning FALSE here
1765
194k
  // if the string is bogus, then only an assignment or similar can revive it
1766
194k
  if(!isWritable()) {
1767
0
    return FALSE;
1768
0
  }
1769
194k
1770
194k
  /*
1771
194k
   * We need to make a copy of the array if
1772
194k
   * the buffer is read-only, or
1773
194k
   * the buffer is refCounted (shared), and refCount>1, or
1774
194k
   * the buffer is too small.
1775
194k
   * Return FALSE if memory could not be allocated.
1776
194k
   */
1777
194k
  if(forceClone ||
1778
194k
     fUnion.fFields.fLengthAndFlags & kBufferIsReadonly ||
1779
194k
     (fUnion.fFields.fLengthAndFlags & kRefCounted && refCount() > 1) ||
1780
194k
     newCapacity > getCapacity()
1781
2.46k
  ) {
1782
2.46k
    // check growCapacity for default value and use of the stack buffer
1783
2.46k
    if(growCapacity < 0) {
1784
2.46k
      growCapacity = newCapacity;
1785
2.46k
    } else if(newCapacity <= US_STACKBUF_SIZE && growCapacity > US_STACKBUF_SIZE) {
1786
0
      growCapacity = US_STACKBUF_SIZE;
1787
0
    }
1788
2.46k
1789
2.46k
    // save old values
1790
2.46k
    UChar oldStackBuffer[US_STACKBUF_SIZE];
1791
2.46k
    UChar *oldArray;
1792
2.46k
    int32_t oldLength = length();
1793
2.46k
    int16_t flags = fUnion.fFields.fLengthAndFlags;
1794
2.46k
1795
2.46k
    if(flags&kUsingStackBuffer) {
1796
41
      U_ASSERT(!(flags&kRefCounted)); /* kRefCounted and kUsingStackBuffer are mutally exclusive */
1797
41
      if(doCopyArray && growCapacity > US_STACKBUF_SIZE) {
1798
41
        // copy the stack buffer contents because it will be overwritten with
1799
41
        // fUnion.fFields values
1800
41
        us_arrayCopy(fUnion.fStackFields.fBuffer, 0, oldStackBuffer, 0, oldLength);
1801
41
        oldArray = oldStackBuffer;
1802
41
      } else {
1803
0
        oldArray = NULL; // no need to copy from the stack buffer to itself
1804
0
      }
1805
2.42k
    } else {
1806
2.42k
      oldArray = fUnion.fFields.fArray;
1807
2.42k
      U_ASSERT(oldArray!=NULL); /* when stack buffer is not used, oldArray must have a non-NULL reference */
1808
2.42k
    }
1809
2.46k
1810
2.46k
    // allocate a new array
1811
2.46k
    if(allocate(growCapacity) ||
1812
2.46k
       (newCapacity < growCapacity && allocate(newCapacity))
1813
2.46k
    ) {
1814
2.46k
      if(doCopyArray) {
1815
2.46k
        // copy the contents
1816
2.46k
        // do not copy more than what fits - it may be smaller than before
1817
2.46k
        int32_t minLength = oldLength;
1818
2.46k
        newCapacity = getCapacity();
1819
2.46k
        if(newCapacity < minLength) {
1820
0
          minLength = newCapacity;
1821
0
        }
1822
2.46k
        if(oldArray != NULL) {
1823
2.46k
          us_arrayCopy(oldArray, 0, getArrayStart(), 0, minLength);
1824
2.46k
        }
1825
2.46k
        setLength(minLength);
1826
2.46k
      } else {
1827
0
        setZeroLength();
1828
0
      }
1829
2.46k
1830
2.46k
      // release the old array
1831
2.46k
      if(flags & kRefCounted) {
1832
18
        // the array is refCounted; decrement and release if 0
1833
18
        u_atomic_int32_t *pRefCount = ((u_atomic_int32_t *)oldArray - 1);
1834
18
        if(umtx_atomic_dec(pRefCount) == 0) {
1835
18
          if(pBufferToDelete == 0) {
1836
18
              // Note: cast to (void *) is needed with MSVC, where u_atomic_int32_t
1837
18
              // is defined as volatile. (Volatile has useful non-standard behavior
1838
18
              //   with this compiler.)
1839
18
            uprv_free((void *)pRefCount);
1840
18
          } else {
1841
0
            // the caller requested to delete it himself
1842
0
            *pBufferToDelete = (int32_t *)pRefCount;
1843
0
          }
1844
18
        }
1845
18
      }
1846
2.46k
    } else {
1847
0
      // not enough memory for growCapacity and not even for the smaller newCapacity
1848
0
      // reset the old values for setToBogus() to release the array
1849
0
      if(!(flags&kUsingStackBuffer)) {
1850
0
        fUnion.fFields.fArray = oldArray;
1851
0
      }
1852
0
      fUnion.fFields.fLengthAndFlags = flags;
1853
0
      setToBogus();
1854
0
      return FALSE;
1855
0
    }
1856
194k
  }
1857
194k
  return TRUE;
1858
194k
}
1859
1860
// UnicodeStringAppendable ------------------------------------------------- ***
1861
1862
0
UnicodeStringAppendable::~UnicodeStringAppendable() {}
1863
1864
UBool
1865
0
UnicodeStringAppendable::appendCodeUnit(UChar c) {
1866
0
  return str.doAppend(&c, 0, 1).isWritable();
1867
0
}
1868
1869
UBool
1870
0
UnicodeStringAppendable::appendCodePoint(UChar32 c) {
1871
0
  UChar buffer[U16_MAX_LENGTH];
1872
0
  int32_t cLength = 0;
1873
0
  UBool isError = FALSE;
1874
0
  U16_APPEND(buffer, cLength, U16_MAX_LENGTH, c, isError);
1875
0
  return !isError && str.doAppend(buffer, 0, cLength).isWritable();
1876
0
}
1877
1878
UBool
1879
0
UnicodeStringAppendable::appendString(const UChar *s, int32_t length) {
1880
0
  return str.doAppend(s, 0, length).isWritable();
1881
0
}
1882
1883
UBool
1884
0
UnicodeStringAppendable::reserveAppendCapacity(int32_t appendCapacity) {
1885
0
  return str.cloneArrayIfNeeded(str.length() + appendCapacity);
1886
0
}
1887
1888
UChar *
1889
UnicodeStringAppendable::getAppendBuffer(int32_t minCapacity,
1890
                                         int32_t desiredCapacityHint,
1891
                                         UChar *scratch, int32_t scratchCapacity,
1892
0
                                         int32_t *resultCapacity) {
1893
0
  if(minCapacity < 1 || scratchCapacity < minCapacity) {
1894
0
    *resultCapacity = 0;
1895
0
    return NULL;
1896
0
  }
1897
0
  int32_t oldLength = str.length();
1898
0
  if(minCapacity <= (kMaxCapacity - oldLength) &&
1899
0
      desiredCapacityHint <= (kMaxCapacity - oldLength) &&
1900
0
      str.cloneArrayIfNeeded(oldLength + minCapacity, oldLength + desiredCapacityHint)) {
1901
0
    *resultCapacity = str.getCapacity() - oldLength;
1902
0
    return str.getArrayStart() + oldLength;
1903
0
  }
1904
0
  *resultCapacity = scratchCapacity;
1905
0
  return scratch;
1906
0
}
1907
1908
U_NAMESPACE_END
1909
1910
U_NAMESPACE_USE
1911
1912
U_CAPI int32_t U_EXPORT2
1913
0
uhash_hashUnicodeString(const UElement key) {
1914
0
    const UnicodeString *str = (const UnicodeString*) key.pointer;
1915
0
    return (str == NULL) ? 0 : str->hashCode();
1916
0
}
1917
1918
// Moved here from uhash_us.cpp so that using a UVector of UnicodeString*
1919
// does not depend on hashtable code.
1920
U_CAPI UBool U_EXPORT2
1921
0
uhash_compareUnicodeString(const UElement key1, const UElement key2) {
1922
0
    const UnicodeString *str1 = (const UnicodeString*) key1.pointer;
1923
0
    const UnicodeString *str2 = (const UnicodeString*) key2.pointer;
1924
0
    if (str1 == str2) {
1925
0
        return TRUE;
1926
0
    }
1927
0
    if (str1 == NULL || str2 == NULL) {
1928
0
        return FALSE;
1929
0
    }
1930
0
    return *str1 == *str2;
1931
0
}
1932
1933
#ifdef U_STATIC_IMPLEMENTATION
1934
/*
1935
This should never be called. It is defined here to make sure that the
1936
virtual vector deleting destructor is defined within unistr.cpp.
1937
The vector deleting destructor is already a part of UObject,
1938
but defining it here makes sure that it is included with this object file.
1939
This makes sure that static library dependencies are kept to a minimum.
1940
*/
1941
0
static void uprv_UnicodeStringDummy(void) {
1942
0
    delete [] (new UnicodeString[2]);
1943
0
}
1944
#endif