OLD | NEW |
1 /* | 1 /* |
2 ****************************************************************************** | 2 ****************************************************************************** |
3 * Copyright (C) 2014, International Business Machines | 3 * Copyright (C) 2014, International Business Machines |
4 * Corporation and others. All Rights Reserved. | 4 * Corporation and others. All Rights Reserved. |
5 ****************************************************************************** | 5 ****************************************************************************** |
6 * simplepatternformatter.cpp | 6 * simplepatternformatter.cpp |
7 */ | 7 */ |
8 #include "simplepatternformatter.h" | 8 #include "simplepatternformatter.h" |
9 #include "cstring.h" | 9 #include "cstring.h" |
10 #include "uassert.h" | 10 #include "uassert.h" |
11 | 11 |
12 U_NAMESPACE_BEGIN | 12 U_NAMESPACE_BEGIN |
13 | 13 |
| 14 static UBool isInvalidArray(const void *array, int32_t size) { |
| 15 return (size < 0 || (size > 0 && array == NULL)); |
| 16 } |
| 17 |
14 typedef enum SimplePatternFormatterCompileState { | 18 typedef enum SimplePatternFormatterCompileState { |
15 INIT, | 19 INIT, |
16 APOSTROPHE, | 20 APOSTROPHE, |
17 PLACEHOLDER | 21 PLACEHOLDER |
18 } SimplePatternFormatterCompileState; | 22 } SimplePatternFormatterCompileState; |
19 | 23 |
| 24 // Handles parsing placeholders in the pattern string, e.g {4} or {35} |
20 class SimplePatternFormatterIdBuilder { | 25 class SimplePatternFormatterIdBuilder { |
21 public: | 26 public: |
22 SimplePatternFormatterIdBuilder() : id(0), idLen(0) { } | 27 SimplePatternFormatterIdBuilder() : id(0), idLen(0) { } |
23 ~SimplePatternFormatterIdBuilder() { } | 28 ~SimplePatternFormatterIdBuilder() { } |
| 29 |
| 30 // Resets so that this object has seen no placeholder ID. |
24 void reset() { id = 0; idLen = 0; } | 31 void reset() { id = 0; idLen = 0; } |
| 32 |
| 33 // Returns the numeric placeholder ID parsed so far |
25 int32_t getId() const { return id; } | 34 int32_t getId() const { return id; } |
| 35 |
| 36 // Appends the numeric placeholder ID parsed so far back to a |
| 37 // UChar buffer. Used to recover if parser using this object finds |
| 38 // no closing curly brace. |
26 void appendTo(UChar *buffer, int32_t *len) const; | 39 void appendTo(UChar *buffer, int32_t *len) const; |
| 40 |
| 41 // Returns true if this object has seen a placeholder ID. |
27 UBool isValid() const { return (idLen > 0); } | 42 UBool isValid() const { return (idLen > 0); } |
| 43 |
| 44 // Processes a single digit character. Pattern string parser calls this |
| 45 // as it processes digits after an opening curly brace. |
28 void add(UChar ch); | 46 void add(UChar ch); |
29 private: | 47 private: |
30 int32_t id; | 48 int32_t id; |
31 int32_t idLen; | 49 int32_t idLen; |
32 SimplePatternFormatterIdBuilder( | 50 SimplePatternFormatterIdBuilder( |
33 const SimplePatternFormatterIdBuilder &other); | 51 const SimplePatternFormatterIdBuilder &other); |
34 SimplePatternFormatterIdBuilder &operator=( | 52 SimplePatternFormatterIdBuilder &operator=( |
35 const SimplePatternFormatterIdBuilder &other); | 53 const SimplePatternFormatterIdBuilder &other); |
36 }; | 54 }; |
37 | 55 |
38 void SimplePatternFormatterIdBuilder::appendTo( | 56 void SimplePatternFormatterIdBuilder::appendTo( |
39 UChar *buffer, int32_t *len) const { | 57 UChar *buffer, int32_t *len) const { |
40 int32_t origLen = *len; | 58 int32_t origLen = *len; |
41 int32_t kId = id; | 59 int32_t kId = id; |
42 for (int32_t i = origLen + idLen - 1; i >= origLen; i--) { | 60 for (int32_t i = origLen + idLen - 1; i >= origLen; i--) { |
43 int32_t digit = kId % 10; | 61 int32_t digit = kId % 10; |
44 buffer[i] = digit + 0x30; | 62 buffer[i] = digit + 0x30; |
45 kId /= 10; | 63 kId /= 10; |
46 } | 64 } |
47 *len = origLen + idLen; | 65 *len = origLen + idLen; |
48 } | 66 } |
49 | 67 |
50 void SimplePatternFormatterIdBuilder::add(UChar ch) { | 68 void SimplePatternFormatterIdBuilder::add(UChar ch) { |
51 id = id * 10 + (ch - 0x30); | 69 id = id * 10 + (ch - 0x30); |
52 idLen++; | 70 idLen++; |
53 } | 71 } |
54 | 72 |
| 73 // Represents placeholder values. |
| 74 class SimplePatternFormatterPlaceholderValues : public UMemory { |
| 75 public: |
| 76 SimplePatternFormatterPlaceholderValues( |
| 77 const UnicodeString * const *values, |
| 78 int32_t valuesCount); |
| 79 |
| 80 // Returns TRUE if appendTo value is at any index besides exceptIndex. |
| 81 UBool isAppendToInAnyIndexExcept( |
| 82 const UnicodeString &appendTo, int32_t exceptIndex) const; |
| 83 |
| 84 // For each appendTo value, stores the snapshot of it in its place. |
| 85 void snapshotAppendTo(const UnicodeString &appendTo); |
| 86 |
| 87 // Returns the placeholder value at index. No range checking performed. |
| 88 // Returned reference is valid for as long as this object exists. |
| 89 const UnicodeString &get(int32_t index) const; |
| 90 private: |
| 91 const UnicodeString * const *fValues; |
| 92 int32_t fValuesCount; |
| 93 const UnicodeString *fAppendTo; |
| 94 UnicodeString fAppendToCopy; |
| 95 SimplePatternFormatterPlaceholderValues( |
| 96 const SimplePatternFormatterPlaceholderValues &); |
| 97 SimplePatternFormatterPlaceholderValues &operator=( |
| 98 const SimplePatternFormatterPlaceholderValues &); |
| 99 }; |
| 100 |
| 101 SimplePatternFormatterPlaceholderValues::SimplePatternFormatterPlaceholderValues
( |
| 102 const UnicodeString * const *values, |
| 103 int32_t valuesCount) |
| 104 : fValues(values), |
| 105 fValuesCount(valuesCount), |
| 106 fAppendTo(NULL), |
| 107 fAppendToCopy() { |
| 108 } |
| 109 |
| 110 UBool SimplePatternFormatterPlaceholderValues::isAppendToInAnyIndexExcept( |
| 111 const UnicodeString &appendTo, int32_t exceptIndex) const { |
| 112 for (int32_t i = 0; i < fValuesCount; ++i) { |
| 113 if (i != exceptIndex && fValues[i] == &appendTo) { |
| 114 return TRUE; |
| 115 } |
| 116 } |
| 117 return FALSE; |
| 118 } |
| 119 |
| 120 void SimplePatternFormatterPlaceholderValues::snapshotAppendTo( |
| 121 const UnicodeString &appendTo) { |
| 122 fAppendTo = &appendTo; |
| 123 fAppendToCopy = appendTo; |
| 124 } |
| 125 |
| 126 const UnicodeString &SimplePatternFormatterPlaceholderValues::get( |
| 127 int32_t index) const { |
| 128 if (fAppendTo == NULL || fAppendTo != fValues[index]) { |
| 129 return *fValues[index]; |
| 130 } |
| 131 return fAppendToCopy; |
| 132 } |
| 133 |
55 SimplePatternFormatter::SimplePatternFormatter() : | 134 SimplePatternFormatter::SimplePatternFormatter() : |
56 noPlaceholders(), | 135 noPlaceholders(), |
57 placeholders(), | 136 placeholders(), |
58 placeholderSize(0), | 137 placeholderSize(0), |
59 placeholderCount(0) { | 138 placeholderCount(0), |
| 139 firstPlaceholderReused(FALSE) { |
60 } | 140 } |
61 | 141 |
62 SimplePatternFormatter::SimplePatternFormatter(const UnicodeString &pattern) : | 142 SimplePatternFormatter::SimplePatternFormatter(const UnicodeString &pattern) : |
63 noPlaceholders(), | 143 noPlaceholders(), |
64 placeholders(), | 144 placeholders(), |
65 placeholderSize(0), | 145 placeholderSize(0), |
66 placeholderCount(0) { | 146 placeholderCount(0), |
| 147 firstPlaceholderReused(FALSE) { |
67 UErrorCode status = U_ZERO_ERROR; | 148 UErrorCode status = U_ZERO_ERROR; |
68 compile(pattern, status); | 149 compile(pattern, status); |
69 } | 150 } |
70 | 151 |
71 SimplePatternFormatter::SimplePatternFormatter( | 152 SimplePatternFormatter::SimplePatternFormatter( |
72 const SimplePatternFormatter &other) : | 153 const SimplePatternFormatter &other) : |
73 noPlaceholders(other.noPlaceholders), | 154 noPlaceholders(other.noPlaceholders), |
74 placeholders(), | 155 placeholders(), |
75 placeholderSize(0), | 156 placeholderSize(0), |
76 placeholderCount(other.placeholderCount) { | 157 placeholderCount(other.placeholderCount), |
| 158 firstPlaceholderReused(other.firstPlaceholderReused) { |
77 placeholderSize = ensureCapacity(other.placeholderSize); | 159 placeholderSize = ensureCapacity(other.placeholderSize); |
78 uprv_memcpy( | 160 uprv_memcpy( |
79 placeholders.getAlias(), | 161 placeholders.getAlias(), |
80 other.placeholders.getAlias(), | 162 other.placeholders.getAlias(), |
81 placeholderSize * sizeof(PlaceholderInfo)); | 163 placeholderSize * sizeof(PlaceholderInfo)); |
82 } | 164 } |
83 | 165 |
84 SimplePatternFormatter &SimplePatternFormatter::operator=( | 166 SimplePatternFormatter &SimplePatternFormatter::operator=( |
85 const SimplePatternFormatter& other) { | 167 const SimplePatternFormatter& other) { |
86 if (this == &other) { | 168 if (this == &other) { |
87 return *this; | 169 return *this; |
88 } | 170 } |
89 noPlaceholders = other.noPlaceholders; | 171 noPlaceholders = other.noPlaceholders; |
90 placeholderSize = ensureCapacity(other.placeholderSize); | 172 placeholderSize = ensureCapacity(other.placeholderSize); |
91 placeholderCount = other.placeholderCount; | 173 placeholderCount = other.placeholderCount; |
| 174 firstPlaceholderReused = other.firstPlaceholderReused; |
92 uprv_memcpy( | 175 uprv_memcpy( |
93 placeholders.getAlias(), | 176 placeholders.getAlias(), |
94 other.placeholders.getAlias(), | 177 other.placeholders.getAlias(), |
95 placeholderSize * sizeof(PlaceholderInfo)); | 178 placeholderSize * sizeof(PlaceholderInfo)); |
96 return *this; | 179 return *this; |
97 } | 180 } |
98 | 181 |
99 SimplePatternFormatter::~SimplePatternFormatter() { | 182 SimplePatternFormatter::~SimplePatternFormatter() { |
100 } | 183 } |
101 | 184 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 idBuilder.appendTo(buffer, &len); | 251 idBuilder.appendTo(buffer, &len); |
169 break; | 252 break; |
170 default: | 253 default: |
171 U_ASSERT(false); | 254 U_ASSERT(false); |
172 break; | 255 break; |
173 } | 256 } |
174 noPlaceholders.releaseBuffer(len); | 257 noPlaceholders.releaseBuffer(len); |
175 return TRUE; | 258 return TRUE; |
176 } | 259 } |
177 | 260 |
178 UBool SimplePatternFormatter::startsWithPlaceholder(int32_t id) const { | |
179 if (placeholderSize == 0) { | |
180 return FALSE; | |
181 } | |
182 return (placeholders[0].offset == 0 && placeholders[0].id == id); | |
183 } | |
184 | |
185 UnicodeString& SimplePatternFormatter::format( | 261 UnicodeString& SimplePatternFormatter::format( |
186 const UnicodeString &arg0, | 262 const UnicodeString &arg0, |
187 UnicodeString &appendTo, | 263 UnicodeString &appendTo, |
188 UErrorCode &status) const { | 264 UErrorCode &status) const { |
189 const UnicodeString *params[] = {&arg0}; | 265 const UnicodeString *params[] = {&arg0}; |
190 return format( | 266 return formatAndAppend( |
191 params, | 267 params, |
192 UPRV_LENGTHOF(params), | 268 UPRV_LENGTHOF(params), |
193 appendTo, | 269 appendTo, |
194 NULL, | 270 NULL, |
195 0, | 271 0, |
196 status); | 272 status); |
197 } | 273 } |
198 | 274 |
199 UnicodeString& SimplePatternFormatter::format( | 275 UnicodeString& SimplePatternFormatter::format( |
200 const UnicodeString &arg0, | 276 const UnicodeString &arg0, |
201 const UnicodeString &arg1, | 277 const UnicodeString &arg1, |
202 UnicodeString &appendTo, | 278 UnicodeString &appendTo, |
203 UErrorCode &status) const { | 279 UErrorCode &status) const { |
204 const UnicodeString *params[] = {&arg0, &arg1}; | 280 const UnicodeString *params[] = {&arg0, &arg1}; |
205 return format( | 281 return formatAndAppend( |
206 params, | 282 params, |
207 UPRV_LENGTHOF(params), | 283 UPRV_LENGTHOF(params), |
208 appendTo, | 284 appendTo, |
209 NULL, | 285 NULL, |
210 0, | 286 0, |
211 status); | 287 status); |
212 } | 288 } |
213 | 289 |
214 UnicodeString& SimplePatternFormatter::format( | 290 UnicodeString& SimplePatternFormatter::format( |
215 const UnicodeString &arg0, | 291 const UnicodeString &arg0, |
216 const UnicodeString &arg1, | 292 const UnicodeString &arg1, |
217 const UnicodeString &arg2, | 293 const UnicodeString &arg2, |
218 UnicodeString &appendTo, | 294 UnicodeString &appendTo, |
219 UErrorCode &status) const { | 295 UErrorCode &status) const { |
220 const UnicodeString *params[] = {&arg0, &arg1, &arg2}; | 296 const UnicodeString *params[] = {&arg0, &arg1, &arg2}; |
221 return format( | 297 return formatAndAppend( |
222 params, | 298 params, |
223 UPRV_LENGTHOF(params), | 299 UPRV_LENGTHOF(params), |
224 appendTo, | 300 appendTo, |
225 NULL, | 301 NULL, |
226 0, | 302 0, |
227 status); | 303 status); |
228 } | 304 } |
229 | 305 |
230 static void updatePlaceholderOffset( | 306 static void updatePlaceholderOffset( |
231 int32_t placeholderId, | 307 int32_t placeholderId, |
232 int32_t placeholderOffset, | 308 int32_t placeholderOffset, |
233 int32_t *offsetArray, | 309 int32_t *offsetArray, |
234 int32_t offsetArrayLength) { | 310 int32_t offsetArrayLength) { |
235 if (placeholderId < offsetArrayLength) { | 311 if (placeholderId < offsetArrayLength) { |
236 offsetArray[placeholderId] = placeholderOffset; | 312 offsetArray[placeholderId] = placeholderOffset; |
237 } | 313 } |
238 } | 314 } |
239 | 315 |
240 static void appendRange( | 316 static void appendRange( |
241 const UnicodeString &src, | 317 const UnicodeString &src, |
242 int32_t start, | 318 int32_t start, |
243 int32_t end, | 319 int32_t end, |
244 UnicodeString &dest) { | 320 UnicodeString &dest) { |
| 321 // This check improves performance significantly. |
| 322 if (start == end) { |
| 323 return; |
| 324 } |
245 dest.append(src, start, end - start); | 325 dest.append(src, start, end - start); |
246 } | 326 } |
247 | 327 |
248 UnicodeString& SimplePatternFormatter::format( | 328 UnicodeString& SimplePatternFormatter::formatAndAppend( |
249 const UnicodeString * const *placeholderValues, | 329 const UnicodeString * const *placeholderValues, |
250 int32_t placeholderValueCount, | 330 int32_t placeholderValueCount, |
251 UnicodeString &appendTo, | 331 UnicodeString &appendTo, |
252 int32_t *offsetArray, | 332 int32_t *offsetArray, |
253 int32_t offsetArrayLength, | 333 int32_t offsetArrayLength, |
254 UErrorCode &status) const { | 334 UErrorCode &status) const { |
255 if (U_FAILURE(status)) { | 335 if (U_FAILURE(status)) { |
256 return appendTo; | 336 return appendTo; |
257 } | 337 } |
| 338 if (isInvalidArray(placeholderValues, placeholderValueCount) |
| 339 || isInvalidArray(offsetArray, offsetArrayLength)) { |
| 340 status = U_ILLEGAL_ARGUMENT_ERROR; |
| 341 return appendTo; |
| 342 } |
258 if (placeholderValueCount < placeholderCount) { | 343 if (placeholderValueCount < placeholderCount) { |
259 status = U_ILLEGAL_ARGUMENT_ERROR; | 344 status = U_ILLEGAL_ARGUMENT_ERROR; |
260 return appendTo; | 345 return appendTo; |
261 } | 346 } |
| 347 |
| 348 // Since we are disallowing parameter values that are the same as |
| 349 // appendTo, we have to check all placeholderValues as opposed to |
| 350 // the first placeholderCount placeholder values. |
| 351 SimplePatternFormatterPlaceholderValues values( |
| 352 placeholderValues, placeholderValueCount); |
| 353 if (values.isAppendToInAnyIndexExcept(appendTo, -1)) { |
| 354 status = U_ILLEGAL_ARGUMENT_ERROR; |
| 355 return appendTo; |
| 356 } |
| 357 return formatAndAppend( |
| 358 values, |
| 359 appendTo, |
| 360 offsetArray, |
| 361 offsetArrayLength); |
| 362 } |
| 363 |
| 364 UnicodeString& SimplePatternFormatter::formatAndReplace( |
| 365 const UnicodeString * const *placeholderValues, |
| 366 int32_t placeholderValueCount, |
| 367 UnicodeString &result, |
| 368 int32_t *offsetArray, |
| 369 int32_t offsetArrayLength, |
| 370 UErrorCode &status) const { |
| 371 if (U_FAILURE(status)) { |
| 372 return result; |
| 373 } |
| 374 if (isInvalidArray(placeholderValues, placeholderValueCount) |
| 375 || isInvalidArray(offsetArray, offsetArrayLength)) { |
| 376 status = U_ILLEGAL_ARGUMENT_ERROR; |
| 377 return result; |
| 378 } |
| 379 if (placeholderValueCount < placeholderCount) { |
| 380 status = U_ILLEGAL_ARGUMENT_ERROR; |
| 381 return result; |
| 382 } |
| 383 SimplePatternFormatterPlaceholderValues values( |
| 384 placeholderValues, placeholderCount); |
| 385 int32_t placeholderAtStart = getUniquePlaceholderAtStart(); |
| 386 |
| 387 // If pattern starts with a unique placeholder and that placeholder |
| 388 // value is result, we may be able to optimize by just appending to result. |
| 389 if (placeholderAtStart >= 0 |
| 390 && placeholderValues[placeholderAtStart] == &result) { |
| 391 |
| 392 // If result is the value for other placeholders, call off optimization. |
| 393 if (values.isAppendToInAnyIndexExcept(result, placeholderAtStart)) { |
| 394 values.snapshotAppendTo(result); |
| 395 result.remove(); |
| 396 return formatAndAppend( |
| 397 values, |
| 398 result, |
| 399 offsetArray, |
| 400 offsetArrayLength); |
| 401 } |
| 402 |
| 403 // Otherwise we can optimize |
| 404 formatAndAppend( |
| 405 values, |
| 406 result, |
| 407 offsetArray, |
| 408 offsetArrayLength); |
| 409 |
| 410 // We have to make the offset for the placeholderAtStart |
| 411 // placeholder be 0. Otherwise it would be the length of the |
| 412 // previous value of result. |
| 413 if (offsetArrayLength > placeholderAtStart) { |
| 414 offsetArray[placeholderAtStart] = 0; |
| 415 } |
| 416 return result; |
| 417 } |
| 418 if (values.isAppendToInAnyIndexExcept(result, -1)) { |
| 419 values.snapshotAppendTo(result); |
| 420 } |
| 421 result.remove(); |
| 422 return formatAndAppend( |
| 423 values, |
| 424 result, |
| 425 offsetArray, |
| 426 offsetArrayLength); |
| 427 } |
| 428 |
| 429 UnicodeString& SimplePatternFormatter::formatAndAppend( |
| 430 const SimplePatternFormatterPlaceholderValues &values, |
| 431 UnicodeString &appendTo, |
| 432 int32_t *offsetArray, |
| 433 int32_t offsetArrayLength) const { |
262 for (int32_t i = 0; i < offsetArrayLength; ++i) { | 434 for (int32_t i = 0; i < offsetArrayLength; ++i) { |
263 offsetArray[i] = -1; | 435 offsetArray[i] = -1; |
264 } | 436 } |
265 if (placeholderSize == 0) { | 437 if (placeholderSize == 0) { |
266 appendTo.append(noPlaceholders); | 438 appendTo.append(noPlaceholders); |
267 return appendTo; | 439 return appendTo; |
268 } | 440 } |
269 if (placeholders[0].offset > 0 || | 441 appendRange( |
270 placeholderValues[placeholders[0].id] != &appendTo) { | 442 noPlaceholders, |
271 appendRange( | 443 0, |
272 noPlaceholders, | 444 placeholders[0].offset, |
273 0, | 445 appendTo); |
274 placeholders[0].offset, | 446 updatePlaceholderOffset( |
275 appendTo); | 447 placeholders[0].id, |
276 updatePlaceholderOffset( | 448 appendTo.length(), |
277 placeholders[0].id, | 449 offsetArray, |
278 appendTo.length(), | 450 offsetArrayLength); |
279 offsetArray, | 451 const UnicodeString *placeholderValue = &values.get(placeholders[0].id); |
280 offsetArrayLength); | 452 if (placeholderValue != &appendTo) { |
281 appendTo.append(*placeholderValues[placeholders[0].id]); | 453 appendTo.append(*placeholderValue); |
282 } else { | |
283 updatePlaceholderOffset( | |
284 placeholders[0].id, | |
285 0, | |
286 offsetArray, | |
287 offsetArrayLength); | |
288 } | 454 } |
289 for (int32_t i = 1; i < placeholderSize; ++i) { | 455 for (int32_t i = 1; i < placeholderSize; ++i) { |
290 appendRange( | 456 appendRange( |
291 noPlaceholders, | 457 noPlaceholders, |
292 placeholders[i - 1].offset, | 458 placeholders[i - 1].offset, |
293 placeholders[i].offset, | 459 placeholders[i].offset, |
294 appendTo); | 460 appendTo); |
295 updatePlaceholderOffset( | 461 updatePlaceholderOffset( |
296 placeholders[i].id, | 462 placeholders[i].id, |
297 appendTo.length(), | 463 appendTo.length(), |
298 offsetArray, | 464 offsetArray, |
299 offsetArrayLength); | 465 offsetArrayLength); |
300 appendTo.append(*placeholderValues[placeholders[i].id]); | 466 placeholderValue = &values.get(placeholders[i].id); |
| 467 if (placeholderValue != &appendTo) { |
| 468 appendTo.append(*placeholderValue); |
| 469 } |
301 } | 470 } |
302 appendRange( | 471 appendRange( |
303 noPlaceholders, | 472 noPlaceholders, |
304 placeholders[placeholderSize - 1].offset, | 473 placeholders[placeholderSize - 1].offset, |
305 noPlaceholders.length(), | 474 noPlaceholders.length(), |
306 appendTo); | 475 appendTo); |
307 return appendTo; | 476 return appendTo; |
308 } | 477 } |
309 | 478 |
| 479 int32_t SimplePatternFormatter::getUniquePlaceholderAtStart() const { |
| 480 if (placeholderSize == 0 |
| 481 || firstPlaceholderReused || placeholders[0].offset != 0) { |
| 482 return -1; |
| 483 } |
| 484 return placeholders[0].id; |
| 485 } |
| 486 |
310 int32_t SimplePatternFormatter::ensureCapacity( | 487 int32_t SimplePatternFormatter::ensureCapacity( |
311 int32_t desiredCapacity, int32_t allocationSize) { | 488 int32_t desiredCapacity, int32_t allocationSize) { |
312 if (allocationSize < desiredCapacity) { | 489 if (allocationSize < desiredCapacity) { |
313 allocationSize = desiredCapacity; | 490 allocationSize = desiredCapacity; |
314 } | 491 } |
315 if (desiredCapacity <= placeholders.getCapacity()) { | 492 if (desiredCapacity <= placeholders.getCapacity()) { |
316 return desiredCapacity; | 493 return desiredCapacity; |
317 } | 494 } |
318 // allocate new buffer | 495 // allocate new buffer |
319 if (placeholders.resize(allocationSize, placeholderSize) == NULL) { | 496 if (placeholders.resize(allocationSize, placeholderSize) == NULL) { |
320 return placeholders.getCapacity(); | 497 return placeholders.getCapacity(); |
321 } | 498 } |
322 return desiredCapacity; | 499 return desiredCapacity; |
323 } | 500 } |
324 | 501 |
325 UBool SimplePatternFormatter::addPlaceholder(int32_t id, int32_t offset) { | 502 UBool SimplePatternFormatter::addPlaceholder(int32_t id, int32_t offset) { |
326 if (ensureCapacity(placeholderSize + 1, 2 * placeholderSize) < placeholderSi
ze + 1) { | 503 if (ensureCapacity(placeholderSize + 1, 2 * placeholderSize) < placeholderSi
ze + 1) { |
327 return FALSE; | 504 return FALSE; |
328 } | 505 } |
329 ++placeholderSize; | 506 ++placeholderSize; |
330 PlaceholderInfo *placeholderEnd = &placeholders[placeholderSize - 1]; | 507 PlaceholderInfo *placeholderEnd = &placeholders[placeholderSize - 1]; |
331 placeholderEnd->offset = offset; | 508 placeholderEnd->offset = offset; |
332 placeholderEnd->id = id; | 509 placeholderEnd->id = id; |
333 if (id >= placeholderCount) { | 510 if (id >= placeholderCount) { |
334 placeholderCount = id + 1; | 511 placeholderCount = id + 1; |
335 } | 512 } |
| 513 if (placeholderSize > 1 |
| 514 && placeholders[placeholderSize - 1].id == placeholders[0].id) { |
| 515 firstPlaceholderReused = TRUE; |
| 516 } |
336 return TRUE; | 517 return TRUE; |
337 } | 518 } |
338 | 519 |
339 U_NAMESPACE_END | 520 U_NAMESPACE_END |
OLD | NEW |