Home | History | Annotate | Download | only in unicode
      1 /*
      2 *******************************************************************************
      3 * Copyright (C) 2008-2013, International Business Machines Corporation and
      4 * others. All Rights Reserved.
      5 *******************************************************************************
      6 *
      7 *
      8 * File PLURRULE.H
      9 *
     10 * Modification History:*
     11 *   Date        Name        Description
     12 *
     13 ********************************************************************************
     14 */
     15 
     16 #ifndef PLURRULE
     17 #define PLURRULE
     18 
     19 #include "unicode/utypes.h"
     20 
     21 /**
     22  * \file
     23  * \brief C++ API: PluralRules object
     24  */
     25 
     26 #if !UCONFIG_NO_FORMATTING
     27 
     28 #include "unicode/format.h"
     29 #include "unicode/upluralrules.h"
     30 
     31 /**
     32  * Value returned by PluralRules::getUniqueKeywordValue() when there is no
     33  * unique value to return.
     34  * @stable ICU 4.8
     35  */
     36 #define UPLRULES_NO_UNIQUE_VALUE ((double)-0.00123456777)
     37 
     38 U_NAMESPACE_BEGIN
     39 
     40 class Hashtable;
     41 class FixedDecimal;
     42 class RuleChain;
     43 class PluralRuleParser;
     44 class PluralKeywordEnumeration;
     45 class AndConstraint;
     46 
     47 /**
     48  * Defines rules for mapping non-negative numeric values onto a small set of
     49  * keywords. Rules are constructed from a text description, consisting
     50  * of a series of keywords and conditions.  The {@link #select} method
     51  * examines each condition in order and returns the keyword for the
     52  * first condition that matches the number.  If none match,
     53  * default rule(other) is returned.
     54  *
     55  * For more information, details, and tips for writing rules, see the
     56  * LDML spec, C.11 Language Plural Rules:
     57  * http://www.unicode.org/draft/reports/tr35/tr35.html#Language_Plural_Rules
     58  *
     59  * Examples:<pre>
     60  *   "one: n is 1; few: n in 2..4"</pre>
     61  *  This defines two rules, for 'one' and 'few'.  The condition for
     62  *  'one' is "n is 1" which means that the number must be equal to
     63  *  1 for this condition to pass.  The condition for 'few' is
     64  *  "n in 2..4" which means that the number must be between 2 and
     65  *  4 inclusive for this condition to pass.  All other numbers
     66  *  are assigned the keyword "other" by the default rule.
     67  *  </p><pre>
     68  *    "zero: n is 0; one: n is 1; zero: n mod 100 in 1..19"</pre>
     69  *  This illustrates that the same keyword can be defined multiple times.
     70  *  Each rule is examined in order, and the first keyword whose condition
     71  *  passes is the one returned.  Also notes that a modulus is applied
     72  *  to n in the last rule.  Thus its condition holds for 119, 219, 319...
     73  *  </p><pre>
     74  *    "one: n is 1; few: n mod 10 in 2..4 and n mod 100 not in 12..14"</pre>
     75  *  This illustrates conjunction and negation.  The condition for 'few'
     76  *  has two parts, both of which must be met: "n mod 10 in 2..4" and
     77  *  "n mod 100 not in 12..14".  The first part applies a modulus to n
     78  *  before the test as in the previous example.  The second part applies
     79  *  a different modulus and also uses negation, thus it matches all
     80  *  numbers _not_ in 12, 13, 14, 112, 113, 114, 212, 213, 214...
     81  *  </p>
     82  *  <p>
     83  * Syntax:<pre>
     84  * \code
     85  * rules         = rule (';' rule)*
     86  * rule          = keyword ':' condition
     87  * keyword       = <identifier>
     88  * condition     = and_condition ('or' and_condition)*
     89  * and_condition = relation ('and' relation)*
     90  * relation      = is_relation | in_relation | within_relation | 'n' <EOL>
     91  * is_relation   = expr 'is' ('not')? value
     92  * in_relation   = expr ('not')? 'in' range_list
     93  * within_relation = expr ('not')? 'within' range
     94  * expr          = ('n' | 'i' | 'f' | 'v' | 'j') ('mod' value)?
     95  * range_list    = (range | value) (',' range_list)*
     96  * value         = digit+  ('.' digit+)?
     97  * digit         = 0|1|2|3|4|5|6|7|8|9
     98  * range         = value'..'value
     99  * \endcode
    100  * </pre></p>
    101  * <p>
    102  * <p>
    103  * The i, f, and v values are defined as follows:
    104  * </p>
    105  * <ul>
    106  * <li>i to be the integer digits.</li>
    107  * <li>f to be the visible fractional digits, as an integer.</li>
    108  * <li>v to be the number of visible fraction digits.</li>
    109  * <li>j is defined to only match integers. That is j is 3 fails if v != 0 (eg for 3.1 or 3.0).</li>
    110  * </ul>
    111  * <p>
    112  * Examples are in the following table:
    113  * </p>
    114  * <table border='1' style="border-collapse:collapse">
    115  * <tbody>
    116  * <tr>
    117  * <th>n</th>
    118  * <th>i</th>
    119  * <th>f</th>
    120  * <th>v</th>
    121  * </tr>
    122  * <tr>
    123  * <td>1.0</td>
    124  * <td>1</td>
    125  * <td align="right">0</td>
    126  * <td>1</td>
    127  * </tr>
    128  * <tr>
    129  * <td>1.00</td>
    130  * <td>1</td>
    131  * <td align="right">0</td>
    132  * <td>2</td>
    133  * </tr>
    134  * <tr>
    135  * <td>1.3</td>
    136  * <td>1</td>
    137  * <td align="right">3</td>
    138  * <td>1</td>
    139  * </tr>
    140  * <tr>
    141  * <td>1.03</td>
    142  * <td>1</td>
    143  * <td align="right">3</td>
    144  * <td>2</td>
    145  * </tr>
    146  * <tr>
    147  * <td>1.23</td>
    148  * <td>1</td>
    149  * <td align="right">23</td>
    150  * <td>2</td>
    151  * </tr>
    152  * </tbody>
    153  * </table>
    154  * <p>
    155  * The difference between 'in' and 'within' is that 'in' only includes integers in the specified range, while 'within'
    156  * includes all values. Using 'within' with a range_list consisting entirely of values is the same as using 'in' (it's
    157  * not an error).
    158  * </p>
    159 
    160  * An "identifier" is a sequence of characters that do not have the
    161  * Unicode Pattern_Syntax or Pattern_White_Space properties.
    162  * <p>
    163  * The difference between 'in' and 'within' is that 'in' only includes
    164  * integers in the specified range, while 'within' includes all values.
    165  * Using 'within' with a range_list consisting entirely of values is the
    166  * same as using 'in' (it's not an error).
    167  *</p>
    168  * <p>
    169  * Keywords
    170  * could be defined by users or from ICU locale data. There are 6
    171  * predefined values in ICU - 'zero', 'one', 'two', 'few', 'many' and
    172  * 'other'. Callers need to check the value of keyword returned by
    173  * {@link #select} method.
    174  * </p>
    175  *
    176  * Examples:<pre>
    177  * UnicodeString keyword = pl->select(number);
    178  * if (keyword== UnicodeString("one") {
    179  *     ...
    180  * }
    181  * else if ( ... )
    182  * </pre>
    183  * <strong>Note:</strong><br>
    184  *  <p>
    185  *   ICU defines plural rules for many locales based on CLDR <i>Language Plural Rules</i>.
    186  *   For these predefined rules, see CLDR page at
    187  *    http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
    188  * </p>
    189  */
    190 class U_I18N_API PluralRules : public UObject {
    191 public:
    192 
    193     /**
    194      * Constructor.
    195      * @param status  Output param set to success/failure code on exit, which
    196      *                must not indicate a failure before the function call.
    197      *
    198      * @stable ICU 4.0
    199      */
    200     PluralRules(UErrorCode& status);
    201 
    202     /**
    203      * Copy constructor.
    204      * @stable ICU 4.0
    205      */
    206     PluralRules(const PluralRules& other);
    207 
    208     /**
    209      * Destructor.
    210      * @stable ICU 4.0
    211      */
    212     virtual ~PluralRules();
    213 
    214     /**
    215      * Clone
    216      * @stable ICU 4.0
    217      */
    218     PluralRules* clone() const;
    219 
    220     /**
    221       * Assignment operator.
    222       * @stable ICU 4.0
    223       */
    224     PluralRules& operator=(const PluralRules&);
    225 
    226     /**
    227      * Creates a PluralRules from a description if it is parsable, otherwise
    228      * returns NULL.
    229      *
    230      * @param description rule description
    231      * @param status      Output param set to success/failure code on exit, which
    232      *                    must not indicate a failure before the function call.
    233      * @return            new PluralRules pointer. NULL if there is an error.
    234      * @stable ICU 4.0
    235      */
    236     static PluralRules* U_EXPORT2 createRules(const UnicodeString& description,
    237                                               UErrorCode& status);
    238 
    239     /**
    240      * The default rules that accept any number.
    241      *
    242      * @param status  Output param set to success/failure code on exit, which
    243      *                must not indicate a failure before the function call.
    244      * @return        new PluralRules pointer. NULL if there is an error.
    245      * @stable ICU 4.0
    246      */
    247     static PluralRules* U_EXPORT2 createDefaultRules(UErrorCode& status);
    248 
    249     /**
    250      * Provides access to the predefined cardinal-number <code>PluralRules</code> for a given
    251      * locale.
    252      * Same as forLocale(locale, UPLURAL_TYPE_CARDINAL, status).
    253      *
    254      * @param locale  The locale for which a <code>PluralRules</code> object is
    255      *                returned.
    256      * @param status  Output param set to success/failure code on exit, which
    257      *                must not indicate a failure before the function call.
    258      * @return        The predefined <code>PluralRules</code> object pointer for
    259      *                this locale. If there's no predefined rules for this locale,
    260      *                the rules for the closest parent in the locale hierarchy
    261      *                that has one will  be returned.  The final fallback always
    262      *                returns the default 'other' rules.
    263      * @stable ICU 4.0
    264      */
    265     static PluralRules* U_EXPORT2 forLocale(const Locale& locale, UErrorCode& status);
    266 
    267     /**
    268      * Provides access to the predefined <code>PluralRules</code> for a given
    269      * locale and the plural type.
    270      *
    271      * @param locale  The locale for which a <code>PluralRules</code> object is
    272      *                returned.
    273      * @param type    The plural type (e.g., cardinal or ordinal).
    274      * @param status  Output param set to success/failure code on exit, which
    275      *                must not indicate a failure before the function call.
    276      * @return        The predefined <code>PluralRules</code> object pointer for
    277      *                this locale. If there's no predefined rules for this locale,
    278      *                the rules for the closest parent in the locale hierarchy
    279      *                that has one will  be returned.  The final fallback always
    280      *                returns the default 'other' rules.
    281      * @stable ICU 50
    282      */
    283     static PluralRules* U_EXPORT2 forLocale(const Locale& locale, UPluralType type, UErrorCode& status);
    284 
    285 #ifndef U_HIDE_INTERNAL_API
    286     /**
    287      * Return a StringEnumeration over the locales for which there is plurals data.
    288      * @return a StringEnumeration over the locales available.
    289      * @internal
    290      */
    291     static StringEnumeration* U_EXPORT2 getAvailableLocales(UErrorCode &status);
    292 
    293     /**
    294      * Returns whether or not there are overrides.
    295      * @param locale       the locale to check.
    296      * @return
    297      * @internal
    298      */
    299     static UBool hasOverride(const Locale &locale);
    300 #endif  /* U_HIDE_INTERNAL_API */
    301 
    302     /**
    303      * Given a number, returns the keyword of the first rule that applies to
    304      * the number.  This function can be used with isKeyword* functions to
    305      * determine the keyword for default plural rules.
    306      *
    307      * @param number  The number for which the rule has to be determined.
    308      * @return        The keyword of the selected rule.
    309      * @stable ICU 4.0
    310      */
    311     UnicodeString select(int32_t number) const;
    312 
    313     /**
    314      * Given a number, returns the keyword of the first rule that applies to
    315      * the number.  This function can be used with isKeyword* functions to
    316      * determine the keyword for default plural rules.
    317      *
    318      * @param number  The number for which the rule has to be determined.
    319      * @return        The keyword of the selected rule.
    320      * @stable ICU 4.0
    321      */
    322     UnicodeString select(double number) const;
    323 
    324 #ifndef U_HIDE_INTERNAL_API
    325     /**
    326       * @internal
    327       */
    328     UnicodeString select(const FixedDecimal &number) const;
    329 #endif  /* U_HIDE_INTERNAL_API */
    330 
    331     /**
    332      * Returns a list of all rule keywords used in this <code>PluralRules</code>
    333      * object.  The rule 'other' is always present by default.
    334      *
    335      * @param status Output param set to success/failure code on exit, which
    336      *               must not indicate a failure before the function call.
    337      * @return       StringEnumeration with the keywords.
    338      *               The caller must delete the object.
    339      * @stable ICU 4.0
    340      */
    341     StringEnumeration* getKeywords(UErrorCode& status) const;
    342 
    343     /**
    344      * Returns a unique value for this keyword if it exists, else the constant
    345      * UPLRULES_NO_UNIQUE_VALUE.
    346      *
    347      * @param keyword The keyword.
    348      * @return        The unique value that generates the keyword, or
    349      *                UPLRULES_NO_UNIQUE_VALUE if the keyword is undefined or there is no
    350      *                unique value that generates this keyword.
    351      * @stable ICU 4.8
    352      */
    353     double getUniqueKeywordValue(const UnicodeString& keyword);
    354 
    355     /**
    356      * Returns all the values for which select() would return the keyword.  If
    357      * the keyword is unknown, returns no values, but this is not an error.  If
    358      * the number of values is unlimited, returns no values and -1 as the
    359      * count.
    360      *
    361      * The number of returned values is typically small.
    362      *
    363      * @param keyword      The keyword.
    364      * @param dest         Array into which to put the returned values.  May
    365      *                     be NULL if destCapacity is 0.
    366      * @param destCapacity The capacity of the array, must be at least 0.
    367      * @param status       The error code.
    368      * @return             The count of values available, or -1.  This count
    369      *                     can be larger than destCapacity, but no more than
    370      *                     destCapacity values will be written.
    371      * @stable ICU 4.8
    372      */
    373     int32_t getAllKeywordValues(const UnicodeString &keyword,
    374                                 double *dest, int32_t destCapacity,
    375                                 UErrorCode& status);
    376 
    377     /**
    378      * Returns sample values for which select() would return the keyword.  If
    379      * the keyword is unknown, returns no values, but this is not an error.
    380      *
    381      * The number of returned values is typically small.
    382      *
    383      * @param keyword      The keyword.
    384      * @param dest         Array into which to put the returned values.  May
    385      *                     be NULL if destCapacity is 0.
    386      * @param destCapacity The capacity of the array, must be at least 0.
    387      * @param status       The error code.
    388      * @return             The count of values written.
    389      *                     If more than destCapacity samples are available, then
    390      *                     only destCapacity are written, and destCapacity is returned as the count,
    391      *                     rather than setting a U_BUFFER_OVERFLOW_ERROR.
    392      *                     (The actual number of keyword values could be unlimited.)
    393      * @stable ICU 4.8
    394      */
    395     int32_t getSamples(const UnicodeString &keyword,
    396                        double *dest, int32_t destCapacity,
    397                        UErrorCode& status);
    398 
    399     /**
    400      * Returns TRUE if the given keyword is defined in this
    401      * <code>PluralRules</code> object.
    402      *
    403      * @param keyword  the input keyword.
    404      * @return         TRUE if the input keyword is defined.
    405      *                 Otherwise, return FALSE.
    406      * @stable ICU 4.0
    407      */
    408     UBool isKeyword(const UnicodeString& keyword) const;
    409 
    410 
    411     /**
    412      * Returns keyword for default plural form.
    413      *
    414      * @return         keyword for default plural form.
    415      * @stable ICU 4.0
    416      */
    417     UnicodeString getKeywordOther() const;
    418 
    419 #ifndef U_HIDE_INTERNAL_API
    420     /**
    421      *
    422      * @internal
    423      */
    424      UnicodeString getRules() const;
    425 #endif  /* U_HIDE_INTERNAL_API */
    426 
    427     /**
    428      * Compares the equality of two PluralRules objects.
    429      *
    430      * @param other The other PluralRules object to be compared with.
    431      * @return      True if the given PluralRules is the same as this
    432      *              PluralRules; false otherwise.
    433      * @stable ICU 4.0
    434      */
    435     virtual UBool operator==(const PluralRules& other) const;
    436 
    437     /**
    438      * Compares the inequality of two PluralRules objects.
    439      *
    440      * @param other The PluralRules object to be compared with.
    441      * @return      True if the given PluralRules is not the same as this
    442      *              PluralRules; false otherwise.
    443      * @stable ICU 4.0
    444      */
    445     UBool operator!=(const PluralRules& other) const  {return !operator==(other);}
    446 
    447 
    448     /**
    449      * ICU "poor man's RTTI", returns a UClassID for this class.
    450      *
    451      * @stable ICU 4.0
    452      *
    453     */
    454     static UClassID U_EXPORT2 getStaticClassID(void);
    455 
    456     /**
    457      * ICU "poor man's RTTI", returns a UClassID for the actual class.
    458      *
    459      * @stable ICU 4.0
    460      */
    461     virtual UClassID getDynamicClassID() const;
    462 
    463 
    464 private:
    465     RuleChain  *mRules;
    466 
    467     PluralRules();   // default constructor not implemented
    468     void            parseDescription(const UnicodeString& ruleData, UErrorCode &status);
    469     int32_t         getNumberValue(const UnicodeString& token) const;
    470     UnicodeString   getRuleFromResource(const Locale& locale, UPluralType type, UErrorCode& status);
    471     RuleChain      *rulesForKeyword(const UnicodeString &keyword) const;
    472 
    473     friend class PluralRuleParser;
    474 };
    475 
    476 U_NAMESPACE_END
    477 
    478 #endif /* #if !UCONFIG_NO_FORMATTING */
    479 
    480 #endif // _PLURRULE
    481 //eof
    482