| OLD | NEW |
| 1 /* | 1 /* |
| 2 ******************************************************************************* | 2 ******************************************************************************* |
| 3 * | 3 * |
| 4 * Copyright (C) 2013, International Business Machines | 4 * Copyright (C) 2013-2014, International Business Machines |
| 5 * Corporation and others. All Rights Reserved. | 5 * Corporation and others. All Rights Reserved. |
| 6 * | 6 * |
| 7 ******************************************************************************* | 7 ******************************************************************************* |
| 8 * file name: listformatter.cpp | 8 * file name: listformatter.cpp |
| 9 * encoding: US-ASCII | 9 * encoding: US-ASCII |
| 10 * tab size: 8 (not used) | 10 * tab size: 8 (not used) |
| 11 * indentation:4 | 11 * indentation:4 |
| 12 * | 12 * |
| 13 * created on: 2012aug27 | 13 * created on: 2012aug27 |
| 14 * created by: Umesh P. Nair | 14 * created by: Umesh P. Nair |
| 15 */ | 15 */ |
| 16 | 16 |
| 17 #include "unicode/listformatter.h" | 17 #include "unicode/listformatter.h" |
| 18 #include "simplepatternformatter.h" |
| 18 #include "mutex.h" | 19 #include "mutex.h" |
| 19 #include "hash.h" | 20 #include "hash.h" |
| 20 #include "cstring.h" | 21 #include "cstring.h" |
| 21 #include "ulocimp.h" | 22 #include "ulocimp.h" |
| 22 #include "charstr.h" | 23 #include "charstr.h" |
| 23 #include "ucln_cmn.h" | 24 #include "ucln_cmn.h" |
| 24 #include "uresimp.h" | 25 #include "uresimp.h" |
| 25 | 26 |
| 26 U_NAMESPACE_BEGIN | 27 U_NAMESPACE_BEGIN |
| 27 | 28 |
| 29 struct ListFormatInternal : public UMemory { |
| 30 SimplePatternFormatter twoPattern; |
| 31 SimplePatternFormatter startPattern; |
| 32 SimplePatternFormatter middlePattern; |
| 33 SimplePatternFormatter endPattern; |
| 34 |
| 35 ListFormatInternal( |
| 36 const UnicodeString& two, |
| 37 const UnicodeString& start, |
| 38 const UnicodeString& middle, |
| 39 const UnicodeString& end) : |
| 40 twoPattern(two), |
| 41 startPattern(start), |
| 42 middlePattern(middle), |
| 43 endPattern(end) {} |
| 44 |
| 45 ListFormatInternal(const ListFormatData &data) : |
| 46 twoPattern(data.twoPattern), |
| 47 startPattern(data.startPattern), |
| 48 middlePattern(data.middlePattern), |
| 49 endPattern(data.endPattern) { } |
| 50 |
| 51 ListFormatInternal(const ListFormatInternal &other) : |
| 52 twoPattern(other.twoPattern), |
| 53 startPattern(other.startPattern), |
| 54 middlePattern(other.middlePattern), |
| 55 endPattern(other.endPattern) { } |
| 56 }; |
| 57 |
| 58 |
| 59 |
| 28 static Hashtable* listPatternHash = NULL; | 60 static Hashtable* listPatternHash = NULL; |
| 29 static UMutex listFormatterMutex = U_MUTEX_INITIALIZER; | 61 static UMutex listFormatterMutex = U_MUTEX_INITIALIZER; |
| 30 static UChar FIRST_PARAMETER[] = { 0x7b, 0x30, 0x7d }; // "{0}" | |
| 31 static UChar SECOND_PARAMETER[] = { 0x7b, 0x31, 0x7d }; // "{0}" | |
| 32 static const char *STANDARD_STYLE = "standard"; | 62 static const char *STANDARD_STYLE = "standard"; |
| 33 | 63 |
| 34 U_CDECL_BEGIN | 64 U_CDECL_BEGIN |
| 35 static UBool U_CALLCONV uprv_listformatter_cleanup() { | 65 static UBool U_CALLCONV uprv_listformatter_cleanup() { |
| 36 delete listPatternHash; | 66 delete listPatternHash; |
| 37 listPatternHash = NULL; | 67 listPatternHash = NULL; |
| 38 return TRUE; | 68 return TRUE; |
| 39 } | 69 } |
| 40 | 70 |
| 41 static void U_CALLCONV | 71 static void U_CALLCONV |
| 42 uprv_deleteListFormatData(void *obj) { | 72 uprv_deleteListFormatInternal(void *obj) { |
| 43 delete static_cast<ListFormatData *>(obj); | 73 delete static_cast<ListFormatInternal *>(obj); |
| 44 } | 74 } |
| 45 | 75 |
| 46 U_CDECL_END | 76 U_CDECL_END |
| 47 | 77 |
| 48 static ListFormatData* loadListFormatData(const Locale& locale, const char* styl
e, UErrorCode& errorCode); | 78 static ListFormatInternal* loadListFormatInternal( |
| 49 static void getStringByKey(const UResourceBundle* rb, const char* key, UnicodeSt
ring& result, UErrorCode& errorCode); | 79 const Locale& locale, |
| 80 const char* style, |
| 81 UErrorCode& errorCode); |
| 50 | 82 |
| 51 ListFormatter::ListFormatter(const ListFormatter& other) : data(other.data) { | 83 static void getStringByKey( |
| 84 const UResourceBundle* rb, |
| 85 const char* key, |
| 86 UnicodeString& result, |
| 87 UErrorCode& errorCode); |
| 88 |
| 89 ListFormatter::ListFormatter(const ListFormatter& other) : |
| 90 owned(other.owned), data(other.data) { |
| 91 if (other.owned != NULL) { |
| 92 owned = new ListFormatInternal(*other.owned); |
| 93 data = owned; |
| 94 } |
| 52 } | 95 } |
| 53 | 96 |
| 54 ListFormatter& ListFormatter::operator=(const ListFormatter& other) { | 97 ListFormatter& ListFormatter::operator=(const ListFormatter& other) { |
| 55 data = other.data; | 98 if (this == &other) { |
| 99 return *this; |
| 100 } |
| 101 delete owned; |
| 102 if (other.owned) { |
| 103 owned = new ListFormatInternal(*other.owned); |
| 104 data = owned; |
| 105 } else { |
| 106 owned = NULL; |
| 107 data = other.data; |
| 108 } |
| 56 return *this; | 109 return *this; |
| 57 } | 110 } |
| 58 | 111 |
| 59 void ListFormatter::initializeHash(UErrorCode& errorCode) { | 112 void ListFormatter::initializeHash(UErrorCode& errorCode) { |
| 60 if (U_FAILURE(errorCode)) { | 113 if (U_FAILURE(errorCode)) { |
| 61 return; | 114 return; |
| 62 } | 115 } |
| 63 | 116 |
| 64 listPatternHash = new Hashtable(); | 117 listPatternHash = new Hashtable(); |
| 65 if (listPatternHash == NULL) { | 118 if (listPatternHash == NULL) { |
| 66 errorCode = U_MEMORY_ALLOCATION_ERROR; | 119 errorCode = U_MEMORY_ALLOCATION_ERROR; |
| 67 return; | 120 return; |
| 68 } | 121 } |
| 69 | 122 |
| 70 listPatternHash->setValueDeleter(uprv_deleteListFormatData); | 123 listPatternHash->setValueDeleter(uprv_deleteListFormatInternal); |
| 71 ucln_common_registerCleanup(UCLN_COMMON_LIST_FORMATTER, uprv_listformatter_c
leanup); | 124 ucln_common_registerCleanup(UCLN_COMMON_LIST_FORMATTER, uprv_listformatter_c
leanup); |
| 72 | 125 |
| 73 } | 126 } |
| 74 | 127 |
| 75 const ListFormatData* ListFormatter::getListFormatData( | 128 const ListFormatInternal* ListFormatter::getListFormatInternal( |
| 76 const Locale& locale, const char *style, UErrorCode& errorCode) { | 129 const Locale& locale, const char *style, UErrorCode& errorCode) { |
| 77 if (U_FAILURE(errorCode)) { | 130 if (U_FAILURE(errorCode)) { |
| 78 return NULL; | 131 return NULL; |
| 79 } | 132 } |
| 80 CharString keyBuffer(locale.getName(), errorCode); | 133 CharString keyBuffer(locale.getName(), errorCode); |
| 81 keyBuffer.append(':', errorCode).append(style, errorCode); | 134 keyBuffer.append(':', errorCode).append(style, errorCode); |
| 82 UnicodeString key(keyBuffer.data(), -1, US_INV); | 135 UnicodeString key(keyBuffer.data(), -1, US_INV); |
| 83 ListFormatData* result = NULL; | 136 ListFormatInternal* result = NULL; |
| 84 { | 137 { |
| 85 Mutex m(&listFormatterMutex); | 138 Mutex m(&listFormatterMutex); |
| 86 if (listPatternHash == NULL) { | 139 if (listPatternHash == NULL) { |
| 87 initializeHash(errorCode); | 140 initializeHash(errorCode); |
| 88 if (U_FAILURE(errorCode)) { | 141 if (U_FAILURE(errorCode)) { |
| 89 return NULL; | 142 return NULL; |
| 90 } | 143 } |
| 91 } | 144 } |
| 92 result = static_cast<ListFormatData*>(listPatternHash->get(key)); | 145 result = static_cast<ListFormatInternal*>(listPatternHash->get(key)); |
| 93 } | 146 } |
| 94 if (result != NULL) { | 147 if (result != NULL) { |
| 95 return result; | 148 return result; |
| 96 } | 149 } |
| 97 result = loadListFormatData(locale, style, errorCode); | 150 result = loadListFormatInternal(locale, style, errorCode); |
| 98 if (U_FAILURE(errorCode)) { | 151 if (U_FAILURE(errorCode)) { |
| 99 return NULL; | 152 return NULL; |
| 100 } | 153 } |
| 101 | 154 |
| 102 { | 155 { |
| 103 Mutex m(&listFormatterMutex); | 156 Mutex m(&listFormatterMutex); |
| 104 ListFormatData* temp = static_cast<ListFormatData*>(listPatternHash->get
(key)); | 157 ListFormatInternal* temp = static_cast<ListFormatInternal*>(listPatternH
ash->get(key)); |
| 105 if (temp != NULL) { | 158 if (temp != NULL) { |
| 106 delete result; | 159 delete result; |
| 107 result = temp; | 160 result = temp; |
| 108 } else { | 161 } else { |
| 109 listPatternHash->put(key, result, errorCode); | 162 listPatternHash->put(key, result, errorCode); |
| 110 if (U_FAILURE(errorCode)) { | 163 if (U_FAILURE(errorCode)) { |
| 111 return NULL; | 164 return NULL; |
| 112 } | 165 } |
| 113 } | 166 } |
| 114 } | 167 } |
| 115 return result; | 168 return result; |
| 116 } | 169 } |
| 117 | 170 |
| 118 static ListFormatData* loadListFormatData( | 171 static ListFormatInternal* loadListFormatInternal( |
| 119 const Locale& locale, const char * style, UErrorCode& errorCode) { | 172 const Locale& locale, const char * style, UErrorCode& errorCode) { |
| 120 UResourceBundle* rb = ures_open(NULL, locale.getName(), &errorCode); | 173 UResourceBundle* rb = ures_open(NULL, locale.getName(), &errorCode); |
| 121 if (U_FAILURE(errorCode)) { | 174 if (U_FAILURE(errorCode)) { |
| 122 ures_close(rb); | 175 ures_close(rb); |
| 123 return NULL; | 176 return NULL; |
| 124 } | 177 } |
| 125 rb = ures_getByKeyWithFallback(rb, "listPattern", rb, &errorCode); | 178 rb = ures_getByKeyWithFallback(rb, "listPattern", rb, &errorCode); |
| 126 rb = ures_getByKeyWithFallback(rb, style, rb, &errorCode); | 179 rb = ures_getByKeyWithFallback(rb, style, rb, &errorCode); |
| 127 | 180 |
| 128 // TODO(Travis Keep): This is a hack until fallbacks can be added for | 181 // TODO(Travis Keep): This is a hack until fallbacks can be added for |
| 129 // listPattern/duration and listPattern/duration-narrow in CLDR. | 182 // listPattern/duration and listPattern/duration-narrow in CLDR. |
| 130 if (errorCode == U_MISSING_RESOURCE_ERROR) { | 183 if (errorCode == U_MISSING_RESOURCE_ERROR) { |
| 131 errorCode = U_ZERO_ERROR; | 184 errorCode = U_ZERO_ERROR; |
| 132 rb = ures_getByKeyWithFallback(rb, "standard", rb, &errorCode); | 185 rb = ures_getByKeyWithFallback(rb, "standard", rb, &errorCode); |
| 133 } | 186 } |
| 134 if (U_FAILURE(errorCode)) { | 187 if (U_FAILURE(errorCode)) { |
| 135 ures_close(rb); | 188 ures_close(rb); |
| 136 return NULL; | 189 return NULL; |
| 137 } | 190 } |
| 138 UnicodeString two, start, middle, end; | 191 UnicodeString two, start, middle, end; |
| 139 getStringByKey(rb, "2", two, errorCode); | 192 getStringByKey(rb, "2", two, errorCode); |
| 140 getStringByKey(rb, "start", start, errorCode); | 193 getStringByKey(rb, "start", start, errorCode); |
| 141 getStringByKey(rb, "middle", middle, errorCode); | 194 getStringByKey(rb, "middle", middle, errorCode); |
| 142 getStringByKey(rb, "end", end, errorCode); | 195 getStringByKey(rb, "end", end, errorCode); |
| 143 ures_close(rb); | 196 ures_close(rb); |
| 144 if (U_FAILURE(errorCode)) { | 197 if (U_FAILURE(errorCode)) { |
| 145 return NULL; | 198 return NULL; |
| 146 } | 199 } |
| 147 ListFormatData* result = new ListFormatData(two, start, middle, end); | 200 ListFormatInternal* result = new ListFormatInternal(two, start, middle, end)
; |
| 148 if (result == NULL) { | 201 if (result == NULL) { |
| 149 errorCode = U_MEMORY_ALLOCATION_ERROR; | 202 errorCode = U_MEMORY_ALLOCATION_ERROR; |
| 150 return NULL; | 203 return NULL; |
| 151 } | 204 } |
| 152 return result; | 205 return result; |
| 153 } | 206 } |
| 154 | 207 |
| 155 static void getStringByKey(const UResourceBundle* rb, const char* key, UnicodeSt
ring& result, UErrorCode& errorCode) { | 208 static void getStringByKey(const UResourceBundle* rb, const char* key, UnicodeSt
ring& result, UErrorCode& errorCode) { |
| 156 int32_t len; | 209 int32_t len; |
| 157 const UChar* ustr = ures_getStringByKeyWithFallback(rb, key, &len, &errorCod
e); | 210 const UChar* ustr = ures_getStringByKeyWithFallback(rb, key, &len, &errorCod
e); |
| 158 if (U_FAILURE(errorCode)) { | 211 if (U_FAILURE(errorCode)) { |
| 159 return; | 212 return; |
| 160 } | 213 } |
| 161 result.setTo(ustr, len); | 214 result.setTo(ustr, len); |
| 162 } | 215 } |
| 163 | 216 |
| 164 ListFormatter* ListFormatter::createInstance(UErrorCode& errorCode) { | 217 ListFormatter* ListFormatter::createInstance(UErrorCode& errorCode) { |
| 165 Locale locale; // The default locale. | 218 Locale locale; // The default locale. |
| 166 return createInstance(locale, errorCode); | 219 return createInstance(locale, errorCode); |
| 167 } | 220 } |
| 168 | 221 |
| 169 ListFormatter* ListFormatter::createInstance(const Locale& locale, UErrorCode& e
rrorCode) { | 222 ListFormatter* ListFormatter::createInstance(const Locale& locale, UErrorCode& e
rrorCode) { |
| 170 return createInstance(locale, STANDARD_STYLE, errorCode); | 223 return createInstance(locale, STANDARD_STYLE, errorCode); |
| 171 } | 224 } |
| 172 | 225 |
| 173 ListFormatter* ListFormatter::createInstance(const Locale& locale, const char *s
tyle, UErrorCode& errorCode) { | 226 ListFormatter* ListFormatter::createInstance(const Locale& locale, const char *s
tyle, UErrorCode& errorCode) { |
| 174 Locale tempLocale = locale; | 227 Locale tempLocale = locale; |
| 175 const ListFormatData* listFormatData = getListFormatData(tempLocale, style,
errorCode); | 228 const ListFormatInternal* listFormatInternal = getListFormatInternal(tempLoc
ale, style, errorCode); |
| 176 if (U_FAILURE(errorCode)) { | 229 if (U_FAILURE(errorCode)) { |
| 177 return NULL; | 230 return NULL; |
| 178 } | 231 } |
| 179 ListFormatter* p = new ListFormatter(listFormatData); | 232 ListFormatter* p = new ListFormatter(listFormatInternal); |
| 180 if (p == NULL) { | 233 if (p == NULL) { |
| 181 errorCode = U_MEMORY_ALLOCATION_ERROR; | 234 errorCode = U_MEMORY_ALLOCATION_ERROR; |
| 182 return NULL; | 235 return NULL; |
| 183 } | 236 } |
| 184 return p; | 237 return p; |
| 185 } | 238 } |
| 186 | 239 |
| 187 | 240 ListFormatter::ListFormatter(const ListFormatData& listFormatData) { |
| 188 ListFormatter::ListFormatter(const ListFormatData* listFormatterData) : data(lis
tFormatterData) { | 241 owned = new ListFormatInternal(listFormatData); |
| 242 data = owned; |
| 189 } | 243 } |
| 190 | 244 |
| 191 ListFormatter::~ListFormatter() {} | 245 ListFormatter::ListFormatter(const ListFormatInternal* listFormatterInternal) :
owned(NULL), data(listFormatterInternal) { |
| 246 } |
| 192 | 247 |
| 193 UnicodeString& ListFormatter::format(const UnicodeString items[], int32_t nItems
, | 248 ListFormatter::~ListFormatter() { |
| 194 UnicodeString& appendTo, UErrorCode& errorCode) const { | 249 delete owned; |
| 250 } |
| 251 |
| 252 /** |
| 253 * Joins first and second using the pattern pat. |
| 254 * On entry offset is an offset into first or -1 if offset unspecified. |
| 255 * On exit offset is offset of second in result if recordOffset was set |
| 256 * Otherwise if it was >=0 it is set to point into result where it used |
| 257 * to point into first. |
| 258 */ |
| 259 static void joinStrings( |
| 260 const SimplePatternFormatter& pat, |
| 261 const UnicodeString& first, |
| 262 const UnicodeString& second, |
| 263 UnicodeString &result, |
| 264 UBool recordOffset, |
| 265 int32_t &offset, |
| 266 UErrorCode& errorCode) { |
| 267 if (U_FAILURE(errorCode)) { |
| 268 return; |
| 269 } |
| 270 const UnicodeString *params[2] = {&first, &second}; |
| 271 int32_t offsets[2]; |
| 272 pat.format( |
| 273 params, |
| 274 UPRV_LENGTHOF(params), |
| 275 result, |
| 276 offsets, |
| 277 UPRV_LENGTHOF(offsets), |
| 278 errorCode); |
| 279 if (U_FAILURE(errorCode)) { |
| 280 return; |
| 281 } |
| 282 if (offsets[0] == -1 || offsets[1] == -1) { |
| 283 errorCode = U_INVALID_FORMAT_ERROR; |
| 284 return; |
| 285 } |
| 286 if (recordOffset) { |
| 287 offset = offsets[1]; |
| 288 } else if (offset >= 0) { |
| 289 offset += offsets[0]; |
| 290 } |
| 291 } |
| 292 |
| 293 UnicodeString& ListFormatter::format( |
| 294 const UnicodeString items[], |
| 295 int32_t nItems, |
| 296 UnicodeString& appendTo, |
| 297 UErrorCode& errorCode) const { |
| 298 int32_t offset; |
| 299 return format(items, nItems, appendTo, -1, offset, errorCode); |
| 300 } |
| 301 |
| 302 UnicodeString& ListFormatter::format( |
| 303 const UnicodeString items[], |
| 304 int32_t nItems, |
| 305 UnicodeString& appendTo, |
| 306 int32_t index, |
| 307 int32_t &offset, |
| 308 UErrorCode& errorCode) const { |
| 309 offset = -1; |
| 195 if (U_FAILURE(errorCode)) { | 310 if (U_FAILURE(errorCode)) { |
| 196 return appendTo; | 311 return appendTo; |
| 197 } | 312 } |
| 198 if (data == NULL) { | 313 if (data == NULL) { |
| 199 errorCode = U_INVALID_STATE_ERROR; | 314 errorCode = U_INVALID_STATE_ERROR; |
| 200 return appendTo; | 315 return appendTo; |
| 201 } | 316 } |
| 202 | 317 |
| 203 if (nItems > 0) { | 318 if (nItems <= 0) { |
| 204 UnicodeString newString = items[0]; | 319 return appendTo; |
| 205 if (nItems == 2) { | 320 } |
| 206 addNewString(data->twoPattern, newString, items[1], errorCode); | 321 if (nItems == 1) { |
| 207 } else if (nItems > 2) { | 322 if (index == 0) { |
| 208 addNewString(data->startPattern, newString, items[1], errorCode); | 323 offset = appendTo.length(); |
| 209 int32_t i; | |
| 210 for (i = 2; i < nItems - 1; ++i) { | |
| 211 addNewString(data->middlePattern, newString, items[i], errorCode
); | |
| 212 } | |
| 213 addNewString(data->endPattern, newString, items[nItems - 1], errorCo
de); | |
| 214 } | 324 } |
| 215 if (U_SUCCESS(errorCode)) { | 325 appendTo.append(items[0]); |
| 216 appendTo += newString; | 326 return appendTo; |
| 327 } |
| 328 if (nItems == 2) { |
| 329 if (index == 0) { |
| 330 offset = 0; |
| 217 } | 331 } |
| 332 joinStrings( |
| 333 data->twoPattern, |
| 334 items[0], |
| 335 items[1], |
| 336 appendTo, |
| 337 index == 1, |
| 338 offset, |
| 339 errorCode); |
| 340 return appendTo; |
| 341 } |
| 342 UnicodeString temp[2]; |
| 343 if (index == 0) { |
| 344 offset = 0; |
| 345 } |
| 346 joinStrings( |
| 347 data->startPattern, |
| 348 items[0], |
| 349 items[1], |
| 350 temp[0], |
| 351 index == 1, |
| 352 offset, |
| 353 errorCode); |
| 354 int32_t i; |
| 355 int32_t pos = 0; |
| 356 int32_t npos = 0; |
| 357 UBool startsWithZeroPlaceholder = |
| 358 data->middlePattern.startsWithPlaceholder(0); |
| 359 for (i = 2; i < nItems - 1; ++i) { |
| 360 if (!startsWithZeroPlaceholder) { |
| 361 npos = (pos + 1) & 1; |
| 362 temp[npos].remove(); |
| 363 } |
| 364 joinStrings( |
| 365 data->middlePattern, |
| 366 temp[pos], |
| 367 items[i], |
| 368 temp[npos], |
| 369 index == i, |
| 370 offset, |
| 371 errorCode); |
| 372 pos = npos; |
| 373 } |
| 374 if (!data->endPattern.startsWithPlaceholder(0)) { |
| 375 npos = (pos + 1) & 1; |
| 376 temp[npos].remove(); |
| 377 } |
| 378 joinStrings( |
| 379 data->endPattern, |
| 380 temp[pos], |
| 381 items[nItems - 1], |
| 382 temp[npos], |
| 383 index == nItems - 1, |
| 384 offset, |
| 385 errorCode); |
| 386 if (U_SUCCESS(errorCode)) { |
| 387 if (offset >= 0) { |
| 388 offset += appendTo.length(); |
| 389 } |
| 390 appendTo += temp[npos]; |
| 218 } | 391 } |
| 219 return appendTo; | 392 return appendTo; |
| 220 } | 393 } |
| 221 | 394 |
| 222 /** | |
| 223 * Joins originalString and nextString using the pattern pat and puts the result
in | |
| 224 * originalString. | |
| 225 */ | |
| 226 void ListFormatter::addNewString(const UnicodeString& pat, UnicodeString& origin
alString, | |
| 227 const UnicodeString& nextString, UErrorCode& er
rorCode) const { | |
| 228 if (U_FAILURE(errorCode)) { | |
| 229 return; | |
| 230 } | |
| 231 | |
| 232 int32_t p0Offset = pat.indexOf(FIRST_PARAMETER, 3, 0); | |
| 233 if (p0Offset < 0) { | |
| 234 errorCode = U_ILLEGAL_ARGUMENT_ERROR; | |
| 235 return; | |
| 236 } | |
| 237 int32_t p1Offset = pat.indexOf(SECOND_PARAMETER, 3, 0); | |
| 238 if (p1Offset < 0) { | |
| 239 errorCode = U_ILLEGAL_ARGUMENT_ERROR; | |
| 240 return; | |
| 241 } | |
| 242 | |
| 243 int32_t i, j; | |
| 244 | |
| 245 const UnicodeString* firstString; | |
| 246 const UnicodeString* secondString; | |
| 247 if (p0Offset < p1Offset) { | |
| 248 i = p0Offset; | |
| 249 j = p1Offset; | |
| 250 firstString = &originalString; | |
| 251 secondString = &nextString; | |
| 252 } else { | |
| 253 i = p1Offset; | |
| 254 j = p0Offset; | |
| 255 firstString = &nextString; | |
| 256 secondString = &originalString; | |
| 257 } | |
| 258 | |
| 259 UnicodeString result = UnicodeString(pat, 0, i) + *firstString; | |
| 260 result += UnicodeString(pat, i+3, j-i-3); | |
| 261 result += *secondString; | |
| 262 result += UnicodeString(pat, j+3); | |
| 263 originalString = result; | |
| 264 } | |
| 265 | |
| 266 U_NAMESPACE_END | 395 U_NAMESPACE_END |
| OLD | NEW |