michael@0: /* michael@0: ******************************************************************************* michael@0: * Copyright (C) 1997-2013, International Business Machines Corporation and others. michael@0: * All Rights Reserved. michael@0: ******************************************************************************* michael@0: */ michael@0: michael@0: #ifndef RBNF_H michael@0: #define RBNF_H michael@0: michael@0: #include "unicode/utypes.h" michael@0: michael@0: /** michael@0: * \file michael@0: * \brief C++ API: Rule Based Number Format michael@0: */ michael@0: michael@0: /** michael@0: * \def U_HAVE_RBNF michael@0: * This will be 0 if RBNF support is not included in ICU michael@0: * and 1 if it is. michael@0: * michael@0: * @stable ICU 2.4 michael@0: */ michael@0: #if UCONFIG_NO_FORMATTING michael@0: #define U_HAVE_RBNF 0 michael@0: #else michael@0: #define U_HAVE_RBNF 1 michael@0: michael@0: #include "unicode/coll.h" michael@0: #include "unicode/dcfmtsym.h" michael@0: #include "unicode/fmtable.h" michael@0: #include "unicode/locid.h" michael@0: #include "unicode/numfmt.h" michael@0: #include "unicode/unistr.h" michael@0: #include "unicode/strenum.h" michael@0: michael@0: U_NAMESPACE_BEGIN michael@0: michael@0: class NFRuleSet; michael@0: class LocalizationInfo; michael@0: michael@0: /** michael@0: * Tags for the predefined rulesets. michael@0: * michael@0: * @stable ICU 2.2 michael@0: */ michael@0: enum URBNFRuleSetTag { michael@0: URBNF_SPELLOUT, michael@0: URBNF_ORDINAL, michael@0: URBNF_DURATION, michael@0: URBNF_NUMBERING_SYSTEM, michael@0: URBNF_COUNT michael@0: }; michael@0: michael@0: #if UCONFIG_NO_COLLATION michael@0: class Collator; michael@0: #endif michael@0: michael@0: /** michael@0: * The RuleBasedNumberFormat class formats numbers according to a set of rules. This number formatter is michael@0: * typically used for spelling out numeric values in words (e.g., 25,3476 as michael@0: * "twenty-five thousand three hundred seventy-six" or "vingt-cinq mille trois michael@0: * cents soixante-seize" or michael@0: * "fünfundzwanzigtausenddreihundertsechsundsiebzig"), but can also be used for michael@0: * other complicated formatting tasks, such as formatting a number of seconds as hours, michael@0: * minutes and seconds (e.g., 3,730 as "1:02:10"). michael@0: * michael@0: *

The resources contain three predefined formatters for each locale: spellout, which michael@0: * spells out a value in words (123 is "one hundred twenty-three"); ordinal, which michael@0: * appends an ordinal suffix to the end of a numeral (123 is "123rd"); and michael@0: * duration, which shows a duration in seconds as hours, minutes, and seconds (123 is michael@0: * "2:03").  The client can also define more specialized RuleBasedNumberFormats michael@0: * by supplying programmer-defined rule sets.

michael@0: * michael@0: *

The behavior of a RuleBasedNumberFormat is specified by a textual description michael@0: * that is either passed to the constructor as a String or loaded from a resource michael@0: * bundle. In its simplest form, the description consists of a semicolon-delimited list of rules. michael@0: * Each rule has a string of output text and a value or range of values it is applicable to. michael@0: * In a typical spellout rule set, the first twenty rules are the words for the numbers from michael@0: * 0 to 19:

michael@0: * michael@0: *
zero; one; two; three; four; five; six; seven; eight; nine;
michael@0:  * ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen; seventeen; eighteen; nineteen;
michael@0: * michael@0: *

For larger numbers, we can use the preceding set of rules to format the ones place, and michael@0: * we only have to supply the words for the multiples of 10:

michael@0: * michael@0: *
 20: twenty[->>];
michael@0:  * 30: thirty[->>];
michael@0:  * 40: forty[->>];
michael@0:  * 50: fifty[->>];
michael@0:  * 60: sixty[->>];
michael@0:  * 70: seventy[->>];
michael@0:  * 80: eighty[->>];
michael@0:  * 90: ninety[->>];
michael@0: * michael@0: *

In these rules, the base value is spelled out explicitly and set off from the michael@0: * rule's output text with a colon. The rules are in a sorted list, and a rule is applicable michael@0: * to all numbers from its own base value to one less than the next rule's base value. The michael@0: * ">>" token is called a substitution and tells the fomatter to michael@0: * isolate the number's ones digit, format it using this same set of rules, and place the michael@0: * result at the position of the ">>" token. Text in brackets is omitted if michael@0: * the number being formatted is an even multiple of 10 (the hyphen is a literal hyphen; 24 michael@0: * is "twenty-four," not "twenty four").

michael@0: * michael@0: *

For even larger numbers, we can actually look up several parts of the number in the michael@0: * list:

michael@0: * michael@0: *
100: << hundred[ >>];
michael@0: * michael@0: *

