1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
359d709d503bab6e2b61931737e662dd293b40578ccornelius* Copyright (C) 1999-2013, International Business Machines Corporation and
4103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius* others. All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* File unistr.cpp
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Modification History:
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Date        Name        Description
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   09/25/98    stephen     Creation.
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   04/20/99    stephen     Overhauled per 4/16 code review.
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   07/09/99    stephen     Renamed {hi,lo},{byte,word} to icu_X for HP/UX
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   11/18/99    aliu        Added handleReplaceBetween() to make inherit from
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           Replaceable.
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   06/25/01    grhoten     Removed the dependency on iostream
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
22b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/appendable.h"
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/putil.h"
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/unistr.h"
28103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/utf.h"
29103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/utf16.h"
30103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "uelement.h"
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ustr_imp.h"
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h"
33103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "uassert.h"
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if 0
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <iostream>
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing namespace std;
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//DEBUGGING
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprint(const UnicodeString& s,
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      const char *name)
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UChar c;
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  cout << name << ":|";
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  for(int i = 0; i < s.length(); ++i) {
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    c = s[i];
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(c>= 0x007E || c < 0x0020)
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      cout << "[0x" << hex << s[i] << "]";
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      cout << (char) s[i];
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  cout << '|' << endl;
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprint(const UChar *s,
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      int32_t len,
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      const char *name)
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UChar c;
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  cout << name << ":|";
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  for(int i = 0; i < len; ++i) {
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    c = s[i];
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(c>= 0x007E || c < 0x0020)
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      cout << "[0x" << hex << s[i] << "]";
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      cout << (char) s[i];
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  cout << '|' << endl;
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// END DEBUGGING
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Local function definitions for now
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// need to copy areas that may overlap
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruinline void
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruus_arrayCopy(const UChar *src, int32_t srcStart,
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         UChar *dst, int32_t dstStart, int32_t count)
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(count>0) {
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memmove(dst+dstStart, src+srcStart, (size_t)(count*sizeof(*src)));
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// u_unescapeAt() callback to get a UChar from a UnicodeString
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UChar U_CALLCONV
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString_charAt(int32_t offset, void *context) {
93103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return ((icu::UnicodeString*) context)->charAt(offset);
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* The Replaceable virtual destructor can't be defined in the header
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   due to how AIX works with multiple definitions of virtual functions.
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable::~Replaceable() {}
1038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(UnicodeString)
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString U_EXPORT2
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruoperator+ (const UnicodeString &s1, const UnicodeString &s2) {
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UnicodeString(s1.length()+s2.length()+1, (UChar32)0, 0).
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            append(s1).
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                append(s2);
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Reference Counting functions, put at top of file so that optimizing compilers
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//                               have a chance to automatically inline.
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
12059d709d503bab6e2b61931737e662dd293b40578ccorneliusUnicodeString::addRef() {
12159d709d503bab6e2b61931737e662dd293b40578ccornelius  umtx_atomic_inc((u_atomic_int32_t *)fUnion.fFields.fArray - 1);
12259d709d503bab6e2b61931737e662dd293b40578ccornelius}
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
12559d709d503bab6e2b61931737e662dd293b40578ccorneliusUnicodeString::removeRef() {
12659d709d503bab6e2b61931737e662dd293b40578ccornelius  return umtx_atomic_dec((u_atomic_int32_t *)fUnion.fFields.fArray - 1);
12759d709d503bab6e2b61931737e662dd293b40578ccornelius}
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
13059d709d503bab6e2b61931737e662dd293b40578ccorneliusUnicodeString::refCount() const {
13159d709d503bab6e2b61931737e662dd293b40578ccornelius  return umtx_loadAcquire(*((u_atomic_int32_t *)fUnion.fFields.fArray - 1));
13259d709d503bab6e2b61931737e662dd293b40578ccornelius}
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::releaseArray() {
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if((fFlags & kRefCounted) && removeRef() == 0) {
137c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    uprv_free((int32_t *)fUnion.fFields.fArray - 1);
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Constructors
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
1478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius// The default constructor is inline in unistr.h.
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(int32_t capacity, UChar32 c, int32_t count)
150c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(0)
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(count <= 0 || (uint32_t)c > 0x10ffff) {
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // just allocate and do not do anything else
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    allocate(capacity);
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // count > 0, allocate and fill the new string with count c's
158103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t unitCount = U16_LENGTH(c), length = count * unitCount;
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(capacity < length) {
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      capacity = length;
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(allocate(capacity)) {
163c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      UChar *array = getArrayStart();
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      int32_t i = 0;
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // fill the new string with c
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(unitCount == 1) {
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // fill with length UChars
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(i < length) {
170c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          array[i++] = (UChar)c;
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // get the code units for c
174103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        UChar units[U16_MAX_LENGTH];
175103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        U16_APPEND_UNSAFE(units, i, c);
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // now it must be i==unitCount
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        i = 0;
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // for Unicode, unitCount can only be 1, 2, 3, or 4
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // 1 is handled above
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(i < length) {
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          int32_t unitIdx = 0;
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          while(unitIdx < unitCount) {
185c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            array[i++]=units[unitIdx++];
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
190c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(length);
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(UChar ch)
195c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(1),
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
198c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fUnion.fStackBuffer[0] = ch;
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(UChar32 ch)
202c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int32_t i = 0;
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UBool isError = FALSE;
207c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  U16_APPEND(fUnion.fStackBuffer, i, US_STACKBUF_SIZE, ch, isError);
208103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // We test isError so that the compiler does not complain that we don't.
209103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // If isError then i==0 which is what we want anyway.
210103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if(!isError) {
211103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    fShortLength = (int8_t)i;
212103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UChar *text)
216c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  doReplace(0, 0, text, 0, -1);
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UChar *text,
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t textLength)
224c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  doReplace(0, 0, text, 0, textLength);
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(UBool isTerminated,
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             const UChar *text,
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t textLength)
233c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kReadonlyAlias)
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(text == NULL) {
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
238c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(textLength < -1 ||
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            (textLength == -1 && !isTerminated) ||
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            (textLength >= 0 && isTerminated && text[textLength] != 0)
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
244c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
245c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(textLength == -1) {
246c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      // text is terminated, or else it would have failed the above test
247c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      textLength = u_strlen(text);
248c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
249c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setArray((UChar *)text, textLength, isTerminated ? textLength + 1 : textLength);
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(UChar *buff,
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t buffLength,
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t buffCapacity)
256c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kWritableAlias)
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(buff == NULL) {
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
261c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(buffLength < -1 || buffCapacity < 0 || buffLength > buffCapacity) {
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
264c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
265c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(buffLength == -1) {
266c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      // fLength = u_strlen(buff); but do not look beyond buffCapacity
267c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      const UChar *p = buff, *limit = buff + buffCapacity;
268c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      while(p != limit && *p != 0) {
269c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        ++p;
270c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
271c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      buffLength = (int32_t)(p - buff);
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
273c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setArray(buff, buffLength, buffCapacity);
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const char *src, int32_t length, EInvariant)
278c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(src==NULL) {
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(length<0) {
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      length=(int32_t)uprv_strlen(src);
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(cloneArrayIfNeeded(length, length, FALSE)) {
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      u_charsToUChars(src, getArrayStart(), length);
289c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      setLength(length);
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      setToBogus();
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
296b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if U_CHARSET_IS_UTF8
297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::UnicodeString(const char *codepageData)
299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  : fShortLength(0),
300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fFlags(kShortString) {
301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(codepageData != 0) {
302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    setToUTF8(codepageData);
303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::UnicodeString(const char *codepageData, int32_t dataLength)
307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  : fShortLength(0),
308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fFlags(kShortString) {
309b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // if there's nothing to convert, do nothing
310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(codepageData == 0 || dataLength == 0 || dataLength < -1) {
311b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return;
312b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
313b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(dataLength == -1) {
314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    dataLength = (int32_t)uprv_strlen(codepageData);
315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  setToUTF8(StringPiece(codepageData, dataLength));
317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
318b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// else see unistr_cnv.cpp
320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UnicodeString& that)
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : Replaceable(),
324c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength(0),
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  copyFrom(that);
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UnicodeString& that,
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t srcStart)
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : Replaceable(),
333c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength(0),
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  setTo(that, srcStart);
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UnicodeString& that,
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t srcStart,
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t srcLength)
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : Replaceable(),
343c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength(0),
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  setTo(that, srcStart, srcLength);
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Replaceable base class clone() default implementation, does not clone
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable *
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable::clone() const {
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return NULL;
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UnicodeString overrides clone() with a real implementation
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable *
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::clone() const {
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return new UnicodeString(*this);
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// array allocation
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::allocate(int32_t capacity) {
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(capacity <= US_STACKBUF_SIZE) {
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = kShortString;
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // count bytes for the refCounter and the string capacity, and
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // round up to a multiple of 16; then divide by 4 and allocate int32_t's
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // to be safely aligned for the refCount
37350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // the +1 is for the NUL terminator, to avoid reallocation in getTerminatedBuffer()
37450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t words = (int32_t)(((sizeof(int32_t) + (capacity + 1) * U_SIZEOF_UCHAR + 15) & ~15) >> 2);
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t *array = (int32_t*) uprv_malloc( sizeof(int32_t) * words );
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(array != 0) {
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // set initial refCount and point behind the refCount
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      *array++ = 1;
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // have fArray point to the first UChar
381c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fArray = (UChar *)array;
382c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fCapacity = (int32_t)((words - 1) * (sizeof(int32_t) / U_SIZEOF_UCHAR));
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = kLongString;
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
385c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fShortLength = 0;
386c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fArray = 0;
387c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fCapacity = 0;
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = kIsBogus;
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return FALSE;
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return TRUE;
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Destructor
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::~UnicodeString()
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
403b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//========================================
404b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Factory methods
405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//========================================
406b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString UnicodeString::fromUTF8(const StringPiece &utf8) {
408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UnicodeString result;
409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  result.setToUTF8(utf8);
410b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return result;
411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString UnicodeString::fromUTF32(const UChar32 *utf32, int32_t length) {
414b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UnicodeString result;
415b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t capacity;
416b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // Most UTF-32 strings will be BMP-only and result in a same-length
417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // UTF-16 string. We overestimate the capacity just slightly,
418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // just in case there are a few supplementary characters.
419b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(length <= US_STACKBUF_SIZE) {
420b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    capacity = US_STACKBUF_SIZE;
421b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  } else {
422b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    capacity = length + (length >> 4) + 4;
423b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  do {
425b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar *utf16 = result.getBuffer(capacity);
426b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t length16;
427b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode errorCode = U_ZERO_ERROR;
428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    u_strFromUTF32WithSub(utf16, result.getCapacity(), &length16,
429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        utf32, length,
430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        0xfffd,  // Substitution character.
431b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        NULL,    // Don't care about number of substitutions.
432b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        &errorCode);
433b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    result.releaseBuffer(length16);
434b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(errorCode == U_BUFFER_OVERFLOW_ERROR) {
435b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      capacity = length16 + 1;  // +1 for the terminating NUL.
436b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      continue;
437b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else if(U_FAILURE(errorCode)) {
438b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      result.setToBogus();
439b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    break;
441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  } while(TRUE);
442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return result;
443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Assignment
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::operator=(const UnicodeString &src) {
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return copyFrom(src);
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::fastCopyFrom(const UnicodeString &src) {
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return copyFrom(src, TRUE);
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::copyFrom(const UnicodeString &src, UBool fastCopy) {
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if assigning to ourselves, do nothing
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(this == 0 || this == &src) {
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // is the right side bogus?
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(&src == 0 || src.isBogus()) {
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // delete the current contents
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
475c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(src.isEmpty()) {
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // empty string - use the stack buffer
477c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
481c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // we always copy the length
482c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t srcLength = src.length();
483c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setLength(srcLength);
484c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // fLength>0 and not an "open" src.getBuffer(minCapacity)
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch(src.fFlags) {
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kShortString:
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // short string using the stack buffer, do the same
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = kShortString;
49050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uprv_memcpy(fUnion.fStackBuffer, src.fUnion.fStackBuffer, srcLength * U_SIZEOF_UCHAR);
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    break;
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kLongString:
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // src uses a refCounted string buffer, use that buffer with refCount
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // src is const, use a cast - we don't really change it
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ((UnicodeString &)src).addRef();
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // copy all fields, share the reference-counted buffer
497c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fArray = src.fUnion.fFields.fArray;
498c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = src.fFlags;
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    break;
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kReadonlyAlias:
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(fastCopy) {
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // src is a readonly alias, do the same
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // -> maintain the readonly alias as such
505c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fArray = src.fUnion.fFields.fArray;
506c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = src.fFlags;
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // else if(!fastCopy) fall through to case kWritableAlias
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // -> allocate a new buffer and copy the contents
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kWritableAlias:
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // src is a writable alias; we make a copy of that instead
514c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(allocate(srcLength)) {
515c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      uprv_memcpy(getArrayStart(), src.getArrayStart(), srcLength * U_SIZEOF_UCHAR);
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if there is not enough memory, then fall through to setting to bogus
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  default:
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if src is bogus, set ourselves to bogus
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // do not call setToBogus() here because fArray and fFlags are not consistent here
522c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength = 0;
523c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fArray = 0;
524c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fCapacity = 0;
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = kIsBogus;
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    break;
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Miscellaneous operations
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString UnicodeString::unescape() const {
537c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString result(length(), (UChar32)0, (int32_t)0); // construct with capacity
538c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UChar *array = getBuffer();
539c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t len = length();
540c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t prev = 0;
541c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (int32_t i=0;;) {
542c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (i == len) {
543c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            result.append(array, prev, len - prev);
544c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
545c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
546c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (array[i++] == 0x5C /*'\\'*/) {
547c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            result.append(array, prev, (i - 1) - prev);
548c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            UChar32 c = unescapeAt(i); // advances i
549c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (c < 0) {
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                result.remove(); // return empty string
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break; // invalid escape sequence
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
553c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            result.append(c);
554c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            prev = i;
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar32 UnicodeString::unescapeAt(int32_t &offset) const {
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return u_unescapeAt(UnicodeString_charAt, &offset, length(), (void*)this);
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Read-only implementation
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
56754dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusUBool
56854dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusUnicodeString::doEquals(const UnicodeString &text, int32_t len) const {
56954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  // Requires: this & text not bogus and have same lengths.
57054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  // Byte-wise comparison works for equality regardless of endianness.
57154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  return uprv_memcmp(getArrayStart(), text.getArrayStart(), len * U_SIZEOF_UCHAR) == 0;
57254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
57354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint8_t
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doCompare( int32_t start,
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t length,
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              const UChar *srcChars,
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcStart,
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcLength) const
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // compare illegal string values
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus()) {
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices to legal values
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcChars == NULL) {
590103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // treat const UChar *srcChars==NULL as an empty string
591103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return length == 0 ? 0 : 1;
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the correct pointer
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  const UChar *chars = getArrayStart();
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  chars += start;
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  srcChars += srcStart;
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int32_t minLength;
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int8_t lengthResult;
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the srcLength if necessary
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcLength < 0) {
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcLength = u_strlen(srcChars + srcStart);
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // are we comparing different lengths?
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(length != srcLength) {
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(length < srcLength) {
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      minLength = length;
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      lengthResult = -1;
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      minLength = srcLength;
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      lengthResult = 1;
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    minLength = length;
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    lengthResult = 0;
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /*
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * note that uprv_memcmp() returns an int but we return an int8_t;
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * we need to take care not to truncate the result -
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * one way to do this is to right-shift the value to
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * move the sign bit into the lower 8 bits and making sure that this
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * does not become 0 itself
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   */
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(minLength > 0 && chars != srcChars) {
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t result;
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   if U_IS_BIG_ENDIAN
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // big-endian: byte comparison works
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      result = uprv_memcmp(chars, srcChars, minLength * sizeof(UChar));
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(result != 0) {
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return (int8_t)(result >> 15 | 1);
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   else
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // little-endian: compare UChar units
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      do {
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result = ((int32_t)*(chars++) - (int32_t)*(srcChars++));
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(result != 0) {
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          return (int8_t)(result >> 15 | 1);
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } while(--minLength > 0);
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   endif
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return lengthResult;
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* String compare in code point order - doCompare() compares in code unit order. */
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint8_t
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doCompareCodePointOrder(int32_t start,
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       int32_t length,
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       const UChar *srcChars,
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       int32_t srcStart,
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       int32_t srcLength) const
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // compare illegal string values
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // treat const UChar *srcChars==NULL as an empty string
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus()) {
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices to legal values
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcChars == NULL) {
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcStart = srcLength = 0;
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
673103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int32_t diff = uprv_strCompare(getArrayStart() + start, length, (srcChars!=NULL)?(srcChars + srcStart):NULL, srcLength, FALSE, TRUE);
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /* translate the 32-bit result into an 8-bit one */
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(diff!=0) {
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (int8_t)(diff >> 15 | 1);
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getLength() const {
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return length();
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getCharAt(int32_t offset) const {
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return charAt(offset);
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar32
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getChar32At(int32_t offset) const {
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return char32At(offset);
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
697103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUChar32
698103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString::char32At(int32_t offset) const
699103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius{
700103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int32_t len = length();
701103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if((uint32_t)offset < (uint32_t)len) {
702103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UChar *array = getArrayStart();
703103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UChar32 c;
704103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    U16_GET(array, 0, offset, len, c);
705103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return c;
706103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  } else {
707103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return kInvalidUChar;
708103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
709103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
710103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
711103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusint32_t
712103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString::getChar32Start(int32_t offset) const {
713103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if((uint32_t)offset < (uint32_t)length()) {
714103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UChar *array = getArrayStart();
715103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    U16_SET_CP_START(array, 0, offset);
716103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return offset;
717103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  } else {
718103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return 0;
719103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
720103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
721103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
722103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusint32_t
723103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString::getChar32Limit(int32_t offset) const {
724103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int32_t len = length();
725103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if((uint32_t)offset < (uint32_t)len) {
726103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UChar *array = getArrayStart();
727103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    U16_SET_CP_LIMIT(array, 0, offset, len);
728103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return offset;
729103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  } else {
730103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return len;
731103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
732103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
733103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::countChar32(int32_t start, int32_t length) const {
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if(isBogus()) then fArray==0 and start==0 - u_countChar32() checks for NULL
738c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  return u_countChar32(getArrayStart()+start, length);
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::hasMoreChar32Than(int32_t start, int32_t length, int32_t number) const {
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if(isBogus()) then fArray==0 and start==0 - u_strHasMoreChar32Than() checks for NULL
745c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  return u_strHasMoreChar32Than(getArrayStart()+start, length, number);
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::moveIndex32(int32_t index, int32_t delta) const {
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin index
751c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t len = length();
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(index<0) {
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    index=0;
754c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else if(index>len) {
755c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    index=len;
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
758c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(delta>0) {
760103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    U16_FWD_N(array, index, len, delta);
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
762103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    U16_BACK_N(array, 0, index, -delta);
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return index;
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doExtract(int32_t start,
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length,
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UChar *dst,
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t dstStart) const
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices to legal values
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // do not copy anything if we alias dst itself
778c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
779c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(array + start != dst + dstStart) {
780c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    us_arrayCopy(array, start, dst, dstStart, length);
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::extract(UChar *dest, int32_t destCapacity,
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       UErrorCode &errorCode) const {
787c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t len = length();
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(U_SUCCESS(errorCode)) {
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isBogus() || destCapacity<0 || (destCapacity>0 && dest==0)) {
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      errorCode=U_ILLEGAL_ARGUMENT_ERROR;
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
792c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      const UChar *array = getArrayStart();
793c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(len>0 && len<=destCapacity && array!=dest) {
794c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        uprv_memcpy(dest, array, len*U_SIZEOF_UCHAR);
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
796c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      return u_terminateUChars(dest, destCapacity, len, &errorCode);
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
800c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  return len;
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::extract(int32_t start,
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       int32_t length,
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       char *target,
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       int32_t targetCapacity,
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       enum EInvariant) const
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if the arguments are illegal, then do nothing
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(targetCapacity < 0 || (targetCapacity > 0 && target == NULL)) {
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin the indices to legal values
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(length <= targetCapacity) {
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_UCharsToChars(getArrayStart() + start, target, length);
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UErrorCode status = U_ZERO_ERROR;
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return u_terminateChars(target, targetCapacity, length, &status);
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
82550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString
82650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString::tempSubString(int32_t start, int32_t len) const {
82750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  pinIndices(start, len);
82850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  const UChar *array = getBuffer();  // not getArrayStart() to check kIsBogus & kOpenGetBuffer
82950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  if(array==NULL) {
83050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    array=fUnion.fStackBuffer;  // anything not NULL because that would make an empty string
83150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    len=-2;  // bogus result string
83250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  }
83350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  return UnicodeString(FALSE, array + start, len);
83450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
83550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
836b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruint32_t
837b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::toUTF8(int32_t start, int32_t len,
838b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                      char *target, int32_t capacity) const {
839b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  pinIndices(start, len);
840b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length8;
841b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UErrorCode errorCode = U_ZERO_ERROR;
842b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  u_strToUTF8WithSub(target, capacity, &length8,
843b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     getBuffer() + start, len,
844b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     0xFFFD,  // Standard substitution character.
845b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     NULL,    // Don't care about number of substitutions.
846b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     &errorCode);
847b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return length8;
848b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
849b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
850b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if U_CHARSET_IS_UTF8
851b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
852b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruint32_t
853b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::extract(int32_t start, int32_t len,
854b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       char *target, uint32_t dstSize) const {
855b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // if the arguments are illegal, then do nothing
856b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(/*dstSize < 0 || */(dstSize > 0 && target == 0)) {
857b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return 0;
858b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
859b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return toUTF8(start, len, target, dstSize <= 0x7fffffff ? (int32_t)dstSize : 0x7fffffff);
860b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
861b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
862b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// else see unistr_cnv.cpp
863b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
864b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::extractBetween(int32_t start,
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t limit,
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  UnicodeString& target) const {
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndex(start);
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndex(limit);
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  doExtract(start, limit - start, target);
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
874b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// When converting from UTF-16 to UTF-8, the result will have at most 3 times
875b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// as many bytes as the source has UChars.
876b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// The "worst cases" are writing systems like Indic, Thai and CJK with
877b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 3:1 bytes:UChars.
878b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid
879b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::toUTF8(ByteSink &sink) const {
880b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length16 = length();
881b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(length16 != 0) {
882b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char stackBuffer[1024];
883b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t capacity = (int32_t)sizeof(stackBuffer);
884b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UBool utf8IsOwned = FALSE;
885b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char *utf8 = sink.GetAppendBuffer(length16 < capacity ? length16 : capacity,
886b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                      3*length16,
887b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                      stackBuffer, capacity,
888b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                      &capacity);
889b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t length8 = 0;
890b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode errorCode = U_ZERO_ERROR;
891b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    u_strToUTF8WithSub(utf8, capacity, &length8,
892b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       getBuffer(), length16,
893b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       0xFFFD,  // Standard substitution character.
894b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       NULL,    // Don't care about number of substitutions.
895b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       &errorCode);
896b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(errorCode == U_BUFFER_OVERFLOW_ERROR) {
897b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      utf8 = (char *)uprv_malloc(length8);
898b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      if(utf8 != NULL) {
899b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        utf8IsOwned = TRUE;
900b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        errorCode = U_ZERO_ERROR;
901b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        u_strToUTF8WithSub(utf8, length8, &length8,
902b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           getBuffer(), length16,
903b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           0xFFFD,  // Standard substitution character.
904b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           NULL,    // Don't care about number of substitutions.
905b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           &errorCode);
906b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      } else {
907b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        errorCode = U_MEMORY_ALLOCATION_ERROR;
908b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      }
909b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
910b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(U_SUCCESS(errorCode)) {
911b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      sink.Append(utf8, length8);
91227f654740f2a26ad62a5c155af9199af9e69b889claireho      sink.Flush();
913b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
914b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(utf8IsOwned) {
915b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      uprv_free(utf8);
916b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
917b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
918b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
919b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
920b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruint32_t
921b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::toUTF32(UChar32 *utf32, int32_t capacity, UErrorCode &errorCode) const {
922b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length32=0;
923b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(U_SUCCESS(errorCode)) {
924b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // getBuffer() and u_strToUTF32WithSub() check for illegal arguments.
925b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    u_strToUTF32WithSub(utf32, capacity, &length32,
926b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        getBuffer(), length(),
927b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        0xfffd,  // Substitution character.
928b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        NULL,    // Don't care about number of substitutions.
929b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        &errorCode);
930b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
931b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return length32;
932b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
933b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::indexOf(const UChar *srcChars,
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcStart,
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcLength,
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t start,
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t length) const
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus() || srcChars == 0 || srcStart < 0 || srcLength == 0) {
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // UnicodeString does not find empty substrings
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcLength < 0 && srcChars[srcStart] == 0) {
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the indices within bounds
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the first occurrence of the substring
954c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
955c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_strFindFirst(array + start, length, srcChars + srcStart, srcLength);
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
959c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doIndexOf(UChar c,
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t start,
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length) const
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the first occurrence of c
972c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
973c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memchr(array + start, c, length);
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
977c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doIndexOf(UChar32 c,
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         int32_t start,
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         int32_t length) const {
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the first occurrence of c
989c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
990c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memchr32(array + start, c, length);
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
994c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::lastIndexOf(const UChar *srcChars,
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcStart,
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcLength,
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t start,
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t length) const
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus() || srcChars == 0 || srcStart < 0 || srcLength == 0) {
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // UnicodeString does not find empty substrings
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcLength < 0 && srcChars[srcStart] == 0) {
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the indices within bounds
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the last occurrence of the substring
1018c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
1019c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_strFindLast(array + start, length, srcChars + srcStart, srcLength);
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1023c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doLastIndexOf(UChar c,
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 int32_t start,
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 int32_t length) const
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus()) {
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the last occurrence of c
1040c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
1041c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memrchr(array + start, c, length);
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1045c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doLastIndexOf(UChar32 c,
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t start,
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t length) const {
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the last occurrence of c
1057c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
1058c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memrchr32(array + start, c, length);
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1062c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Write implementation
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::findAndReplace(int32_t start,
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t length,
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const UnicodeString& oldText,
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t oldStart,
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t oldLength,
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const UnicodeString& newText,
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t newStart,
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t newLength)
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus() || oldText.isBogus() || newText.isBogus()) {
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  oldText.pinIndices(oldStart, oldLength);
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  newText.pinIndices(newStart, newLength);
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(oldLength == 0) {
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  while(length > 0 && length >= oldLength) {
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t pos = indexOf(oldText, oldStart, oldLength, start, length);
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pos < 0) {
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // no more oldText's here: done
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // we found oldText, replace it by newText and go beyond it
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      replace(pos, oldLength, newText, newStart, newLength);
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      length -= pos + oldLength - start;
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      start = pos + newLength;
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setToBogus()
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1114c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fShortLength = 0;
1115c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fUnion.fFields.fArray = 0;
1116c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fUnion.fFields.fCapacity = 0;
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fFlags = kIsBogus;
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// turn a bogus string into an empty one
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::unBogus() {
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags & kIsBogus) {
1124c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
112859d709d503bab6e2b61931737e662dd293b40578ccorneliusconst UChar *
112959d709d503bab6e2b61931737e662dd293b40578ccorneliusUnicodeString::getTerminatedBuffer() {
113059d709d503bab6e2b61931737e662dd293b40578ccornelius  if(!isWritable()) {
113159d709d503bab6e2b61931737e662dd293b40578ccornelius    return 0;
113259d709d503bab6e2b61931737e662dd293b40578ccornelius  }
113359d709d503bab6e2b61931737e662dd293b40578ccornelius  UChar *array = getArrayStart();
113459d709d503bab6e2b61931737e662dd293b40578ccornelius  int32_t len = length();
113559d709d503bab6e2b61931737e662dd293b40578ccornelius  if(len < getCapacity()) {
113659d709d503bab6e2b61931737e662dd293b40578ccornelius    if(fFlags & kBufferIsReadonly) {
113759d709d503bab6e2b61931737e662dd293b40578ccornelius      // If len<capacity on a read-only alias, then array[len] is
113859d709d503bab6e2b61931737e662dd293b40578ccornelius      // either the original NUL (if constructed with (TRUE, s, length))
113959d709d503bab6e2b61931737e662dd293b40578ccornelius      // or one of the original string contents characters (if later truncated),
114059d709d503bab6e2b61931737e662dd293b40578ccornelius      // therefore we can assume that array[len] is initialized memory.
114159d709d503bab6e2b61931737e662dd293b40578ccornelius      if(array[len] == 0) {
114259d709d503bab6e2b61931737e662dd293b40578ccornelius        return array;
114359d709d503bab6e2b61931737e662dd293b40578ccornelius      }
114459d709d503bab6e2b61931737e662dd293b40578ccornelius    } else if(((fFlags & kRefCounted) == 0 || refCount() == 1)) {
114559d709d503bab6e2b61931737e662dd293b40578ccornelius      // kRefCounted: Do not write the NUL if the buffer is shared.
114659d709d503bab6e2b61931737e662dd293b40578ccornelius      // That is mostly safe, except when the length of one copy was modified
114759d709d503bab6e2b61931737e662dd293b40578ccornelius      // without copy-on-write, e.g., via truncate(newLength) or remove(void).
114859d709d503bab6e2b61931737e662dd293b40578ccornelius      // Then the NUL would be written into the middle of another copy's string.
114959d709d503bab6e2b61931737e662dd293b40578ccornelius
115059d709d503bab6e2b61931737e662dd293b40578ccornelius      // Otherwise, the buffer is fully writable and it is anyway safe to write the NUL.
115159d709d503bab6e2b61931737e662dd293b40578ccornelius      // Do not test if there is a NUL already because it might be uninitialized memory.
115259d709d503bab6e2b61931737e662dd293b40578ccornelius      // (That would be safe, but tools like valgrind & Purify would complain.)
115359d709d503bab6e2b61931737e662dd293b40578ccornelius      array[len] = 0;
115459d709d503bab6e2b61931737e662dd293b40578ccornelius      return array;
115559d709d503bab6e2b61931737e662dd293b40578ccornelius    }
115659d709d503bab6e2b61931737e662dd293b40578ccornelius  }
115759d709d503bab6e2b61931737e662dd293b40578ccornelius  if(cloneArrayIfNeeded(len+1)) {
115859d709d503bab6e2b61931737e662dd293b40578ccornelius    array = getArrayStart();
115959d709d503bab6e2b61931737e662dd293b40578ccornelius    array[len] = 0;
116059d709d503bab6e2b61931737e662dd293b40578ccornelius    return array;
116159d709d503bab6e2b61931737e662dd293b40578ccornelius  } else {
116259d709d503bab6e2b61931737e662dd293b40578ccornelius    return NULL;
116359d709d503bab6e2b61931737e662dd293b40578ccornelius  }
116459d709d503bab6e2b61931737e662dd293b40578ccornelius}
116559d709d503bab6e2b61931737e662dd293b40578ccornelius
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// setTo() analogous to the readonly-aliasing constructor with the same signature
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setTo(UBool isTerminated,
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     const UChar *text,
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     int32_t textLength)
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags & kOpenGetBuffer) {
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // do not modify a string that has an "open" getBuffer(minCapacity)
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(text == NULL) {
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    releaseArray();
1180c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if( textLength < -1 ||
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      (textLength == -1 && !isTerminated) ||
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      (textLength >= 0 && isTerminated && text[textLength] != 0)
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1194c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(textLength == -1) {
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // text is terminated, or else it would have failed the above test
1196c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    textLength = u_strlen(text);
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1198c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setArray((UChar *)text, textLength, isTerminated ? textLength + 1 : textLength);
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fFlags = kReadonlyAlias;
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// setTo() analogous to the writable-aliasing constructor with the same signature
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setTo(UChar *buffer,
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     int32_t buffLength,
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     int32_t buffCapacity) {
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags & kOpenGetBuffer) {
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // do not modify a string that has an "open" getBuffer(minCapacity)
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(buffer == NULL) {
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    releaseArray();
1217c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(buffLength < -1 || buffCapacity < 0 || buffLength > buffCapacity) {
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(buffLength == -1) {
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // buffLength = u_strlen(buff); but do not look beyond buffCapacity
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar *p = buffer, *limit = buffer + buffCapacity;
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(p != limit && *p != 0) {
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      ++p;
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    buffLength = (int32_t)(p - buffer);
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1235c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setArray(buffer, buffLength, buffCapacity);
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fFlags = kWritableAlias;
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString &UnicodeString::setToUTF8(const StringPiece &utf8) {
1241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  unBogus();
1242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length = utf8.length();
1243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t capacity;
1244b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // The UTF-16 string will be at most as long as the UTF-8 string.
1245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(length <= US_STACKBUF_SIZE) {
1246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    capacity = US_STACKBUF_SIZE;
1247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  } else {
1248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    capacity = length + 1;  // +1 for the terminating NUL.
1249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
1250b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UChar *utf16 = getBuffer(capacity);
1251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length16;
1252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UErrorCode errorCode = U_ZERO_ERROR;
1253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  u_strFromUTF8WithSub(utf16, getCapacity(), &length16,
1254b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      utf8.data(), length,
1255b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      0xfffd,  // Substitution character.
1256b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      NULL,    // Don't care about number of substitutions.
1257b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      &errorCode);
1258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  releaseBuffer(length16);
1259b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(U_FAILURE(errorCode)) {
1260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    setToBogus();
1261b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
1262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return *this;
1263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setCharAt(int32_t offset,
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UChar c)
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1269c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t len = length();
1270c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(cloneArrayIfNeeded() && len > 0) {
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(offset < 0) {
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      offset = 0;
1273c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if(offset >= len) {
1274c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      offset = len - 1;
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1277c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    getArrayStart()[offset] = c;
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1283103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString::replace(int32_t start,
1284103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius               int32_t _length,
1285103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius               UChar32 srcChar) {
1286103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  UChar buffer[U16_MAX_LENGTH];
1287103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int32_t count = 0;
1288103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  UBool isError = FALSE;
1289103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  U16_APPEND(buffer, count, U16_MAX_LENGTH, srcChar, isError);
1290103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // We test isError so that the compiler does not complain that we don't.
129154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  // If isError (srcChar is not a valid code point) then count==0 which means
129254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  // we remove the source segment rather than replacing it with srcChar.
129354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  return doReplace(start, _length, buffer, 0, isError ? 0 : count);
1294103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
1295103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1296103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString&
1297103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString::append(UChar32 srcChar) {
1298103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  UChar buffer[U16_MAX_LENGTH];
1299103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int32_t _length = 0;
1300103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  UBool isError = FALSE;
1301103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  U16_APPEND(buffer, _length, U16_MAX_LENGTH, srcChar, isError);
1302103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // We test isError so that the compiler does not complain that we don't.
1303103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // If isError then _length==0 which turns the doReplace() into a no-op anyway.
1304103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return isError ? *this : doReplace(length(), 0, buffer, 0, _length);
1305103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
1306103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1307103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString&
1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doReplace( int32_t start,
1309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t length,
1310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              const UnicodeString& src,
1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcStart,
1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcLength)
1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(!src.isBogus()) {
1315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // pin the indices to legal values
1316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    src.pinIndices(srcStart, srcLength);
1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // get the characters from src
1319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // and replace the range in ourselves with them
1320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return doReplace(start, length, src.getArrayStart(), srcStart, srcLength);
1321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // remove the range
1323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return doReplace(start, length, 0, 0, 0);
1324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doReplace(int32_t start,
1329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length,
1330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             const UChar *srcChars,
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t srcStart,
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t srcLength)
1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1334c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(!isWritable()) {
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
133850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  int32_t oldLength = this->length();
133950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
134050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // optimize (read-only alias).remove(0, start) and .remove(start, end)
134150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  if((fFlags&kBufferIsReadonly) && srcLength == 0) {
134250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(start == 0) {
134350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      // remove prefix by adjusting the array pointer
134450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      pinIndex(length);
134550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      fUnion.fFields.fArray += length;
134650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      fUnion.fFields.fCapacity -= length;
134750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      setLength(oldLength - length);
134850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      return *this;
134950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else {
135050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      pinIndex(start);
135150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      if(length >= (oldLength - start)) {
135250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        // remove suffix by reducing the length (like truncate())
135350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        setLength(start);
135450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        fUnion.fFields.fCapacity = start;  // not NUL-terminated any more
135550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return *this;
135650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      }
135750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
135850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  }
135950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcChars == 0) {
1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcStart = srcLength = 0;
1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(srcLength < 0) {
1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // get the srcLength if necessary
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcLength = u_strlen(srcChars + srcStart);
1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1367c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // calculate the size of the string after the replace
1368b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  int32_t newLength;
1369c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1370c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // optimize append() onto a large-enough, owned string
1371c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(start >= oldLength) {
1372103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if(srcLength == 0) {
1373103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      return *this;
1374103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1375b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    newLength = oldLength + srcLength;
1376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(newLength <= getCapacity() && isBufferWritable()) {
1377b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      UChar *oldArray = getArrayStart();
1378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      // Do not copy characters when
1379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      //   UChar *buffer=str.getAppendBuffer(...);
1380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      // is followed by
1381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      //   str.append(buffer, length);
1382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      // or
1383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      //   str.appendString(buffer, length)
1384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      // or similar.
1385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      if(srcChars + srcStart != oldArray + start || start > oldLength) {
1386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        us_arrayCopy(srcChars, srcStart, oldArray, oldLength, srcLength);
1387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      }
1388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      setLength(newLength);
1389c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      return *this;
1390c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1391c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      // pin the indices to legal values
1392c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      start = oldLength;
1393c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      length = 0;
1394c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1395c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
1396c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // pin the indices to legal values
1397c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    pinIndices(start, length);
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1399b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    newLength = oldLength - length + srcLength;
1400c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1402c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // the following may change fArray but will not copy the current contents;
1403c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // therefore we need to keep the current fArray
1404c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar oldStackBuffer[US_STACKBUF_SIZE];
1405c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar *oldArray;
1406b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if((fFlags&kUsingStackBuffer) && (newLength > US_STACKBUF_SIZE)) {
1407c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // copy the stack buffer contents because it will be overwritten with
1408c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // fUnion.fFields values
1409c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    u_memcpy(oldStackBuffer, fUnion.fStackBuffer, oldLength);
1410c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    oldArray = oldStackBuffer;
1411c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
1412c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    oldArray = getArrayStart();
1413c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // clone our array and allocate a bigger array if needed
1416c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t *bufferToDelete = 0;
1417b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if(!cloneArrayIfNeeded(newLength, newLength + (newLength >> 2) + kGrowSize,
1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         FALSE, &bufferToDelete)
1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // now do the replace
1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1425c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar *newArray = getArrayStart();
1426c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(newArray != oldArray) {
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if fArray changed, then we need to copy everything except what will change
1428c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    us_arrayCopy(oldArray, 0, newArray, 0, start);
1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    us_arrayCopy(oldArray, start + length,
1430c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 newArray, start + srcLength,
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 oldLength - (start + length));
1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(length != srcLength) {
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fArray did not change; copy only the portion that isn't changing, leaving a hole
1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    us_arrayCopy(oldArray, start + length,
1435c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 newArray, start + srcLength,
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 oldLength - (start + length));
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // now fill in the hole with the new string
1440c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  us_arrayCopy(srcChars, srcStart, newArray, start, srcLength);
1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1442b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  setLength(newLength);
1443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // delayed delete in case srcChars == fArray when we started, and
1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // to keep oldArray alive for the above operations
1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (bufferToDelete) {
1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(bufferToDelete);
1448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::handleReplaceBetween(int32_t start,
1458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    int32_t limit,
1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    const UnicodeString& text) {
1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    replaceBetween(start, limit, text);
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::copy(int32_t start, int32_t limit, int32_t dest) {
1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (limit <= start) {
1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return; // Nothing to do; avoid bogus malloc call
1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar* text = (UChar*) uprv_malloc( sizeof(UChar) * (limit - start) );
1472c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // Check to make sure text is not null.
1473c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (text != NULL) {
1474c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	    extractBetween(start, limit, text, 0);
1475c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	    insert(dest, text, 0, limit - start);
1476c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	    uprv_free(text);
1477c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * NOTE: This is for the Replaceable class.  There is no rep.cpp,
1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * so we implement this function here.
1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool Replaceable::hasMetaData() const {
1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool UnicodeString::hasMetaData() const {
1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
149827f654740f2a26ad62a5c155af9199af9e69b889clairehoUnicodeString::doReverse(int32_t start, int32_t length) {
149927f654740f2a26ad62a5c155af9199af9e69b889claireho  if(length <= 1 || !cloneArrayIfNeeded()) {
1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin the indices to legal values
1504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
150527f654740f2a26ad62a5c155af9199af9e69b889claireho  if(length <= 1) {  // pinIndices() might have shrunk the length
150627f654740f2a26ad62a5c155af9199af9e69b889claireho    return *this;
150727f654740f2a26ad62a5c155af9199af9e69b889claireho  }
1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UChar *left = getArrayStart() + start;
151027f654740f2a26ad62a5c155af9199af9e69b889claireho  UChar *right = left + length - 1;  // -1 for inclusive boundary (length>=2)
1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UChar swap;
1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UBool hasSupplementary = FALSE;
1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
151427f654740f2a26ad62a5c155af9199af9e69b889claireho  // Before the loop we know left<right because length>=2.
151527f654740f2a26ad62a5c155af9199af9e69b889claireho  do {
151627f654740f2a26ad62a5c155af9199af9e69b889claireho    hasSupplementary |= (UBool)U16_IS_LEAD(swap = *left);
151727f654740f2a26ad62a5c155af9199af9e69b889claireho    hasSupplementary |= (UBool)U16_IS_LEAD(*left++ = *right);
151827f654740f2a26ad62a5c155af9199af9e69b889claireho    *right-- = swap;
151927f654740f2a26ad62a5c155af9199af9e69b889claireho  } while(left < right);
152027f654740f2a26ad62a5c155af9199af9e69b889claireho  // Make sure to test the middle code unit of an odd-length string.
152127f654740f2a26ad62a5c155af9199af9e69b889claireho  // Redundant if the length is even.
152227f654740f2a26ad62a5c155af9199af9e69b889claireho  hasSupplementary |= (UBool)U16_IS_LEAD(*left);
1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /* if there are supplementary code points in the reversed range, then re-swap their surrogates */
1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(hasSupplementary) {
1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar swap2;
1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    left = getArrayStart() + start;
1529c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    right = left + length - 1; // -1 so that we can look at *(left+1) if left<right
1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(left < right) {
153127f654740f2a26ad62a5c155af9199af9e69b889claireho      if(U16_IS_TRAIL(swap = *left) && U16_IS_LEAD(swap2 = *(left + 1))) {
1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *left++ = swap2;
1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *left++ = swap;
1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++left;
1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::padLeading(int32_t targetLength,
1545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          UChar padChar)
1546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1547c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t oldLength = length();
1548c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(oldLength >= targetLength || !cloneArrayIfNeeded(targetLength)) {
1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // move contents up by padding width
1552c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar *array = getArrayStart();
1553c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t start = targetLength - oldLength;
1554c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    us_arrayCopy(array, 0, array, start, oldLength);
1555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fill in padding character
1557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(--start >= 0) {
1558c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      array[start] = padChar;
1559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1560c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(targetLength);
1561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::padTrailing(int32_t targetLength,
1567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                           UChar padChar)
1568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1569c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t oldLength = length();
1570c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(oldLength >= targetLength || !cloneArrayIfNeeded(targetLength)) {
1571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fill in padding character
1574c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar *array = getArrayStart();
1575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t length = targetLength;
1576c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    while(--length >= oldLength) {
1577c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      array[length] = padChar;
1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1579c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(targetLength);
1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Hashing
1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doHashCode() const
1589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Delegate hash computation to uhash.  This makes UnicodeString
1591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * hashing consistent with UChar* hashing.  */
1592103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t hashCode = ustr_hashUCharsN(getArrayStart(), length());
1593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (hashCode == kInvalidHashCode) {
1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hashCode = kEmptyHashCode;
1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return hashCode;
1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// External Buffer
1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar *
1604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getBuffer(int32_t minCapacity) {
1605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(minCapacity>=-1 && cloneArrayIfNeeded(minCapacity)) {
1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags|=kOpenGetBuffer;
1607c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength=0;
1608c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return getArrayStart();
1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::releaseBuffer(int32_t newLength) {
1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags&kOpenGetBuffer && newLength>=-1) {
1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // set the new fLength
1618c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t capacity=getCapacity();
1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(newLength==-1) {
1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // the new length is the string length, capped by fCapacity
1621c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      const UChar *array=getArrayStart(), *p=array, *limit=array+capacity;
1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      while(p<limit && *p!=0) {
1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++p;
1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1625c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      newLength=(int32_t)(p-array);
1626c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if(newLength>capacity) {
1627c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      newLength=capacity;
1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1629c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(newLength);
1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags&=~kOpenGetBuffer;
1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Miscellaneous
1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::cloneArrayIfNeeded(int32_t newCapacity,
1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  int32_t growCapacity,
1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  UBool doCopyArray,
1641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  int32_t **pBufferToDelete,
1642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  UBool forceClone) {
1643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // default parameters need to be static, therefore
1644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // the defaults are -1 to have convenience defaults
1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(newCapacity == -1) {
1646c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    newCapacity = getCapacity();
1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // while a getBuffer(minCapacity) is "open",
1650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // prevent any modifications of the string by returning FALSE here
1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if the string is bogus, then only an assignment or similar can revive it
1652c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(!isWritable()) {
1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /*
1657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * We need to make a copy of the array if
1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * the buffer is read-only, or
1659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * the buffer is refCounted (shared), and refCount>1, or
1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * the buffer is too small.
1661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * Return FALSE if memory could not be allocated.
1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   */
1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(forceClone ||
1664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     fFlags & kBufferIsReadonly ||
166527f654740f2a26ad62a5c155af9199af9e69b889claireho     (fFlags & kRefCounted && refCount() > 1) ||
1666c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     newCapacity > getCapacity()
1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
1668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // check growCapacity for default value and use of the stack buffer
1669103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if(growCapacity < 0) {
1670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      growCapacity = newCapacity;
1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if(newCapacity <= US_STACKBUF_SIZE && growCapacity > US_STACKBUF_SIZE) {
1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      growCapacity = US_STACKBUF_SIZE;
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1675c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // save old values
1676c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar oldStackBuffer[US_STACKBUF_SIZE];
1677c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar *oldArray;
1678c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    uint8_t flags = fFlags;
1679c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1680c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(flags&kUsingStackBuffer) {
1681103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      U_ASSERT(!(flags&kRefCounted)); /* kRefCounted and kUsingStackBuffer are mutally exclusive */
1682c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(doCopyArray && growCapacity > US_STACKBUF_SIZE) {
1683c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // copy the stack buffer contents because it will be overwritten with
1684c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // fUnion.fFields values
1685c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        us_arrayCopy(fUnion.fStackBuffer, 0, oldStackBuffer, 0, fShortLength);
1686c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        oldArray = oldStackBuffer;
1687c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      } else {
1688c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        oldArray = 0; // no need to copy from stack buffer to itself
1689c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
1690c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1691c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      oldArray = fUnion.fFields.fArray;
1692103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      U_ASSERT(oldArray!=NULL); /* when stack buffer is not used, oldArray must have a non-NULL reference */
1693c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1694c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // allocate a new array
1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(allocate(growCapacity) ||
169727f654740f2a26ad62a5c155af9199af9e69b889claireho       (newCapacity < growCapacity && allocate(newCapacity))
1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ) {
1699c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(doCopyArray && oldArray != 0) {
1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // copy the contents
1701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // do not copy more than what fits - it may be smaller than before
1702c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t minLength = length();
1703c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        newCapacity = getCapacity();
1704c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if(newCapacity < minLength) {
1705c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          minLength = newCapacity;
1706c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          setLength(minLength);
1707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1708c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        us_arrayCopy(oldArray, 0, getArrayStart(), 0, minLength);
1709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
1710c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fShortLength = 0;
1711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // release the old array
1714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(flags & kRefCounted) {
1715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // the array is refCounted; decrement and release if 0
171659d709d503bab6e2b61931737e662dd293b40578ccornelius        u_atomic_int32_t *pRefCount = ((u_atomic_int32_t *)oldArray - 1);
1717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(umtx_atomic_dec(pRefCount) == 0) {
1718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          if(pBufferToDelete == 0) {
171959d709d503bab6e2b61931737e662dd293b40578ccornelius              // Note: cast to (void *) is needed with MSVC, where u_atomic_int32_t
172059d709d503bab6e2b61931737e662dd293b40578ccornelius              // is defined as volatile. (Volatile has useful non-standard behavior
172159d709d503bab6e2b61931737e662dd293b40578ccornelius              //   with this compiler.)
172259d709d503bab6e2b61931737e662dd293b40578ccornelius            uprv_free((void *)pRefCount);
1723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          } else {
1724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // the caller requested to delete it himself
172559d709d503bab6e2b61931737e662dd293b40578ccornelius            *pBufferToDelete = (int32_t *)pRefCount;
1726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
1727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // not enough memory for growCapacity and not even for the smaller newCapacity
1731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // reset the old values for setToBogus() to release the array
1732c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(!(flags&kUsingStackBuffer)) {
1733c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fUnion.fFields.fArray = oldArray;
1734c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
1735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = flags;
1736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      setToBogus();
1737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return FALSE;
1738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return TRUE;
1741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1742b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1743b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// UnicodeStringAppendable ------------------------------------------------- ***
1744b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1745103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeStringAppendable::~UnicodeStringAppendable() {}
1746103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1747b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1748b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeStringAppendable::appendCodeUnit(UChar c) {
1749b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  return str.doReplace(str.length(), 0, &c, 0, 1).isWritable();
1750b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1751b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1752b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1753b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeStringAppendable::appendCodePoint(UChar32 c) {
1754b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  UChar buffer[U16_MAX_LENGTH];
1755b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  int32_t cLength = 0;
1756b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  UBool isError = FALSE;
1757b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  U16_APPEND(buffer, cLength, U16_MAX_LENGTH, c, isError);
1758b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  return !isError && str.doReplace(str.length(), 0, buffer, 0, cLength).isWritable();
1759b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1760b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1761b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1762b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeStringAppendable::appendString(const UChar *s, int32_t length) {
1763b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  return str.doReplace(str.length(), 0, s, 0, length).isWritable();
1764b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1765b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1766b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1767b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeStringAppendable::reserveAppendCapacity(int32_t appendCapacity) {
1768b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  return str.cloneArrayIfNeeded(str.length() + appendCapacity);
1769b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1770b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1771b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUChar *
1772b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeStringAppendable::getAppendBuffer(int32_t minCapacity,
1773b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                         int32_t desiredCapacityHint,
1774b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                         UChar *scratch, int32_t scratchCapacity,
1775b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                         int32_t *resultCapacity) {
1776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if(minCapacity < 1 || scratchCapacity < minCapacity) {
1777b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    *resultCapacity = 0;
1778b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return NULL;
1779b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  }
1780b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  int32_t oldLength = str.length();
1781b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if(str.cloneArrayIfNeeded(oldLength + minCapacity, oldLength + desiredCapacityHint)) {
1782b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    *resultCapacity = str.getCapacity() - oldLength;
1783b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return str.getArrayStart() + oldLength;
1784b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  }
1785b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  *resultCapacity = scratchCapacity;
1786b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  return scratch;
1787b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1788b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
1790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1791103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_NAMESPACE_USE
1792103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1793103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CAPI int32_t U_EXPORT2
1794103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusuhash_hashUnicodeString(const UElement key) {
1795103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UnicodeString *str = (const UnicodeString*) key.pointer;
1796103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return (str == NULL) ? 0 : str->hashCode();
1797103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
1798103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1799103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Moved here from uhash_us.cpp so that using a UVector of UnicodeString*
1800103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// does not depend on hashtable code.
1801103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CAPI UBool U_EXPORT2
1802103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusuhash_compareUnicodeString(const UElement key1, const UElement key2) {
1803103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UnicodeString *str1 = (const UnicodeString*) key1.pointer;
1804103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UnicodeString *str2 = (const UnicodeString*) key2.pointer;
1805103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (str1 == str2) {
1806103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        return TRUE;
1807103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1808103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (str1 == NULL || str2 == NULL) {
1809103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        return FALSE;
1810103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1811103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return *str1 == *str2;
1812103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
1813103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_STATIC_IMPLEMENTATION
1815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
1816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThis should never be called. It is defined here to make sure that the
1817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvirtual vector deleting destructor is defined within unistr.cpp.
1818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThe vector deleting destructor is already a part of UObject,
1819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querubut defining it here makes sure that it is included with this object file.
1820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThis makes sure that static library dependencies are kept to a minimum.
1821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void uprv_UnicodeStringDummy(void) {
1823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete [] (new UnicodeString[2]);
1824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1826