unistr.cpp revision c69afcec261fc345fda8daf46f0ea6b4351dc777
1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
3c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru* Copyright (C) 1999-2008, 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
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UnicodeString& that)
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : Replaceable(),
300c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength(0),
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  copyFrom(that);
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UnicodeString& that,
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t srcStart)
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : Replaceable(),
309c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength(0),
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  setTo(that, srcStart);
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UnicodeString& that,
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t srcStart,
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t srcLength)
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : Replaceable(),
319c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength(0),
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  setTo(that, srcStart, srcLength);
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Replaceable base class clone() default implementation, does not clone
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable *
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable::clone() const {
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return NULL;
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UnicodeString overrides clone() with a real implementation
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable *
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::clone() const {
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return new UnicodeString(*this);
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// array allocation
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::allocate(int32_t capacity) {
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(capacity <= US_STACKBUF_SIZE) {
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = kShortString;
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // count bytes for the refCounter and the string capacity, and
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // round up to a multiple of 16; then divide by 4 and allocate int32_t's
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // to be safely aligned for the refCount
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t words = (int32_t)(((sizeof(int32_t) + capacity * U_SIZEOF_UCHAR + 15) & ~15) >> 2);
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t *array = (int32_t*) uprv_malloc( sizeof(int32_t) * words );
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(array != 0) {
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // set initial refCount and point behind the refCount
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      *array++ = 1;
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // have fArray point to the first UChar
356c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fArray = (UChar *)array;
357c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fCapacity = (int32_t)((words - 1) * (sizeof(int32_t) / U_SIZEOF_UCHAR));
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = kLongString;
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
360c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fShortLength = 0;
361c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fArray = 0;
362c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fCapacity = 0;
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = kIsBogus;
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return FALSE;
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return TRUE;
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Destructor
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::~UnicodeString()
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Assignment
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::operator=(const UnicodeString &src) {
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return copyFrom(src);
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::fastCopyFrom(const UnicodeString &src) {
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return copyFrom(src, TRUE);
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::copyFrom(const UnicodeString &src, UBool fastCopy) {
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if assigning to ourselves, do nothing
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(this == 0 || this == &src) {
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // is the right side bogus?
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(&src == 0 || src.isBogus()) {
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // delete the current contents
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
409c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(src.isEmpty()) {
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // empty string - use the stack buffer
411c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
415c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // we always copy the length
416c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t srcLength = src.length();
417c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setLength(srcLength);
418c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // fLength>0 and not an "open" src.getBuffer(minCapacity)
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch(src.fFlags) {
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kShortString:
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // short string using the stack buffer, do the same
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = kShortString;
424c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    uprv_memcpy(fUnion.fStackBuffer, src.fUnion.fStackBuffer, fShortLength * U_SIZEOF_UCHAR);
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    break;
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kLongString:
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // src uses a refCounted string buffer, use that buffer with refCount
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // src is const, use a cast - we don't really change it
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ((UnicodeString &)src).addRef();
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // copy all fields, share the reference-counted buffer
431c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fArray = src.fUnion.fFields.fArray;
432c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = src.fFlags;
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    break;
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kReadonlyAlias:
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(fastCopy) {
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // src is a readonly alias, do the same
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // -> maintain the readonly alias as such
439c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fArray = src.fUnion.fFields.fArray;
440c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = src.fFlags;
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // else if(!fastCopy) fall through to case kWritableAlias
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // -> allocate a new buffer and copy the contents
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kWritableAlias:
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // src is a writable alias; we make a copy of that instead
448c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(allocate(srcLength)) {
449c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      uprv_memcpy(getArrayStart(), src.getArrayStart(), srcLength * U_SIZEOF_UCHAR);
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if there is not enough memory, then fall through to setting to bogus
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  default:
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if src is bogus, set ourselves to bogus
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // do not call setToBogus() here because fArray and fFlags are not consistent here
456c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength = 0;
457c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fArray = 0;
458c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fCapacity = 0;
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = kIsBogus;
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    break;
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Miscellaneous operations
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString UnicodeString::unescape() const {
471c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString result(length(), (UChar32)0, (int32_t)0); // construct with capacity
472c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UChar *array = getBuffer();
473c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t len = length();
474c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t prev = 0;
475c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (int32_t i=0;;) {
476c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (i == len) {
477c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            result.append(array, prev, len - prev);
478c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
479c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
480c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (array[i++] == 0x5C /*'\\'*/) {
481c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            result.append(array, prev, (i - 1) - prev);
482c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            UChar32 c = unescapeAt(i); // advances i
483c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (c < 0) {
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                result.remove(); // return empty string
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break; // invalid escape sequence
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
487c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            result.append(c);
488c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            prev = i;
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar32 UnicodeString::unescapeAt(int32_t &offset) const {
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return u_unescapeAt(UnicodeString_charAt, &offset, length(), (void*)this);
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Read-only implementation
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint8_t
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doCompare( int32_t start,
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t length,
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              const UChar *srcChars,
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcStart,
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcLength) const
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // compare illegal string values
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // treat const UChar *srcChars==NULL as an empty string
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus()) {
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices to legal values
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcChars == NULL) {
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcStart = srcLength = 0;
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the correct pointer
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  const UChar *chars = getArrayStart();
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  chars += start;
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  srcChars += srcStart;
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int32_t minLength;
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int8_t lengthResult;
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the srcLength if necessary
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcLength < 0) {
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcLength = u_strlen(srcChars + srcStart);
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // are we comparing different lengths?
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(length != srcLength) {
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(length < srcLength) {
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      minLength = length;
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      lengthResult = -1;
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      minLength = srcLength;
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      lengthResult = 1;
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    minLength = length;
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    lengthResult = 0;
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /*
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * note that uprv_memcmp() returns an int but we return an int8_t;
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * we need to take care not to truncate the result -
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * one way to do this is to right-shift the value to
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * move the sign bit into the lower 8 bits and making sure that this
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * does not become 0 itself
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   */
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(minLength > 0 && chars != srcChars) {
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t result;
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   if U_IS_BIG_ENDIAN
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // big-endian: byte comparison works
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      result = uprv_memcmp(chars, srcChars, minLength * sizeof(UChar));
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(result != 0) {
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return (int8_t)(result >> 15 | 1);
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   else
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // little-endian: compare UChar units
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      do {
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result = ((int32_t)*(chars++) - (int32_t)*(srcChars++));
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(result != 0) {
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          return (int8_t)(result >> 15 | 1);
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } while(--minLength > 0);
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   endif
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return lengthResult;
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* String compare in code point order - doCompare() compares in code unit order. */
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint8_t
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doCompareCodePointOrder(int32_t start,
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       int32_t length,
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       const UChar *srcChars,
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       int32_t srcStart,
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       int32_t srcLength) const
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // compare illegal string values
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // treat const UChar *srcChars==NULL as an empty string
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus()) {
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices to legal values
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcChars == NULL) {
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcStart = srcLength = 0;
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
600c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t diff = uprv_strCompare(getArrayStart() + start, length, srcChars + srcStart, srcLength, FALSE, TRUE);
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /* translate the 32-bit result into an 8-bit one */
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(diff!=0) {
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (int8_t)(diff >> 15 | 1);
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getLength() const {
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return length();
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getCharAt(int32_t offset) const {
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return charAt(offset);
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar32
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getChar32At(int32_t offset) const {
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return char32At(offset);
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::countChar32(int32_t start, int32_t length) const {
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if(isBogus()) then fArray==0 and start==0 - u_countChar32() checks for NULL
628c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  return u_countChar32(getArrayStart()+start, length);
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::hasMoreChar32Than(int32_t start, int32_t length, int32_t number) const {
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if(isBogus()) then fArray==0 and start==0 - u_strHasMoreChar32Than() checks for NULL
635c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  return u_strHasMoreChar32Than(getArrayStart()+start, length, number);
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::moveIndex32(int32_t index, int32_t delta) const {
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin index
641c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t len = length();
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(index<0) {
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    index=0;
644c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else if(index>len) {
645c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    index=len;
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
648c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(delta>0) {
650c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UTF_FWD_N(array, index, len, delta);
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
652c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UTF_BACK_N(array, 0, index, -delta);
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return index;
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doExtract(int32_t start,
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length,
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UChar *dst,
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t dstStart) const
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices to legal values
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // do not copy anything if we alias dst itself
668c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
669c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(array + start != dst + dstStart) {
670c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    us_arrayCopy(array, start, dst, dstStart, length);
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::extract(UChar *dest, int32_t destCapacity,
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       UErrorCode &errorCode) const {
677c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t len = length();
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(U_SUCCESS(errorCode)) {
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isBogus() || destCapacity<0 || (destCapacity>0 && dest==0)) {
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      errorCode=U_ILLEGAL_ARGUMENT_ERROR;
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
682c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      const UChar *array = getArrayStart();
683c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(len>0 && len<=destCapacity && array!=dest) {
684c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        uprv_memcpy(dest, array, len*U_SIZEOF_UCHAR);
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
686c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      return u_terminateUChars(dest, destCapacity, len, &errorCode);
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
690c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  return len;
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::extract(int32_t start,
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       int32_t length,
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       char *target,
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       int32_t targetCapacity,
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       enum EInvariant) const
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if the arguments are illegal, then do nothing
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(targetCapacity < 0 || (targetCapacity > 0 && target == NULL)) {
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin the indices to legal values
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(length <= targetCapacity) {
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_UCharsToChars(getArrayStart() + start, target, length);
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UErrorCode status = U_ZERO_ERROR;
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return u_terminateChars(target, targetCapacity, length, &status);
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::extractBetween(int32_t start,
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t limit,
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  UnicodeString& target) const {
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndex(start);
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndex(limit);
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  doExtract(start, limit - start, target);
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::indexOf(const UChar *srcChars,
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcStart,
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcLength,
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t start,
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t length) const
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus() || srcChars == 0 || srcStart < 0 || srcLength == 0) {
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // UnicodeString does not find empty substrings
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcLength < 0 && srcChars[srcStart] == 0) {
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the indices within bounds
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the first occurrence of the substring
744c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
745c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_strFindFirst(array + start, length, srcChars + srcStart, srcLength);
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
749c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doIndexOf(UChar c,
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t start,
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length) const
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the first occurrence of c
762c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
763c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memchr(array + start, c, length);
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
767c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doIndexOf(UChar32 c,
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         int32_t start,
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         int32_t length) const {
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the first occurrence of c
779c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
780c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memchr32(array + start, c, length);
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
784c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::lastIndexOf(const UChar *srcChars,
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcStart,
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcLength,
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t start,
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t length) const
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus() || srcChars == 0 || srcStart < 0 || srcLength == 0) {
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // UnicodeString does not find empty substrings
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcLength < 0 && srcChars[srcStart] == 0) {
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the indices within bounds
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the last occurrence of the substring
808c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
809c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_strFindLast(array + start, length, srcChars + srcStart, srcLength);
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
813c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doLastIndexOf(UChar c,
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 int32_t start,
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 int32_t length) const
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus()) {
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the last occurrence of c
830c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
831c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memrchr(array + start, c, length);
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
835c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doLastIndexOf(UChar32 c,
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t start,
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t length) const {
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the last occurrence of c
847c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
848c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memrchr32(array + start, c, length);
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
852c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Write implementation
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::findAndReplace(int32_t start,
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t length,
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const UnicodeString& oldText,
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t oldStart,
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t oldLength,
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const UnicodeString& newText,
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t newStart,
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t newLength)
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus() || oldText.isBogus() || newText.isBogus()) {
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  oldText.pinIndices(oldStart, oldLength);
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  newText.pinIndices(newStart, newLength);
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(oldLength == 0) {
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  while(length > 0 && length >= oldLength) {
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t pos = indexOf(oldText, oldStart, oldLength, start, length);
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pos < 0) {
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // no more oldText's here: done
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // we found oldText, replace it by newText and go beyond it
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      replace(pos, oldLength, newText, newStart, newLength);
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      length -= pos + oldLength - start;
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      start = pos + newLength;
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setToBogus()
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
904c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fShortLength = 0;
905c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fUnion.fFields.fArray = 0;
906c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fUnion.fFields.fCapacity = 0;
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fFlags = kIsBogus;
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// turn a bogus string into an empty one
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::unBogus() {
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags & kIsBogus) {
914c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// setTo() analogous to the readonly-aliasing constructor with the same signature
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setTo(UBool isTerminated,
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     const UChar *text,
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     int32_t textLength)
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags & kOpenGetBuffer) {
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // do not modify a string that has an "open" getBuffer(minCapacity)
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(text == NULL) {
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    releaseArray();
932c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if( textLength < -1 ||
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      (textLength == -1 && !isTerminated) ||
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      (textLength >= 0 && isTerminated && text[textLength] != 0)
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
946c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(textLength == -1) {
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // text is terminated, or else it would have failed the above test
948c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    textLength = u_strlen(text);
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
950c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setArray((UChar *)text, textLength, isTerminated ? textLength + 1 : textLength);
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fFlags = kReadonlyAlias;
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// setTo() analogous to the writable-aliasing constructor with the same signature
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setTo(UChar *buffer,
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     int32_t buffLength,
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     int32_t buffCapacity) {
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags & kOpenGetBuffer) {
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // do not modify a string that has an "open" getBuffer(minCapacity)
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(buffer == NULL) {
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    releaseArray();
969c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(buffLength < -1 || buffCapacity < 0 || buffLength > buffCapacity) {
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(buffLength == -1) {
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // buffLength = u_strlen(buff); but do not look beyond buffCapacity
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar *p = buffer, *limit = buffer + buffCapacity;
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(p != limit && *p != 0) {
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      ++p;
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    buffLength = (int32_t)(p - buffer);
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
987c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setArray(buffer, buffLength, buffCapacity);
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fFlags = kWritableAlias;
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setCharAt(int32_t offset,
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UChar c)
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
996c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t len = length();
997c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(cloneArrayIfNeeded() && len > 0) {
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(offset < 0) {
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      offset = 0;
1000c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if(offset >= len) {
1001c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      offset = len - 1;
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1004c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    getArrayStart()[offset] = c;
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doReplace( int32_t start,
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t length,
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              const UnicodeString& src,
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcStart,
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcLength)
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(!src.isBogus()) {
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // pin the indices to legal values
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    src.pinIndices(srcStart, srcLength);
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // get the characters from src
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // and replace the range in ourselves with them
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return doReplace(start, length, src.getArrayStart(), srcStart, srcLength);
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // remove the range
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return doReplace(start, length, 0, 0, 0);
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doReplace(int32_t start,
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length,
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             const UChar *srcChars,
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t srcStart,
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t srcLength)
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1036c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(!isWritable()) {
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcChars == 0) {
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcStart = srcLength = 0;
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(srcLength < 0) {
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // get the srcLength if necessary
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcLength = u_strlen(srcChars + srcStart);
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1047c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t oldLength = this->length();
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1049c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // calculate the size of the string after the replace
1050c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t newSize;
1051c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1052c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // optimize append() onto a large-enough, owned string
1053c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(start >= oldLength) {
1054c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    newSize = oldLength + srcLength;
1055c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(newSize <= getCapacity() && isBufferWritable()) {
1056c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      us_arrayCopy(srcChars, srcStart, getArrayStart(), oldLength, srcLength);
1057c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      setLength(newSize);
1058c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      return *this;
1059c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1060c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      // pin the indices to legal values
1061c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      start = oldLength;
1062c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      length = 0;
1063c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1064c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
1065c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // pin the indices to legal values
1066c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    pinIndices(start, length);
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1068c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    newSize = oldLength - length + srcLength;
1069c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1071c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // the following may change fArray but will not copy the current contents;
1072c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // therefore we need to keep the current fArray
1073c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar oldStackBuffer[US_STACKBUF_SIZE];
1074c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar *oldArray;
1075c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if((fFlags&kUsingStackBuffer) && (newSize > US_STACKBUF_SIZE)) {
1076c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // copy the stack buffer contents because it will be overwritten with
1077c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // fUnion.fFields values
1078c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    u_memcpy(oldStackBuffer, fUnion.fStackBuffer, oldLength);
1079c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    oldArray = oldStackBuffer;
1080c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
1081c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    oldArray = getArrayStart();
1082c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // clone our array and allocate a bigger array if needed
1085c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t *bufferToDelete = 0;
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(!cloneArrayIfNeeded(newSize, newSize + (newSize >> 2) + kGrowSize,
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         FALSE, &bufferToDelete)
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // now do the replace
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1094c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar *newArray = getArrayStart();
1095c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(newArray != oldArray) {
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if fArray changed, then we need to copy everything except what will change
1097c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    us_arrayCopy(oldArray, 0, newArray, 0, start);
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    us_arrayCopy(oldArray, start + length,
1099c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 newArray, start + srcLength,
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 oldLength - (start + length));
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(length != srcLength) {
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fArray did not change; copy only the portion that isn't changing, leaving a hole
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    us_arrayCopy(oldArray, start + length,
1104c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 newArray, start + srcLength,
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 oldLength - (start + length));
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // now fill in the hole with the new string
1109c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  us_arrayCopy(srcChars, srcStart, newArray, start, srcLength);
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1111c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setLength(newSize);
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // delayed delete in case srcChars == fArray when we started, and
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // to keep oldArray alive for the above operations
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (bufferToDelete) {
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(bufferToDelete);
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::handleReplaceBetween(int32_t start,
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    int32_t limit,
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    const UnicodeString& text) {
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    replaceBetween(start, limit, text);
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::copy(int32_t start, int32_t limit, int32_t dest) {
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (limit <= start) {
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return; // Nothing to do; avoid bogus malloc call
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar* text = (UChar*) uprv_malloc( sizeof(UChar) * (limit - start) );
1141c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // Check to make sure text is not null.
1142c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (text != NULL) {
1143c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	    extractBetween(start, limit, text, 0);
1144c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	    insert(dest, text, 0, limit - start);
1145c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	    uprv_free(text);
1146c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * NOTE: This is for the Replaceable class.  There is no rep.cpp,
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * so we implement this function here.
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool Replaceable::hasMetaData() const {
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool UnicodeString::hasMetaData() const {
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doReverse(int32_t start,
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length)
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1170c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(this->length() <= 1 || !cloneArrayIfNeeded()) {
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin the indices to legal values
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UChar *left = getArrayStart() + start;
1178c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar *right = left + length;
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UChar swap;
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UBool hasSupplementary = FALSE;
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  while(left < --right) {
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    hasSupplementary |= (UBool)UTF_IS_LEAD(swap = *left);
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    hasSupplementary |= (UBool)UTF_IS_LEAD(*left++ = *right);
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *right = swap;
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /* if there are supplementary code points in the reversed range, then re-swap their surrogates */
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(hasSupplementary) {
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar swap2;
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    left = getArrayStart() + start;
1193c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    right = left + length - 1; // -1 so that we can look at *(left+1) if left<right
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(left < right) {
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(UTF_IS_TRAIL(swap = *left) && UTF_IS_LEAD(swap2 = *(left + 1))) {
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *left++ = swap2;
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *left++ = swap;
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++left;
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::padLeading(int32_t targetLength,
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          UChar padChar)
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1211c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t oldLength = length();
1212c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(oldLength >= targetLength || !cloneArrayIfNeeded(targetLength)) {
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // move contents up by padding width
1216c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar *array = getArrayStart();
1217c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t start = targetLength - oldLength;
1218c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    us_arrayCopy(array, 0, array, start, oldLength);
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fill in padding character
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(--start >= 0) {
1222c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      array[start] = padChar;
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1224c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(targetLength);
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::padTrailing(int32_t targetLength,
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                           UChar padChar)
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1233c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t oldLength = length();
1234c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(oldLength >= targetLength || !cloneArrayIfNeeded(targetLength)) {
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fill in padding character
1238c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar *array = getArrayStart();
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t length = targetLength;
1240c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    while(--length >= oldLength) {
1241c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      array[length] = padChar;
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1243c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(targetLength);
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Hashing
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doHashCode() const
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Delegate hash computation to uhash.  This makes UnicodeString
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * hashing consistent with UChar* hashing.  */
1256c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t hashCode = uhash_hashUCharsN(getArrayStart(), length());
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (hashCode == kInvalidHashCode) {
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hashCode = kEmptyHashCode;
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return hashCode;
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// External Buffer
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar *
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getBuffer(int32_t minCapacity) {
1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(minCapacity>=-1 && cloneArrayIfNeeded(minCapacity)) {
1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags|=kOpenGetBuffer;
1271c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength=0;
1272c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return getArrayStart();
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::releaseBuffer(int32_t newLength) {
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags&kOpenGetBuffer && newLength>=-1) {
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // set the new fLength
1282c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t capacity=getCapacity();
1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(newLength==-1) {
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // the new length is the string length, capped by fCapacity
1285c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      const UChar *array=getArrayStart(), *p=array, *limit=array+capacity;
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      while(p<limit && *p!=0) {
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++p;
1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1289c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      newLength=(int32_t)(p-array);
1290c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if(newLength>capacity) {
1291c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      newLength=capacity;
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1293c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(newLength);
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags&=~kOpenGetBuffer;
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Miscellaneous
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::cloneArrayIfNeeded(int32_t newCapacity,
1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  int32_t growCapacity,
1304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  UBool doCopyArray,
1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  int32_t **pBufferToDelete,
1306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  UBool forceClone) {
1307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // default parameters need to be static, therefore
1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // the defaults are -1 to have convenience defaults
1309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(newCapacity == -1) {
1310c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    newCapacity = getCapacity();
1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // while a getBuffer(minCapacity) is "open",
1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // prevent any modifications of the string by returning FALSE here
1315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if the string is bogus, then only an assignment or similar can revive it
1316c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(!isWritable()) {
1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /*
1321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * We need to make a copy of the array if
1322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * the buffer is read-only, or
1323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * the buffer is refCounted (shared), and refCount>1, or
1324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * the buffer is too small.
1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * Return FALSE if memory could not be allocated.
1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   */
1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(forceClone ||
1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     fFlags & kBufferIsReadonly ||
1329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     fFlags & kRefCounted && refCount() > 1 ||
1330c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     newCapacity > getCapacity()
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // check growCapacity for default value and use of the stack buffer
1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(growCapacity == -1) {
1334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      growCapacity = newCapacity;
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if(newCapacity <= US_STACKBUF_SIZE && growCapacity > US_STACKBUF_SIZE) {
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      growCapacity = US_STACKBUF_SIZE;
1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1339c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // save old values
1340c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar oldStackBuffer[US_STACKBUF_SIZE];
1341c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar *oldArray;
1342c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    uint8_t flags = fFlags;
1343c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1344c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(flags&kUsingStackBuffer) {
1345c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(doCopyArray && growCapacity > US_STACKBUF_SIZE) {
1346c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // copy the stack buffer contents because it will be overwritten with
1347c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // fUnion.fFields values
1348c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        us_arrayCopy(fUnion.fStackBuffer, 0, oldStackBuffer, 0, fShortLength);
1349c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        oldArray = oldStackBuffer;
1350c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      } else {
1351c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        oldArray = 0; // no need to copy from stack buffer to itself
1352c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
1353c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1354c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      oldArray = fUnion.fFields.fArray;
1355c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1356c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // allocate a new array
1358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(allocate(growCapacity) ||
1359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       newCapacity < growCapacity && allocate(newCapacity)
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ) {
1361c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(doCopyArray && oldArray != 0) {
1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // copy the contents
1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // do not copy more than what fits - it may be smaller than before
1364c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t minLength = length();
1365c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        newCapacity = getCapacity();
1366c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if(newCapacity < minLength) {
1367c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          minLength = newCapacity;
1368c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          setLength(minLength);
1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1370c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        us_arrayCopy(oldArray, 0, getArrayStart(), 0, minLength);
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
1372c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fShortLength = 0;
1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // release the old array
1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(flags & kRefCounted) {
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // the array is refCounted; decrement and release if 0
1378c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t *pRefCount = ((int32_t *)oldArray - 1);
1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(umtx_atomic_dec(pRefCount) == 0) {
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          if(pBufferToDelete == 0) {
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_free(pRefCount);
1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          } else {
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // the caller requested to delete it himself
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pBufferToDelete = pRefCount;
1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // not enough memory for growCapacity and not even for the smaller newCapacity
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // reset the old values for setToBogus() to release the array
1391c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(!(flags&kUsingStackBuffer)) {
1392c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fUnion.fFields.fArray = oldArray;
1393c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = flags;
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      setToBogus();
1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return FALSE;
1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return TRUE;
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_STATIC_IMPLEMENTATION
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThis should never be called. It is defined here to make sure that the
1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvirtual vector deleting destructor is defined within unistr.cpp.
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThe vector deleting destructor is already a part of UObject,
1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querubut defining it here makes sure that it is included with this object file.
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThis makes sure that static library dependencies are kept to a minimum.
1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void uprv_UnicodeStringDummy(void) {
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_NAMESPACE_USE
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete [] (new UnicodeString[2]);
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1417