The "<<" represents a new kind of substitution. The << isolates michael@0: * the hundreds digit (and any digits to its left), formats it using this same rule set, and michael@0: * places the result where the "<<" was. Notice also that the meaning of michael@0: * >> has changed: it now refers to both the tens and the ones digits. The meaning of michael@0: * both substitutions depends on the rule's base value. The base value determines the rule's divisor, michael@0: * which is the highest power of 10 that is less than or equal to the base value (the user michael@0: * can change this). To fill in the substitutions, the formatter divides the number being michael@0: * formatted by the divisor. The integral quotient is used to fill in the << michael@0: * substitution, and the remainder is used to fill in the >> substitution. The meaning michael@0: * of the brackets changes similarly: text in brackets is omitted if the value being michael@0: * formatted is an even multiple of the rule's divisor. The rules are applied recursively, so michael@0: * if a substitution is filled in with text that includes another substitution, that michael@0: * substitution is also filled in.

michael@0: * michael@0: *

This rule covers values up to 999, at which point we add another rule:

michael@0: * michael@0: *
1000: << thousand[ >>];
michael@0: * michael@0: *

Again, the meanings of the brackets and substitution tokens shift because the rule's michael@0: * base value is a higher power of 10, changing the rule's divisor. This rule can actually be michael@0: * used all the way up to 999,999. This allows us to finish out the rules as follows:

michael@0: * michael@0: *
 1,000,000: << million[ >>];
michael@0:  * 1,000,000,000: << billion[ >>];
michael@0:  * 1,000,000,000,000: << trillion[ >>];
michael@0:  * 1,000,000,000,000,000: OUT OF RANGE!;
michael@0: * michael@0: *

Commas, periods, and spaces can be used in the base values to improve legibility and michael@0: * are ignored by the rule parser. The last rule in the list is customarily treated as an michael@0: * "overflow rule," applying to everything from its base value on up, and often (as michael@0: * in this example) being used to print out an error message or default representation. michael@0: * Notice also that the size of the major groupings in large numbers is controlled by the michael@0: * spacing of the rules: because in English we group numbers by thousand, the higher rules michael@0: * are separated from each other by a factor of 1,000.

michael@0: * michael@0: *

To see how these rules actually work in practice, consider the following example: michael@0: * Formatting 25,430 with this rule set would work like this:

michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: *
<< thousand >>[the rule whose base value is 1,000 is applicable to 25,340]
twenty->> thousand >>[25,340 over 1,000 is 25. The rule for 20 applies.]
twenty-five thousand >>[25 mod 10 is 5. The rule for 5 is "five."
twenty-five thousand << hundred >>[25,340 mod 1,000 is 340. The rule for 100 applies.]
twenty-five thousand three hundred >>[340 over 100 is 3. The rule for 3 is "three."]
twenty-five thousand three hundred forty[340 mod 100 is 40. The rule for 40 applies. Since 40 divides michael@0: * evenly by 10, the hyphen and substitution in the brackets are omitted.]
michael@0: * michael@0: *

The above syntax suffices only to format positive integers. To format negative numbers, michael@0: * we add a special rule:

michael@0: * michael@0: *
-x: minus >>;
michael@0: * michael@0: *

This is called a negative-number rule, and is identified by "-x" michael@0: * where the base value would be. This rule is used to format all negative numbers. the michael@0: * >> token here means "find the number's absolute value, format it with these michael@0: * rules, and put the result here."

michael@0: * michael@0: *

We also add a special rule called a fraction rule for numbers with fractional michael@0: * parts:

michael@0: * michael@0: *
x.x: << point >>;
michael@0: * michael@0: *

This rule is used for all positive non-integers (negative non-integers pass through the michael@0: * negative-number rule first and then through this rule). Here, the << token refers to michael@0: * the number's integral part, and the >> to the number's fractional part. The michael@0: * fractional part is formatted as a series of single-digit numbers (e.g., 123.456 would be michael@0: * formatted as "one hundred twenty-three point four five six").

michael@0: * michael@0: *

To see how this rule syntax is applied to various languages, examine the resource data.

michael@0: * michael@0: *

There is actually much more flexibility built into the rule language than the michael@0: * description above shows. A formatter may own multiple rule sets, which can be selected by michael@0: * the caller, and which can use each other to fill in their substitutions. Substitutions can michael@0: * also be filled in with digits, using a DecimalFormat object. There is syntax that can be michael@0: * used to alter a rule's divisor in various ways. And there is provision for much more michael@0: * flexible fraction handling. A complete description of the rule syntax follows:

michael@0: * michael@0: *
michael@0: * michael@0: *

The description of a RuleBasedNumberFormat's behavior consists of one or more rule michael@0: * sets. Each rule set consists of a name, a colon, and a list of rules. A rule michael@0: * set name must begin with a % sign. Rule sets with names that begin with a single % sign michael@0: * are public: the caller can specify that they be used to format and parse numbers. michael@0: * Rule sets with names that begin with %% are private: they exist only for the use michael@0: * of other rule sets. If a formatter only has one rule set, the name may be omitted.

michael@0: * michael@0: *

The user can also specify a special "rule set" named %%lenient-parse. michael@0: * The body of %%lenient-parse isn't a set of number-formatting rules, but a RuleBasedCollator michael@0: * description which is used to define equivalences for lenient parsing. For more information michael@0: * on the syntax, see RuleBasedCollator. For more information on lenient parsing, michael@0: * see setLenientParse(). Note: symbols that have syntactic meaning michael@0: * in collation rules, such as '&', have no particular meaning when appearing outside michael@0: * of the lenient-parse rule set.

michael@0: * michael@0: *

The body of a rule set consists of an ordered, semicolon-delimited list of rules. michael@0: * Internally, every rule has a base value, a divisor, rule text, and zero, one, or two substitutions. michael@0: * These parameters are controlled by the description syntax, which consists of a rule michael@0: * descriptor, a colon, and a rule body.

michael@0: * michael@0: *

A rule descriptor can take one of the following forms (text in italics is the michael@0: * name of a token):

michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: *
bv:bv specifies the rule's base value. bv is a decimal michael@0: * number expressed using ASCII digits. bv may contain spaces, period, and commas, michael@0: * which are ignored. The rule's divisor is the highest power of 10 less than or equal to michael@0: * the base value.
bv/rad:bv specifies the rule's base value. The rule's divisor is the michael@0: * highest power of rad less than or equal to the base value.
bv>:bv specifies the rule's base value. To calculate the divisor, michael@0: * let the radix be 10, and the exponent be the highest exponent of the radix that yields a michael@0: * result less than or equal to the base value. Every > character after the base value michael@0: * decreases the exponent by 1. If the exponent is positive or 0, the divisor is the radix michael@0: * raised to the power of the exponent; otherwise, the divisor is 1.
bv/rad>:bv specifies the rule's base value. To calculate the divisor, michael@0: * let the radix be rad, and the exponent be the highest exponent of the radix that michael@0: * yields a result less than or equal to the base value. Every > character after the radix michael@0: * decreases the exponent by 1. If the exponent is positive or 0, the divisor is the radix michael@0: * raised to the power of the exponent; otherwise, the divisor is 1.
-x:The rule is a negative-number rule.
x.x:The rule is an improper fraction rule.
0.x:The rule is a proper fraction rule.
x.0:The rule is a master rule.
nothingIf the rule's rule descriptor is left out, the base value is one plus the michael@0: * preceding rule's base value (or zero if this is the first rule in the list) in a normal michael@0: * rule set.  In a fraction rule set, the base value is the same as the preceding rule's michael@0: * base value.
michael@0: * michael@0: *

A rule set may be either a regular rule set or a fraction rule set, depending michael@0: * on whether it is used to format a number's integral part (or the whole number) or a michael@0: * number's fractional part. Using a rule set to format a rule's fractional part makes it a michael@0: * fraction rule set.

michael@0: * michael@0: *

Which rule is used to format a number is defined according to one of the following michael@0: * algorithms: If the rule set is a regular rule set, do the following: michael@0: * michael@0: *

michael@0: * michael@0: *

If the rule set is a fraction rule set, do the following: michael@0: * michael@0: *

michael@0: * michael@0: *

A rule's body consists of a string of characters terminated by a semicolon. The rule michael@0: * may include zero, one, or two substitution tokens, and a range of text in michael@0: * brackets. The brackets denote optional text (and may also include one or both michael@0: * substitutions). The exact meanings of the substitution tokens, and under what conditions michael@0: * optional text is omitted, depend on the syntax of the substitution token and the context. michael@0: * The rest of the text in a rule body is literal text that is output when the rule matches michael@0: * the number being formatted.

michael@0: * michael@0: *

A substitution token begins and ends with a token character. The token michael@0: * character and the context together specify a mathematical operation to be performed on the michael@0: * number being formatted. An optional substitution descriptor specifies how the michael@0: * value resulting from that operation is used to fill in the substitution. The position of michael@0: * the substitution token in the rule body specifies the location of the resultant text in michael@0: * the original rule text.

michael@0: * michael@0: *

The meanings of the substitution token characters are as follows:

michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: *
>>in normal ruleDivide the number by the rule's divisor and format the remainder
in negative-number ruleFind the absolute value of the number and format the result
in fraction or master ruleIsolate the number's fractional part and format it.
in rule in fraction rule setNot allowed.
>>>in normal ruleDivide the number by the rule's divisor and format the remainder, michael@0: * but bypass the normal rule-selection process and just use the michael@0: * rule that precedes this one in this rule list.
in all other rulesNot allowed.
<<in normal ruleDivide the number by the rule's divisor and format the quotient
in negative-number ruleNot allowed.
in fraction or master ruleIsolate the number's integral part and format it.
in rule in fraction rule setMultiply the number by the rule's base value and format the result.
==in all rule setsFormat the number unchanged
[]in normal ruleOmit the optional text if the number is an even multiple of the rule's divisor
in negative-number ruleNot allowed.
in improper-fraction ruleOmit the optional text if the number is between 0 and 1 (same as specifying both an michael@0: * x.x rule and a 0.x rule)
in master ruleOmit the optional text if the number is an integer (same as specifying both an x.x michael@0: * rule and an x.0 rule)
in proper-fraction ruleNot allowed.
in rule in fraction rule setOmit the optional text if multiplying the number by the rule's base value yields 1.
michael@0: * michael@0: *

The substitution descriptor (i.e., the text between the token characters) may take one michael@0: * of three forms:

michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: * michael@0: *
a rule set namePerform the mathematical operation on the number, and format the result using the michael@0: * named rule set.
a DecimalFormat patternPerform the mathematical operation on the number, and format the result using a michael@0: * DecimalFormat with the specified pattern.  The pattern must begin with 0 or #.
nothingPerform the mathematical operation on the number, and format the result using the rule michael@0: * set containing the current rule, except: michael@0: *
    michael@0: *
  • You can't have an empty substitution descriptor with a == substitution.
  • michael@0: *
  • If you omit the substitution descriptor in a >> substitution in a fraction rule, michael@0: * format the result one digit at a time using the rule set containing the current rule.
  • michael@0: *
  • If you omit the substitution descriptor in a << substitution in a rule in a michael@0: * fraction rule set, format the result using the default rule set for this formatter.
  • michael@0: *
michael@0: *
michael@0: * michael@0: *

Whitespace is ignored between a rule set name and a rule set body, between a rule michael@0: * descriptor and a rule body, or between rules. If a rule body begins with an apostrophe, michael@0: * the apostrophe is ignored, but all text after it becomes significant (this is how you can michael@0: * have a rule's rule text begin with whitespace). There is no escape function: the semicolon michael@0: * is not allowed in rule set names or in rule text, and the colon is not allowed in rule set michael@0: * names. The characters beginning a substitution token are always treated as the beginning michael@0: * of a substitution token.

michael@0: * michael@0: *

See the resource data and the demo program for annotated examples of real rule sets michael@0: * using these features.

michael@0: * michael@0: *

User subclasses are not supported. While clients may write michael@0: * subclasses, such code will not necessarily work and will not be michael@0: * guaranteed to work stably from release to release. michael@0: * michael@0: *

Localizations

michael@0: *

Constructors are available that allow the specification of localizations for the michael@0: * public rule sets (and also allow more control over what public rule sets are available). michael@0: * Localization data is represented as a textual description. The description represents michael@0: * an array of arrays of string. The first element is an array of the public rule set names, michael@0: * each of these must be one of the public rule set names that appear in the rules. Only michael@0: * names in this array will be treated as public rule set names by the API. Each subsequent michael@0: * element is an array of localizations of these names. The first element of one of these michael@0: * subarrays is the locale name, and the remaining elements are localizations of the michael@0: * public rule set names, in the same order as they were listed in the first arrray.

michael@0: *

In the syntax, angle brackets '<', '>' are used to delimit the arrays, and comma ',' is used michael@0: * to separate elements of an array. Whitespace is ignored, unless quoted.

michael@0: *

For example:

michael@0:  * < < %foo, %bar, %baz >,
michael@0:  *   < en, Foo, Bar, Baz >,
michael@0:  *   < fr, 'le Foo', 'le Bar', 'le Baz' >
michael@0:  *   < zh, \\u7532, \\u4e59, \\u4e19 > >
michael@0:  * 

michael@0: * @author Richard Gillam michael@0: * @see NumberFormat michael@0: * @see DecimalFormat michael@0: * @stable ICU 2.0 michael@0: */ michael@0: class U_I18N_API RuleBasedNumberFormat : public NumberFormat { michael@0: public: michael@0: michael@0: //----------------------------------------------------------------------- michael@0: // constructors michael@0: //----------------------------------------------------------------------- michael@0: michael@0: /** michael@0: * Creates a RuleBasedNumberFormat that behaves according to the description michael@0: * passed in. The formatter uses the default locale. michael@0: * @param rules A description of the formatter's desired behavior. michael@0: * See the class documentation for a complete explanation of the description michael@0: * syntax. michael@0: * @param perror The parse error if an error was encountered. michael@0: * @param status The status indicating whether the constructor succeeded. michael@0: * @stable ICU 3.2 michael@0: */ michael@0: RuleBasedNumberFormat(const UnicodeString& rules, UParseError& perror, UErrorCode& status); michael@0: michael@0: /** michael@0: * Creates a RuleBasedNumberFormat that behaves according to the description michael@0: * passed in. The formatter uses the default locale. michael@0: *

michael@0: * The localizations data provides information about the public michael@0: * rule sets and their localized display names for different michael@0: * locales. The first element in the list is an array of the names michael@0: * of the public rule sets. The first element in this array is michael@0: * the initial default ruleset. The remaining elements in the michael@0: * list are arrays of localizations of the names of the public michael@0: * rule sets. Each of these is one longer than the initial array, michael@0: * with the first String being the ULocale ID, and the remaining michael@0: * Strings being the localizations of the rule set names, in the michael@0: * same order as the initial array. Arrays are NULL-terminated. michael@0: * @param rules A description of the formatter's desired behavior. michael@0: * See the class documentation for a complete explanation of the description michael@0: * syntax. michael@0: * @param localizations the localization information. michael@0: * names in the description. These will be copied by the constructor. michael@0: * @param perror The parse error if an error was encountered. michael@0: * @param status The status indicating whether the constructor succeeded. michael@0: * @stable ICU 3.2 michael@0: */ michael@0: RuleBasedNumberFormat(const UnicodeString& rules, const UnicodeString& localizations, michael@0: UParseError& perror, UErrorCode& status); michael@0: michael@0: /** michael@0: * Creates a RuleBasedNumberFormat that behaves according to the rules michael@0: * passed in. The formatter uses the specified locale to determine the michael@0: * characters to use when formatting numerals, and to define equivalences michael@0: * for lenient parsing. michael@0: * @param rules The formatter rules. michael@0: * See the class documentation for a complete explanation of the rule michael@0: * syntax. michael@0: * @param locale A locale that governs which characters are used for michael@0: * formatting values in numerals and which characters are equivalent in michael@0: * lenient parsing. michael@0: * @param perror The parse error if an error was encountered. michael@0: * @param status The status indicating whether the constructor succeeded. michael@0: * @stable ICU 2.0 michael@0: */ michael@0: RuleBasedNumberFormat(const UnicodeString& rules, const Locale& locale, michael@0: UParseError& perror, UErrorCode& status); michael@0: michael@0: /** michael@0: * Creates a RuleBasedNumberFormat that behaves according to the description michael@0: * passed in. The formatter uses the default locale. michael@0: *

michael@0: * The localizations data provides information about the public michael@0: * rule sets and their localized display names for different michael@0: * locales. The first element in the list is an array of the names michael@0: * of the public rule sets. The first element in this array is michael@0: * the initial default ruleset. The remaining elements in the michael@0: * list are arrays of localizations of the names of the public michael@0: * rule sets. Each of these is one longer than the initial array, michael@0: * with the first String being the ULocale ID, and the remaining michael@0: * Strings being the localizations of the rule set names, in the michael@0: * same order as the initial array. Arrays are NULL-terminated. michael@0: * @param rules A description of the formatter's desired behavior. michael@0: * See the class documentation for a complete explanation of the description michael@0: * syntax. michael@0: * @param localizations a list of localizations for the rule set michael@0: * names in the description. These will be copied by the constructor. michael@0: * @param locale A locale that governs which characters are used for michael@0: * formatting values in numerals and which characters are equivalent in michael@0: * lenient parsing. michael@0: * @param perror The parse error if an error was encountered. michael@0: * @param status The status indicating whether the constructor succeeded. michael@0: * @stable ICU 3.2 michael@0: */ michael@0: RuleBasedNumberFormat(const UnicodeString& rules, const UnicodeString& localizations, michael@0: const Locale& locale, UParseError& perror, UErrorCode& status); michael@0: michael@0: /** michael@0: * Creates a RuleBasedNumberFormat from a predefined ruleset. The selector michael@0: * code choosed among three possible predefined formats: spellout, ordinal, michael@0: * and duration. michael@0: * @param tag A selector code specifying which kind of formatter to create for that michael@0: * locale. There are four legal values: URBNF_SPELLOUT, which creates a formatter that michael@0: * spells out a value in words in the desired language, URBNF_ORDINAL, which attaches michael@0: * an ordinal suffix from the desired language to the end of a number (e.g. "123rd"), michael@0: * URBNF_DURATION, which formats a duration in seconds as hours, minutes, and seconds, michael@0: * and URBNF_NUMBERING_SYSTEM, which is used to invoke rules for alternate numbering michael@0: * systems such as the Hebrew numbering system, or for Roman Numerals, etc. michael@0: * @param locale The locale for the formatter. michael@0: * @param status The status indicating whether the constructor succeeded. michael@0: * @stable ICU 2.0 michael@0: */ michael@0: RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale& locale, UErrorCode& status); michael@0: michael@0: //----------------------------------------------------------------------- michael@0: // boilerplate michael@0: //----------------------------------------------------------------------- michael@0: michael@0: /** michael@0: * Copy constructor michael@0: * @param rhs the object to be copied from. michael@0: * @stable ICU 2.6 michael@0: */ michael@0: RuleBasedNumberFormat(const RuleBasedNumberFormat& rhs); michael@0: michael@0: /** michael@0: * Assignment operator michael@0: * @param rhs the object to be copied from. michael@0: * @stable ICU 2.6 michael@0: */ michael@0: RuleBasedNumberFormat& operator=(const RuleBasedNumberFormat& rhs); michael@0: michael@0: /** michael@0: * Release memory allocated for a RuleBasedNumberFormat when you are finished with it. michael@0: * @stable ICU 2.6 michael@0: */ michael@0: virtual ~RuleBasedNumberFormat(); michael@0: michael@0: /** michael@0: * Clone this object polymorphically. The caller is responsible michael@0: * for deleting the result when done. michael@0: * @return A copy of the object. michael@0: * @stable ICU 2.6 michael@0: */ michael@0: virtual Format* clone(void) const; michael@0: michael@0: /** michael@0: * Return true if the given Format objects are semantically equal. michael@0: * Objects of different subclasses are considered unequal. michael@0: * @param other the object to be compared with. michael@0: * @return true if the given Format objects are semantically equal. michael@0: * @stable ICU 2.6 michael@0: */ michael@0: virtual UBool operator==(const Format& other) const; michael@0: michael@0: //----------------------------------------------------------------------- michael@0: // public API functions michael@0: //----------------------------------------------------------------------- michael@0: michael@0: /** michael@0: * return the rules that were provided to the RuleBasedNumberFormat. michael@0: * @return the result String that was passed in michael@0: * @stable ICU 2.0 michael@0: */ michael@0: virtual UnicodeString getRules() const; michael@0: michael@0: /** michael@0: * Return the number of public rule set names. michael@0: * @return the number of public rule set names. michael@0: * @stable ICU 2.0 michael@0: */ michael@0: virtual int32_t getNumberOfRuleSetNames() const; michael@0: michael@0: /** michael@0: * Return the name of the index'th public ruleSet. If index is not valid, michael@0: * the function returns null. michael@0: * @param index the index of the ruleset michael@0: * @return the name of the index'th public ruleSet. michael@0: * @stable ICU 2.0 michael@0: */ michael@0: virtual UnicodeString getRuleSetName(int32_t index) const; michael@0: michael@0: /** michael@0: * Return the number of locales for which we have localized rule set display names. michael@0: * @return the number of locales for which we have localized rule set display names. michael@0: * @stable ICU 3.2 michael@0: */ michael@0: virtual int32_t getNumberOfRuleSetDisplayNameLocales(void) const; michael@0: michael@0: /** michael@0: * Return the index'th display name locale. michael@0: * @param index the index of the locale michael@0: * @param status set to a failure code when this function fails michael@0: * @return the locale michael@0: * @see #getNumberOfRuleSetDisplayNameLocales michael@0: * @stable ICU 3.2 michael@0: */ michael@0: virtual Locale getRuleSetDisplayNameLocale(int32_t index, UErrorCode& status) const; michael@0: michael@0: /** michael@0: * Return the rule set display names for the provided locale. These are in the same order michael@0: * as those returned by getRuleSetName. The locale is matched against the locales for michael@0: * which there is display name data, using normal fallback rules. If no locale matches, michael@0: * the default display names are returned. (These are the internal rule set names minus michael@0: * the leading '%'.) michael@0: * @param index the index of the rule set michael@0: * @param locale the locale (returned by getRuleSetDisplayNameLocales) for which the localized michael@0: * display name is desired michael@0: * @return the display name for the given index, which might be bogus if there is an error michael@0: * @see #getRuleSetName michael@0: * @stable ICU 3.2 michael@0: */ michael@0: virtual UnicodeString getRuleSetDisplayName(int32_t index, michael@0: const Locale& locale = Locale::getDefault()); michael@0: michael@0: /** michael@0: * Return the rule set display name for the provided rule set and locale. michael@0: * The locale is matched against the locales for which there is display name data, using michael@0: * normal fallback rules. If no locale matches, the default display name is returned. michael@0: * @return the display name for the rule set michael@0: * @stable ICU 3.2 michael@0: * @see #getRuleSetDisplayName michael@0: */ michael@0: virtual UnicodeString getRuleSetDisplayName(const UnicodeString& ruleSetName, michael@0: const Locale& locale = Locale::getDefault()); michael@0: michael@0: michael@0: using NumberFormat::format; michael@0: michael@0: /** michael@0: * Formats the specified 32-bit number using the default ruleset. michael@0: * @param number The number to format. michael@0: * @param toAppendTo the string that will hold the (appended) result michael@0: * @param pos the fieldposition michael@0: * @return A textual representation of the number. michael@0: * @stable ICU 2.0 michael@0: */ michael@0: virtual UnicodeString& format(int32_t number, michael@0: UnicodeString& toAppendTo, michael@0: FieldPosition& pos) const; michael@0: michael@0: /** michael@0: * Formats the specified 64-bit number using the default ruleset. michael@0: * @param number The number to format. michael@0: * @param toAppendTo the string that will hold the (appended) result michael@0: * @param pos the fieldposition michael@0: * @return A textual representation of the number. michael@0: * @stable ICU 2.1 michael@0: */ michael@0: virtual UnicodeString& format(int64_t number, michael@0: UnicodeString& toAppendTo, michael@0: FieldPosition& pos) const; michael@0: /** michael@0: * Formats the specified number using the default ruleset. michael@0: * @param number The number to format. michael@0: * @param toAppendTo the string that will hold the (appended) result michael@0: * @param pos the fieldposition michael@0: * @return A textual representation of the number. michael@0: * @stable ICU 2.0 michael@0: */ michael@0: virtual UnicodeString& format(double number, michael@0: UnicodeString& toAppendTo, michael@0: FieldPosition& pos) const; michael@0: michael@0: /** michael@0: * Formats the specified number using the named ruleset. michael@0: * @param number The number to format. michael@0: * @param ruleSetName The name of the rule set to format the number with. michael@0: * This must be the name of a valid public rule set for this formatter. michael@0: * @param toAppendTo the string that will hold the (appended) result michael@0: * @param pos the fieldposition michael@0: * @param status the status michael@0: * @return A textual representation of the number. michael@0: * @stable ICU 2.0 michael@0: */ michael@0: virtual UnicodeString& format(int32_t number, michael@0: const UnicodeString& ruleSetName, michael@0: UnicodeString& toAppendTo, michael@0: FieldPosition& pos, michael@0: UErrorCode& status) const; michael@0: /** michael@0: * Formats the specified 64-bit number using the named ruleset. michael@0: * @param number The number to format. michael@0: * @param ruleSetName The name of the rule set to format the number with. michael@0: * This must be the name of a valid public rule set for this formatter. michael@0: * @param toAppendTo the string that will hold the (appended) result michael@0: * @param pos the fieldposition michael@0: * @param status the status michael@0: * @return A textual representation of the number. michael@0: * @stable ICU 2.1 michael@0: */ michael@0: virtual UnicodeString& format(int64_t number, michael@0: const UnicodeString& ruleSetName, michael@0: UnicodeString& toAppendTo, michael@0: FieldPosition& pos, michael@0: UErrorCode& status) const; michael@0: /** michael@0: * Formats the specified number using the named ruleset. michael@0: * @param number The number to format. michael@0: * @param ruleSetName The name of the rule set to format the number with. michael@0: * This must be the name of a valid public rule set for this formatter. michael@0: * @param toAppendTo the string that will hold the (appended) result michael@0: * @param pos the fieldposition michael@0: * @param status the status michael@0: * @return A textual representation of the number. michael@0: * @stable ICU 2.0 michael@0: */ michael@0: virtual UnicodeString& format(double number, michael@0: const UnicodeString& ruleSetName, michael@0: UnicodeString& toAppendTo, michael@0: FieldPosition& pos, michael@0: UErrorCode& status) const; michael@0: michael@0: using NumberFormat::parse; michael@0: michael@0: /** michael@0: * Parses the specfied string, beginning at the specified position, according michael@0: * to this formatter's rules. This will match the string against all of the michael@0: * formatter's public rule sets and return the value corresponding to the longest michael@0: * parseable substring. This function's behavior is affected by the lenient michael@0: * parse mode. michael@0: * @param text The string to parse michael@0: * @param result the result of the parse, either a double or a long. michael@0: * @param parsePosition On entry, contains the position of the first character michael@0: * in "text" to examine. On exit, has been updated to contain the position michael@0: * of the first character in "text" that wasn't consumed by the parse. michael@0: * @see #setLenient michael@0: * @stable ICU 2.0 michael@0: */ michael@0: virtual void parse(const UnicodeString& text, michael@0: Formattable& result, michael@0: ParsePosition& parsePosition) const; michael@0: michael@0: #if !UCONFIG_NO_COLLATION michael@0: michael@0: /** michael@0: * Turns lenient parse mode on and off. michael@0: * michael@0: * When in lenient parse mode, the formatter uses a Collator for parsing the text. michael@0: * Only primary differences are treated as significant. This means that case michael@0: * differences, accent differences, alternate spellings of the same letter michael@0: * (e.g., ae and a-umlaut in German), ignorable characters, etc. are ignored in michael@0: * matching the text. In many cases, numerals will be accepted in place of words michael@0: * or phrases as well. michael@0: * michael@0: * For example, all of the following will correctly parse as 255 in English in michael@0: * lenient-parse mode: michael@0: *
"two hundred fifty-five" michael@0: *
"two hundred fifty five" michael@0: *
"TWO HUNDRED FIFTY-FIVE" michael@0: *
"twohundredfiftyfive" michael@0: *
"2 hundred fifty-5" michael@0: * michael@0: * The Collator used is determined by the locale that was michael@0: * passed to this object on construction. The description passed to this object michael@0: * on construction may supply additional collation rules that are appended to the michael@0: * end of the default collator for the locale, enabling additional equivalences michael@0: * (such as adding more ignorable characters or permitting spelled-out version of michael@0: * symbols; see the demo program for examples). michael@0: * michael@0: * It's important to emphasize that even strict parsing is relatively lenient: it michael@0: * will accept some text that it won't produce as output. In English, for example, michael@0: * it will correctly parse "two hundred zero" and "fifteen hundred". michael@0: * michael@0: * @param enabled If true, turns lenient-parse mode on; if false, turns it off. michael@0: * @see RuleBasedCollator michael@0: * @stable ICU 2.0 michael@0: */ michael@0: virtual void setLenient(UBool enabled); michael@0: michael@0: /** michael@0: * Returns true if lenient-parse mode is turned on. Lenient parsing is off michael@0: * by default. michael@0: * @return true if lenient-parse mode is turned on. michael@0: * @see #setLenient michael@0: * @stable ICU 2.0 michael@0: */ michael@0: virtual inline UBool isLenient(void) const; michael@0: michael@0: #endif michael@0: michael@0: /** michael@0: * Override the default rule set to use. If ruleSetName is null, reset michael@0: * to the initial default rule set. If the rule set is not a public rule set name, michael@0: * U_ILLEGAL_ARGUMENT_ERROR is returned in status. michael@0: * @param ruleSetName the name of the rule set, or null to reset the initial default. michael@0: * @param status set to failure code when a problem occurs. michael@0: * @stable ICU 2.6 michael@0: */ michael@0: virtual void setDefaultRuleSet(const UnicodeString& ruleSetName, UErrorCode& status); michael@0: michael@0: /** michael@0: * Return the name of the current default rule set. If the current rule set is michael@0: * not public, returns a bogus (and empty) UnicodeString. michael@0: * @return the name of the current default rule set michael@0: * @stable ICU 3.0 michael@0: */ michael@0: virtual UnicodeString getDefaultRuleSetName() const; michael@0: michael@0: public: michael@0: /** michael@0: * ICU "poor man's RTTI", returns a UClassID for this class. michael@0: * michael@0: * @stable ICU 2.8 michael@0: */ michael@0: static UClassID U_EXPORT2 getStaticClassID(void); michael@0: michael@0: /** michael@0: * ICU "poor man's RTTI", returns a UClassID for the actual class. michael@0: * michael@0: * @stable ICU 2.8 michael@0: */ michael@0: virtual UClassID getDynamicClassID(void) const; michael@0: michael@0: /** michael@0: * Sets the decimal format symbols, which is generally not changed michael@0: * by the programmer or user. The formatter takes ownership of michael@0: * symbolsToAdopt; the client must not delete it. michael@0: * michael@0: * @param symbolsToAdopt DecimalFormatSymbols to be adopted. michael@0: * @stable ICU 49 michael@0: */ michael@0: virtual void adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt); michael@0: michael@0: /** michael@0: * Sets the decimal format symbols, which is generally not changed michael@0: * by the programmer or user. A clone of the symbols is created and michael@0: * the symbols is _not_ adopted; the client is still responsible for michael@0: * deleting it. michael@0: * michael@0: * @param symbols DecimalFormatSymbols. michael@0: * @stable ICU 49 michael@0: */ michael@0: virtual void setDecimalFormatSymbols(const DecimalFormatSymbols& symbols); michael@0: michael@0: private: michael@0: RuleBasedNumberFormat(); // default constructor not implemented michael@0: michael@0: // this will ref the localizations if they are not NULL michael@0: // caller must deref to get adoption michael@0: RuleBasedNumberFormat(const UnicodeString& description, LocalizationInfo* localizations, michael@0: const Locale& locale, UParseError& perror, UErrorCode& status); michael@0: michael@0: void init(const UnicodeString& rules, LocalizationInfo* localizations, UParseError& perror, UErrorCode& status); michael@0: void dispose(); michael@0: void stripWhitespace(UnicodeString& src); michael@0: void initDefaultRuleSet(); michael@0: void format(double number, NFRuleSet& ruleSet); michael@0: NFRuleSet* findRuleSet(const UnicodeString& name, UErrorCode& status) const; michael@0: michael@0: /* friend access */ michael@0: friend class NFSubstitution; michael@0: friend class NFRule; michael@0: friend class FractionalPartSubstitution; michael@0: michael@0: inline NFRuleSet * getDefaultRuleSet() const; michael@0: Collator * getCollator() const; michael@0: DecimalFormatSymbols * getDecimalFormatSymbols() const; michael@0: michael@0: private: michael@0: NFRuleSet **ruleSets; michael@0: UnicodeString* ruleSetDescriptions; michael@0: int32_t numRuleSets; michael@0: NFRuleSet *defaultRuleSet; michael@0: Locale locale; michael@0: Collator* collator; michael@0: DecimalFormatSymbols* decimalFormatSymbols; michael@0: UBool lenient; michael@0: UnicodeString* lenientParseRules; michael@0: LocalizationInfo* localizations; michael@0: }; michael@0: michael@0: // --------------- michael@0: michael@0: #if !UCONFIG_NO_COLLATION michael@0: michael@0: inline UBool michael@0: RuleBasedNumberFormat::isLenient(void) const { michael@0: return lenient; michael@0: } michael@0: michael@0: #endif michael@0: michael@0: inline NFRuleSet* michael@0: RuleBasedNumberFormat::getDefaultRuleSet() const { michael@0: return defaultRuleSet; michael@0: } michael@0: michael@0: U_NAMESPACE_END michael@0: michael@0: /* U_HAVE_RBNF */ michael@0: #endif michael@0: michael@0: /* RBNF_H */ michael@0: #endif