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