OLD | NEW |
1 /* | 1 /* |
2 ****************************************************************************** | 2 ****************************************************************************** |
3 * Copyright (C) 1997-2011, International Business Machines | 3 * Copyright (C) 1997-2014, International Business Machines |
4 * Corporation and others. All Rights Reserved. | 4 * Corporation and others. All Rights Reserved. |
5 ****************************************************************************** | 5 ****************************************************************************** |
6 * file name: nfrule.cpp | 6 * file name: nfrule.cpp |
7 * encoding: US-ASCII | 7 * encoding: US-ASCII |
8 * tab size: 8 (not used) | 8 * tab size: 8 (not used) |
9 * indentation:4 | 9 * indentation:4 |
10 * | 10 * |
11 * Modification history | 11 * Modification history |
12 * Date Name Comments | 12 * Date Name Comments |
13 * 10/11/2001 Doug Ported from ICU4J | 13 * 10/11/2001 Doug Ported from ICU4J |
14 */ | 14 */ |
15 | 15 |
16 #include "nfrule.h" | 16 #include "nfrule.h" |
17 | 17 |
18 #if U_HAVE_RBNF | 18 #if U_HAVE_RBNF |
19 | 19 |
| 20 #include "unicode/localpointer.h" |
20 #include "unicode/rbnf.h" | 21 #include "unicode/rbnf.h" |
21 #include "unicode/tblcoll.h" | 22 #include "unicode/tblcoll.h" |
| 23 #include "unicode/plurfmt.h" |
| 24 #include "unicode/upluralrules.h" |
22 #include "unicode/coleitr.h" | 25 #include "unicode/coleitr.h" |
23 #include "unicode/uchar.h" | 26 #include "unicode/uchar.h" |
24 #include "nfrs.h" | 27 #include "nfrs.h" |
25 #include "nfrlist.h" | 28 #include "nfrlist.h" |
26 #include "nfsubs.h" | 29 #include "nfsubs.h" |
27 #include "patternprops.h" | 30 #include "patternprops.h" |
28 | 31 |
29 U_NAMESPACE_BEGIN | 32 U_NAMESPACE_BEGIN |
30 | 33 |
31 NFRule::NFRule(const RuleBasedNumberFormat* _rbnf) | 34 NFRule::NFRule(const RuleBasedNumberFormat* _rbnf) |
32 : baseValue((int32_t)0) | 35 : baseValue((int32_t)0) |
33 , radix(0) | 36 , radix(0) |
34 , exponent(0) | 37 , exponent(0) |
35 , ruleText() | 38 , ruleText() |
36 , sub1(NULL) | 39 , sub1(NULL) |
37 , sub2(NULL) | 40 , sub2(NULL) |
38 , formatter(_rbnf) | 41 , formatter(_rbnf) |
| 42 , rulePatternFormat(NULL) |
39 { | 43 { |
40 } | 44 } |
41 | 45 |
42 NFRule::~NFRule() | 46 NFRule::~NFRule() |
43 { | 47 { |
44 delete sub1; | 48 if (sub1 != sub2) { |
45 delete sub2; | 49 delete sub2; |
| 50 } |
| 51 delete sub1; |
| 52 delete rulePatternFormat; |
46 } | 53 } |
47 | 54 |
48 static const UChar gLeftBracket = 0x005b; | 55 static const UChar gLeftBracket = 0x005b; |
49 static const UChar gRightBracket = 0x005d; | 56 static const UChar gRightBracket = 0x005d; |
50 static const UChar gColon = 0x003a; | 57 static const UChar gColon = 0x003a; |
51 static const UChar gZero = 0x0030; | 58 static const UChar gZero = 0x0030; |
52 static const UChar gNine = 0x0039; | 59 static const UChar gNine = 0x0039; |
53 static const UChar gSpace = 0x0020; | 60 static const UChar gSpace = 0x0020; |
54 static const UChar gSlash = 0x002f; | 61 static const UChar gSlash = 0x002f; |
55 static const UChar gGreaterThan = 0x003e; | 62 static const UChar gGreaterThan = 0x003e; |
56 static const UChar gLessThan = 0x003c; | 63 static const UChar gLessThan = 0x003c; |
57 static const UChar gComma = 0x002c; | 64 static const UChar gComma = 0x002c; |
58 static const UChar gDot = 0x002e; | 65 static const UChar gDot = 0x002e; |
59 static const UChar gTick = 0x0027; | 66 static const UChar gTick = 0x0027; |
60 //static const UChar gMinus = 0x002d; | 67 //static const UChar gMinus = 0x002d; |
61 static const UChar gSemicolon = 0x003b; | 68 static const UChar gSemicolon = 0x003b; |
62 | 69 |
63 static const UChar gMinusX[] = {0x2D, 0x78, 0}; /* "-x" */ | 70 static const UChar gMinusX[] = {0x2D, 0x78, 0}; /* "-x" */ |
64 static const UChar gXDotX[] = {0x78, 0x2E, 0x78, 0}; /* "x.x"
*/ | 71 static const UChar gXDotX[] = {0x78, 0x2E, 0x78, 0}; /* "x.x"
*/ |
65 static const UChar gXDotZero[] = {0x78, 0x2E, 0x30, 0}; /* "x.0"
*/ | 72 static const UChar gXDotZero[] = {0x78, 0x2E, 0x30, 0}; /* "x.0"
*/ |
66 static const UChar gZeroDotX[] = {0x30, 0x2E, 0x78, 0}; /* "0.x"
*/ | 73 static const UChar gZeroDotX[] = {0x30, 0x2E, 0x78, 0}; /* "0.x"
*/ |
67 | 74 |
| 75 static const UChar gDollarOpenParenthesis[] = {0x24, 0x28, 0}; /* "$(" */ |
| 76 static const UChar gClosedParenthesisDollar[] = {0x29, 0x24, 0}; /* ")$" */ |
| 77 |
68 static const UChar gLessLess[] = {0x3C, 0x3C, 0}; /* "<<" */ | 78 static const UChar gLessLess[] = {0x3C, 0x3C, 0}; /* "<<" */ |
69 static const UChar gLessPercent[] = {0x3C, 0x25, 0}; /* "<%" */ | 79 static const UChar gLessPercent[] = {0x3C, 0x25, 0}; /* "<%" */ |
70 static const UChar gLessHash[] = {0x3C, 0x23, 0}; /* "<#" */ | 80 static const UChar gLessHash[] = {0x3C, 0x23, 0}; /* "<#" */ |
71 static const UChar gLessZero[] = {0x3C, 0x30, 0}; /* "<0" */ | 81 static const UChar gLessZero[] = {0x3C, 0x30, 0}; /* "<0" */ |
72 static const UChar gGreaterGreater[] = {0x3E, 0x3E, 0}; /* ">>" */ | 82 static const UChar gGreaterGreater[] = {0x3E, 0x3E, 0}; /* ">>" */ |
73 static const UChar gGreaterPercent[] = {0x3E, 0x25, 0}; /* ">%" */ | 83 static const UChar gGreaterPercent[] = {0x3E, 0x25, 0}; /* ">%" */ |
74 static const UChar gGreaterHash[] = {0x3E, 0x23, 0}; /* ">#" */ | 84 static const UChar gGreaterHash[] = {0x3E, 0x23, 0}; /* ">#" */ |
75 static const UChar gGreaterZero[] = {0x3E, 0x30, 0}; /* ">0" */ | 85 static const UChar gGreaterZero[] = {0x3E, 0x30, 0}; /* ">0" */ |
76 static const UChar gEqualPercent[] = {0x3D, 0x25, 0}; /* "=%" */ | 86 static const UChar gEqualPercent[] = {0x3D, 0x25, 0}; /* "=%" */ |
77 static const UChar gEqualHash[] = {0x3D, 0x23, 0}; /* "=#" */ | 87 static const UChar gEqualHash[] = {0x3D, 0x23, 0}; /* "=#" */ |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 int32_t brack1 = description.indexOf(gLeftBracket); | 119 int32_t brack1 = description.indexOf(gLeftBracket); |
110 int32_t brack2 = description.indexOf(gRightBracket); | 120 int32_t brack2 = description.indexOf(gRightBracket); |
111 | 121 |
112 // if the description doesn't contain a matched pair of brackets, | 122 // if the description doesn't contain a matched pair of brackets, |
113 // or if it's of a type that doesn't recognize bracketed text, | 123 // or if it's of a type that doesn't recognize bracketed text, |
114 // then leave the description alone, initialize the rule's | 124 // then leave the description alone, initialize the rule's |
115 // rule text and substitutions, and return that rule | 125 // rule text and substitutions, and return that rule |
116 if (brack1 == -1 || brack2 == -1 || brack1 > brack2 | 126 if (brack1 == -1 || brack2 == -1 || brack1 > brack2 |
117 || rule1->getType() == kProperFractionRule | 127 || rule1->getType() == kProperFractionRule |
118 || rule1->getType() == kNegativeNumberRule) { | 128 || rule1->getType() == kNegativeNumberRule) { |
119 rule1->ruleText = description; | 129 rule1->extractSubstitutions(ruleSet, description, predecessor, status); |
120 rule1->extractSubstitutions(ruleSet, predecessor, rbnf, status); | |
121 rules.add(rule1); | 130 rules.add(rule1); |
122 } else { | 131 } else { |
123 // if the description does contain a matched pair of brackets, | 132 // if the description does contain a matched pair of brackets, |
124 // then it's really shorthand for two rules (with one exception) | 133 // then it's really shorthand for two rules (with one exception) |
125 NFRule* rule2 = NULL; | 134 NFRule* rule2 = NULL; |
126 UnicodeString sbuf; | 135 UnicodeString sbuf; |
127 | 136 |
128 // we'll actually only split the rule into two rules if its | 137 // we'll actually only split the rule into two rules if its |
129 // base value is an even multiple of its divisor (or it's one | 138 // base value is an even multiple of its divisor (or it's one |
130 // of the special rules) | 139 // of the special rules) |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 // same divisor) | 179 // same divisor) |
171 rule2->radix = rule1->radix; | 180 rule2->radix = rule1->radix; |
172 rule2->exponent = rule1->exponent; | 181 rule2->exponent = rule1->exponent; |
173 | 182 |
174 // rule2's rule text omits the stuff in brackets: initalize | 183 // rule2's rule text omits the stuff in brackets: initalize |
175 // its rule text and substitutions accordingly | 184 // its rule text and substitutions accordingly |
176 sbuf.append(description, 0, brack1); | 185 sbuf.append(description, 0, brack1); |
177 if (brack2 + 1 < description.length()) { | 186 if (brack2 + 1 < description.length()) { |
178 sbuf.append(description, brack2 + 1, description.length() - brac
k2 - 1); | 187 sbuf.append(description, brack2 + 1, description.length() - brac
k2 - 1); |
179 } | 188 } |
180 rule2->ruleText.setTo(sbuf); | 189 rule2->extractSubstitutions(ruleSet, sbuf, predecessor, status); |
181 rule2->extractSubstitutions(ruleSet, predecessor, rbnf, status); | |
182 } | 190 } |
183 | 191 |
184 // rule1's text includes the text in the brackets but omits | 192 // rule1's text includes the text in the brackets but omits |
185 // the brackets themselves: initialize _its_ rule text and | 193 // the brackets themselves: initialize _its_ rule text and |
186 // substitutions accordingly | 194 // substitutions accordingly |
187 sbuf.setTo(description, 0, brack1); | 195 sbuf.setTo(description, 0, brack1); |
188 sbuf.append(description, brack1 + 1, brack2 - brack1 - 1); | 196 sbuf.append(description, brack1 + 1, brack2 - brack1 - 1); |
189 if (brack2 + 1 < description.length()) { | 197 if (brack2 + 1 < description.length()) { |
190 sbuf.append(description, brack2 + 1, description.length() - brack2 -
1); | 198 sbuf.append(description, brack2 + 1, description.length() - brack2 -
1); |
191 } | 199 } |
192 rule1->ruleText.setTo(sbuf); | 200 rule1->extractSubstitutions(ruleSet, sbuf, predecessor, status); |
193 rule1->extractSubstitutions(ruleSet, predecessor, rbnf, status); | |
194 | 201 |
195 // if we only have one rule, return it; if we have two, return | 202 // if we only have one rule, return it; if we have two, return |
196 // a two-element array containing them (notice that rule2 goes | 203 // a two-element array containing them (notice that rule2 goes |
197 // BEFORE rule1 in the list: in all cases, rule2 OMITS the | 204 // BEFORE rule1 in the list: in all cases, rule2 OMITS the |
198 // material in the brackets and rule1 INCLUDES the material | 205 // material in the brackets and rule1 INCLUDES the material |
199 // in the brackets) | 206 // in the brackets) |
200 if (rule2 != NULL) { | 207 if (rule2 != NULL) { |
201 rules.add(rule2); | 208 rules.add(rule2); |
202 } | 209 } |
203 rules.add(rule1); | 210 rules.add(rule1); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 /** | 369 /** |
363 * Searches the rule's rule text for the substitution tokens, | 370 * Searches the rule's rule text for the substitution tokens, |
364 * creates the substitutions, and removes the substitution tokens | 371 * creates the substitutions, and removes the substitution tokens |
365 * from the rule's rule text. | 372 * from the rule's rule text. |
366 * @param owner The rule set containing this rule | 373 * @param owner The rule set containing this rule |
367 * @param predecessor The rule preseding this one in "owners" rule list | 374 * @param predecessor The rule preseding this one in "owners" rule list |
368 * @param ownersOwner The RuleBasedFormat that owns this rule | 375 * @param ownersOwner The RuleBasedFormat that owns this rule |
369 */ | 376 */ |
370 void | 377 void |
371 NFRule::extractSubstitutions(const NFRuleSet* ruleSet, | 378 NFRule::extractSubstitutions(const NFRuleSet* ruleSet, |
| 379 const UnicodeString &ruleText, |
372 const NFRule* predecessor, | 380 const NFRule* predecessor, |
373 const RuleBasedNumberFormat* rbnf, | |
374 UErrorCode& status) | 381 UErrorCode& status) |
375 { | 382 { |
376 if (U_SUCCESS(status)) { | 383 if (U_FAILURE(status)) { |
377 sub1 = extractSubstitution(ruleSet, predecessor, rbnf, status); | 384 return; |
378 sub2 = extractSubstitution(ruleSet, predecessor, rbnf, status); | 385 } |
| 386 this->ruleText = ruleText; |
| 387 this->rulePatternFormat = NULL; |
| 388 sub1 = extractSubstitution(ruleSet, predecessor, status); |
| 389 if (sub1 == NULL || sub1->isNullSubstitution()) { |
| 390 // Small optimization. There is no need to create a redundant NullSubsti
tution. |
| 391 sub2 = sub1; |
| 392 } |
| 393 else { |
| 394 sub2 = extractSubstitution(ruleSet, predecessor, status); |
| 395 } |
| 396 int32_t pluralRuleStart = this->ruleText.indexOf(gDollarOpenParenthesis, -1,
0); |
| 397 int32_t pluralRuleEnd = (pluralRuleStart >= 0 ? this->ruleText.indexOf(gClos
edParenthesisDollar, -1, pluralRuleStart) : -1); |
| 398 if (pluralRuleEnd >= 0) { |
| 399 int32_t endType = this->ruleText.indexOf(gComma, pluralRuleStart); |
| 400 if (endType < 0) { |
| 401 status = U_PARSE_ERROR; |
| 402 return; |
| 403 } |
| 404 UnicodeString type(this->ruleText.tempSubString(pluralRuleStart + 2, end
Type - pluralRuleStart - 2)); |
| 405 UPluralType pluralType; |
| 406 if (type.startsWith(UNICODE_STRING_SIMPLE("cardinal"))) { |
| 407 pluralType = UPLURAL_TYPE_CARDINAL; |
| 408 } |
| 409 else if (type.startsWith(UNICODE_STRING_SIMPLE("ordinal"))) { |
| 410 pluralType = UPLURAL_TYPE_ORDINAL; |
| 411 } |
| 412 else { |
| 413 status = U_ILLEGAL_ARGUMENT_ERROR; |
| 414 return; |
| 415 } |
| 416 rulePatternFormat = formatter->createPluralFormat(pluralType, |
| 417 this->ruleText.tempSubString(endType + 1, pluralRuleEnd - endTyp
e - 1), status); |
379 } | 418 } |
380 } | 419 } |
381 | 420 |
382 /** | 421 /** |
383 * Searches the rule's rule text for the first substitution token, | 422 * Searches the rule's rule text for the first substitution token, |
384 * creates a substitution based on it, and removes the token from | 423 * creates a substitution based on it, and removes the token from |
385 * the rule's rule text. | 424 * the rule's rule text. |
386 * @param owner The rule set containing this rule | 425 * @param owner The rule set containing this rule |
387 * @param predecessor The rule preceding this one in the rule set's | 426 * @param predecessor The rule preceding this one in the rule set's |
388 * rule list | 427 * rule list |
389 * @param ownersOwner The RuleBasedNumberFormat that owns this rule | 428 * @param ownersOwner The RuleBasedNumberFormat that owns this rule |
390 * @return The newly-created substitution. This is never null; if | 429 * @return The newly-created substitution. This is never null; if |
391 * the rule text doesn't contain any substitution tokens, this will | 430 * the rule text doesn't contain any substitution tokens, this will |
392 * be a NullSubstitution. | 431 * be a NullSubstitution. |
393 */ | 432 */ |
394 NFSubstitution * | 433 NFSubstitution * |
395 NFRule::extractSubstitution(const NFRuleSet* ruleSet, | 434 NFRule::extractSubstitution(const NFRuleSet* ruleSet, |
396 const NFRule* predecessor, | 435 const NFRule* predecessor, |
397 const RuleBasedNumberFormat* rbnf, | |
398 UErrorCode& status) | 436 UErrorCode& status) |
399 { | 437 { |
400 NFSubstitution* result = NULL; | 438 NFSubstitution* result = NULL; |
401 | 439 |
402 // search the rule's rule text for the first two characters of | 440 // search the rule's rule text for the first two characters of |
403 // a substitution token | 441 // a substitution token |
404 int32_t subStart = indexOfAny(tokenStrings); | 442 int32_t subStart = indexOfAny(tokenStrings); |
405 int32_t subEnd = subStart; | 443 int32_t subEnd = subStart; |
406 | 444 |
407 // if we didn't find one, create a null substitution positioned | 445 // if we didn't find one, create a null substitution positioned |
408 // at the end of the rule text | 446 // at the end of the rule text |
409 if (subStart == -1) { | 447 if (subStart == -1) { |
410 return NFSubstitution::makeSubstitution(ruleText.length(), this, predece
ssor, | 448 return NFSubstitution::makeSubstitution(ruleText.length(), this, predece
ssor, |
411 ruleSet, rbnf, UnicodeString(), status); | 449 ruleSet, this->formatter, UnicodeString(), status); |
412 } | 450 } |
413 | 451 |
414 // special-case the ">>>" token, since searching for the > at the | 452 // special-case the ">>>" token, since searching for the > at the |
415 // end will actually find the > in the middle | 453 // end will actually find the > in the middle |
416 if (ruleText.indexOf(gGreaterGreaterGreater, 3, 0) == subStart) { | 454 if (ruleText.indexOf(gGreaterGreaterGreater, 3, 0) == subStart) { |
417 subEnd = subStart + 2; | 455 subEnd = subStart + 2; |
418 | 456 |
419 // otherwise the substitution token ends with the same character | 457 // otherwise the substitution token ends with the same character |
420 // it began with | 458 // it began with |
421 } else { | 459 } else { |
422 UChar c = ruleText.charAt(subStart); | 460 UChar c = ruleText.charAt(subStart); |
423 subEnd = ruleText.indexOf(c, subStart + 1); | 461 subEnd = ruleText.indexOf(c, subStart + 1); |
424 // special case for '<%foo<<' | 462 // special case for '<%foo<<' |
425 if (c == gLessThan && subEnd != -1 && subEnd < ruleText.length() - 1 &&
ruleText.charAt(subEnd+1) == c) { | 463 if (c == gLessThan && subEnd != -1 && subEnd < ruleText.length() - 1 &&
ruleText.charAt(subEnd+1) == c) { |
426 // ordinals use "=#,##0==%abbrev=" as their rule. Notice that the '
==' in the middle | 464 // ordinals use "=#,##0==%abbrev=" as their rule. Notice that the '
==' in the middle |
427 // occurs because of the juxtaposition of two different rules. The
check for '<' is a hack | 465 // occurs because of the juxtaposition of two different rules. The
check for '<' is a hack |
428 // to get around this. Having the duplicate at the front would caus
e problems with | 466 // to get around this. Having the duplicate at the front would caus
e problems with |
429 // rules like "<<%" to format, say, percents... | 467 // rules like "<<%" to format, say, percents... |
430 ++subEnd; | 468 ++subEnd; |
431 } | 469 } |
432 } | 470 } |
433 | 471 |
434 // if we don't find the end of the token (i.e., if we're on a single, | 472 // if we don't find the end of the token (i.e., if we're on a single, |
435 // unmatched token character), create a null substitution positioned | 473 // unmatched token character), create a null substitution positioned |
436 // at the end of the rule | 474 // at the end of the rule |
437 if (subEnd == -1) { | 475 if (subEnd == -1) { |
438 return NFSubstitution::makeSubstitution(ruleText.length(), this, predece
ssor, | 476 return NFSubstitution::makeSubstitution(ruleText.length(), this, predece
ssor, |
439 ruleSet, rbnf, UnicodeString(), status); | 477 ruleSet, this->formatter, UnicodeString(), status); |
440 } | 478 } |
441 | 479 |
442 // if we get here, we have a real substitution token (or at least | 480 // if we get here, we have a real substitution token (or at least |
443 // some text bounded by substitution token characters). Use | 481 // some text bounded by substitution token characters). Use |
444 // makeSubstitution() to create the right kind of substitution | 482 // makeSubstitution() to create the right kind of substitution |
445 UnicodeString subToken; | 483 UnicodeString subToken; |
446 subToken.setTo(ruleText, subStart, subEnd + 1 - subStart); | 484 subToken.setTo(ruleText, subStart, subEnd + 1 - subStart); |
447 result = NFSubstitution::makeSubstitution(subStart, this, predecessor, ruleS
et, | 485 result = NFSubstitution::makeSubstitution(subStart, this, predecessor, ruleS
et, |
448 rbnf, subToken, status); | 486 this->formatter, subToken, status); |
449 | 487 |
450 // remove the substitution from the rule text | 488 // remove the substitution from the rule text |
451 ruleText.removeBetween(subStart, subEnd+1); | 489 ruleText.removeBetween(subStart, subEnd+1); |
452 | 490 |
453 return result; | 491 return result; |
454 } | 492 } |
455 | 493 |
456 /** | 494 /** |
457 * Sets the rule's base value, and causes the radix and exponent | 495 * Sets the rule's base value, and causes the radix and exponent |
458 * to be recalculated. This is used during construction when we | 496 * to be recalculated. This is used during construction when we |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 /** | 675 /** |
638 * Formats the number, and inserts the resulting text into | 676 * Formats the number, and inserts the resulting text into |
639 * toInsertInto. | 677 * toInsertInto. |
640 * @param number The number being formatted | 678 * @param number The number being formatted |
641 * @param toInsertInto The string where the resultant text should | 679 * @param toInsertInto The string where the resultant text should |
642 * be inserted | 680 * be inserted |
643 * @param pos The position in toInsertInto where the resultant text | 681 * @param pos The position in toInsertInto where the resultant text |
644 * should be inserted | 682 * should be inserted |
645 */ | 683 */ |
646 void | 684 void |
647 NFRule::doFormat(int64_t number, UnicodeString& toInsertInto, int32_t pos) const | 685 NFRule::doFormat(int64_t number, UnicodeString& toInsertInto, int32_t pos, UErro
rCode& status) const |
648 { | 686 { |
649 // first, insert the rule's rule text into toInsertInto at the | 687 // first, insert the rule's rule text into toInsertInto at the |
650 // specified position, then insert the results of the substitutions | 688 // specified position, then insert the results of the substitutions |
651 // into the right places in toInsertInto (notice we do the | 689 // into the right places in toInsertInto (notice we do the |
652 // substitutions in reverse order so that the offsets don't get | 690 // substitutions in reverse order so that the offsets don't get |
653 // messed up) | 691 // messed up) |
654 toInsertInto.insert(pos, ruleText); | 692 int32_t pluralRuleStart = ruleText.length(); |
655 sub2->doSubstitution(number, toInsertInto, pos); | 693 int32_t lengthOffset = 0; |
656 sub1->doSubstitution(number, toInsertInto, pos); | 694 if (!rulePatternFormat) { |
| 695 toInsertInto.insert(pos, ruleText); |
| 696 } |
| 697 else { |
| 698 pluralRuleStart = ruleText.indexOf(gDollarOpenParenthesis, -1, 0); |
| 699 int pluralRuleEnd = ruleText.indexOf(gClosedParenthesisDollar, -1, plura
lRuleStart); |
| 700 int initialLength = toInsertInto.length(); |
| 701 if (pluralRuleEnd < ruleText.length() - 1) { |
| 702 toInsertInto.insert(pos, ruleText.tempSubString(pluralRuleEnd + 2)); |
| 703 } |
| 704 toInsertInto.insert(pos, |
| 705 rulePatternFormat->format((int32_t)(number/uprv_pow(radix, exponent)
), status)); |
| 706 if (pluralRuleStart > 0) { |
| 707 toInsertInto.insert(pos, ruleText.tempSubString(0, pluralRuleStart))
; |
| 708 } |
| 709 lengthOffset = ruleText.length() - (toInsertInto.length() - initialLengt
h); |
| 710 } |
| 711 |
| 712 if (!sub2->isNullSubstitution()) { |
| 713 sub2->doSubstitution(number, toInsertInto, pos - (sub2->getPos() > plura
lRuleStart ? lengthOffset : 0), status); |
| 714 } |
| 715 if (!sub1->isNullSubstitution()) { |
| 716 sub1->doSubstitution(number, toInsertInto, pos - (sub1->getPos() > plura
lRuleStart ? lengthOffset : 0), status); |
| 717 } |
657 } | 718 } |
658 | 719 |
659 /** | 720 /** |
660 * Formats the number, and inserts the resulting text into | 721 * Formats the number, and inserts the resulting text into |
661 * toInsertInto. | 722 * toInsertInto. |
662 * @param number The number being formatted | 723 * @param number The number being formatted |
663 * @param toInsertInto The string where the resultant text should | 724 * @param toInsertInto The string where the resultant text should |
664 * be inserted | 725 * be inserted |
665 * @param pos The position in toInsertInto where the resultant text | 726 * @param pos The position in toInsertInto where the resultant text |
666 * should be inserted | 727 * should be inserted |
667 */ | 728 */ |
668 void | 729 void |
669 NFRule::doFormat(double number, UnicodeString& toInsertInto, int32_t pos) const | 730 NFRule::doFormat(double number, UnicodeString& toInsertInto, int32_t pos, UError
Code& status) const |
670 { | 731 { |
671 // first, insert the rule's rule text into toInsertInto at the | 732 // first, insert the rule's rule text into toInsertInto at the |
672 // specified position, then insert the results of the substitutions | 733 // specified position, then insert the results of the substitutions |
673 // into the right places in toInsertInto | 734 // into the right places in toInsertInto |
674 // [again, we have two copies of this routine that do the same thing | 735 // [again, we have two copies of this routine that do the same thing |
675 // so that we don't sacrifice precision in a long by casting it | 736 // so that we don't sacrifice precision in a long by casting it |
676 // to a double] | 737 // to a double] |
677 toInsertInto.insert(pos, ruleText); | 738 int32_t pluralRuleStart = ruleText.length(); |
678 sub2->doSubstitution(number, toInsertInto, pos); | 739 int32_t lengthOffset = 0; |
679 sub1->doSubstitution(number, toInsertInto, pos); | 740 if (!rulePatternFormat) { |
| 741 toInsertInto.insert(pos, ruleText); |
| 742 } |
| 743 else { |
| 744 pluralRuleStart = ruleText.indexOf(gDollarOpenParenthesis, -1, 0); |
| 745 int pluralRuleEnd = ruleText.indexOf(gClosedParenthesisDollar, -1, plura
lRuleStart); |
| 746 int initialLength = toInsertInto.length(); |
| 747 if (pluralRuleEnd < ruleText.length() - 1) { |
| 748 toInsertInto.insert(pos, ruleText.tempSubString(pluralRuleEnd + 2)); |
| 749 } |
| 750 toInsertInto.insert(pos, |
| 751 rulePatternFormat->format((int32_t)(number/uprv_pow(radix, exponent)
), status)); |
| 752 if (pluralRuleStart > 0) { |
| 753 toInsertInto.insert(pos, ruleText.tempSubString(0, pluralRuleStart))
; |
| 754 } |
| 755 lengthOffset = ruleText.length() - (toInsertInto.length() - initialLengt
h); |
| 756 } |
| 757 |
| 758 if (!sub2->isNullSubstitution()) { |
| 759 sub2->doSubstitution(number, toInsertInto, pos - (sub2->getPos() > plura
lRuleStart ? lengthOffset : 0), status); |
| 760 } |
| 761 if (!sub1->isNullSubstitution()) { |
| 762 sub1->doSubstitution(number, toInsertInto, pos - (sub1->getPos() > plura
lRuleStart ? lengthOffset : 0), status); |
| 763 } |
680 } | 764 } |
681 | 765 |
682 /** | 766 /** |
683 * Used by the owning rule set to determine whether to invoke the | 767 * Used by the owning rule set to determine whether to invoke the |
684 * rollback rule (i.e., whether this rule or the one that precedes | 768 * rollback rule (i.e., whether this rule or the one that precedes |
685 * it in the rule set's list should be used to format the number) | 769 * it in the rule set's list should be used to format the number) |
686 * @param The number being formatted | 770 * @param The number being formatted |
687 * @return True if the rule set should use the rule that precedes | 771 * @return True if the rule set should use the rule that precedes |
688 * this one in its list; false if it should use this rule | 772 * this one in its list; false if it should use this rule |
689 */ | 773 */ |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 #if !UCONFIG_NO_COLLATION | 1213 #if !UCONFIG_NO_COLLATION |
1130 // go through all this grief if we're in lenient-parse mode | 1214 // go through all this grief if we're in lenient-parse mode |
1131 if (formatter->isLenient()) { | 1215 if (formatter->isLenient()) { |
1132 // get the formatter's collator and use it to create two | 1216 // get the formatter's collator and use it to create two |
1133 // collation element iterators, one over the target string | 1217 // collation element iterators, one over the target string |
1134 // and another over the prefix (right now, we'll throw an | 1218 // and another over the prefix (right now, we'll throw an |
1135 // exception if the collator we get back from the formatter | 1219 // exception if the collator we get back from the formatter |
1136 // isn't a RuleBasedCollator, because RuleBasedCollator defines | 1220 // isn't a RuleBasedCollator, because RuleBasedCollator defines |
1137 // the CollationElementIterator protocol. Hopefully, this | 1221 // the CollationElementIterator protocol. Hopefully, this |
1138 // will change someday.) | 1222 // will change someday.) |
1139 RuleBasedCollator* collator = (RuleBasedCollator*)formatter->getCollator
(); | 1223 const RuleBasedCollator* collator = formatter->getCollator(); |
1140 CollationElementIterator* strIter = collator->createCollationElementIter
ator(str); | 1224 if (collator == NULL) { |
1141 CollationElementIterator* prefixIter = collator->createCollationElementI
terator(prefix); | 1225 status = U_MEMORY_ALLOCATION_ERROR; |
| 1226 return 0; |
| 1227 } |
| 1228 LocalPointer<CollationElementIterator> strIter(collator->createCollation
ElementIterator(str)); |
| 1229 LocalPointer<CollationElementIterator> prefixIter(collator->createCollat
ionElementIterator(prefix)); |
1142 // Check for memory allocation error. | 1230 // Check for memory allocation error. |
1143 if (collator == NULL || strIter == NULL || prefixIter == NULL) { | 1231 if (strIter.isNull() || prefixIter.isNull()) { |
1144 » delete collator; | 1232 status = U_MEMORY_ALLOCATION_ERROR; |
1145 » delete strIter; | 1233 return 0; |
1146 » delete prefixIter; | |
1147 » status = U_MEMORY_ALLOCATION_ERROR; | |
1148 » return 0; | |
1149 } | 1234 } |
1150 | 1235 |
1151 UErrorCode err = U_ZERO_ERROR; | 1236 UErrorCode err = U_ZERO_ERROR; |
1152 | 1237 |
1153 // The original code was problematic. Consider this match: | 1238 // The original code was problematic. Consider this match: |
1154 // prefix = "fifty-" | 1239 // prefix = "fifty-" |
1155 // string = " fifty-7" | 1240 // string = " fifty-7" |
1156 // The intent is to match string up to the '7', by matching 'fifty-' at
position 1 | 1241 // The intent is to match string up to the '7', by matching 'fifty-' at
position 1 |
1157 // in the string. Unfortunately, we were getting a match, and then comp
uting where | 1242 // in the string. Unfortunately, we were getting a match, and then comp
uting where |
1158 // the match terminated by rematching the string. The rematch code was
using as an | 1243 // the match terminated by rematching the string. The rematch code was
using as an |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1190 | 1275 |
1191 // if skipping over ignorables brought to the end of | 1276 // if skipping over ignorables brought to the end of |
1192 // the prefix, we DID match: drop out of the loop | 1277 // the prefix, we DID match: drop out of the loop |
1193 if (oPrefix == CollationElementIterator::NULLORDER) { | 1278 if (oPrefix == CollationElementIterator::NULLORDER) { |
1194 break; | 1279 break; |
1195 } | 1280 } |
1196 | 1281 |
1197 // if skipping over ignorables brought us to the end | 1282 // if skipping over ignorables brought us to the end |
1198 // of the target string, we didn't match and return 0 | 1283 // of the target string, we didn't match and return 0 |
1199 if (oStr == CollationElementIterator::NULLORDER) { | 1284 if (oStr == CollationElementIterator::NULLORDER) { |
1200 delete prefixIter; | |
1201 delete strIter; | |
1202 return 0; | 1285 return 0; |
1203 } | 1286 } |
1204 | 1287 |
1205 // match collation elements from the two strings | 1288 // match collation elements from the two strings |
1206 // (considering only primary differences). If we | 1289 // (considering only primary differences). If we |
1207 // get a mismatch, dump out and return 0 | 1290 // get a mismatch, dump out and return 0 |
1208 if (CollationElementIterator::primaryOrder(oStr) | 1291 if (CollationElementIterator::primaryOrder(oStr) |
1209 != CollationElementIterator::primaryOrder(oPrefix)) { | 1292 != CollationElementIterator::primaryOrder(oPrefix)) { |
1210 delete prefixIter; | |
1211 delete strIter; | |
1212 return 0; | 1293 return 0; |
1213 | 1294 |
1214 // otherwise, advance to the next character in each string | 1295 // otherwise, advance to the next character in each string |
1215 // and loop (we drop out of the loop when we exhaust | 1296 // and loop (we drop out of the loop when we exhaust |
1216 // collation elements in the prefix) | 1297 // collation elements in the prefix) |
1217 } else { | 1298 } else { |
1218 oStr = strIter->next(err); | 1299 oStr = strIter->next(err); |
1219 oPrefix = prefixIter->next(err); | 1300 oPrefix = prefixIter->next(err); |
1220 } | 1301 } |
1221 } | 1302 } |
1222 | 1303 |
1223 int32_t result = strIter->getOffset(); | 1304 int32_t result = strIter->getOffset(); |
1224 if (oStr != CollationElementIterator::NULLORDER) { | 1305 if (oStr != CollationElementIterator::NULLORDER) { |
1225 --result; // back over character that we don't want to consume; | 1306 --result; // back over character that we don't want to consume; |
1226 } | 1307 } |
1227 | 1308 |
1228 #ifdef RBNF_DEBUG | 1309 #ifdef RBNF_DEBUG |
1229 fprintf(stderr, "prefix length: %d\n", result); | 1310 fprintf(stderr, "prefix length: %d\n", result); |
1230 #endif | 1311 #endif |
1231 delete prefixIter; | |
1232 delete strIter; | |
1233 | |
1234 return result; | 1312 return result; |
1235 #if 0 | 1313 #if 0 |
1236 //---------------------------------------------------------------- | 1314 //---------------------------------------------------------------- |
1237 // JDK 1.2-specific API call | 1315 // JDK 1.2-specific API call |
1238 // return strIter.getOffset(); | 1316 // return strIter.getOffset(); |
1239 //---------------------------------------------------------------- | 1317 //---------------------------------------------------------------- |
1240 // JDK 1.1 HACK (take out for 1.2-specific code) | 1318 // JDK 1.1 HACK (take out for 1.2-specific code) |
1241 | 1319 |
1242 // if we make it to here, we have a successful match. Now we | 1320 // if we make it to here, we have a successful match. Now we |
1243 // have to find out HOW MANY characters from the target string | 1321 // have to find out HOW MANY characters from the target string |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1307 * of the match, or -1 if there was no match. Element 1 is the | 1385 * of the match, or -1 if there was no match. Element 1 is the |
1308 * number of characters in "str" that matched (which isn't necessarily | 1386 * number of characters in "str" that matched (which isn't necessarily |
1309 * the same as the length of "key") | 1387 * the same as the length of "key") |
1310 */ | 1388 */ |
1311 int32_t | 1389 int32_t |
1312 NFRule::findText(const UnicodeString& str, | 1390 NFRule::findText(const UnicodeString& str, |
1313 const UnicodeString& key, | 1391 const UnicodeString& key, |
1314 int32_t startingAt, | 1392 int32_t startingAt, |
1315 int32_t* length) const | 1393 int32_t* length) const |
1316 { | 1394 { |
1317 #if !UCONFIG_NO_COLLATION | 1395 if (rulePatternFormat) { |
1318 // if lenient parsing is turned off, this is easy: just call | 1396 Formattable result; |
1319 // String.indexOf() and we're done | 1397 FieldPosition position(UNUM_INTEGER_FIELD); |
| 1398 position.setBeginIndex(startingAt); |
| 1399 rulePatternFormat->parseType(str, this, result, position); |
| 1400 int start = position.getBeginIndex(); |
| 1401 if (start >= 0) { |
| 1402 int32_t pluralRuleStart = ruleText.indexOf(gDollarOpenParenthesis, -
1, 0); |
| 1403 int32_t pluralRuleSuffix = ruleText.indexOf(gClosedParenthesisDollar
, -1, pluralRuleStart) + 2; |
| 1404 int32_t matchLen = position.getEndIndex() - start; |
| 1405 UnicodeString prefix(ruleText.tempSubString(0, pluralRuleStart)); |
| 1406 UnicodeString suffix(ruleText.tempSubString(pluralRuleSuffix)); |
| 1407 if (str.compare(start - prefix.length(), prefix.length(), prefix, 0,
prefix.length()) == 0 |
| 1408 && str.compare(start + matchLen, suffix.length(), suffix, 0,
suffix.length()) == 0) |
| 1409 { |
| 1410 *length = matchLen + prefix.length() + suffix.length(); |
| 1411 return start - prefix.length(); |
| 1412 } |
| 1413 } |
| 1414 *length = 0; |
| 1415 return -1; |
| 1416 } |
1320 if (!formatter->isLenient()) { | 1417 if (!formatter->isLenient()) { |
| 1418 // if lenient parsing is turned off, this is easy: just call |
| 1419 // String.indexOf() and we're done |
1321 *length = key.length(); | 1420 *length = key.length(); |
1322 return str.indexOf(key, startingAt); | 1421 return str.indexOf(key, startingAt); |
1323 | 1422 } |
| 1423 else { |
1324 // but if lenient parsing is turned ON, we've got some work | 1424 // but if lenient parsing is turned ON, we've got some work |
1325 // ahead of us | 1425 // ahead of us |
1326 } else | 1426 return findTextLenient(str, key, startingAt, length); |
1327 #endif | |
1328 { | |
1329 //---------------------------------------------------------------- | |
1330 // JDK 1.1 HACK (take out of 1.2-specific code) | |
1331 | |
1332 // in JDK 1.2, CollationElementIterator provides us with an | |
1333 // API to map between character offsets and collation elements | |
1334 // and we can do this by marching through the string comparing | |
1335 // collation elements. We can't do that in JDK 1.1. Insted, | |
1336 // we have to go through this horrible slow mess: | |
1337 int32_t p = startingAt; | |
1338 int32_t keyLen = 0; | |
1339 | |
1340 // basically just isolate smaller and smaller substrings of | |
1341 // the target string (each running to the end of the string, | |
1342 // and with the first one running from startingAt to the end) | |
1343 // and then use prefixLength() to see if the search key is at | |
1344 // the beginning of each substring. This is excruciatingly | |
1345 // slow, but it will locate the key and tell use how long the | |
1346 // matching text was. | |
1347 UnicodeString temp; | |
1348 UErrorCode status = U_ZERO_ERROR; | |
1349 while (p < str.length() && keyLen == 0) { | |
1350 temp.setTo(str, p, str.length() - p); | |
1351 keyLen = prefixLength(temp, key, status); | |
1352 if (U_FAILURE(status)) { | |
1353 » break; | |
1354 } | |
1355 if (keyLen != 0) { | |
1356 *length = keyLen; | |
1357 return p; | |
1358 } | |
1359 ++p; | |
1360 } | |
1361 // if we make it to here, we didn't find it. Return -1 for the | |
1362 // location. The length should be ignored, but set it to 0, | |
1363 // which should be "safe" | |
1364 *length = 0; | |
1365 return -1; | |
1366 | |
1367 //---------------------------------------------------------------- | |
1368 // JDK 1.2 version of this routine | |
1369 //RuleBasedCollator collator = (RuleBasedCollator)formatter.getCollator(
); | |
1370 // | |
1371 //CollationElementIterator strIter = collator.getCollationElementIterato
r(str); | |
1372 //CollationElementIterator keyIter = collator.getCollationElementIterato
r(key); | |
1373 // | |
1374 //int keyStart = -1; | |
1375 // | |
1376 //str.setOffset(startingAt); | |
1377 // | |
1378 //int oStr = strIter.next(); | |
1379 //int oKey = keyIter.next(); | |
1380 //while (oKey != CollationElementIterator.NULLORDER) { | |
1381 // while (oStr != CollationElementIterator.NULLORDER && | |
1382 // CollationElementIterator.primaryOrder(oStr) == 0) | |
1383 // oStr = strIter.next(); | |
1384 // | |
1385 // while (oKey != CollationElementIterator.NULLORDER && | |
1386 // CollationElementIterator.primaryOrder(oKey) == 0) | |
1387 // oKey = keyIter.next(); | |
1388 // | |
1389 // if (oStr == CollationElementIterator.NULLORDER) { | |
1390 // return new int[] { -1, 0 }; | |
1391 // } | |
1392 // | |
1393 // if (oKey == CollationElementIterator.NULLORDER) { | |
1394 // break; | |
1395 // } | |
1396 // | |
1397 // if (CollationElementIterator.primaryOrder(oStr) == | |
1398 // CollationElementIterator.primaryOrder(oKey)) { | |
1399 // keyStart = strIter.getOffset(); | |
1400 // oStr = strIter.next(); | |
1401 // oKey = keyIter.next(); | |
1402 // } else { | |
1403 // if (keyStart != -1) { | |
1404 // keyStart = -1; | |
1405 // keyIter.reset(); | |
1406 // } else { | |
1407 // oStr = strIter.next(); | |
1408 // } | |
1409 // } | |
1410 //} | |
1411 // | |
1412 //if (oKey == CollationElementIterator.NULLORDER) { | |
1413 // return new int[] { keyStart, strIter.getOffset() - keyStart }; | |
1414 //} else { | |
1415 // return new int[] { -1, 0 }; | |
1416 //} | |
1417 } | 1427 } |
1418 } | 1428 } |
1419 | 1429 |
| 1430 int32_t |
| 1431 NFRule::findTextLenient(const UnicodeString& str, |
| 1432 const UnicodeString& key, |
| 1433 int32_t startingAt, |
| 1434 int32_t* length) const |
| 1435 { |
| 1436 //---------------------------------------------------------------- |
| 1437 // JDK 1.1 HACK (take out of 1.2-specific code) |
| 1438 |
| 1439 // in JDK 1.2, CollationElementIterator provides us with an |
| 1440 // API to map between character offsets and collation elements |
| 1441 // and we can do this by marching through the string comparing |
| 1442 // collation elements. We can't do that in JDK 1.1. Insted, |
| 1443 // we have to go through this horrible slow mess: |
| 1444 int32_t p = startingAt; |
| 1445 int32_t keyLen = 0; |
| 1446 |
| 1447 // basically just isolate smaller and smaller substrings of |
| 1448 // the target string (each running to the end of the string, |
| 1449 // and with the first one running from startingAt to the end) |
| 1450 // and then use prefixLength() to see if the search key is at |
| 1451 // the beginning of each substring. This is excruciatingly |
| 1452 // slow, but it will locate the key and tell use how long the |
| 1453 // matching text was. |
| 1454 UnicodeString temp; |
| 1455 UErrorCode status = U_ZERO_ERROR; |
| 1456 while (p < str.length() && keyLen == 0) { |
| 1457 temp.setTo(str, p, str.length() - p); |
| 1458 keyLen = prefixLength(temp, key, status); |
| 1459 if (U_FAILURE(status)) { |
| 1460 break; |
| 1461 } |
| 1462 if (keyLen != 0) { |
| 1463 *length = keyLen; |
| 1464 return p; |
| 1465 } |
| 1466 ++p; |
| 1467 } |
| 1468 // if we make it to here, we didn't find it. Return -1 for the |
| 1469 // location. The length should be ignored, but set it to 0, |
| 1470 // which should be "safe" |
| 1471 *length = 0; |
| 1472 return -1; |
| 1473 } |
| 1474 |
1420 /** | 1475 /** |
1421 * Checks to see whether a string consists entirely of ignorable | 1476 * Checks to see whether a string consists entirely of ignorable |
1422 * characters. | 1477 * characters. |
1423 * @param str The string to test. | 1478 * @param str The string to test. |
1424 * @return true if the string is empty of consists entirely of | 1479 * @return true if the string is empty of consists entirely of |
1425 * characters that the number formatter's collator says are | 1480 * characters that the number formatter's collator says are |
1426 * ignorable at the primary-order level. false otherwise. | 1481 * ignorable at the primary-order level. false otherwise. |
1427 */ | 1482 */ |
1428 UBool | 1483 UBool |
1429 NFRule::allIgnorable(const UnicodeString& str, UErrorCode& status) const | 1484 NFRule::allIgnorable(const UnicodeString& str, UErrorCode& status) const |
1430 { | 1485 { |
1431 // if the string is empty, we can just return true | 1486 // if the string is empty, we can just return true |
1432 if (str.length() == 0) { | 1487 if (str.length() == 0) { |
1433 return TRUE; | 1488 return TRUE; |
1434 } | 1489 } |
1435 | 1490 |
1436 #if !UCONFIG_NO_COLLATION | 1491 #if !UCONFIG_NO_COLLATION |
1437 // if lenient parsing is turned on, walk through the string with | 1492 // if lenient parsing is turned on, walk through the string with |
1438 // a collation element iterator and make sure each collation | 1493 // a collation element iterator and make sure each collation |
1439 // element is 0 (ignorable) at the primary level | 1494 // element is 0 (ignorable) at the primary level |
1440 if (formatter->isLenient()) { | 1495 if (formatter->isLenient()) { |
1441 RuleBasedCollator* collator = (RuleBasedCollator*)(formatter->getCollato
r()); | 1496 const RuleBasedCollator* collator = formatter->getCollator(); |
1442 CollationElementIterator* iter = collator->createCollationElementIterato
r(str); | 1497 if (collator == NULL) { |
1443 | 1498 status = U_MEMORY_ALLOCATION_ERROR; |
| 1499 return FALSE; |
| 1500 } |
| 1501 LocalPointer<CollationElementIterator> iter(collator->createCollationEle
mentIterator(str)); |
| 1502 |
1444 // Memory allocation error check. | 1503 // Memory allocation error check. |
1445 if (collator == NULL || iter == NULL) { | 1504 if (iter.isNull()) { |
1446 » delete collator; | 1505 status = U_MEMORY_ALLOCATION_ERROR; |
1447 » delete iter; | 1506 return FALSE; |
1448 » status = U_MEMORY_ALLOCATION_ERROR; | |
1449 » return FALSE; | |
1450 } | 1507 } |
1451 | 1508 |
1452 UErrorCode err = U_ZERO_ERROR; | 1509 UErrorCode err = U_ZERO_ERROR; |
1453 int32_t o = iter->next(err); | 1510 int32_t o = iter->next(err); |
1454 while (o != CollationElementIterator::NULLORDER | 1511 while (o != CollationElementIterator::NULLORDER |
1455 && CollationElementIterator::primaryOrder(o) == 0) { | 1512 && CollationElementIterator::primaryOrder(o) == 0) { |
1456 o = iter->next(err); | 1513 o = iter->next(err); |
1457 } | 1514 } |
1458 | 1515 |
1459 delete iter; | |
1460 return o == CollationElementIterator::NULLORDER; | 1516 return o == CollationElementIterator::NULLORDER; |
1461 } | 1517 } |
1462 #endif | 1518 #endif |
1463 | 1519 |
1464 // if lenient parsing is turned off, there is no such thing as | 1520 // if lenient parsing is turned off, there is no such thing as |
1465 // an ignorable character: return true only if the string is empty | 1521 // an ignorable character: return true only if the string is empty |
1466 return FALSE; | 1522 return FALSE; |
1467 } | 1523 } |
1468 | 1524 |
1469 U_NAMESPACE_END | 1525 U_NAMESPACE_END |
1470 | 1526 |
1471 /* U_HAVE_RBNF */ | 1527 /* U_HAVE_RBNF */ |
1472 #endif | 1528 #endif |
1473 | |
1474 | |
OLD | NEW |