unistr.cpp revision 50294ead5e5d23f5bbfed76e00e6b510bd41eee1
1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* Copyright (C) 1999-2010, International Business Machines Corporation and   *
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 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"
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/putil.h"
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/unistr.h"
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uhash.h"
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ustr_imp.h"
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h"
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if 0
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if U_IOSTREAM_SOURCE >= 199711
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <iostream>
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing namespace std;
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#elif U_IOSTREAM_SOURCE >= 198506
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <iostream.h>
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
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) {
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return ((U_NAMESPACE_QUALIFIER 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() {}
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable::Replaceable() {}
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
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::addRef()
121c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{  umtx_atomic_inc((int32_t *)fUnion.fFields.fArray - 1);}
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::removeRef()
125c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{ return umtx_atomic_dec((int32_t *)fUnion.fFields.fArray - 1);}
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::refCount() const
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_lock(NULL);
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Note: without the lock to force a memory barrier, we might see a very
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //       stale value on some multi-processor systems.
133c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t  count = *((int32_t *)fUnion.fFields.fArray - 1);
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    umtx_unlock(NULL);
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return count;
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::releaseArray() {
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if((fFlags & kRefCounted) && removeRef() == 0) {
141c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    uprv_free((int32_t *)fUnion.fFields.fArray - 1);
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Constructors
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString()
151c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{}
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(int32_t capacity, UChar32 c, int32_t count)
156c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(0)
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(count <= 0 || (uint32_t)c > 0x10ffff) {
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // just allocate and do not do anything else
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    allocate(capacity);
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // count > 0, allocate and fill the new string with count c's
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t unitCount = UTF_CHAR_LENGTH(c), length = count * unitCount;
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(capacity < length) {
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      capacity = length;
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(allocate(capacity)) {
169c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      UChar *array = getArrayStart();
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      int32_t i = 0;
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // fill the new string with c
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(unitCount == 1) {
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // fill with length UChars
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(i < length) {
176c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          array[i++] = (UChar)c;
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // get the code units for c
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UChar units[UTF_MAX_CHAR_LENGTH];
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UTF_APPEND_CHAR_UNSAFE(units, i, c);
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // now it must be i==unitCount
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        i = 0;
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // for Unicode, unitCount can only be 1, 2, 3, or 4
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // 1 is handled above
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(i < length) {
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          int32_t unitIdx = 0;
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          while(unitIdx < unitCount) {
191c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            array[i++]=units[unitIdx++];
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
196c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(length);
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(UChar ch)
201c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(1),
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
204c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fUnion.fStackBuffer[0] = ch;
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(UChar32 ch)
208c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int32_t i = 0;
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UBool isError = FALSE;
213c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  U16_APPEND(fUnion.fStackBuffer, i, US_STACKBUF_SIZE, ch, isError);
214c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fShortLength = (int8_t)i;
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UChar *text)
218c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  doReplace(0, 0, text, 0, -1);
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UChar *text,
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t textLength)
226c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  doReplace(0, 0, text, 0, textLength);
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(UBool isTerminated,
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             const UChar *text,
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t textLength)
235c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kReadonlyAlias)
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(text == NULL) {
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
240c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(textLength < -1 ||
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            (textLength == -1 && !isTerminated) ||
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            (textLength >= 0 && isTerminated && text[textLength] != 0)
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
246c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
247c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(textLength == -1) {
248c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      // text is terminated, or else it would have failed the above test
249c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      textLength = u_strlen(text);
250c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
251c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setArray((UChar *)text, textLength, isTerminated ? textLength + 1 : textLength);
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(UChar *buff,
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t buffLength,
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t buffCapacity)
258c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kWritableAlias)
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(buff == NULL) {
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
263c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(buffLength < -1 || buffCapacity < 0 || buffLength > buffCapacity) {
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
266c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
267c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(buffLength == -1) {
268c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      // fLength = u_strlen(buff); but do not look beyond buffCapacity
269c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      const UChar *p = buff, *limit = buff + buffCapacity;
270c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      while(p != limit && *p != 0) {
271c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        ++p;
272c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
273c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      buffLength = (int32_t)(p - buff);
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
275c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setArray(buff, buffLength, buffCapacity);
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const char *src, int32_t length, EInvariant)
280c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(src==NULL) {
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(length<0) {
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      length=(int32_t)uprv_strlen(src);
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(cloneArrayIfNeeded(length, length, FALSE)) {
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      u_charsToUChars(src, getArrayStart(), length);
291c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      setLength(length);
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      setToBogus();
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if U_CHARSET_IS_UTF8
299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::UnicodeString(const char *codepageData)
301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  : fShortLength(0),
302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fFlags(kShortString) {
303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(codepageData != 0) {
304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    setToUTF8(codepageData);
305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::UnicodeString(const char *codepageData, int32_t dataLength)
309b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  : fShortLength(0),
310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fFlags(kShortString) {
311b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // if there's nothing to convert, do nothing
312b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(codepageData == 0 || dataLength == 0 || dataLength < -1) {
313b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return;
314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(dataLength == -1) {
316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    dataLength = (int32_t)uprv_strlen(codepageData);
317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
318b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  setToUTF8(StringPiece(codepageData, dataLength));
319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// else see unistr_cnv.cpp
322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UnicodeString& that)
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : Replaceable(),
326c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength(0),
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  copyFrom(that);
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UnicodeString& that,
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t srcStart)
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : Replaceable(),
335c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength(0),
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  setTo(that, srcStart);
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UnicodeString& that,
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t srcStart,
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t srcLength)
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : Replaceable(),
345c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength(0),
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  setTo(that, srcStart, srcLength);
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Replaceable base class clone() default implementation, does not clone
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable *
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable::clone() const {
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return NULL;
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UnicodeString overrides clone() with a real implementation
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable *
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::clone() const {
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return new UnicodeString(*this);
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// array allocation
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::allocate(int32_t capacity) {
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(capacity <= US_STACKBUF_SIZE) {
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = kShortString;
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // count bytes for the refCounter and the string capacity, and
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // round up to a multiple of 16; then divide by 4 and allocate int32_t's
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // to be safely aligned for the refCount
37550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // the +1 is for the NUL terminator, to avoid reallocation in getTerminatedBuffer()
37650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t words = (int32_t)(((sizeof(int32_t) + (capacity + 1) * U_SIZEOF_UCHAR + 15) & ~15) >> 2);
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t *array = (int32_t*) uprv_malloc( sizeof(int32_t) * words );
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(array != 0) {
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // set initial refCount and point behind the refCount
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      *array++ = 1;
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // have fArray point to the first UChar
383c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fArray = (UChar *)array;
384c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fCapacity = (int32_t)((words - 1) * (sizeof(int32_t) / U_SIZEOF_UCHAR));
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = kLongString;
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
387c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fShortLength = 0;
388c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fArray = 0;
389c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fCapacity = 0;
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = kIsBogus;
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return FALSE;
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return TRUE;
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Destructor
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::~UnicodeString()
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//========================================
406b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Factory methods
407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//========================================
408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString UnicodeString::fromUTF8(const StringPiece &utf8) {
410b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UnicodeString result;
411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  result.setToUTF8(utf8);
412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return result;
413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
414b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
415b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString UnicodeString::fromUTF32(const UChar32 *utf32, int32_t length) {
416b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UnicodeString result;
417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t capacity;
418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // Most UTF-32 strings will be BMP-only and result in a same-length
419b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // UTF-16 string. We overestimate the capacity just slightly,
420b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // just in case there are a few supplementary characters.
421b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(length <= US_STACKBUF_SIZE) {
422b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    capacity = US_STACKBUF_SIZE;
423b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  } else {
424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    capacity = length + (length >> 4) + 4;
425b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
426b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  do {
427b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar *utf16 = result.getBuffer(capacity);
428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t length16;
429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode errorCode = U_ZERO_ERROR;
430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    u_strFromUTF32WithSub(utf16, result.getCapacity(), &length16,
431b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        utf32, length,
432b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        0xfffd,  // Substitution character.
433b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        NULL,    // Don't care about number of substitutions.
434b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        &errorCode);
435b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    result.releaseBuffer(length16);
436b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(errorCode == U_BUFFER_OVERFLOW_ERROR) {
437b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      capacity = length16 + 1;  // +1 for the terminating NUL.
438b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      continue;
439b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else if(U_FAILURE(errorCode)) {
440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      result.setToBogus();
441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    break;
443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  } while(TRUE);
444b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return result;
445b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Assignment
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::operator=(const UnicodeString &src) {
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return copyFrom(src);
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::fastCopyFrom(const UnicodeString &src) {
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return copyFrom(src, TRUE);
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::copyFrom(const UnicodeString &src, UBool fastCopy) {
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if assigning to ourselves, do nothing
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(this == 0 || this == &src) {
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // is the right side bogus?
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(&src == 0 || src.isBogus()) {
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // delete the current contents
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
477c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(src.isEmpty()) {
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // empty string - use the stack buffer
479c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
483c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // we always copy the length
484c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t srcLength = src.length();
485c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setLength(srcLength);
486c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // fLength>0 and not an "open" src.getBuffer(minCapacity)
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch(src.fFlags) {
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kShortString:
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // short string using the stack buffer, do the same
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = kShortString;
49250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uprv_memcpy(fUnion.fStackBuffer, src.fUnion.fStackBuffer, srcLength * U_SIZEOF_UCHAR);
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    break;
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kLongString:
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // src uses a refCounted string buffer, use that buffer with refCount
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // src is const, use a cast - we don't really change it
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ((UnicodeString &)src).addRef();
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // copy all fields, share the reference-counted buffer
499c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fArray = src.fUnion.fFields.fArray;
500c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = src.fFlags;
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    break;
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kReadonlyAlias:
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(fastCopy) {
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // src is a readonly alias, do the same
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // -> maintain the readonly alias as such
507c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fArray = src.fUnion.fFields.fArray;
508c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = src.fFlags;
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // else if(!fastCopy) fall through to case kWritableAlias
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // -> allocate a new buffer and copy the contents
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kWritableAlias:
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // src is a writable alias; we make a copy of that instead
516c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(allocate(srcLength)) {
517c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      uprv_memcpy(getArrayStart(), src.getArrayStart(), srcLength * U_SIZEOF_UCHAR);
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if there is not enough memory, then fall through to setting to bogus
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  default:
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if src is bogus, set ourselves to bogus
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // do not call setToBogus() here because fArray and fFlags are not consistent here
524c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength = 0;
525c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fArray = 0;
526c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fCapacity = 0;
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = kIsBogus;
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    break;
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Miscellaneous operations
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString UnicodeString::unescape() const {
539c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString result(length(), (UChar32)0, (int32_t)0); // construct with capacity
540c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UChar *array = getBuffer();
541c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t len = length();
542c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t prev = 0;
543c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (int32_t i=0;;) {
544c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (i == len) {
545c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            result.append(array, prev, len - prev);
546c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
547c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
548c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (array[i++] == 0x5C /*'\\'*/) {
549c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            result.append(array, prev, (i - 1) - prev);
550c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            UChar32 c = unescapeAt(i); // advances i
551c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (c < 0) {
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                result.remove(); // return empty string
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break; // invalid escape sequence
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
555c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            result.append(c);
556c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            prev = i;
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar32 UnicodeString::unescapeAt(int32_t &offset) const {
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return u_unescapeAt(UnicodeString_charAt, &offset, length(), (void*)this);
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Read-only implementation
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint8_t
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doCompare( int32_t start,
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t length,
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              const UChar *srcChars,
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcStart,
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcLength) const
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // compare illegal string values
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // treat const UChar *srcChars==NULL as an empty string
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus()) {
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices to legal values
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcChars == NULL) {
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcStart = srcLength = 0;
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the correct pointer
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  const UChar *chars = getArrayStart();
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  chars += start;
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  srcChars += srcStart;
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int32_t minLength;
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int8_t lengthResult;
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the srcLength if necessary
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcLength < 0) {
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcLength = u_strlen(srcChars + srcStart);
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // are we comparing different lengths?
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(length != srcLength) {
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(length < srcLength) {
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      minLength = length;
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      lengthResult = -1;
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      minLength = srcLength;
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      lengthResult = 1;
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    minLength = length;
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    lengthResult = 0;
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /*
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * note that uprv_memcmp() returns an int but we return an int8_t;
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * we need to take care not to truncate the result -
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * one way to do this is to right-shift the value to
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * move the sign bit into the lower 8 bits and making sure that this
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * does not become 0 itself
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   */
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(minLength > 0 && chars != srcChars) {
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t result;
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   if U_IS_BIG_ENDIAN
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // big-endian: byte comparison works
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      result = uprv_memcmp(chars, srcChars, minLength * sizeof(UChar));
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(result != 0) {
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return (int8_t)(result >> 15 | 1);
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   else
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // little-endian: compare UChar units
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      do {
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result = ((int32_t)*(chars++) - (int32_t)*(srcChars++));
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(result != 0) {
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          return (int8_t)(result >> 15 | 1);
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } while(--minLength > 0);
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   endif
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return lengthResult;
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* String compare in code point order - doCompare() compares in code unit order. */
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint8_t
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doCompareCodePointOrder(int32_t start,
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       int32_t length,
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       const UChar *srcChars,
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       int32_t srcStart,
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       int32_t srcLength) const
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // compare illegal string values
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // treat const UChar *srcChars==NULL as an empty string
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus()) {
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices to legal values
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcChars == NULL) {
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcStart = srcLength = 0;
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
668c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t diff = uprv_strCompare(getArrayStart() + start, length, srcChars + srcStart, srcLength, FALSE, TRUE);
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /* translate the 32-bit result into an 8-bit one */
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(diff!=0) {
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (int8_t)(diff >> 15 | 1);
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getLength() const {
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return length();
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getCharAt(int32_t offset) const {
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return charAt(offset);
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar32
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getChar32At(int32_t offset) const {
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return char32At(offset);
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::countChar32(int32_t start, int32_t length) const {
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if(isBogus()) then fArray==0 and start==0 - u_countChar32() checks for NULL
696c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  return u_countChar32(getArrayStart()+start, length);
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::hasMoreChar32Than(int32_t start, int32_t length, int32_t number) const {
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if(isBogus()) then fArray==0 and start==0 - u_strHasMoreChar32Than() checks for NULL
703c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  return u_strHasMoreChar32Than(getArrayStart()+start, length, number);
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::moveIndex32(int32_t index, int32_t delta) const {
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin index
709c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t len = length();
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(index<0) {
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    index=0;
712c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else if(index>len) {
713c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    index=len;
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
716c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(delta>0) {
718c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UTF_FWD_N(array, index, len, delta);
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
720c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UTF_BACK_N(array, 0, index, -delta);
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return index;
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doExtract(int32_t start,
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length,
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UChar *dst,
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t dstStart) const
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices to legal values
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // do not copy anything if we alias dst itself
736c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
737c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(array + start != dst + dstStart) {
738c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    us_arrayCopy(array, start, dst, dstStart, length);
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::extract(UChar *dest, int32_t destCapacity,
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       UErrorCode &errorCode) const {
745c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t len = length();
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(U_SUCCESS(errorCode)) {
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isBogus() || destCapacity<0 || (destCapacity>0 && dest==0)) {
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      errorCode=U_ILLEGAL_ARGUMENT_ERROR;
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
750c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      const UChar *array = getArrayStart();
751c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(len>0 && len<=destCapacity && array!=dest) {
752c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        uprv_memcpy(dest, array, len*U_SIZEOF_UCHAR);
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
754c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      return u_terminateUChars(dest, destCapacity, len, &errorCode);
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
758c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  return len;
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::extract(int32_t start,
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       int32_t length,
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       char *target,
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       int32_t targetCapacity,
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       enum EInvariant) const
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if the arguments are illegal, then do nothing
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(targetCapacity < 0 || (targetCapacity > 0 && target == NULL)) {
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin the indices to legal values
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(length <= targetCapacity) {
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_UCharsToChars(getArrayStart() + start, target, length);
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UErrorCode status = U_ZERO_ERROR;
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return u_terminateChars(target, targetCapacity, length, &status);
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
78350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString
78450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString::tempSubString(int32_t start, int32_t len) const {
78550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  pinIndices(start, len);
78650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  const UChar *array = getBuffer();  // not getArrayStart() to check kIsBogus & kOpenGetBuffer
78750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  if(array==NULL) {
78850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    array=fUnion.fStackBuffer;  // anything not NULL because that would make an empty string
78950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    len=-2;  // bogus result string
79050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  }
79150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  return UnicodeString(FALSE, array + start, len);
79250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
79350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
794b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruint32_t
795b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::toUTF8(int32_t start, int32_t len,
796b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                      char *target, int32_t capacity) const {
797b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  pinIndices(start, len);
798b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length8;
799b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UErrorCode errorCode = U_ZERO_ERROR;
800b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  u_strToUTF8WithSub(target, capacity, &length8,
801b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     getBuffer() + start, len,
802b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     0xFFFD,  // Standard substitution character.
803b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     NULL,    // Don't care about number of substitutions.
804b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     &errorCode);
805b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return length8;
806b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
807b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
808b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if U_CHARSET_IS_UTF8
809b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
810b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruint32_t
811b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::extract(int32_t start, int32_t len,
812b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       char *target, uint32_t dstSize) const {
813b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // if the arguments are illegal, then do nothing
814b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(/*dstSize < 0 || */(dstSize > 0 && target == 0)) {
815b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return 0;
816b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
817b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return toUTF8(start, len, target, dstSize <= 0x7fffffff ? (int32_t)dstSize : 0x7fffffff);
818b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
819b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
820b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// else see unistr_cnv.cpp
821b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
822b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::extractBetween(int32_t start,
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t limit,
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  UnicodeString& target) const {
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndex(start);
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndex(limit);
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  doExtract(start, limit - start, target);
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
832b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// When converting from UTF-16 to UTF-8, the result will have at most 3 times
833b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// as many bytes as the source has UChars.
834b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// The "worst cases" are writing systems like Indic, Thai and CJK with
835b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 3:1 bytes:UChars.
836b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid
837b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::toUTF8(ByteSink &sink) const {
838b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length16 = length();
839b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(length16 != 0) {
840b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char stackBuffer[1024];
841b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t capacity = (int32_t)sizeof(stackBuffer);
842b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UBool utf8IsOwned = FALSE;
843b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char *utf8 = sink.GetAppendBuffer(length16 < capacity ? length16 : capacity,
844b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                      3*length16,
845b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                      stackBuffer, capacity,
846b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                      &capacity);
847b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t length8 = 0;
848b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode errorCode = U_ZERO_ERROR;
849b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    u_strToUTF8WithSub(utf8, capacity, &length8,
850b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       getBuffer(), length16,
851b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       0xFFFD,  // Standard substitution character.
852b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       NULL,    // Don't care about number of substitutions.
853b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       &errorCode);
854b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(errorCode == U_BUFFER_OVERFLOW_ERROR) {
855b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      utf8 = (char *)uprv_malloc(length8);
856b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      if(utf8 != NULL) {
857b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        utf8IsOwned = TRUE;
858b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        errorCode = U_ZERO_ERROR;
859b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        u_strToUTF8WithSub(utf8, length8, &length8,
860b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           getBuffer(), length16,
861b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           0xFFFD,  // Standard substitution character.
862b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           NULL,    // Don't care about number of substitutions.
863b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           &errorCode);
864b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      } else {
865b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        errorCode = U_MEMORY_ALLOCATION_ERROR;
866b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      }
867b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
868b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(U_SUCCESS(errorCode)) {
869b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      sink.Append(utf8, length8);
870b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
871b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(utf8IsOwned) {
872b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      uprv_free(utf8);
873b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
874b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
875b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
876b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
877b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruint32_t
878b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::toUTF32(UChar32 *utf32, int32_t capacity, UErrorCode &errorCode) const {
879b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length32=0;
880b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(U_SUCCESS(errorCode)) {
881b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // getBuffer() and u_strToUTF32WithSub() check for illegal arguments.
882b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    u_strToUTF32WithSub(utf32, capacity, &length32,
883b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        getBuffer(), length(),
884b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        0xfffd,  // Substitution character.
885b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        NULL,    // Don't care about number of substitutions.
886b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        &errorCode);
887b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
888b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return length32;
889b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
890b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::indexOf(const UChar *srcChars,
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcStart,
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcLength,
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t start,
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t length) const
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus() || srcChars == 0 || srcStart < 0 || srcLength == 0) {
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // UnicodeString does not find empty substrings
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcLength < 0 && srcChars[srcStart] == 0) {
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the indices within bounds
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the first occurrence of the substring
911c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
912c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_strFindFirst(array + start, length, srcChars + srcStart, srcLength);
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
916c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doIndexOf(UChar c,
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t start,
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length) const
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the first occurrence of c
929c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
930c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memchr(array + start, c, length);
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
934c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doIndexOf(UChar32 c,
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         int32_t start,
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         int32_t length) const {
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the first occurrence of c
946c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
947c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memchr32(array + start, c, length);
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
951c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::lastIndexOf(const UChar *srcChars,
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcStart,
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcLength,
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t start,
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t length) const
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus() || srcChars == 0 || srcStart < 0 || srcLength == 0) {
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // UnicodeString does not find empty substrings
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcLength < 0 && srcChars[srcStart] == 0) {
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the indices within bounds
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the last occurrence of the substring
975c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
976c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_strFindLast(array + start, length, srcChars + srcStart, srcLength);
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
980c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doLastIndexOf(UChar c,
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 int32_t start,
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 int32_t length) const
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus()) {
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the last occurrence of c
997c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
998c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memrchr(array + start, c, length);
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1002c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doLastIndexOf(UChar32 c,
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t start,
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t length) const {
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the last occurrence of c
1014c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
1015c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memrchr32(array + start, c, length);
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1019c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Write implementation
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::findAndReplace(int32_t start,
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t length,
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const UnicodeString& oldText,
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t oldStart,
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t oldLength,
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const UnicodeString& newText,
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t newStart,
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t newLength)
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus() || oldText.isBogus() || newText.isBogus()) {
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  oldText.pinIndices(oldStart, oldLength);
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  newText.pinIndices(newStart, newLength);
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(oldLength == 0) {
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  while(length > 0 && length >= oldLength) {
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t pos = indexOf(oldText, oldStart, oldLength, start, length);
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pos < 0) {
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // no more oldText's here: done
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // we found oldText, replace it by newText and go beyond it
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      replace(pos, oldLength, newText, newStart, newLength);
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      length -= pos + oldLength - start;
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      start = pos + newLength;
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setToBogus()
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1071c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fShortLength = 0;
1072c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fUnion.fFields.fArray = 0;
1073c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fUnion.fFields.fCapacity = 0;
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fFlags = kIsBogus;
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// turn a bogus string into an empty one
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::unBogus() {
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags & kIsBogus) {
1081c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// setTo() analogous to the readonly-aliasing constructor with the same signature
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setTo(UBool isTerminated,
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     const UChar *text,
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     int32_t textLength)
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags & kOpenGetBuffer) {
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // do not modify a string that has an "open" getBuffer(minCapacity)
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(text == NULL) {
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    releaseArray();
1099c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if( textLength < -1 ||
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      (textLength == -1 && !isTerminated) ||
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      (textLength >= 0 && isTerminated && text[textLength] != 0)
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1113c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(textLength == -1) {
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // text is terminated, or else it would have failed the above test
1115c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    textLength = u_strlen(text);
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1117c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setArray((UChar *)text, textLength, isTerminated ? textLength + 1 : textLength);
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fFlags = kReadonlyAlias;
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// setTo() analogous to the writable-aliasing constructor with the same signature
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setTo(UChar *buffer,
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     int32_t buffLength,
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     int32_t buffCapacity) {
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags & kOpenGetBuffer) {
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // do not modify a string that has an "open" getBuffer(minCapacity)
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(buffer == NULL) {
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    releaseArray();
1136c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(buffLength < -1 || buffCapacity < 0 || buffLength > buffCapacity) {
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(buffLength == -1) {
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // buffLength = u_strlen(buff); but do not look beyond buffCapacity
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar *p = buffer, *limit = buffer + buffCapacity;
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(p != limit && *p != 0) {
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      ++p;
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    buffLength = (int32_t)(p - buffer);
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1154c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setArray(buffer, buffLength, buffCapacity);
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fFlags = kWritableAlias;
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString &UnicodeString::setToUTF8(const StringPiece &utf8) {
1160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  unBogus();
1161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length = utf8.length();
1162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t capacity;
1163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // The UTF-16 string will be at most as long as the UTF-8 string.
1164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(length <= US_STACKBUF_SIZE) {
1165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    capacity = US_STACKBUF_SIZE;
1166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  } else {
1167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    capacity = length + 1;  // +1 for the terminating NUL.
1168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
1169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UChar *utf16 = getBuffer(capacity);
1170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length16;
1171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UErrorCode errorCode = U_ZERO_ERROR;
1172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  u_strFromUTF8WithSub(utf16, getCapacity(), &length16,
1173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      utf8.data(), length,
1174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      0xfffd,  // Substitution character.
1175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      NULL,    // Don't care about number of substitutions.
1176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      &errorCode);
1177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  releaseBuffer(length16);
1178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(U_FAILURE(errorCode)) {
1179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    setToBogus();
1180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
1181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return *this;
1182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setCharAt(int32_t offset,
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UChar c)
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1188c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t len = length();
1189c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(cloneArrayIfNeeded() && len > 0) {
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(offset < 0) {
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      offset = 0;
1192c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if(offset >= len) {
1193c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      offset = len - 1;
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1196c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    getArrayStart()[offset] = c;
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doReplace( int32_t start,
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t length,
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              const UnicodeString& src,
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcStart,
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcLength)
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(!src.isBogus()) {
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // pin the indices to legal values
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    src.pinIndices(srcStart, srcLength);
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // get the characters from src
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // and replace the range in ourselves with them
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return doReplace(start, length, src.getArrayStart(), srcStart, srcLength);
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // remove the range
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return doReplace(start, length, 0, 0, 0);
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doReplace(int32_t start,
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length,
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             const UChar *srcChars,
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t srcStart,
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t srcLength)
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1228c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(!isWritable()) {
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
123250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  int32_t oldLength = this->length();
123350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
123450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // optimize (read-only alias).remove(0, start) and .remove(start, end)
123550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  if((fFlags&kBufferIsReadonly) && srcLength == 0) {
123650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(start == 0) {
123750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      // remove prefix by adjusting the array pointer
123850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      pinIndex(length);
123950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      fUnion.fFields.fArray += length;
124050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      fUnion.fFields.fCapacity -= length;
124150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      setLength(oldLength - length);
124250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      return *this;
124350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else {
124450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      pinIndex(start);
124550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      if(length >= (oldLength - start)) {
124650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        // remove suffix by reducing the length (like truncate())
124750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        setLength(start);
124850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        fUnion.fFields.fCapacity = start;  // not NUL-terminated any more
124950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return *this;
125050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      }
125150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
125250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  }
125350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcChars == 0) {
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcStart = srcLength = 0;
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(srcLength < 0) {
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // get the srcLength if necessary
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcLength = u_strlen(srcChars + srcStart);
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1261c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // calculate the size of the string after the replace
1262c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t newSize;
1263c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1264c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // optimize append() onto a large-enough, owned string
1265c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(start >= oldLength) {
1266c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    newSize = oldLength + srcLength;
1267c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(newSize <= getCapacity() && isBufferWritable()) {
1268c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      us_arrayCopy(srcChars, srcStart, getArrayStart(), oldLength, srcLength);
1269c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      setLength(newSize);
1270c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      return *this;
1271c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1272c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      // pin the indices to legal values
1273c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      start = oldLength;
1274c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      length = 0;
1275c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1276c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
1277c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // pin the indices to legal values
1278c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    pinIndices(start, length);
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1280c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    newSize = oldLength - length + srcLength;
1281c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1283c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // the following may change fArray but will not copy the current contents;
1284c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // therefore we need to keep the current fArray
1285c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar oldStackBuffer[US_STACKBUF_SIZE];
1286c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar *oldArray;
1287c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if((fFlags&kUsingStackBuffer) && (newSize > US_STACKBUF_SIZE)) {
1288c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // copy the stack buffer contents because it will be overwritten with
1289c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // fUnion.fFields values
1290c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    u_memcpy(oldStackBuffer, fUnion.fStackBuffer, oldLength);
1291c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    oldArray = oldStackBuffer;
1292c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
1293c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    oldArray = getArrayStart();
1294c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // clone our array and allocate a bigger array if needed
1297c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t *bufferToDelete = 0;
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(!cloneArrayIfNeeded(newSize, newSize + (newSize >> 2) + kGrowSize,
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         FALSE, &bufferToDelete)
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // now do the replace
1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1306c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar *newArray = getArrayStart();
1307c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(newArray != oldArray) {
1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if fArray changed, then we need to copy everything except what will change
1309c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    us_arrayCopy(oldArray, 0, newArray, 0, start);
1310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    us_arrayCopy(oldArray, start + length,
1311c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 newArray, start + srcLength,
1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 oldLength - (start + length));
1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(length != srcLength) {
1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fArray did not change; copy only the portion that isn't changing, leaving a hole
1315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    us_arrayCopy(oldArray, start + length,
1316c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 newArray, start + srcLength,
1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 oldLength - (start + length));
1318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // now fill in the hole with the new string
1321c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  us_arrayCopy(srcChars, srcStart, newArray, start, srcLength);
1322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1323c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setLength(newSize);
1324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // delayed delete in case srcChars == fArray when we started, and
1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // to keep oldArray alive for the above operations
1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (bufferToDelete) {
1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(bufferToDelete);
1329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::handleReplaceBetween(int32_t start,
1339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    int32_t limit,
1340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    const UnicodeString& text) {
1341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    replaceBetween(start, limit, text);
1342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::copy(int32_t start, int32_t limit, int32_t dest) {
1349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (limit <= start) {
1350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return; // Nothing to do; avoid bogus malloc call
1351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar* text = (UChar*) uprv_malloc( sizeof(UChar) * (limit - start) );
1353c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // Check to make sure text is not null.
1354c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (text != NULL) {
1355c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	    extractBetween(start, limit, text, 0);
1356c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	    insert(dest, text, 0, limit - start);
1357c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	    uprv_free(text);
1358c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * NOTE: This is for the Replaceable class.  There is no rep.cpp,
1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * so we implement this function here.
1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool Replaceable::hasMetaData() const {
1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool UnicodeString::hasMetaData() const {
1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doReverse(int32_t start,
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length)
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1382c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(this->length() <= 1 || !cloneArrayIfNeeded()) {
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin the indices to legal values
1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UChar *left = getArrayStart() + start;
1390c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar *right = left + length;
1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UChar swap;
1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UBool hasSupplementary = FALSE;
1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  while(left < --right) {
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    hasSupplementary |= (UBool)UTF_IS_LEAD(swap = *left);
1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    hasSupplementary |= (UBool)UTF_IS_LEAD(*left++ = *right);
1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *right = swap;
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /* if there are supplementary code points in the reversed range, then re-swap their surrogates */
1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(hasSupplementary) {
1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar swap2;
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    left = getArrayStart() + start;
1405c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    right = left + length - 1; // -1 so that we can look at *(left+1) if left<right
1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(left < right) {
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(UTF_IS_TRAIL(swap = *left) && UTF_IS_LEAD(swap2 = *(left + 1))) {
1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *left++ = swap2;
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *left++ = swap;
1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++left;
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::padLeading(int32_t targetLength,
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          UChar padChar)
1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1423c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t oldLength = length();
1424c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(oldLength >= targetLength || !cloneArrayIfNeeded(targetLength)) {
1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // move contents up by padding width
1428c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar *array = getArrayStart();
1429c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t start = targetLength - oldLength;
1430c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    us_arrayCopy(array, 0, array, start, oldLength);
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fill in padding character
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(--start >= 0) {
1434c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      array[start] = padChar;
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1436c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(targetLength);
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::padTrailing(int32_t targetLength,
1443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                           UChar padChar)
1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1445c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t oldLength = length();
1446c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(oldLength >= targetLength || !cloneArrayIfNeeded(targetLength)) {
1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fill in padding character
1450c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar *array = getArrayStart();
1451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t length = targetLength;
1452c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    while(--length >= oldLength) {
1453c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      array[length] = padChar;
1454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1455c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(targetLength);
1456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Hashing
1462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doHashCode() const
1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Delegate hash computation to uhash.  This makes UnicodeString
1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * hashing consistent with UChar* hashing.  */
1468c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t hashCode = uhash_hashUCharsN(getArrayStart(), length());
1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (hashCode == kInvalidHashCode) {
1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hashCode = kEmptyHashCode;
1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return hashCode;
1473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// External Buffer
1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar *
1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getBuffer(int32_t minCapacity) {
1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(minCapacity>=-1 && cloneArrayIfNeeded(minCapacity)) {
1482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags|=kOpenGetBuffer;
1483c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength=0;
1484c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return getArrayStart();
1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::releaseBuffer(int32_t newLength) {
1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags&kOpenGetBuffer && newLength>=-1) {
1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // set the new fLength
1494c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t capacity=getCapacity();
1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(newLength==-1) {
1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // the new length is the string length, capped by fCapacity
1497c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      const UChar *array=getArrayStart(), *p=array, *limit=array+capacity;
1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      while(p<limit && *p!=0) {
1499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++p;
1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1501c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      newLength=(int32_t)(p-array);
1502c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if(newLength>capacity) {
1503c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      newLength=capacity;
1504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1505c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(newLength);
1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags&=~kOpenGetBuffer;
1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Miscellaneous
1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::cloneArrayIfNeeded(int32_t newCapacity,
1515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  int32_t growCapacity,
1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  UBool doCopyArray,
1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  int32_t **pBufferToDelete,
1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  UBool forceClone) {
1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // default parameters need to be static, therefore
1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // the defaults are -1 to have convenience defaults
1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(newCapacity == -1) {
1522c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    newCapacity = getCapacity();
1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // while a getBuffer(minCapacity) is "open",
1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // prevent any modifications of the string by returning FALSE here
1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if the string is bogus, then only an assignment or similar can revive it
1528c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(!isWritable()) {
1529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /*
1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * We need to make a copy of the array if
1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * the buffer is read-only, or
1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * the buffer is refCounted (shared), and refCount>1, or
1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * the buffer is too small.
1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * Return FALSE if memory could not be allocated.
1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   */
1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(forceClone ||
1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     fFlags & kBufferIsReadonly ||
1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     fFlags & kRefCounted && refCount() > 1 ||
1542c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     newCapacity > getCapacity()
1543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
1544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // check growCapacity for default value and use of the stack buffer
1545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(growCapacity == -1) {
1546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      growCapacity = newCapacity;
1547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if(newCapacity <= US_STACKBUF_SIZE && growCapacity > US_STACKBUF_SIZE) {
1548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      growCapacity = US_STACKBUF_SIZE;
1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1551c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // save old values
1552c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar oldStackBuffer[US_STACKBUF_SIZE];
1553c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar *oldArray;
1554c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    uint8_t flags = fFlags;
1555c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1556c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(flags&kUsingStackBuffer) {
1557c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(doCopyArray && growCapacity > US_STACKBUF_SIZE) {
1558c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // copy the stack buffer contents because it will be overwritten with
1559c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // fUnion.fFields values
1560c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        us_arrayCopy(fUnion.fStackBuffer, 0, oldStackBuffer, 0, fShortLength);
1561c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        oldArray = oldStackBuffer;
1562c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      } else {
1563c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        oldArray = 0; // no need to copy from stack buffer to itself
1564c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
1565c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1566c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      oldArray = fUnion.fFields.fArray;
1567c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1568c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // allocate a new array
1570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(allocate(growCapacity) ||
1571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       newCapacity < growCapacity && allocate(newCapacity)
1572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ) {
1573c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(doCopyArray && oldArray != 0) {
1574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // copy the contents
1575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // do not copy more than what fits - it may be smaller than before
1576c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t minLength = length();
1577c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        newCapacity = getCapacity();
1578c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if(newCapacity < minLength) {
1579c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          minLength = newCapacity;
1580c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          setLength(minLength);
1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1582c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        us_arrayCopy(oldArray, 0, getArrayStart(), 0, minLength);
1583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
1584c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fShortLength = 0;
1585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // release the old array
1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(flags & kRefCounted) {
1589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // the array is refCounted; decrement and release if 0
1590c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t *pRefCount = ((int32_t *)oldArray - 1);
1591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(umtx_atomic_dec(pRefCount) == 0) {
1592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          if(pBufferToDelete == 0) {
1593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_free(pRefCount);
1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          } else {
1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // the caller requested to delete it himself
1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pBufferToDelete = pRefCount;
1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // not enough memory for growCapacity and not even for the smaller newCapacity
1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // reset the old values for setToBogus() to release the array
1603c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(!(flags&kUsingStackBuffer)) {
1604c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fUnion.fFields.fArray = oldArray;
1605c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = flags;
1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      setToBogus();
1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return FALSE;
1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return TRUE;
1612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_STATIC_IMPLEMENTATION
1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThis should never be called. It is defined here to make sure that the
1618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvirtual vector deleting destructor is defined within unistr.cpp.
1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThe vector deleting destructor is already a part of UObject,
1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querubut defining it here makes sure that it is included with this object file.
1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThis makes sure that static library dependencies are kept to a minimum.
1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void uprv_UnicodeStringDummy(void) {
1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_NAMESPACE_USE
1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete [] (new UnicodeString[2]);
1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1628