1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
3103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius* Copyright (C) 1999-2012, International Business Machines Corporation and
4103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius* others. All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* File unistr.cpp
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Modification History:
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Date        Name        Description
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   09/25/98    stephen     Creation.
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   04/20/99    stephen     Overhauled per 4/16 code review.
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   07/09/99    stephen     Renamed {hi,lo},{byte,word} to icu_X for HP/UX
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   11/18/99    aliu        Added handleReplaceBetween() to make inherit from
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           Replaceable.
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   06/25/01    grhoten     Removed the dependency on iostream
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
22b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/appendable.h"
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/putil.h"
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/unistr.h"
28103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/utf.h"
29103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/utf16.h"
30103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "uelement.h"
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ustr_imp.h"
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h"
33103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "uassert.h"
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if 0
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <iostream>
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruusing namespace std;
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//DEBUGGING
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprint(const UnicodeString& s,
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      const char *name)
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UChar c;
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  cout << name << ":|";
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  for(int i = 0; i < s.length(); ++i) {
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    c = s[i];
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(c>= 0x007E || c < 0x0020)
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      cout << "[0x" << hex << s[i] << "]";
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      cout << (char) s[i];
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  cout << '|' << endl;
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprint(const UChar *s,
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      int32_t len,
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      const char *name)
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UChar c;
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  cout << name << ":|";
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  for(int i = 0; i < len; ++i) {
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    c = s[i];
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(c>= 0x007E || c < 0x0020)
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      cout << "[0x" << hex << s[i] << "]";
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      cout << (char) s[i];
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  cout << '|' << endl;
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// END DEBUGGING
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Local function definitions for now
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// need to copy areas that may overlap
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruinline void
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruus_arrayCopy(const UChar *src, int32_t srcStart,
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         UChar *dst, int32_t dstStart, int32_t count)
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(count>0) {
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memmove(dst+dstStart, src+srcStart, (size_t)(count*sizeof(*src)));
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// u_unescapeAt() callback to get a UChar from a UnicodeString
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UChar U_CALLCONV
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString_charAt(int32_t offset, void *context) {
93103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return ((icu::UnicodeString*) context)->charAt(offset);
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* The Replaceable virtual destructor can't be defined in the header
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   due to how AIX works with multiple definitions of virtual functions.
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable::~Replaceable() {}
1038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(UnicodeString)
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString U_EXPORT2
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruoperator+ (const UnicodeString &s1, const UnicodeString &s2) {
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UnicodeString(s1.length()+s2.length()+1, (UChar32)0, 0).
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            append(s1).
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                append(s2);
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Reference Counting functions, put at top of file so that optimizing compilers
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//                               have a chance to automatically inline.
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
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//========================================
1508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
1518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius// The default constructor is inline in unistr.h.
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(int32_t capacity, UChar32 c, int32_t count)
154c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(0)
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(count <= 0 || (uint32_t)c > 0x10ffff) {
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // just allocate and do not do anything else
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    allocate(capacity);
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // count > 0, allocate and fill the new string with count c's
162103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t unitCount = U16_LENGTH(c), length = count * unitCount;
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(capacity < length) {
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      capacity = length;
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(allocate(capacity)) {
167c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      UChar *array = getArrayStart();
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      int32_t i = 0;
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // fill the new string with c
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(unitCount == 1) {
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // fill with length UChars
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(i < length) {
174c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          array[i++] = (UChar)c;
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // get the code units for c
178103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        UChar units[U16_MAX_LENGTH];
179103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        U16_APPEND_UNSAFE(units, i, c);
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // now it must be i==unitCount
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        i = 0;
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // for Unicode, unitCount can only be 1, 2, 3, or 4
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // 1 is handled above
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(i < length) {
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          int32_t unitIdx = 0;
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          while(unitIdx < unitCount) {
189c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            array[i++]=units[unitIdx++];
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
194c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(length);
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(UChar ch)
199c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(1),
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
202c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fUnion.fStackBuffer[0] = ch;
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(UChar32 ch)
206c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int32_t i = 0;
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UBool isError = FALSE;
211c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  U16_APPEND(fUnion.fStackBuffer, i, US_STACKBUF_SIZE, ch, isError);
212103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // We test isError so that the compiler does not complain that we don't.
213103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // If isError then i==0 which is what we want anyway.
214103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if(!isError) {
215103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    fShortLength = (int8_t)i;
216103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UChar *text)
220c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  doReplace(0, 0, text, 0, -1);
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UChar *text,
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t textLength)
228c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  doReplace(0, 0, text, 0, textLength);
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(UBool isTerminated,
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             const UChar *text,
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t textLength)
237c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kReadonlyAlias)
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(text == NULL) {
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
242c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(textLength < -1 ||
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            (textLength == -1 && !isTerminated) ||
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            (textLength >= 0 && isTerminated && text[textLength] != 0)
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
248c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
249c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(textLength == -1) {
250c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      // text is terminated, or else it would have failed the above test
251c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      textLength = u_strlen(text);
252c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
253c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setArray((UChar *)text, textLength, isTerminated ? textLength + 1 : textLength);
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(UChar *buff,
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t buffLength,
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t buffCapacity)
260c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kWritableAlias)
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(buff == NULL) {
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
265c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(buffLength < -1 || buffCapacity < 0 || buffLength > buffCapacity) {
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
268c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
269c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(buffLength == -1) {
270c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      // fLength = u_strlen(buff); but do not look beyond buffCapacity
271c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      const UChar *p = buff, *limit = buff + buffCapacity;
272c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      while(p != limit && *p != 0) {
273c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        ++p;
274c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
275c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      buffLength = (int32_t)(p - buff);
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
277c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setArray(buff, buffLength, buffCapacity);
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const char *src, int32_t length, EInvariant)
282c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  : fShortLength(0),
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(src==NULL) {
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(length<0) {
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      length=(int32_t)uprv_strlen(src);
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(cloneArrayIfNeeded(length, length, FALSE)) {
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      u_charsToUChars(src, getArrayStart(), length);
293c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      setLength(length);
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      setToBogus();
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if U_CHARSET_IS_UTF8
301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::UnicodeString(const char *codepageData)
303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  : fShortLength(0),
304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fFlags(kShortString) {
305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(codepageData != 0) {
306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    setToUTF8(codepageData);
307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
309b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::UnicodeString(const char *codepageData, int32_t dataLength)
311b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  : fShortLength(0),
312b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fFlags(kShortString) {
313b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // if there's nothing to convert, do nothing
314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(codepageData == 0 || dataLength == 0 || dataLength < -1) {
315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return;
316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(dataLength == -1) {
318b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    dataLength = (int32_t)uprv_strlen(codepageData);
319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  setToUTF8(StringPiece(codepageData, dataLength));
321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// else see unistr_cnv.cpp
324b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
325b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UnicodeString& that)
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : Replaceable(),
328c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength(0),
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  copyFrom(that);
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UnicodeString& that,
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t srcStart)
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : Replaceable(),
337c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength(0),
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  setTo(that, srcStart);
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::UnicodeString(const UnicodeString& that,
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t srcStart,
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t srcLength)
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  : Replaceable(),
347c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength(0),
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags(kShortString)
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  setTo(that, srcStart, srcLength);
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Replaceable base class clone() default implementation, does not clone
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable *
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable::clone() const {
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return NULL;
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UnicodeString overrides clone() with a real implementation
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruReplaceable *
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::clone() const {
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return new UnicodeString(*this);
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// array allocation
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::allocate(int32_t capacity) {
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(capacity <= US_STACKBUF_SIZE) {
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = kShortString;
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // count bytes for the refCounter and the string capacity, and
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // round up to a multiple of 16; then divide by 4 and allocate int32_t's
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // to be safely aligned for the refCount
37750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // the +1 is for the NUL terminator, to avoid reallocation in getTerminatedBuffer()
37850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t words = (int32_t)(((sizeof(int32_t) + (capacity + 1) * U_SIZEOF_UCHAR + 15) & ~15) >> 2);
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t *array = (int32_t*) uprv_malloc( sizeof(int32_t) * words );
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(array != 0) {
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // set initial refCount and point behind the refCount
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      *array++ = 1;
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // have fArray point to the first UChar
385c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fArray = (UChar *)array;
386c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fCapacity = (int32_t)((words - 1) * (sizeof(int32_t) / U_SIZEOF_UCHAR));
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = kLongString;
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
389c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fShortLength = 0;
390c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fArray = 0;
391c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fCapacity = 0;
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = kIsBogus;
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return FALSE;
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return TRUE;
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Destructor
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::~UnicodeString()
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//========================================
408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Factory methods
409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//========================================
410b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString UnicodeString::fromUTF8(const StringPiece &utf8) {
412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UnicodeString result;
413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  result.setToUTF8(utf8);
414b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return result;
415b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
416b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString UnicodeString::fromUTF32(const UChar32 *utf32, int32_t length) {
418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UnicodeString result;
419b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t capacity;
420b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // Most UTF-32 strings will be BMP-only and result in a same-length
421b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // UTF-16 string. We overestimate the capacity just slightly,
422b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // just in case there are a few supplementary characters.
423b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(length <= US_STACKBUF_SIZE) {
424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    capacity = US_STACKBUF_SIZE;
425b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  } else {
426b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    capacity = length + (length >> 4) + 4;
427b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  do {
429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar *utf16 = result.getBuffer(capacity);
430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t length16;
431b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode errorCode = U_ZERO_ERROR;
432b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    u_strFromUTF32WithSub(utf16, result.getCapacity(), &length16,
433b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        utf32, length,
434b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        0xfffd,  // Substitution character.
435b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        NULL,    // Don't care about number of substitutions.
436b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        &errorCode);
437b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    result.releaseBuffer(length16);
438b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(errorCode == U_BUFFER_OVERFLOW_ERROR) {
439b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      capacity = length16 + 1;  // +1 for the terminating NUL.
440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      continue;
441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else if(U_FAILURE(errorCode)) {
442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      result.setToBogus();
443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
444b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    break;
445b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  } while(TRUE);
446b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return result;
447b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Assignment
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::operator=(const UnicodeString &src) {
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return copyFrom(src);
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::fastCopyFrom(const UnicodeString &src) {
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return copyFrom(src, TRUE);
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::copyFrom(const UnicodeString &src, UBool fastCopy) {
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if assigning to ourselves, do nothing
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(this == 0 || this == &src) {
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // is the right side bogus?
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(&src == 0 || src.isBogus()) {
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // delete the current contents
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
479c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(src.isEmpty()) {
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // empty string - use the stack buffer
481c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
485c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // we always copy the length
486c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t srcLength = src.length();
487c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setLength(srcLength);
488c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // fLength>0 and not an "open" src.getBuffer(minCapacity)
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  switch(src.fFlags) {
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kShortString:
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // short string using the stack buffer, do the same
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = kShortString;
49450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uprv_memcpy(fUnion.fStackBuffer, src.fUnion.fStackBuffer, srcLength * U_SIZEOF_UCHAR);
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    break;
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kLongString:
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // src uses a refCounted string buffer, use that buffer with refCount
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // src is const, use a cast - we don't really change it
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ((UnicodeString &)src).addRef();
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // copy all fields, share the reference-counted buffer
501c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fArray = src.fUnion.fFields.fArray;
502c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = src.fFlags;
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    break;
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kReadonlyAlias:
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(fastCopy) {
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // src is a readonly alias, do the same
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // -> maintain the readonly alias as such
509c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fArray = src.fUnion.fFields.fArray;
510c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = src.fFlags;
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // else if(!fastCopy) fall through to case kWritableAlias
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // -> allocate a new buffer and copy the contents
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  case kWritableAlias:
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // src is a writable alias; we make a copy of that instead
518c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(allocate(srcLength)) {
519c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      uprv_memcpy(getArrayStart(), src.getArrayStart(), srcLength * U_SIZEOF_UCHAR);
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if there is not enough memory, then fall through to setting to bogus
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  default:
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if src is bogus, set ourselves to bogus
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // do not call setToBogus() here because fArray and fFlags are not consistent here
526c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength = 0;
527c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fArray = 0;
528c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fUnion.fFields.fCapacity = 0;
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags = kIsBogus;
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    break;
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Miscellaneous operations
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString UnicodeString::unescape() const {
541c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString result(length(), (UChar32)0, (int32_t)0); // construct with capacity
542c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UChar *array = getBuffer();
543c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t len = length();
544c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t prev = 0;
545c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (int32_t i=0;;) {
546c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (i == len) {
547c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            result.append(array, prev, len - prev);
548c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
549c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
550c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (array[i++] == 0x5C /*'\\'*/) {
551c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            result.append(array, prev, (i - 1) - prev);
552c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            UChar32 c = unescapeAt(i); // advances i
553c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (c < 0) {
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                result.remove(); // return empty string
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break; // invalid escape sequence
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
557c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            result.append(c);
558c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            prev = i;
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar32 UnicodeString::unescapeAt(int32_t &offset) const {
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return u_unescapeAt(UnicodeString_charAt, &offset, length(), (void*)this);
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Read-only implementation
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
57154dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusUBool
57254dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusUnicodeString::doEquals(const UnicodeString &text, int32_t len) const {
57354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  // Requires: this & text not bogus and have same lengths.
57454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  // Byte-wise comparison works for equality regardless of endianness.
57554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  return uprv_memcmp(getArrayStart(), text.getArrayStart(), len * U_SIZEOF_UCHAR) == 0;
57654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
57754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint8_t
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doCompare( int32_t start,
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t length,
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              const UChar *srcChars,
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcStart,
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcLength) const
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // compare illegal string values
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus()) {
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices to legal values
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcChars == NULL) {
594103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // treat const UChar *srcChars==NULL as an empty string
595103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return length == 0 ? 0 : 1;
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the correct pointer
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  const UChar *chars = getArrayStart();
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  chars += start;
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  srcChars += srcStart;
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int32_t minLength;
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int8_t lengthResult;
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the srcLength if necessary
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcLength < 0) {
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcLength = u_strlen(srcChars + srcStart);
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // are we comparing different lengths?
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(length != srcLength) {
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(length < srcLength) {
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      minLength = length;
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      lengthResult = -1;
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      minLength = srcLength;
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      lengthResult = 1;
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    minLength = length;
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    lengthResult = 0;
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /*
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * note that uprv_memcmp() returns an int but we return an int8_t;
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * we need to take care not to truncate the result -
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * one way to do this is to right-shift the value to
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * move the sign bit into the lower 8 bits and making sure that this
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * does not become 0 itself
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   */
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(minLength > 0 && chars != srcChars) {
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t result;
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   if U_IS_BIG_ENDIAN
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // big-endian: byte comparison works
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      result = uprv_memcmp(chars, srcChars, minLength * sizeof(UChar));
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(result != 0) {
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return (int8_t)(result >> 15 | 1);
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   else
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // little-endian: compare UChar units
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      do {
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result = ((int32_t)*(chars++) - (int32_t)*(srcChars++));
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(result != 0) {
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          return (int8_t)(result >> 15 | 1);
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } while(--minLength > 0);
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#   endif
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return lengthResult;
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* String compare in code point order - doCompare() compares in code unit order. */
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint8_t
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doCompareCodePointOrder(int32_t start,
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       int32_t length,
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       const UChar *srcChars,
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       int32_t srcStart,
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                       int32_t srcLength) const
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // compare illegal string values
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // treat const UChar *srcChars==NULL as an empty string
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus()) {
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices to legal values
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcChars == NULL) {
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcStart = srcLength = 0;
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
677103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int32_t diff = uprv_strCompare(getArrayStart() + start, length, (srcChars!=NULL)?(srcChars + srcStart):NULL, srcLength, FALSE, TRUE);
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /* translate the 32-bit result into an 8-bit one */
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(diff!=0) {
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (int8_t)(diff >> 15 | 1);
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getLength() const {
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return length();
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getCharAt(int32_t offset) const {
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return charAt(offset);
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar32
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getChar32At(int32_t offset) const {
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return char32At(offset);
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
701103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUChar32
702103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString::char32At(int32_t offset) const
703103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius{
704103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int32_t len = length();
705103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if((uint32_t)offset < (uint32_t)len) {
706103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UChar *array = getArrayStart();
707103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UChar32 c;
708103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    U16_GET(array, 0, offset, len, c);
709103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return c;
710103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  } else {
711103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return kInvalidUChar;
712103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
713103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
714103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
715103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusint32_t
716103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString::getChar32Start(int32_t offset) const {
717103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if((uint32_t)offset < (uint32_t)length()) {
718103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UChar *array = getArrayStart();
719103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    U16_SET_CP_START(array, 0, offset);
720103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return offset;
721103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  } else {
722103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return 0;
723103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
724103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
725103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
726103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusint32_t
727103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString::getChar32Limit(int32_t offset) const {
728103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int32_t len = length();
729103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  if((uint32_t)offset < (uint32_t)len) {
730103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UChar *array = getArrayStart();
731103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    U16_SET_CP_LIMIT(array, 0, offset, len);
732103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return offset;
733103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  } else {
734103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return len;
735103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  }
736103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
737103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::countChar32(int32_t start, int32_t length) const {
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if(isBogus()) then fArray==0 and start==0 - u_countChar32() checks for NULL
742c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  return u_countChar32(getArrayStart()+start, length);
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::hasMoreChar32Than(int32_t start, int32_t length, int32_t number) const {
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if(isBogus()) then fArray==0 and start==0 - u_strHasMoreChar32Than() checks for NULL
749c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  return u_strHasMoreChar32Than(getArrayStart()+start, length, number);
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::moveIndex32(int32_t index, int32_t delta) const {
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin index
755c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t len = length();
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(index<0) {
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    index=0;
758c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else if(index>len) {
759c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    index=len;
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
762c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(delta>0) {
764103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    U16_FWD_N(array, index, len, delta);
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
766103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    U16_BACK_N(array, 0, index, -delta);
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return index;
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doExtract(int32_t start,
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length,
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UChar *dst,
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t dstStart) const
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices to legal values
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // do not copy anything if we alias dst itself
782c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
783c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(array + start != dst + dstStart) {
784c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    us_arrayCopy(array, start, dst, dstStart, length);
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::extract(UChar *dest, int32_t destCapacity,
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       UErrorCode &errorCode) const {
791c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t len = length();
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(U_SUCCESS(errorCode)) {
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(isBogus() || destCapacity<0 || (destCapacity>0 && dest==0)) {
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      errorCode=U_ILLEGAL_ARGUMENT_ERROR;
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
796c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      const UChar *array = getArrayStart();
797c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(len>0 && len<=destCapacity && array!=dest) {
798c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        uprv_memcpy(dest, array, len*U_SIZEOF_UCHAR);
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
800c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      return u_terminateUChars(dest, destCapacity, len, &errorCode);
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
804c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  return len;
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::extract(int32_t start,
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       int32_t length,
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       char *target,
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       int32_t targetCapacity,
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       enum EInvariant) const
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if the arguments are illegal, then do nothing
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(targetCapacity < 0 || (targetCapacity > 0 && target == NULL)) {
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin the indices to legal values
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(length <= targetCapacity) {
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_UCharsToChars(getArrayStart() + start, target, length);
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UErrorCode status = U_ZERO_ERROR;
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return u_terminateChars(target, targetCapacity, length, &status);
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
82950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString
83050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString::tempSubString(int32_t start, int32_t len) const {
83150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  pinIndices(start, len);
83250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  const UChar *array = getBuffer();  // not getArrayStart() to check kIsBogus & kOpenGetBuffer
83350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  if(array==NULL) {
83450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    array=fUnion.fStackBuffer;  // anything not NULL because that would make an empty string
83550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    len=-2;  // bogus result string
83650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  }
83750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  return UnicodeString(FALSE, array + start, len);
83850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
83950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
840b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruint32_t
841b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::toUTF8(int32_t start, int32_t len,
842b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                      char *target, int32_t capacity) const {
843b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  pinIndices(start, len);
844b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length8;
845b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UErrorCode errorCode = U_ZERO_ERROR;
846b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  u_strToUTF8WithSub(target, capacity, &length8,
847b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     getBuffer() + start, len,
848b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     0xFFFD,  // Standard substitution character.
849b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     NULL,    // Don't care about number of substitutions.
850b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     &errorCode);
851b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return length8;
852b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
853b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
854b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if U_CHARSET_IS_UTF8
855b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
856b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruint32_t
857b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::extract(int32_t start, int32_t len,
858b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       char *target, uint32_t dstSize) const {
859b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // if the arguments are illegal, then do nothing
860b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(/*dstSize < 0 || */(dstSize > 0 && target == 0)) {
861b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return 0;
862b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
863b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return toUTF8(start, len, target, dstSize <= 0x7fffffff ? (int32_t)dstSize : 0x7fffffff);
864b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
865b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
866b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// else see unistr_cnv.cpp
867b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
868b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::extractBetween(int32_t start,
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t limit,
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  UnicodeString& target) const {
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndex(start);
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndex(limit);
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  doExtract(start, limit - start, target);
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
878b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// When converting from UTF-16 to UTF-8, the result will have at most 3 times
879b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// as many bytes as the source has UChars.
880b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// The "worst cases" are writing systems like Indic, Thai and CJK with
881b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 3:1 bytes:UChars.
882b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid
883b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::toUTF8(ByteSink &sink) const {
884b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length16 = length();
885b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(length16 != 0) {
886b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char stackBuffer[1024];
887b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t capacity = (int32_t)sizeof(stackBuffer);
888b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UBool utf8IsOwned = FALSE;
889b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char *utf8 = sink.GetAppendBuffer(length16 < capacity ? length16 : capacity,
890b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                      3*length16,
891b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                      stackBuffer, capacity,
892b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                      &capacity);
893b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t length8 = 0;
894b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode errorCode = U_ZERO_ERROR;
895b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    u_strToUTF8WithSub(utf8, capacity, &length8,
896b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       getBuffer(), length16,
897b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       0xFFFD,  // Standard substitution character.
898b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       NULL,    // Don't care about number of substitutions.
899b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       &errorCode);
900b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(errorCode == U_BUFFER_OVERFLOW_ERROR) {
901b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      utf8 = (char *)uprv_malloc(length8);
902b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      if(utf8 != NULL) {
903b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        utf8IsOwned = TRUE;
904b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        errorCode = U_ZERO_ERROR;
905b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        u_strToUTF8WithSub(utf8, length8, &length8,
906b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           getBuffer(), length16,
907b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           0xFFFD,  // Standard substitution character.
908b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           NULL,    // Don't care about number of substitutions.
909b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           &errorCode);
910b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      } else {
911b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        errorCode = U_MEMORY_ALLOCATION_ERROR;
912b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      }
913b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
914b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(U_SUCCESS(errorCode)) {
915b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      sink.Append(utf8, length8);
91627f654740f2a26ad62a5c155af9199af9e69b889claireho      sink.Flush();
917b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
918b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if(utf8IsOwned) {
919b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      uprv_free(utf8);
920b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
921b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
922b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
923b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
924b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruint32_t
925b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString::toUTF32(UChar32 *utf32, int32_t capacity, UErrorCode &errorCode) const {
926b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length32=0;
927b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(U_SUCCESS(errorCode)) {
928b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // getBuffer() and u_strToUTF32WithSub() check for illegal arguments.
929b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    u_strToUTF32WithSub(utf32, capacity, &length32,
930b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        getBuffer(), length(),
931b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        0xfffd,  // Substitution character.
932b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        NULL,    // Don't care about number of substitutions.
933b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        &errorCode);
934b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
935b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return length32;
936b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
937b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::indexOf(const UChar *srcChars,
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcStart,
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcLength,
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t start,
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t length) const
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus() || srcChars == 0 || srcStart < 0 || srcLength == 0) {
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // UnicodeString does not find empty substrings
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcLength < 0 && srcChars[srcStart] == 0) {
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the indices within bounds
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the first occurrence of the substring
958c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
959c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_strFindFirst(array + start, length, srcChars + srcStart, srcLength);
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
963c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doIndexOf(UChar c,
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t start,
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length) const
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the first occurrence of c
976c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
977c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memchr(array + start, c, length);
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
981c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doIndexOf(UChar32 c,
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         int32_t start,
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         int32_t length) const {
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the first occurrence of c
993c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
994c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memchr32(array + start, c, length);
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
998c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::lastIndexOf(const UChar *srcChars,
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcStart,
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t srcLength,
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t start,
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t length) const
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus() || srcChars == 0 || srcStart < 0 || srcLength == 0) {
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // UnicodeString does not find empty substrings
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcLength < 0 && srcChars[srcStart] == 0) {
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // get the indices within bounds
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the last occurrence of the substring
1022c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
1023c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_strFindLast(array + start, length, srcChars + srcStart, srcLength);
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1027c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doLastIndexOf(UChar c,
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 int32_t start,
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 int32_t length) const
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus()) {
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the last occurrence of c
1044c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
1045c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memrchr(array + start, c, length);
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1049c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doLastIndexOf(UChar32 c,
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t start,
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             int32_t length) const {
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin indices
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // find the last occurrence of c
1061c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *array = getArrayStart();
1062c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  const UChar *match = u_memrchr32(array + start, c, length);
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(match == NULL) {
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1066c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return (int32_t)(match - array);
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Write implementation
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::findAndReplace(int32_t start,
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t length,
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const UnicodeString& oldText,
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t oldStart,
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t oldLength,
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const UnicodeString& newText,
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t newStart,
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  int32_t newLength)
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(isBogus() || oldText.isBogus() || newText.isBogus()) {
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  oldText.pinIndices(oldStart, oldLength);
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  newText.pinIndices(newStart, newLength);
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(oldLength == 0) {
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  while(length > 0 && length >= oldLength) {
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t pos = indexOf(oldText, oldStart, oldLength, start, length);
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pos < 0) {
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // no more oldText's here: done
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      break;
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // we found oldText, replace it by newText and go beyond it
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      replace(pos, oldLength, newText, newStart, newLength);
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      length -= pos + oldLength - start;
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      start = pos + newLength;
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setToBogus()
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1118c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fShortLength = 0;
1119c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fUnion.fFields.fArray = 0;
1120c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  fUnion.fFields.fCapacity = 0;
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fFlags = kIsBogus;
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// turn a bogus string into an empty one
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::unBogus() {
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags & kIsBogus) {
1128c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// setTo() analogous to the readonly-aliasing constructor with the same signature
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setTo(UBool isTerminated,
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     const UChar *text,
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     int32_t textLength)
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags & kOpenGetBuffer) {
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // do not modify a string that has an "open" getBuffer(minCapacity)
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(text == NULL) {
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    releaseArray();
1146c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if( textLength < -1 ||
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      (textLength == -1 && !isTerminated) ||
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      (textLength >= 0 && isTerminated && text[textLength] != 0)
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1160c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(textLength == -1) {
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // text is terminated, or else it would have failed the above test
1162c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    textLength = u_strlen(text);
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1164c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setArray((UChar *)text, textLength, isTerminated ? textLength + 1 : textLength);
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fFlags = kReadonlyAlias;
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// setTo() analogous to the writable-aliasing constructor with the same signature
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString &
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setTo(UChar *buffer,
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     int32_t buffLength,
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     int32_t buffCapacity) {
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags & kOpenGetBuffer) {
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // do not modify a string that has an "open" getBuffer(minCapacity)
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(buffer == NULL) {
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // treat as an empty string, do not alias
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    releaseArray();
1183c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setToEmpty();
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(buffLength < -1 || buffCapacity < 0 || buffLength > buffCapacity) {
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setToBogus();
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(buffLength == -1) {
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // buffLength = u_strlen(buff); but do not look beyond buffCapacity
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar *p = buffer, *limit = buffer + buffCapacity;
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(p != limit && *p != 0) {
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      ++p;
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    buffLength = (int32_t)(p - buffer);
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  releaseArray();
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1201c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  setArray(buffer, buffLength, buffCapacity);
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fFlags = kWritableAlias;
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString &UnicodeString::setToUTF8(const StringPiece &utf8) {
1207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  unBogus();
1208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length = utf8.length();
1209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t capacity;
1210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  // The UTF-16 string will be at most as long as the UTF-8 string.
1211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(length <= US_STACKBUF_SIZE) {
1212b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    capacity = US_STACKBUF_SIZE;
1213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  } else {
1214b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    capacity = length + 1;  // +1 for the terminating NUL.
1215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
1216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UChar *utf16 = getBuffer(capacity);
1217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  int32_t length16;
1218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  UErrorCode errorCode = U_ZERO_ERROR;
1219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  u_strFromUTF8WithSub(utf16, getCapacity(), &length16,
1220b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      utf8.data(), length,
1221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      0xfffd,  // Substitution character.
1222b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      NULL,    // Don't care about number of substitutions.
1223b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru      &errorCode);
1224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  releaseBuffer(length16);
1225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  if(U_FAILURE(errorCode)) {
1226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    setToBogus();
1227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  }
1228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru  return *this;
1229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::setCharAt(int32_t offset,
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             UChar c)
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1235c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t len = length();
1236c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(cloneArrayIfNeeded() && len > 0) {
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(offset < 0) {
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      offset = 0;
1239c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if(offset >= len) {
1240c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      offset = len - 1;
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1243c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    getArrayStart()[offset] = c;
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1249103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString::replace(int32_t start,
1250103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius               int32_t _length,
1251103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius               UChar32 srcChar) {
1252103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  UChar buffer[U16_MAX_LENGTH];
1253103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int32_t count = 0;
1254103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  UBool isError = FALSE;
1255103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  U16_APPEND(buffer, count, U16_MAX_LENGTH, srcChar, isError);
1256103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // We test isError so that the compiler does not complain that we don't.
125754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  // If isError (srcChar is not a valid code point) then count==0 which means
125854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  // we remove the source segment rather than replacing it with srcChar.
125954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  return doReplace(start, _length, buffer, 0, isError ? 0 : count);
1260103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
1261103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1262103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString&
1263103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString::append(UChar32 srcChar) {
1264103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  UChar buffer[U16_MAX_LENGTH];
1265103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  int32_t _length = 0;
1266103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  UBool isError = FALSE;
1267103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  U16_APPEND(buffer, _length, U16_MAX_LENGTH, srcChar, isError);
1268103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // We test isError so that the compiler does not complain that we don't.
1269103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  // If isError then _length==0 which turns the doReplace() into a no-op anyway.
1270103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  return isError ? *this : doReplace(length(), 0, buffer, 0, _length);
1271103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
1272103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1273103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString&
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doReplace( int32_t start,
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t length,
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              const UnicodeString& src,
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcStart,
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t srcLength)
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(!src.isBogus()) {
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // pin the indices to legal values
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    src.pinIndices(srcStart, srcLength);
1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // get the characters from src
1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // and replace the range in ourselves with them
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return doReplace(start, length, src.getArrayStart(), srcStart, srcLength);
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // remove the range
1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return doReplace(start, length, 0, 0, 0);
1290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doReplace(int32_t start,
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t length,
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             const UChar *srcChars,
1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t srcStart,
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             int32_t srcLength)
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1300c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(!isWritable()) {
1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
130450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  int32_t oldLength = this->length();
130550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
130650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // optimize (read-only alias).remove(0, start) and .remove(start, end)
130750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  if((fFlags&kBufferIsReadonly) && srcLength == 0) {
130850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(start == 0) {
130950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      // remove prefix by adjusting the array pointer
131050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      pinIndex(length);
131150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      fUnion.fFields.fArray += length;
131250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      fUnion.fFields.fCapacity -= length;
131350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      setLength(oldLength - length);
131450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      return *this;
131550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else {
131650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      pinIndex(start);
131750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      if(length >= (oldLength - start)) {
131850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        // remove suffix by reducing the length (like truncate())
131950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        setLength(start);
132050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        fUnion.fFields.fCapacity = start;  // not NUL-terminated any more
132150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return *this;
132250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      }
132350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
132450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  }
132550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(srcChars == 0) {
1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcStart = srcLength = 0;
1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(srcLength < 0) {
1329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // get the srcLength if necessary
1330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    srcLength = u_strlen(srcChars + srcStart);
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1333c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // calculate the size of the string after the replace
1334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  int32_t newLength;
1335c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1336c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // optimize append() onto a large-enough, owned string
1337c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(start >= oldLength) {
1338103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if(srcLength == 0) {
1339103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      return *this;
1340103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    newLength = oldLength + srcLength;
1342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(newLength <= getCapacity() && isBufferWritable()) {
1343b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      UChar *oldArray = getArrayStart();
1344b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      // Do not copy characters when
1345b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      //   UChar *buffer=str.getAppendBuffer(...);
1346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      // is followed by
1347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      //   str.append(buffer, length);
1348b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      // or
1349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      //   str.appendString(buffer, length)
1350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      // or similar.
1351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      if(srcChars + srcStart != oldArray + start || start > oldLength) {
1352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        us_arrayCopy(srcChars, srcStart, oldArray, oldLength, srcLength);
1353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      }
1354b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      setLength(newLength);
1355c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      return *this;
1356c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1357c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      // pin the indices to legal values
1358c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      start = oldLength;
1359c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      length = 0;
1360c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1361c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
1362c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // pin the indices to legal values
1363c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    pinIndices(start, length);
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1365b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    newLength = oldLength - length + srcLength;
1366c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1368c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // the following may change fArray but will not copy the current contents;
1369c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  // therefore we need to keep the current fArray
1370c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar oldStackBuffer[US_STACKBUF_SIZE];
1371c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar *oldArray;
1372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if((fFlags&kUsingStackBuffer) && (newLength > US_STACKBUF_SIZE)) {
1373c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // copy the stack buffer contents because it will be overwritten with
1374c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // fUnion.fFields values
1375c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    u_memcpy(oldStackBuffer, fUnion.fStackBuffer, oldLength);
1376c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    oldArray = oldStackBuffer;
1377c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  } else {
1378c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    oldArray = getArrayStart();
1379c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  }
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // clone our array and allocate a bigger array if needed
1382c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t *bufferToDelete = 0;
1383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if(!cloneArrayIfNeeded(newLength, newLength + (newLength >> 2) + kGrowSize,
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         FALSE, &bufferToDelete)
1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // now do the replace
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1391c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  UChar *newArray = getArrayStart();
1392c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(newArray != oldArray) {
1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if fArray changed, then we need to copy everything except what will change
1394c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    us_arrayCopy(oldArray, 0, newArray, 0, start);
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    us_arrayCopy(oldArray, start + length,
1396c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 newArray, start + srcLength,
1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 oldLength - (start + length));
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else if(length != srcLength) {
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fArray did not change; copy only the portion that isn't changing, leaving a hole
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    us_arrayCopy(oldArray, start + length,
1401c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 newArray, start + srcLength,
1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 oldLength - (start + length));
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // now fill in the hole with the new string
1406c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  us_arrayCopy(srcChars, srcStart, newArray, start, srcLength);
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1408b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  setLength(newLength);
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // delayed delete in case srcChars == fArray when we started, and
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // to keep oldArray alive for the above operations
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if (bufferToDelete) {
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(bufferToDelete);
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::handleReplaceBetween(int32_t start,
1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    int32_t limit,
1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    const UnicodeString& text) {
1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    replaceBetween(start, limit, text);
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::copy(int32_t start, int32_t limit, int32_t dest) {
1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (limit <= start) {
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return; // Nothing to do; avoid bogus malloc call
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar* text = (UChar*) uprv_malloc( sizeof(UChar) * (limit - start) );
1438c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // Check to make sure text is not null.
1439c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (text != NULL) {
1440c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	    extractBetween(start, limit, text, 0);
1441c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	    insert(dest, text, 0, limit - start);
1442c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	    uprv_free(text);
1443c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * NOTE: This is for the Replaceable class.  There is no rep.cpp,
1450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * so we implement this function here.
1451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool Replaceable::hasMetaData() const {
1453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Replaceable API
1458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool UnicodeString::hasMetaData() const {
1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
146427f654740f2a26ad62a5c155af9199af9e69b889clairehoUnicodeString::doReverse(int32_t start, int32_t length) {
146527f654740f2a26ad62a5c155af9199af9e69b889claireho  if(length <= 1 || !cloneArrayIfNeeded()) {
1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // pin the indices to legal values
1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  pinIndices(start, length);
147127f654740f2a26ad62a5c155af9199af9e69b889claireho  if(length <= 1) {  // pinIndices() might have shrunk the length
147227f654740f2a26ad62a5c155af9199af9e69b889claireho    return *this;
147327f654740f2a26ad62a5c155af9199af9e69b889claireho  }
1474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UChar *left = getArrayStart() + start;
147627f654740f2a26ad62a5c155af9199af9e69b889claireho  UChar *right = left + length - 1;  // -1 for inclusive boundary (length>=2)
1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UChar swap;
1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UBool hasSupplementary = FALSE;
1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
148027f654740f2a26ad62a5c155af9199af9e69b889claireho  // Before the loop we know left<right because length>=2.
148127f654740f2a26ad62a5c155af9199af9e69b889claireho  do {
148227f654740f2a26ad62a5c155af9199af9e69b889claireho    hasSupplementary |= (UBool)U16_IS_LEAD(swap = *left);
148327f654740f2a26ad62a5c155af9199af9e69b889claireho    hasSupplementary |= (UBool)U16_IS_LEAD(*left++ = *right);
148427f654740f2a26ad62a5c155af9199af9e69b889claireho    *right-- = swap;
148527f654740f2a26ad62a5c155af9199af9e69b889claireho  } while(left < right);
148627f654740f2a26ad62a5c155af9199af9e69b889claireho  // Make sure to test the middle code unit of an odd-length string.
148727f654740f2a26ad62a5c155af9199af9e69b889claireho  // Redundant if the length is even.
148827f654740f2a26ad62a5c155af9199af9e69b889claireho  hasSupplementary |= (UBool)U16_IS_LEAD(*left);
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /* if there are supplementary code points in the reversed range, then re-swap their surrogates */
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(hasSupplementary) {
1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar swap2;
1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    left = getArrayStart() + start;
1495c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    right = left + length - 1; // -1 so that we can look at *(left+1) if left<right
1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(left < right) {
149727f654740f2a26ad62a5c155af9199af9e69b889claireho      if(U16_IS_TRAIL(swap = *left) && U16_IS_LEAD(swap2 = *(left + 1))) {
1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *left++ = swap2;
1499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *left++ = swap;
1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++left;
1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return *this;
1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::padLeading(int32_t targetLength,
1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          UChar padChar)
1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1513c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t oldLength = length();
1514c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(oldLength >= targetLength || !cloneArrayIfNeeded(targetLength)) {
1515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // move contents up by padding width
1518c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar *array = getArrayStart();
1519c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t start = targetLength - oldLength;
1520c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    us_arrayCopy(array, 0, array, start, oldLength);
1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fill in padding character
1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(--start >= 0) {
1524c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      array[start] = padChar;
1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1526c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(targetLength);
1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::padTrailing(int32_t targetLength,
1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                           UChar padChar)
1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1535c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  int32_t oldLength = length();
1536c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(oldLength >= targetLength || !cloneArrayIfNeeded(targetLength)) {
1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fill in padding character
1540c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar *array = getArrayStart();
1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t length = targetLength;
1542c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    while(--length >= oldLength) {
1543c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      array[length] = padChar;
1544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1545c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(targetLength);
1546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Hashing
1552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::doHashCode() const
1555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Delegate hash computation to uhash.  This makes UnicodeString
1557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * hashing consistent with UChar* hashing.  */
1558103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t hashCode = ustr_hashUCharsN(getArrayStart(), length());
1559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (hashCode == kInvalidHashCode) {
1560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hashCode = kEmptyHashCode;
1561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return hashCode;
1563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// External Buffer
1567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUChar *
1570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::getBuffer(int32_t minCapacity) {
1571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(minCapacity>=-1 && cloneArrayIfNeeded(minCapacity)) {
1572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags|=kOpenGetBuffer;
1573c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fShortLength=0;
1574c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return getArrayStart();
1575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  } else {
1576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
1577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::releaseBuffer(int32_t newLength) {
1582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(fFlags&kOpenGetBuffer && newLength>=-1) {
1583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // set the new fLength
1584c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t capacity=getCapacity();
1585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(newLength==-1) {
1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // the new length is the string length, capped by fCapacity
1587c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      const UChar *array=getArrayStart(), *p=array, *limit=array+capacity;
1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      while(p<limit && *p!=0) {
1589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++p;
1590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1591c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      newLength=(int32_t)(p-array);
1592c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else if(newLength>capacity) {
1593c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      newLength=capacity;
1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1595c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setLength(newLength);
1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fFlags&=~kOpenGetBuffer;
1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Miscellaneous
1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//========================================
1603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString::cloneArrayIfNeeded(int32_t newCapacity,
1605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  int32_t growCapacity,
1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  UBool doCopyArray,
1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  int32_t **pBufferToDelete,
1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                  UBool forceClone) {
1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // default parameters need to be static, therefore
1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // the defaults are -1 to have convenience defaults
1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(newCapacity == -1) {
1612c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    newCapacity = getCapacity();
1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // while a getBuffer(minCapacity) is "open",
1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // prevent any modifications of the string by returning FALSE here
1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // if the string is bogus, then only an assignment or similar can revive it
1618c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru  if(!isWritable()) {
1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /*
1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * We need to make a copy of the array if
1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * the buffer is read-only, or
1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * the buffer is refCounted (shared), and refCount>1, or
1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * the buffer is too small.
1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * Return FALSE if memory could not be allocated.
1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   */
1629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(forceClone ||
1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     fFlags & kBufferIsReadonly ||
163127f654740f2a26ad62a5c155af9199af9e69b889claireho     (fFlags & kRefCounted && refCount() > 1) ||
1632c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru     newCapacity > getCapacity()
1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  ) {
1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // check growCapacity for default value and use of the stack buffer
1635103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if(growCapacity < 0) {
1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      growCapacity = newCapacity;
1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if(newCapacity <= US_STACKBUF_SIZE && growCapacity > US_STACKBUF_SIZE) {
1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      growCapacity = US_STACKBUF_SIZE;
1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1641c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // save old values
1642c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar oldStackBuffer[US_STACKBUF_SIZE];
1643c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar *oldArray;
1644c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    uint8_t flags = fFlags;
1645c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1646c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(flags&kUsingStackBuffer) {
1647103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      U_ASSERT(!(flags&kRefCounted)); /* kRefCounted and kUsingStackBuffer are mutally exclusive */
1648c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(doCopyArray && growCapacity > US_STACKBUF_SIZE) {
1649c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // copy the stack buffer contents because it will be overwritten with
1650c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // fUnion.fFields values
1651c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        us_arrayCopy(fUnion.fStackBuffer, 0, oldStackBuffer, 0, fShortLength);
1652c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        oldArray = oldStackBuffer;
1653c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      } else {
1654c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        oldArray = 0; // no need to copy from stack buffer to itself
1655c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
1656c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1657c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      oldArray = fUnion.fFields.fArray;
1658103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      U_ASSERT(oldArray!=NULL); /* when stack buffer is not used, oldArray must have a non-NULL reference */
1659c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1660c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // allocate a new array
1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(allocate(growCapacity) ||
166327f654740f2a26ad62a5c155af9199af9e69b889claireho       (newCapacity < growCapacity && allocate(newCapacity))
1664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ) {
1665c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(doCopyArray && oldArray != 0) {
1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // copy the contents
1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // do not copy more than what fits - it may be smaller than before
1668c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t minLength = length();
1669c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        newCapacity = getCapacity();
1670c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if(newCapacity < minLength) {
1671c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          minLength = newCapacity;
1672c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru          setLength(minLength);
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1674c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        us_arrayCopy(oldArray, 0, getArrayStart(), 0, minLength);
1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
1676c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fShortLength = 0;
1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // release the old array
1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(flags & kRefCounted) {
1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // the array is refCounted; decrement and release if 0
1682c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t *pRefCount = ((int32_t *)oldArray - 1);
1683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(umtx_atomic_dec(pRefCount) == 0) {
1684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          if(pBufferToDelete == 0) {
1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_free(pRefCount);
1686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          } else {
1687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // the caller requested to delete it himself
1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pBufferToDelete = pRefCount;
1689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          }
1690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
1692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // not enough memory for growCapacity and not even for the smaller newCapacity
1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      // reset the old values for setToBogus() to release the array
1695c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      if(!(flags&kUsingStackBuffer)) {
1696c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fUnion.fFields.fArray = oldArray;
1697c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru      }
1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      fFlags = flags;
1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      setToBogus();
1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return FALSE;
1701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
1703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return TRUE;
1704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1705b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1706b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// UnicodeStringAppendable ------------------------------------------------- ***
1707b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1708103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeStringAppendable::~UnicodeStringAppendable() {}
1709103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1710b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1711b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeStringAppendable::appendCodeUnit(UChar c) {
1712b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  return str.doReplace(str.length(), 0, &c, 0, 1).isWritable();
1713b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1714b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1715b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1716b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeStringAppendable::appendCodePoint(UChar32 c) {
1717b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  UChar buffer[U16_MAX_LENGTH];
1718b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  int32_t cLength = 0;
1719b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  UBool isError = FALSE;
1720b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  U16_APPEND(buffer, cLength, U16_MAX_LENGTH, c, isError);
1721b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  return !isError && str.doReplace(str.length(), 0, buffer, 0, cLength).isWritable();
1722b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1723b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1724b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1725b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeStringAppendable::appendString(const UChar *s, int32_t length) {
1726b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  return str.doReplace(str.length(), 0, s, 0, length).isWritable();
1727b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1728b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1729b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1730b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeStringAppendable::reserveAppendCapacity(int32_t appendCapacity) {
1731b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  return str.cloneArrayIfNeeded(str.length() + appendCapacity);
1732b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1733b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1734b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUChar *
1735b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeStringAppendable::getAppendBuffer(int32_t minCapacity,
1736b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                         int32_t desiredCapacityHint,
1737b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                         UChar *scratch, int32_t scratchCapacity,
1738b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                         int32_t *resultCapacity) {
1739b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if(minCapacity < 1 || scratchCapacity < minCapacity) {
1740b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    *resultCapacity = 0;
1741b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return NULL;
1742b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  }
1743b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  int32_t oldLength = str.length();
1744b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if(str.cloneArrayIfNeeded(oldLength + minCapacity, oldLength + desiredCapacityHint)) {
1745b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    *resultCapacity = str.getCapacity() - oldLength;
1746b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return str.getArrayStart() + oldLength;
1747b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  }
1748b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  *resultCapacity = scratchCapacity;
1749b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  return scratch;
1750b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1751b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
1753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1754103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_NAMESPACE_USE
1755103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1756103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CAPI int32_t U_EXPORT2
1757103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusuhash_hashUnicodeString(const UElement key) {
1758103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UnicodeString *str = (const UnicodeString*) key.pointer;
1759103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return (str == NULL) ? 0 : str->hashCode();
1760103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
1761103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1762103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Moved here from uhash_us.cpp so that using a UVector of UnicodeString*
1763103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// does not depend on hashtable code.
1764103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CAPI UBool U_EXPORT2
1765103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusuhash_compareUnicodeString(const UElement key1, const UElement key2) {
1766103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UnicodeString *str1 = (const UnicodeString*) key1.pointer;
1767103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UnicodeString *str2 = (const UnicodeString*) key2.pointer;
1768103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (str1 == str2) {
1769103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        return TRUE;
1770103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1771103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (str1 == NULL || str2 == NULL) {
1772103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        return FALSE;
1773103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1774103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return *str1 == *str2;
1775103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
1776103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_STATIC_IMPLEMENTATION
1778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
1779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThis should never be called. It is defined here to make sure that the
1780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvirtual vector deleting destructor is defined within unistr.cpp.
1781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThe vector deleting destructor is already a part of UObject,
1782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querubut defining it here makes sure that it is included with this object file.
1783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruThis makes sure that static library dependencies are kept to a minimum.
1784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void uprv_UnicodeStringDummy(void) {
1786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete [] (new UnicodeString[2]);
1787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1789