Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(146)

Side by Side Diff: source/i18n/nfrs.cpp

Issue 1621843002: ICU 56 update step 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@561
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « source/i18n/nfrs.h ('k') | source/i18n/nfrule.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 ****************************************************************************** 2 ******************************************************************************
3 * Copyright (C) 1997-2014, International Business Machines 3 * Copyright (C) 1997-2015, International Business Machines
4 * Corporation and others. All Rights Reserved. 4 * Corporation and others. All Rights Reserved.
5 ****************************************************************************** 5 ******************************************************************************
6 * file name: nfrs.cpp 6 * file name: nfrs.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 "nfrs.h" 16 #include "nfrs.h"
17 17
18 #if U_HAVE_RBNF 18 #if U_HAVE_RBNF
19 19
20 #include "unicode/uchar.h" 20 #include "unicode/uchar.h"
21 #include "nfrule.h" 21 #include "nfrule.h"
22 #include "nfrlist.h" 22 #include "nfrlist.h"
23 #include "patternprops.h" 23 #include "patternprops.h"
24 24
25 #ifdef RBNF_DEBUG 25 #ifdef RBNF_DEBUG
26 #include "cmemory.h" 26 #include "cmemory.h"
27 #endif 27 #endif
28 28
29 enum {
30 /** -x */
31 NEGATIVE_RULE_INDEX = 0,
32 /** x.x */
33 IMPROPER_FRACTION_RULE_INDEX = 1,
34 /** 0.x */
35 PROPER_FRACTION_RULE_INDEX = 2,
36 /** x.0 */
37 MASTER_RULE_INDEX = 3,
38 /** Inf */
39 INFINITY_RULE_INDEX = 4,
40 /** NaN */
41 NAN_RULE_INDEX = 5,
42 NON_NUMERICAL_RULE_LENGTH = 6
43 };
44
29 U_NAMESPACE_BEGIN 45 U_NAMESPACE_BEGIN
30 46
31 #if 0 47 #if 0
32 // euclid's algorithm works with doubles 48 // euclid's algorithm works with doubles
33 // note, doubles only get us up to one quadrillion or so, which 49 // note, doubles only get us up to one quadrillion or so, which
34 // isn't as much range as we get with longs. We probably still 50 // isn't as much range as we get with longs. We probably still
35 // want either 64-bit math, or BigInteger. 51 // want either 64-bit math, or BigInteger.
36 52
37 static int64_t 53 static int64_t
38 util_lcm(int64_t x, int64_t y) 54 util_lcm(int64_t x, int64_t y)
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 // x * y == gcd(x, y) * lcm(x, y) 113 // x * y == gcd(x, y) * lcm(x, y)
98 return x / gcd * y; 114 return x / gcd * y;
99 } 115 }
100 #endif 116 #endif
101 117
102 static const UChar gPercent = 0x0025; 118 static const UChar gPercent = 0x0025;
103 static const UChar gColon = 0x003a; 119 static const UChar gColon = 0x003a;
104 static const UChar gSemicolon = 0x003b; 120 static const UChar gSemicolon = 0x003b;
105 static const UChar gLineFeed = 0x000a; 121 static const UChar gLineFeed = 0x000a;
106 122
107 static const UChar gFourSpaces[] =
108 {
109 0x20, 0x20, 0x20, 0x20, 0
110 }; /* " " */
111 static const UChar gPercentPercent[] = 123 static const UChar gPercentPercent[] =
112 { 124 {
113 0x25, 0x25, 0 125 0x25, 0x25, 0
114 }; /* "%%" */ 126 }; /* "%%" */
115 127
116 static const UChar gNoparse[] = 128 static const UChar gNoparse[] =
117 { 129 {
118 0x40, 0x6E, 0x6F, 0x70, 0x61, 0x72, 0x73, 0x65, 0 130 0x40, 0x6E, 0x6F, 0x70, 0x61, 0x72, 0x73, 0x65, 0
119 }; /* "@noparse" */ 131 }; /* "@noparse" */
120 132
121 NFRuleSet::NFRuleSet(UnicodeString* descriptions, int32_t index, UErrorCode& sta tus) 133 NFRuleSet::NFRuleSet(RuleBasedNumberFormat *_owner, UnicodeString* descriptions, int32_t index, UErrorCode& status)
122 : name() 134 : name()
123 , rules(0) 135 , rules(0)
124 , negativeNumberRule(NULL) 136 , owner(_owner)
137 , fractionRules()
125 , fIsFractionRuleSet(FALSE) 138 , fIsFractionRuleSet(FALSE)
126 , fIsPublic(FALSE) 139 , fIsPublic(FALSE)
127 , fIsParseable(TRUE) 140 , fIsParseable(TRUE)
128 , fRecursionCount(0)
129 { 141 {
130 for (int i = 0; i < 3; ++i) { 142 for (int32_t i = 0; i < NON_NUMERICAL_RULE_LENGTH; ++i) {
131 fractionRules[i] = NULL; 143 nonNumericalRules[i] = NULL;
132 } 144 }
133 145
134 if (U_FAILURE(status)) { 146 if (U_FAILURE(status)) {
135 return; 147 return;
136 } 148 }
137 149
138 UnicodeString& description = descriptions[index]; // !!! make sure index is valid 150 UnicodeString& description = descriptions[index]; // !!! make sure index is valid
139 151
140 if (description.length() == 0) { 152 if (description.length() == 0) {
141 // throw new IllegalArgumentException("Empty rule set description"); 153 // throw new IllegalArgumentException("Empty rule set description");
(...skipping 30 matching lines...) Expand all
172 if ( name.endsWith(gNoparse,8) ) { 184 if ( name.endsWith(gNoparse,8) ) {
173 fIsParseable = FALSE; 185 fIsParseable = FALSE;
174 name.truncate(name.length()-8); // remove the @noparse from the name 186 name.truncate(name.length()-8); // remove the @noparse from the name
175 } 187 }
176 188
177 // all of the other members of NFRuleSet are initialized 189 // all of the other members of NFRuleSet are initialized
178 // by parseRules() 190 // by parseRules()
179 } 191 }
180 192
181 void 193 void
182 NFRuleSet::parseRules(UnicodeString& description, const RuleBasedNumberFormat* o wner, UErrorCode& status) 194 NFRuleSet::parseRules(UnicodeString& description, UErrorCode& status)
183 { 195 {
184 // start by creating a Vector whose elements are Strings containing 196 // start by creating a Vector whose elements are Strings containing
185 // the descriptions of the rules (one rule per element). The rules 197 // the descriptions of the rules (one rule per element). The rules
186 // are separated by semicolons (there's no escape facility: ALL 198 // are separated by semicolons (there's no escape facility: ALL
187 // semicolons are rule delimiters) 199 // semicolons are rule delimiters)
188 200
189 if (U_FAILURE(status)) { 201 if (U_FAILURE(status)) {
190 return; 202 return;
191 } 203 }
192 204
(...skipping 17 matching lines...) Expand all
210 222
211 // for rules that didn't specify a base value, their base values 223 // for rules that didn't specify a base value, their base values
212 // were initialized to 0. Make another pass through the list and 224 // were initialized to 0. Make another pass through the list and
213 // set all those rules' base values. We also remove any special 225 // set all those rules' base values. We also remove any special
214 // rules from the list and put them into their own member variables 226 // rules from the list and put them into their own member variables
215 int64_t defaultBaseValue = 0; 227 int64_t defaultBaseValue = 0;
216 228
217 // (this isn't a for loop because we might be deleting items from 229 // (this isn't a for loop because we might be deleting items from
218 // the vector-- we want to make sure we only increment i when 230 // the vector-- we want to make sure we only increment i when
219 // we _didn't_ delete aything from the vector) 231 // we _didn't_ delete aything from the vector)
220 uint32_t i = 0; 232 int32_t rulesSize = rules.size();
221 while (i < rules.size()) { 233 for (int32_t i = 0; i < rulesSize; i++) {
222 NFRule* rule = rules[i]; 234 NFRule* rule = rules[i];
235 int64_t baseValue = rule->getBaseValue();
223 236
224 switch (rule->getType()) { 237 if (baseValue == 0) {
225 // if the rule's base value is 0, fill in a default 238 // if the rule's base value is 0, fill in a default
226 // base value (this will be 1 plus the preceding 239 // base value (this will be 1 plus the preceding
227 // rule's base value for regular rule sets, and the 240 // rule's base value for regular rule sets, and the
228 // same as the preceding rule's base value in fraction 241 // same as the preceding rule's base value in fraction
229 // rule sets) 242 // rule sets)
230 case NFRule::kNoBase:
231 rule->setBaseValue(defaultBaseValue, status); 243 rule->setBaseValue(defaultBaseValue, status);
232 if (!isFractionRuleSet()) { 244 }
233 ++defaultBaseValue; 245 else {
234 }
235 ++i;
236 break;
237
238 // if it's the negative-number rule, copy it into its own
239 // data member and delete it from the list
240 case NFRule::kNegativeNumberRule:
241 if (negativeNumberRule) {
242 delete negativeNumberRule;
243 }
244 negativeNumberRule = rules.remove(i);
245 break;
246
247 // if it's the improper fraction rule, copy it into the
248 // correct element of fractionRules
249 case NFRule::kImproperFractionRule:
250 if (fractionRules[0]) {
251 delete fractionRules[0];
252 }
253 fractionRules[0] = rules.remove(i);
254 break;
255
256 // if it's the proper fraction rule, copy it into the
257 // correct element of fractionRules
258 case NFRule::kProperFractionRule:
259 if (fractionRules[1]) {
260 delete fractionRules[1];
261 }
262 fractionRules[1] = rules.remove(i);
263 break;
264
265 // if it's the master rule, copy it into the
266 // correct element of fractionRules
267 case NFRule::kMasterRule:
268 if (fractionRules[2]) {
269 delete fractionRules[2];
270 }
271 fractionRules[2] = rules.remove(i);
272 break;
273
274 // if it's a regular rule that already knows its base value, 246 // if it's a regular rule that already knows its base value,
275 // check to make sure the rules are in order, and update 247 // check to make sure the rules are in order, and update
276 // the default base value for the next rule 248 // the default base value for the next rule
277 default: 249 if (baseValue < defaultBaseValue) {
278 if (rule->getBaseValue() < defaultBaseValue) {
279 // throw new IllegalArgumentException("Rules are not in order"); 250 // throw new IllegalArgumentException("Rules are not in order");
280 status = U_PARSE_ERROR; 251 status = U_PARSE_ERROR;
281 return; 252 return;
282 } 253 }
283 defaultBaseValue = rule->getBaseValue(); 254 defaultBaseValue = baseValue;
284 if (!isFractionRuleSet()) {
285 ++defaultBaseValue;
286 }
287 ++i;
288 break;
289 } 255 }
256 if (!fIsFractionRuleSet) {
257 ++defaultBaseValue;
258 }
259 }
260 }
261
262 /**
263 * Set one of the non-numerical rules.
264 * @param rule The rule to set.
265 */
266 void NFRuleSet::setNonNumericalRule(NFRule *rule) {
267 int64_t baseValue = rule->getBaseValue();
268 if (baseValue == NFRule::kNegativeNumberRule) {
269 delete nonNumericalRules[NEGATIVE_RULE_INDEX];
270 nonNumericalRules[NEGATIVE_RULE_INDEX] = rule;
271 }
272 else if (baseValue == NFRule::kImproperFractionRule) {
273 setBestFractionRule(IMPROPER_FRACTION_RULE_INDEX, rule, TRUE);
274 }
275 else if (baseValue == NFRule::kProperFractionRule) {
276 setBestFractionRule(PROPER_FRACTION_RULE_INDEX, rule, TRUE);
277 }
278 else if (baseValue == NFRule::kMasterRule) {
279 setBestFractionRule(MASTER_RULE_INDEX, rule, TRUE);
280 }
281 else if (baseValue == NFRule::kInfinityRule) {
282 delete nonNumericalRules[INFINITY_RULE_INDEX];
283 nonNumericalRules[INFINITY_RULE_INDEX] = rule;
284 }
285 else if (baseValue == NFRule::kNaNRule) {
286 delete nonNumericalRules[NAN_RULE_INDEX];
287 nonNumericalRules[NAN_RULE_INDEX] = rule;
288 }
289 }
290
291 /**
292 * Determine the best fraction rule to use. Rules matching the decimal point fro m
293 * DecimalFormatSymbols become the main set of rules to use.
294 * @param originalIndex The index into nonNumericalRules
295 * @param newRule The new rule to consider
296 * @param rememberRule Should the new rule be added to fractionRules.
297 */
298 void NFRuleSet::setBestFractionRule(int32_t originalIndex, NFRule *newRule, UBoo l rememberRule) {
299 if (rememberRule) {
300 fractionRules.add(newRule);
301 }
302 NFRule *bestResult = nonNumericalRules[originalIndex];
303 if (bestResult == NULL) {
304 nonNumericalRules[originalIndex] = newRule;
305 }
306 else {
307 // We have more than one. Which one is better?
308 const DecimalFormatSymbols *decimalFormatSymbols = owner->getDecimalForm atSymbols();
309 if (decimalFormatSymbols->getSymbol(DecimalFormatSymbols::kDecimalSepara torSymbol).charAt(0)
310 == newRule->getDecimalPoint())
311 {
312 nonNumericalRules[originalIndex] = newRule;
313 }
314 // else leave it alone
290 } 315 }
291 } 316 }
292 317
293 NFRuleSet::~NFRuleSet() 318 NFRuleSet::~NFRuleSet()
294 { 319 {
295 delete negativeNumberRule; 320 for (int i = 0; i < NON_NUMERICAL_RULE_LENGTH; i++) {
296 delete fractionRules[0]; 321 if (i != IMPROPER_FRACTION_RULE_INDEX
297 delete fractionRules[1]; 322 && i != PROPER_FRACTION_RULE_INDEX
298 delete fractionRules[2]; 323 && i != MASTER_RULE_INDEX)
324 {
325 delete nonNumericalRules[i];
326 }
327 // else it will be deleted via NFRuleList fractionRules
328 }
299 } 329 }
300 330
301 static UBool 331 static UBool
302 util_equalRules(const NFRule* rule1, const NFRule* rule2) 332 util_equalRules(const NFRule* rule1, const NFRule* rule2)
303 { 333 {
304 if (rule1) { 334 if (rule1) {
305 if (rule2) { 335 if (rule2) {
306 return *rule1 == *rule2; 336 return *rule1 == *rule2;
307 } 337 }
308 } else if (!rule2) { 338 } else if (!rule2) {
309 return TRUE; 339 return TRUE;
310 } 340 }
311 return FALSE; 341 return FALSE;
312 } 342 }
313 343
314 UBool 344 UBool
315 NFRuleSet::operator==(const NFRuleSet& rhs) const 345 NFRuleSet::operator==(const NFRuleSet& rhs) const
316 { 346 {
317 if (rules.size() == rhs.rules.size() && 347 if (rules.size() == rhs.rules.size() &&
318 fIsFractionRuleSet == rhs.fIsFractionRuleSet && 348 fIsFractionRuleSet == rhs.fIsFractionRuleSet &&
319 name == rhs.name && 349 name == rhs.name) {
320 util_equalRules(negativeNumberRule, rhs.negativeNumberRule) &&
321 util_equalRules(fractionRules[0], rhs.fractionRules[0]) &&
322 util_equalRules(fractionRules[1], rhs.fractionRules[1]) &&
323 util_equalRules(fractionRules[2], rhs.fractionRules[2])) {
324 350
351 // ...then compare the non-numerical rule lists...
352 for (int i = 0; i < NON_NUMERICAL_RULE_LENGTH; i++) {
353 if (!util_equalRules(nonNumericalRules[i], rhs.nonNumericalRules[i]) ) {
354 return FALSE;
355 }
356 }
357
358 // ...then compare the rule lists...
325 for (uint32_t i = 0; i < rules.size(); ++i) { 359 for (uint32_t i = 0; i < rules.size(); ++i) {
326 if (*rules[i] != *rhs.rules[i]) { 360 if (*rules[i] != *rhs.rules[i]) {
327 return FALSE; 361 return FALSE;
328 } 362 }
329 } 363 }
330 return TRUE; 364 return TRUE;
331 } 365 }
332 return FALSE; 366 return FALSE;
333 } 367 }
334 368
335 #define RECURSION_LIMIT 50 369 void
370 NFRuleSet::setDecimalFormatSymbols(const DecimalFormatSymbols &newSymbols, UErro rCode& status) {
371 for (uint32_t i = 0; i < rules.size(); ++i) {
372 rules[i]->setDecimalFormatSymbols(newSymbols, status);
373 }
374 // Switch the fraction rules to mirror the DecimalFormatSymbols.
375 for (int32_t nonNumericalIdx = IMPROPER_FRACTION_RULE_INDEX; nonNumericalIdx <= MASTER_RULE_INDEX; nonNumericalIdx++) {
376 if (nonNumericalRules[nonNumericalIdx]) {
377 for (uint32_t fIdx = 0; fIdx < fractionRules.size(); fIdx++) {
378 NFRule *fractionRule = fractionRules[fIdx];
379 if (nonNumericalRules[nonNumericalIdx]->getBaseValue() == fracti onRule->getBaseValue()) {
380 setBestFractionRule(nonNumericalIdx, fractionRule, FALSE);
381 }
382 }
383 }
384 }
336 385
337 void 386 for (uint32_t nnrIdx = 0; nnrIdx < NON_NUMERICAL_RULE_LENGTH; nnrIdx++) {
338 NFRuleSet::format(int64_t number, UnicodeString& toAppendTo, int32_t pos, UError Code& status) const 387 NFRule *rule = nonNumericalRules[nnrIdx];
339 { 388 if (rule) {
340 NFRule *rule = findNormalRule(number); 389 rule->setDecimalFormatSymbols(newSymbols, status);
341 if (rule) { // else error, but can't report it
342 NFRuleSet* ncThis = (NFRuleSet*)this;
343 if (ncThis->fRecursionCount++ >= RECURSION_LIMIT) {
344 // stop recursion
345 ncThis->fRecursionCount = 0;
346 } else {
347 rule->doFormat(number, toAppendTo, pos, status);
348 ncThis->fRecursionCount--;
349 } 390 }
350 } 391 }
351 } 392 }
352 393
394 #define RECURSION_LIMIT 64
395
353 void 396 void
354 NFRuleSet::format(double number, UnicodeString& toAppendTo, int32_t pos, UErrorC ode& status) const 397 NFRuleSet::format(int64_t number, UnicodeString& toAppendTo, int32_t pos, int32_ t recursionCount, UErrorCode& status) const
355 { 398 {
356 NFRule *rule = findDoubleRule(number); 399 if (recursionCount >= RECURSION_LIMIT) {
400 // stop recursion
401 status = U_INVALID_STATE_ERROR;
402 return;
403 }
404 const NFRule *rule = findNormalRule(number);
357 if (rule) { // else error, but can't report it 405 if (rule) { // else error, but can't report it
358 NFRuleSet* ncThis = (NFRuleSet*)this; 406 rule->doFormat(number, toAppendTo, pos, ++recursionCount, status);
359 if (ncThis->fRecursionCount++ >= RECURSION_LIMIT) {
360 // stop recursion
361 ncThis->fRecursionCount = 0;
362 } else {
363 rule->doFormat(number, toAppendTo, pos, status);
364 ncThis->fRecursionCount--;
365 }
366 } 407 }
367 } 408 }
368 409
369 NFRule* 410 void
411 NFRuleSet::format(double number, UnicodeString& toAppendTo, int32_t pos, int32_t recursionCount, UErrorCode& status) const
412 {
413 if (recursionCount >= RECURSION_LIMIT) {
414 // stop recursion
415 status = U_INVALID_STATE_ERROR;
416 return;
417 }
418 const NFRule *rule = findDoubleRule(number);
419 if (rule) { // else error, but can't report it
420 rule->doFormat(number, toAppendTo, pos, ++recursionCount, status);
421 }
422 }
423
424 const NFRule*
370 NFRuleSet::findDoubleRule(double number) const 425 NFRuleSet::findDoubleRule(double number) const
371 { 426 {
372 // if this is a fraction rule set, use findFractionRuleSetRule() 427 // if this is a fraction rule set, use findFractionRuleSetRule()
373 if (isFractionRuleSet()) { 428 if (isFractionRuleSet()) {
374 return findFractionRuleSetRule(number); 429 return findFractionRuleSetRule(number);
375 } 430 }
376 431
432 if (uprv_isNaN(number)) {
433 const NFRule *rule = nonNumericalRules[NAN_RULE_INDEX];
434 if (!rule) {
435 rule = owner->getDefaultNaNRule();
436 }
437 return rule;
438 }
439
377 // if the number is negative, return the negative number rule 440 // if the number is negative, return the negative number rule
378 // (if there isn't a negative-number rule, we pretend it's a 441 // (if there isn't a negative-number rule, we pretend it's a
379 // positive number) 442 // positive number)
380 if (number < 0) { 443 if (number < 0) {
381 if (negativeNumberRule) { 444 if (nonNumericalRules[NEGATIVE_RULE_INDEX]) {
382 return negativeNumberRule; 445 return nonNumericalRules[NEGATIVE_RULE_INDEX];
383 } else { 446 } else {
384 number = -number; 447 number = -number;
385 } 448 }
386 } 449 }
387 450
451 if (uprv_isInfinite(number)) {
452 const NFRule *rule = nonNumericalRules[INFINITY_RULE_INDEX];
453 if (!rule) {
454 rule = owner->getDefaultInfinityRule();
455 }
456 return rule;
457 }
458
388 // if the number isn't an integer, we use one of the fraction rules... 459 // if the number isn't an integer, we use one of the fraction rules...
389 if (number != uprv_floor(number)) { 460 if (number != uprv_floor(number)) {
390 // if the number is between 0 and 1, return the proper 461 // if the number is between 0 and 1, return the proper
391 // fraction rule 462 // fraction rule
392 if (number < 1 && fractionRules[1]) { 463 if (number < 1 && nonNumericalRules[PROPER_FRACTION_RULE_INDEX]) {
393 return fractionRules[1]; 464 return nonNumericalRules[PROPER_FRACTION_RULE_INDEX];
394 } 465 }
395 // otherwise, return the improper fraction rule 466 // otherwise, return the improper fraction rule
396 else if (fractionRules[0]) { 467 else if (nonNumericalRules[IMPROPER_FRACTION_RULE_INDEX]) {
397 return fractionRules[0]; 468 return nonNumericalRules[IMPROPER_FRACTION_RULE_INDEX];
398 } 469 }
399 } 470 }
400 471
401 // if there's a master rule, use it to format the number 472 // if there's a master rule, use it to format the number
402 if (fractionRules[2]) { 473 if (nonNumericalRules[MASTER_RULE_INDEX]) {
403 return fractionRules[2]; 474 return nonNumericalRules[MASTER_RULE_INDEX];
404 } 475 }
405 476
406 // and if we haven't yet returned a rule, use findNormalRule() 477 // and if we haven't yet returned a rule, use findNormalRule()
407 // to find the applicable rule 478 // to find the applicable rule
408 int64_t r = util64_fromDouble(number + 0.5); 479 int64_t r = util64_fromDouble(number + 0.5);
409 return findNormalRule(r); 480 return findNormalRule(r);
410 } 481 }
411 482
412 NFRule * 483 const NFRule *
413 NFRuleSet::findNormalRule(int64_t number) const 484 NFRuleSet::findNormalRule(int64_t number) const
414 { 485 {
415 // if this is a fraction rule set, use findFractionRuleSetRule() 486 // if this is a fraction rule set, use findFractionRuleSetRule()
416 // to find the rule (we should only go into this clause if the 487 // to find the rule (we should only go into this clause if the
417 // value is 0) 488 // value is 0)
418 if (fIsFractionRuleSet) { 489 if (fIsFractionRuleSet) {
419 return findFractionRuleSetRule((double)number); 490 return findFractionRuleSetRule((double)number);
420 } 491 }
421 492
422 // if the number is negative, return the negative-number rule 493 // if the number is negative, return the negative-number rule
423 // (if there isn't one, pretend the number is positive) 494 // (if there isn't one, pretend the number is positive)
424 if (number < 0) { 495 if (number < 0) {
425 if (negativeNumberRule) { 496 if (nonNumericalRules[NEGATIVE_RULE_INDEX]) {
426 return negativeNumberRule; 497 return nonNumericalRules[NEGATIVE_RULE_INDEX];
427 } else { 498 } else {
428 number = -number; 499 number = -number;
429 } 500 }
430 } 501 }
431 502
432 // we have to repeat the preceding two checks, even though we 503 // we have to repeat the preceding two checks, even though we
433 // do them in findRule(), because the version of format() that 504 // do them in findRule(), because the version of format() that
434 // takes a long bypasses findRule() and goes straight to this 505 // takes a long bypasses findRule() and goes straight to this
435 // function. This function does skip the fraction rules since 506 // function. This function does skip the fraction rules since
436 // we know the value is an integer (it also skips the master 507 // we know the value is an integer (it also skips the master
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 // return 544 // return
474 if (result->shouldRollBack((double)number)) { 545 if (result->shouldRollBack((double)number)) {
475 if (hi == 1) { // bad rule set, no prior rule to rollback to from th is base 546 if (hi == 1) { // bad rule set, no prior rule to rollback to from th is base
476 return NULL; 547 return NULL;
477 } 548 }
478 result = rules[hi - 2]; 549 result = rules[hi - 2];
479 } 550 }
480 return result; 551 return result;
481 } 552 }
482 // else use the master rule 553 // else use the master rule
483 return fractionRules[2]; 554 return nonNumericalRules[MASTER_RULE_INDEX];
484 } 555 }
485 556
486 /** 557 /**
487 * If this rule is a fraction rule set, this function is used by 558 * If this rule is a fraction rule set, this function is used by
488 * findRule() to select the most appropriate rule for formatting 559 * findRule() to select the most appropriate rule for formatting
489 * the number. Basically, the base value of each rule in the rule 560 * the number. Basically, the base value of each rule in the rule
490 * set is treated as the denominator of a fraction. Whichever 561 * set is treated as the denominator of a fraction. Whichever
491 * denominator can produce the fraction closest in value to the 562 * denominator can produce the fraction closest in value to the
492 * number passed in is the result. If there's a tie, the earlier 563 * number passed in is the result. If there's a tie, the earlier
493 * one in the list wins. (If there are two rules in a row with the 564 * one in the list wins. (If there are two rules in a row with the
494 * same base value, the first one is used when the numerator of the 565 * same base value, the first one is used when the numerator of the
495 * fraction would be 1, and the second rule is used the rest of the 566 * fraction would be 1, and the second rule is used the rest of the
496 * time. 567 * time.
497 * @param number The number being formatted (which will always be 568 * @param number The number being formatted (which will always be
498 * a number between 0 and 1) 569 * a number between 0 and 1)
499 * @return The rule to use to format this number 570 * @return The rule to use to format this number
500 */ 571 */
501 NFRule* 572 const NFRule*
502 NFRuleSet::findFractionRuleSetRule(double number) const 573 NFRuleSet::findFractionRuleSetRule(double number) const
503 { 574 {
504 // the obvious way to do this (multiply the value being formatted 575 // the obvious way to do this (multiply the value being formatted
505 // by each rule's base value until you get an integral result) 576 // by each rule's base value until you get an integral result)
506 // doesn't work because of rounding error. This method is more 577 // doesn't work because of rounding error. This method is more
507 // accurate 578 // accurate
508 579
509 // find the least common multiple of the rules' base values 580 // find the least common multiple of the rules' base values
510 // and multiply this by the number being formatted. This is 581 // and multiply this by the number being formatted. This is
511 // all the precision we need, and we can do all of the rest 582 // all the precision we need, and we can do all of the rest
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 ParsePosition workingPos = pos; 695 ParsePosition workingPos = pos;
625 696
626 #ifdef RBNF_DEBUG 697 #ifdef RBNF_DEBUG
627 fprintf(stderr, "<nfrs> %x '", this); 698 fprintf(stderr, "<nfrs> %x '", this);
628 dumpUS(stderr, name); 699 dumpUS(stderr, name);
629 fprintf(stderr, "' text '"); 700 fprintf(stderr, "' text '");
630 dumpUS(stderr, text); 701 dumpUS(stderr, text);
631 fprintf(stderr, "'\n"); 702 fprintf(stderr, "'\n");
632 fprintf(stderr, " parse negative: %d\n", this, negativeNumberRule != 0); 703 fprintf(stderr, " parse negative: %d\n", this, negativeNumberRule != 0);
633 #endif 704 #endif
634 705 // Try each of the negative rules, fraction rules, infinity rules and NaN ru les
635 // start by trying the negative number rule (if there is one) 706 for (int i = 0; i < NON_NUMERICAL_RULE_LENGTH; i++) {
636 if (negativeNumberRule) { 707 if (nonNumericalRules[i]) {
637 Formattable tempResult; 708 Formattable tempResult;
638 #ifdef RBNF_DEBUG 709 UBool success = nonNumericalRules[i]->doParse(text, workingPos, 0, u pperBound, tempResult);
639 fprintf(stderr, " <nfrs before negative> %x ub: %g\n", negativeNumberRu le, upperBound); 710 if (success && (workingPos.getIndex() > highWaterMark.getIndex())) {
640 #endif 711 result = tempResult;
641 UBool success = negativeNumberRule->doParse(text, workingPos, 0, upperBo und, tempResult); 712 highWaterMark = workingPos;
642 #ifdef RBNF_DEBUG
643 fprintf(stderr, " <nfrs after negative> success: %d wpi: %d\n", success , workingPos.getIndex());
644 #endif
645 if (success && workingPos.getIndex() > highWaterMark.getIndex()) {
646 result = tempResult;
647 highWaterMark = workingPos;
648 }
649 workingPos = pos;
650 }
651 #ifdef RBNF_DEBUG
652 fprintf(stderr, "<nfrs> continue fractional with text '");
653 dumpUS(stderr, text);
654 fprintf(stderr, "' hwm: %d\n", highWaterMark.getIndex());
655 #endif
656 // then try each of the fraction rules
657 {
658 for (int i = 0; i < 3; i++) {
659 if (fractionRules[i]) {
660 Formattable tempResult;
661 UBool success = fractionRules[i]->doParse(text, workingPos, 0, u pperBound, tempResult);
662 if (success && (workingPos.getIndex() > highWaterMark.getIndex() )) {
663 result = tempResult;
664 highWaterMark = workingPos;
665 }
666 workingPos = pos;
667 } 713 }
714 workingPos = pos;
668 } 715 }
669 } 716 }
670 #ifdef RBNF_DEBUG 717 #ifdef RBNF_DEBUG
671 fprintf(stderr, "<nfrs> continue other with text '"); 718 fprintf(stderr, "<nfrs> continue other with text '");
672 dumpUS(stderr, text); 719 dumpUS(stderr, text);
673 fprintf(stderr, "' hwm: %d\n", highWaterMark.getIndex()); 720 fprintf(stderr, "' hwm: %d\n", highWaterMark.getIndex());
674 #endif 721 #endif
675 722
676 // finally, go through the regular rules one at a time. We start 723 // finally, go through the regular rules one at a time. We start
677 // at the end of the list because we want to try matching the most 724 // at the end of the list because we want to try matching the most
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 // first character we didn't use, and return the result that 760 // first character we didn't use, and return the result that
714 // corresponds to that string of characters 761 // corresponds to that string of characters
715 pos = highWaterMark; 762 pos = highWaterMark;
716 763
717 return 1; 764 return 1;
718 } 765 }
719 766
720 void 767 void
721 NFRuleSet::appendRules(UnicodeString& result) const 768 NFRuleSet::appendRules(UnicodeString& result) const
722 { 769 {
770 uint32_t i;
771
723 // the rule set name goes first... 772 // the rule set name goes first...
724 result.append(name); 773 result.append(name);
725 result.append(gColon); 774 result.append(gColon);
726 result.append(gLineFeed); 775 result.append(gLineFeed);
727 776
728 // followed by the regular rules... 777 // followed by the regular rules...
729 for (uint32_t i = 0; i < rules.size(); i++) { 778 for (i = 0; i < rules.size(); i++) {
730 result.append(gFourSpaces, 4);
731 rules[i]->_appendRuleText(result); 779 rules[i]->_appendRuleText(result);
732 result.append(gLineFeed); 780 result.append(gLineFeed);
733 } 781 }
734 782
735 // followed by the special rules (if they exist) 783 // followed by the special rules (if they exist)
736 if (negativeNumberRule) { 784 for (i = 0; i < NON_NUMERICAL_RULE_LENGTH; ++i) {
737 result.append(gFourSpaces, 4); 785 NFRule *rule = nonNumericalRules[i];
738 negativeNumberRule->_appendRuleText(result); 786 if (nonNumericalRules[i]) {
739 result.append(gLineFeed); 787 if (rule->getBaseValue() == NFRule::kImproperFractionRule
740 } 788 || rule->getBaseValue() == NFRule::kProperFractionRule
741 789 || rule->getBaseValue() == NFRule::kMasterRule)
742 { 790 {
743 for (uint32_t i = 0; i < 3; ++i) { 791 for (uint32_t fIdx = 0; fIdx < fractionRules.size(); fIdx++) {
744 if (fractionRules[i]) { 792 NFRule *fractionRule = fractionRules[fIdx];
745 result.append(gFourSpaces, 4); 793 if (fractionRule->getBaseValue() == rule->getBaseValue()) {
746 fractionRules[i]->_appendRuleText(result); 794 fractionRule->_appendRuleText(result);
795 result.append(gLineFeed);
796 }
797 }
798 }
799 else {
800 rule->_appendRuleText(result);
747 result.append(gLineFeed); 801 result.append(gLineFeed);
748 } 802 }
749 } 803 }
750 } 804 }
751 } 805 }
752 806
753 // utility functions 807 // utility functions
754 808
755 int64_t util64_fromDouble(double d) { 809 int64_t util64_fromDouble(double d) {
756 int64_t result = 0; 810 int64_t result = 0;
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
962 1016
963 return len; 1017 return len;
964 } 1018 }
965 1019
966 1020
967 U_NAMESPACE_END 1021 U_NAMESPACE_END
968 1022
969 /* U_HAVE_RBNF */ 1023 /* U_HAVE_RBNF */
970 #endif 1024 #endif
971 1025
OLDNEW
« no previous file with comments | « source/i18n/nfrs.h ('k') | source/i18n/nfrule.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698