2 ******************************************************************************
3 * Copyright (C) 1997-2004, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 ******************************************************************************
8 * tab size: 8 (not used)
11 * Modification history
13 * 10/11/2001 Doug Ported from ICU4J
19 #include "unicode/utypes.h"
20 #include "unicode/uobject.h"
25 #include "unicode/utypes.h"
26 #include "unicode/decimfmt.h"
32 class NFSubstitution
: public UObject
{
34 const NFRuleSet
* ruleSet
;
35 const DecimalFormat
* numberFormat
;
38 NFSubstitution(int32_t pos
,
39 const NFRuleSet
* ruleSet
,
40 const RuleBasedNumberFormat
* rbnf
,
41 const UnicodeString
& description
,
45 * Get the Ruleset of the object.
46 * @return the Ruleset of the object.
48 const NFRuleSet
* getRuleSet() const { return ruleSet
; }
51 * get the NumberFormat of this object.
52 * @return the numberformat of this object.
54 const DecimalFormat
* getNumberFormat() const { return numberFormat
; }
57 static NFSubstitution
* makeSubstitution(int32_t pos
,
59 const NFRule
* predecessor
,
60 const NFRuleSet
* ruleSet
,
61 const RuleBasedNumberFormat
* rbnf
,
62 const UnicodeString
& description
,
68 virtual ~NFSubstitution();
71 * Return true if the given Format objects are semantically equal.
72 * Objects of different subclasses are considered unequal.
73 * @param rhs the object to be compared with.
74 * @return true if the given Format objects are semantically equal.
76 virtual UBool
operator==(const NFSubstitution
& rhs
) const;
79 * Return true if the given Format objects are semantically unequal.
80 * Objects of different subclasses are considered unequal.
81 * @param rhs the object to be compared with.
82 * @return true if the given Format objects are semantically unequal.
84 UBool
operator!=(const NFSubstitution
& rhs
) const { return !operator==(rhs
); }
87 * Sets the substitution's divisor. Used by NFRule.setBaseValue().
88 * A no-op for all substitutions except multiplier and modulus
90 * @param radix The radix of the divisor
91 * @param exponent The exponent of the divisor
93 virtual void setDivisor(int32_t radix
, int32_t exponent
, UErrorCode
& status
);
96 * Replaces result with the string describing the substitution.
97 * @param result Output param which will receive the string.
99 virtual void toString(UnicodeString
& result
) const;
101 //-----------------------------------------------------------------------
103 //-----------------------------------------------------------------------
106 * Performs a mathematical operation on the number, formats it using
107 * either ruleSet or decimalFormat, and inserts the result into
109 * @param number The number being formatted.
110 * @param toInsertInto The string we insert the result into
111 * @param pos The position in toInsertInto where the owning rule's
112 * rule text begins (this value is added to this substitution's
113 * position to determine exactly where to insert the new text)
115 virtual void doSubstitution(int64_t number
, UnicodeString
& toInsertInto
, int32_t pos
) const;
118 * Performs a mathematical operation on the number, formats it using
119 * either ruleSet or decimalFormat, and inserts the result into
121 * @param number The number being formatted.
122 * @param toInsertInto The string we insert the result into
123 * @param pos The position in toInsertInto where the owning rule's
124 * rule text begins (this value is added to this substitution's
125 * position to determine exactly where to insert the new text)
127 virtual void doSubstitution(double number
, UnicodeString
& toInsertInto
, int32_t pos
) const;
131 * Subclasses override this function to perform some kind of
132 * mathematical operation on the number. The result of this operation
133 * is formatted using the rule set or DecimalFormat that this
134 * substitution refers to, and the result is inserted into the result
136 * @param The number being formatted
137 * @return The result of performing the opreration on the number
139 virtual int64_t transformNumber(int64_t number
) const = 0;
142 * Subclasses override this function to perform some kind of
143 * mathematical operation on the number. The result of this operation
144 * is formatted using the rule set or DecimalFormat that this
145 * substitution refers to, and the result is inserted into the result
147 * @param The number being formatted
148 * @return The result of performing the opreration on the number
150 virtual double transformNumber(double number
) const = 0;
153 //-----------------------------------------------------------------------
155 //-----------------------------------------------------------------------
158 * Parses a string using the rule set or DecimalFormat belonging
159 * to this substitution. If there's a match, a mathematical
160 * operation (the inverse of the one used in formatting) is
161 * performed on the result of the parse and the value passed in
162 * and returned as the result. The parse position is updated to
163 * point to the first unmatched character in the string.
164 * @param text The string to parse
165 * @param parsePosition On entry, ignored, but assumed to be 0.
166 * On exit, this is updated to point to the first unmatched
167 * character (or 0 if the substitution didn't match)
168 * @param baseValue A partial parse result that should be
169 * combined with the result of this parse
170 * @param upperBound When searching the rule set for a rule
171 * matching the string passed in, only rules with base values
172 * lower than this are considered
173 * @param lenientParse If true and matching against rules fails,
174 * the substitution will also try matching the text against
175 * numerals using a default-costructed NumberFormat. If false,
176 * no extra work is done. (This value is false whenever the
177 * formatter isn't in lenient-parse mode, but is also false
178 * under some conditions even when the formatter _is_ in
179 * lenient-parse mode.)
180 * @return If there's a match, this is the result of composing
181 * baseValue with whatever was returned from matching the
182 * characters. This will be either a Long or a Double. If there's
183 * no match this is new Long(0) (not null), and parsePosition
186 virtual UBool
doParse(const UnicodeString
& text
,
187 ParsePosition
& parsePosition
,
191 Formattable
& result
) const;
194 * Derives a new value from the two values passed in. The two values
195 * are typically either the base values of two rules (the one containing
196 * the substitution and the one matching the substitution) or partial
197 * parse results derived in some other way. The operation is generally
198 * the inverse of the operation performed by transformNumber().
199 * @param newRuleValue The value produced by matching this substitution
200 * @param oldRuleValue The value that was passed to the substitution
201 * by the rule that owns it
202 * @return A third value derived from the other two, representing a
203 * partial parse result
205 virtual double composeRuleValue(double newRuleValue
, double oldRuleValue
) const = 0;
208 * Calculates an upper bound when searching for a rule that matches
209 * this substitution. Rules with base values greater than or equal
210 * to upperBound are not considered.
211 * @param oldUpperBound The current upper-bound setting. The new
212 * upper bound can't be any higher.
213 * @return the upper bound when searching for a rule that matches
216 virtual double calcUpperBound(double oldUpperBound
) const = 0;
218 //-----------------------------------------------------------------------
220 //-----------------------------------------------------------------------
223 * Returns the substitution's position in the rule that owns it.
224 * @return The substitution's position in the rule that owns it.
226 int32_t getPos() const { return pos
; }
229 * Returns the character used in the textual representation of
230 * substitutions of this type. Used by toString().
231 * @return This substitution's token character.
233 virtual UChar
tokenChar() const = 0;
236 * Returns true if this is a null substitution. (We didn't do this
237 * with instanceof partially because it causes source files to
238 * proliferate and partially because we have to port this to C++.)
239 * @return true if this object is an instance of NullSubstitution
241 virtual UBool
isNullSubstitution() const;
244 * Returns true if this is a modulus substitution. (We didn't do this
245 * with instanceof partially because it causes source files to
246 * proliferate and partially because we have to port this to C++.)
247 * @return true if this object is an instance of ModulusSubstitution
249 virtual UBool
isModulusSubstitution() const;
252 NFSubstitution(const NFSubstitution
&other
); // forbid copying of this class
253 NFSubstitution
&operator=(const NFSubstitution
&other
); // forbid copying of this class
255 static const char fgClassID
;
258 static UClassID
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
259 virtual UClassID
getDynamicClassID(void) const;
262 class SameValueSubstitution
: public NFSubstitution
{
264 SameValueSubstitution(int32_t pos
,
265 const NFRuleSet
* ruleset
,
266 const RuleBasedNumberFormat
* formatter
,
267 const UnicodeString
& description
,
270 virtual int64_t transformNumber(int64_t number
) const { return number
; }
271 virtual double transformNumber(double number
) const { return number
; }
272 virtual double composeRuleValue(double newRuleValue
, double /*oldRuleValue*/) const { return newRuleValue
; }
273 virtual double calcUpperBound(double oldUpperBound
) const { return oldUpperBound
; }
274 virtual UChar
tokenChar() const { return (UChar
)0x003d; } // '='
276 static const char fgClassID
;
279 static UClassID
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
280 virtual UClassID
getDynamicClassID(void) const;
283 class MultiplierSubstitution
: public NFSubstitution
{
288 MultiplierSubstitution(int32_t _pos
,
290 const NFRuleSet
* _ruleSet
,
291 const RuleBasedNumberFormat
* formatter
,
292 const UnicodeString
& description
,
294 : NFSubstitution(_pos
, _ruleSet
, formatter
, description
, status
), divisor(_divisor
)
296 ldivisor
= util64_fromDouble(divisor
);
298 status
= U_PARSE_ERROR
;
302 virtual void setDivisor(int32_t radix
, int32_t exponent
, UErrorCode
& status
) {
303 divisor
= uprv_pow(radix
, exponent
);
304 ldivisor
= util64_fromDouble(divisor
);
307 status
= U_PARSE_ERROR
;
311 virtual UBool
operator==(const NFSubstitution
& rhs
) const;
313 virtual int64_t transformNumber(int64_t number
) const {
314 return number
/ ldivisor
;
317 virtual double transformNumber(double number
) const {
318 return uprv_floor(number
/ divisor
);
321 virtual double composeRuleValue(double newRuleValue
, double /*oldRuleValue*/) const {
322 return newRuleValue
* divisor
;
325 virtual double calcUpperBound(double /*oldUpperBound*/) const { return divisor
; }
327 virtual UChar
tokenChar() const { return (UChar
)0x003c; } // '<'
329 static const char fgClassID
;
332 static UClassID
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
333 virtual UClassID
getDynamicClassID(void) const;
336 class ModulusSubstitution
: public NFSubstitution
{
339 const NFRule
* ruleToUse
;
341 ModulusSubstitution(int32_t pos
,
343 const NFRule
* rulePredecessor
,
344 const NFRuleSet
* ruleSet
,
345 const RuleBasedNumberFormat
* formatter
,
346 const UnicodeString
& description
,
349 virtual void setDivisor(int32_t radix
, int32_t exponent
, UErrorCode
& status
) {
350 divisor
= uprv_pow(radix
, exponent
);
351 ldivisor
= util64_fromDouble(divisor
);
354 status
= U_PARSE_ERROR
;
358 virtual UBool
operator==(const NFSubstitution
& rhs
) const;
360 virtual void doSubstitution(int64_t number
, UnicodeString
& toInsertInto
, int32_t pos
) const;
361 virtual void doSubstitution(double number
, UnicodeString
& toInsertInto
, int32_t pos
) const;
363 virtual int64_t transformNumber(int64_t number
) const { return number
% ldivisor
; }
364 virtual double transformNumber(double number
) const { return uprv_fmod(number
, divisor
); }
366 virtual UBool
doParse(const UnicodeString
& text
,
367 ParsePosition
& parsePosition
,
371 Formattable
& result
) const;
373 virtual double composeRuleValue(double newRuleValue
, double oldRuleValue
) const {
374 return oldRuleValue
- uprv_fmod(oldRuleValue
, divisor
) + newRuleValue
;
377 virtual double calcUpperBound(double /*oldUpperBound*/) const { return divisor
; }
379 virtual UBool
isModulusSubstitution() const { return TRUE
; }
381 virtual UChar
tokenChar() const { return (UChar
)0x003e; } // '>'
383 static const char fgClassID
;
386 static UClassID
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
387 virtual UClassID
getDynamicClassID(void) const;
390 class IntegralPartSubstitution
: public NFSubstitution
{
392 IntegralPartSubstitution(int32_t _pos
,
393 const NFRuleSet
* _ruleSet
,
394 const RuleBasedNumberFormat
* formatter
,
395 const UnicodeString
& description
,
397 : NFSubstitution(_pos
, _ruleSet
, formatter
, description
, status
) {}
399 virtual int64_t transformNumber(int64_t number
) const { return number
; }
400 virtual double transformNumber(double number
) const { return uprv_floor(number
); }
401 virtual double composeRuleValue(double newRuleValue
, double oldRuleValue
) const { return newRuleValue
+ oldRuleValue
; }
402 virtual double calcUpperBound(double /*oldUpperBound*/) const { return DBL_MAX
; }
403 virtual UChar
tokenChar() const { return (UChar
)0x003c; } // '<'
405 static const char fgClassID
;
408 static UClassID
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
409 virtual UClassID
getDynamicClassID(void) const;
412 class FractionalPartSubstitution
: public NFSubstitution
{
415 enum { kMaxDecimalDigits
= 8 };
417 FractionalPartSubstitution(int32_t pos
,
418 const NFRuleSet
* ruleSet
,
419 const RuleBasedNumberFormat
* formatter
,
420 const UnicodeString
& description
,
423 virtual UBool
operator==(const NFSubstitution
& rhs
) const;
425 virtual void doSubstitution(double number
, UnicodeString
& toInsertInto
, int32_t pos
) const;
426 virtual void doSubstitution(int64_t /*number*/, UnicodeString
& /*toInsertInto*/, int32_t /*_pos*/) const {}
427 virtual int64_t transformNumber(int64_t /*number*/) const { return 0; }
428 virtual double transformNumber(double number
) const { return number
- uprv_floor(number
); }
430 virtual UBool
doParse(const UnicodeString
& text
,
431 ParsePosition
& parsePosition
,
435 Formattable
& result
) const;
437 virtual double composeRuleValue(double newRuleValue
, double oldRuleValue
) const { return newRuleValue
+ oldRuleValue
; }
438 virtual double calcUpperBound(double /*oldUpperBound*/) const { return 0.0; }
439 virtual UChar
tokenChar() const { return (UChar
)0x003e; } // '>'
441 static const char fgClassID
;
444 static UClassID
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
445 virtual UClassID
getDynamicClassID(void) const;
448 class AbsoluteValueSubstitution
: public NFSubstitution
{
450 AbsoluteValueSubstitution(int32_t _pos
,
451 const NFRuleSet
* _ruleSet
,
452 const RuleBasedNumberFormat
* formatter
,
453 const UnicodeString
& description
,
455 : NFSubstitution(_pos
, _ruleSet
, formatter
, description
, status
) {}
457 virtual int64_t transformNumber(int64_t number
) const { return number
>= 0 ? number
: -number
; }
458 virtual double transformNumber(double number
) const { return uprv_fabs(number
); }
459 virtual double composeRuleValue(double newRuleValue
, double /*oldRuleValue*/) const { return -newRuleValue
; }
460 virtual double calcUpperBound(double /*oldUpperBound*/) const { return DBL_MAX
; }
461 virtual UChar
tokenChar() const { return (UChar
)0x003e; } // '>'
463 static const char fgClassID
;
466 static UClassID
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
467 virtual UClassID
getDynamicClassID(void) const;
470 class NumeratorSubstitution
: public NFSubstitution
{
472 int64_t ldenominator
;
474 NumeratorSubstitution(int32_t _pos
,
476 const NFRuleSet
* _ruleSet
,
477 const RuleBasedNumberFormat
* formatter
,
478 const UnicodeString
& description
,
480 : NFSubstitution(_pos
, _ruleSet
, formatter
, description
, status
), denominator(_denominator
)
482 ldenominator
= util64_fromDouble(denominator
);
485 virtual UBool
operator==(const NFSubstitution
& rhs
) const;
487 virtual int64_t transformNumber(int64_t number
) const { return number
* ldenominator
; }
488 virtual double transformNumber(double number
) const { return uprv_round(number
* denominator
); }
490 virtual UBool
doParse(const UnicodeString
& text
,
491 ParsePosition
& parsePosition
,
494 UBool
/*lenientParse*/,
495 Formattable
& result
) const
497 // we don't have to do anything special to do the parsing here,
498 // but we have to turn lenient parsing off-- if we leave it on,
499 // it SERIOUSLY messes up the algorithm
500 return NFSubstitution::doParse(text
, parsePosition
, baseValue
, upperBound
, FALSE
, result
);
502 virtual double composeRuleValue(double newRuleValue
, double oldRuleValue
) const { return newRuleValue
/ oldRuleValue
; }
503 virtual double calcUpperBound(double /*oldUpperBound*/) const { return denominator
; }
504 virtual UChar
tokenChar() const { return (UChar
)0x003c; } // '<'
506 static const char fgClassID
;
509 static UClassID
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
510 virtual UClassID
getDynamicClassID(void) const;
513 class NullSubstitution
: public NFSubstitution
{
515 NullSubstitution(int32_t _pos
,
516 const NFRuleSet
* _ruleSet
,
517 const RuleBasedNumberFormat
* formatter
,
518 const UnicodeString
& description
,
520 : NFSubstitution(_pos
, _ruleSet
, formatter
, description
, status
) {}
522 virtual void toString(UnicodeString
& /*result*/) const {}
523 virtual void doSubstitution(double /*number*/, UnicodeString
& /*toInsertInto*/, int32_t /*_pos*/) const {}
524 virtual void doSubstitution(int64_t /*number*/, UnicodeString
& /*toInsertInto*/, int32_t /*_pos*/) const {}
525 virtual int64_t transformNumber(int64_t /*number*/) const { return 0; }
526 virtual double transformNumber(double /*number*/) const { return 0; }
527 virtual UBool
doParse(const UnicodeString
& /*text*/,
528 ParsePosition
& /*parsePosition*/,
530 double /*upperBound*/,
531 UBool
/*lenientParse*/,
532 Formattable
& result
) const
533 { result
.setDouble(baseValue
); return TRUE
; }
534 virtual double composeRuleValue(double /*newRuleValue*/, double /*oldRuleValue*/) const { return 0.0; } // never called
535 virtual double calcUpperBound(double /*oldUpperBound*/) const { return 0; } // never called
536 virtual UBool
isNullSubstitution() const { return TRUE
; }
537 virtual UChar
tokenChar() const { return (UChar
)0x0020; } // ' ' never called
539 static const char fgClassID
;
542 static UClassID
getStaticClassID(void) { return (UClassID
)&fgClassID
; }
543 virtual UClassID
getDynamicClassID(void) const;