Home | History | Annotate | Download | only in unicode
      1 /*
      2 *******************************************************************************
      3 * Copyright (C) 2008-2012, 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 RuleChain;
     42 class RuleParser;
     43 class PluralKeywordEnumeration;
     44 
     45 /**
     46  * Defines rules for mapping non-negative numeric values onto a small set of
     47  * keywords. Rules are constructed from a text description, consisting
     48  * of a series of keywords and conditions.  The {@link #select} method
     49  * examines each condition in order and returns the keyword for the
     50  * first condition that matches the number.  If none match,
     51  * default rule(other) is returned.
     52  *
     53  * For more information, details, and tips for writing rules, see the
     54  * LDML spec, C.11 Language Plural Rules:
     55  * http://www.unicode.org/draft/reports/tr35/tr35.html#Language_Plural_Rules
     56  *
     57  * Examples:<pre>
     58  *   "one: n is 1; few: n in 2..4"</pre>
     59  *  This defines two rules, for 'one' and 'few'.  The condition for
     60  *  'one' is "n is 1" which means that the number must be equal to
     61  *  1 for this condition to pass.  The condition for 'few' is
     62  *  "n in 2..4" which means that the number must be between 2 and
     63  *  4 inclusive for this condition to pass.  All other numbers
     64  *  are assigned the keyword "other" by the default rule.
     65  *  </p><pre>
     66  *    "zero: n is 0; one: n is 1; zero: n mod 100 in 1..19"</pre>
     67  *  This illustrates that the same keyword can be defined multiple times.
     68  *  Each rule is examined in order, and the first keyword whose condition
     69  *  passes is the one returned.  Also notes that a modulus is applied
     70  *  to n in the last rule.  Thus its condition holds for 119, 219, 319...
     71  *  </p><pre>
     72  *    "one: n is 1; few: n mod 10 in 2..4 and n mod 100 not in 12..14"</pre>
     73  *  This illustrates conjunction and negation.  The condition for 'few'
     74  *  has two parts, both of which must be met: "n mod 10 in 2..4" and
     75  *  "n mod 100 not in 12..14".  The first part applies a modulus to n
     76  *  before the test as in the previous example.  The second part applies
     77  *  a different modulus and also uses negation, thus it matches all
     78  *  numbers _not_ in 12, 13, 14, 112, 113, 114, 212, 213, 214...
     79  *  </p>
     80  *  <p>
     81  * Syntax:<pre>
     82  * \code
     83  * rules         = rule (';' rule)*
     84  * rule          = keyword ':' condition
     85  * keyword       = <identifier>
     86  * condition     = and_condition ('or' and_condition)*
     87  * and_condition = relation ('and' relation)*
     88  * relation      = is_relation | in_relation | within_relation | 'n' <EOL>
     89  * is_relation   = expr 'is' ('not')? value
     90  * in_relation   = expr ('not')? 'in' range_list
     91  * within_relation = expr ('not')? 'within' range
     92  * expr          = 'n' ('mod' value)?
     93  * range_list    = (range | value) (',' range_list)*
     94  * value         = digit+
     95  * digit         = 0|1|2|3|4|5|6|7|8|9
     96  * range         = value'..'value
     97  * \endcode
     98  * </pre></p>
     99  * <p>
    100  * An "identifier" is a sequence of characters that do not have the
    101  * Unicode Pattern_Syntax or Pattern_White_Space properties.
    102  * <p>
    103  * The difference between 'in' and 'within' is that 'in' only includes
    104  * integers in the specified range, while 'within' includes all values.</p>
    105  * <p>
    106  * Keywords
    107  * could be defined by users or from ICU locale data. There are 6
    108  * predefined values in ICU - 'zero', 'one', 'two', 'few', 'many' and
    109  * 'other'. Callers need to check the value of keyword returned by
    110  * {@link #select} method.
    111  * </p>
    112  *
    113  * Examples:<pre>
    114  * UnicodeString keyword = pl->select(number);
    115  * if (keyword== UnicodeString("one") {
    116  *     ...
    117  * }
    118  * else if ( ... )
    119  * </pre>
    120  * <strong>Note:</strong><br>
    121  *  <p>
    122  *   ICU defines plural rules for many locales based on CLDR <i>Language Plural Rules</i>.
    123  *   For these predefined rules, see CLDR page at
    124  *    http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
    125  * </p>
    126  */
    127 class U_I18N_API PluralRules : public UObject {
    128 public:
    129 
    130     /**
    131      * Constructor.
    132      * @param status  Output param set to success/failure code on exit, which
    133      *                must not indicate a failure before the function call.
    134      *
    135      * @stable ICU 4.0
    136      */
    137     PluralRules(UErrorCode& status);
    138 
    139     /**
    140      * Copy constructor.
    141      * @stable ICU 4.0
    142      */
    143     PluralRules(const PluralRules& other);
    144 
    145     /**
    146      * Destructor.
    147      * @stable ICU 4.0
    148      */
    149     virtual ~PluralRules();
    150 
    151     /**
    152      * Clone
    153      * @stable ICU 4.0
    154      */
    155     PluralRules* clone() const;
    156 
    157     /**
    158       * Assignment operator.
    159       * @stable ICU 4.0
    160       */
    161     PluralRules& operator=(const PluralRules&);
    162 
    163     /**
    164      * Creates a PluralRules from a description if it is parsable, otherwise
    165      * returns NULL.
    166      *
    167      * @param description rule description
    168      * @param status      Output param set to success/failure code on exit, which
    169      *                    must not indicate a failure before the function call.
    170      * @return            new PluralRules pointer. NULL if there is an error.
    171      * @stable ICU 4.0
    172      */
    173     static PluralRules* U_EXPORT2 createRules(const UnicodeString& description,
    174                                               UErrorCode& status);
    175 
    176     /**
    177      * The default rules that accept any number.
    178      *
    179      * @param status  Output param set to success/failure code on exit, which
    180      *                must not indicate a failure before the function call.
    181      * @return        new PluralRules pointer. NULL if there is an error.
    182      * @stable ICU 4.0
    183      */
    184     static PluralRules* U_EXPORT2 createDefaultRules(UErrorCode& status);
    185 
    186     /**
    187      * Provides access to the predefined cardinal-number <code>PluralRules</code> for a given
    188      * locale.
    189      * Same as forLocale(locale, UPLURAL_TYPE_CARDINAL, status).
    190      *
    191      * @param locale  The locale for which a <code>PluralRules</code> object is
    192      *                returned.
    193      * @param status  Output param set to success/failure code on exit, which
    194      *                must not indicate a failure before the function call.
    195      * @return        The predefined <code>PluralRules</code> object pointer for
    196      *                this locale. If there's no predefined rules for this locale,
    197      *                the rules for the closest parent in the locale hierarchy
    198      *                that has one will  be returned.  The final fallback always
    199      *                returns the default 'other' rules.
    200      * @stable ICU 4.0
    201      */
    202     static PluralRules* U_EXPORT2 forLocale(const Locale& locale, UErrorCode& status);
    203 
    204     /**
    205      * Provides access to the predefined <code>PluralRules</code> for a given
    206      * locale and the plural type.
    207      *
    208      * @param locale  The locale for which a <code>PluralRules</code> object is
    209      *                returned.
    210      * @param type    The plural type (e.g., cardinal or ordinal).
    211      * @param status  Output param set to success/failure code on exit, which
    212      *                must not indicate a failure before the function call.
    213      * @return        The predefined <code>PluralRules</code> object pointer for
    214      *                this locale. If there's no predefined rules for this locale,
    215      *                the rules for the closest parent in the locale hierarchy
    216      *                that has one will  be returned.  The final fallback always
    217      *                returns the default 'other' rules.
    218      * @draft ICU 50
    219      */
    220     static PluralRules* U_EXPORT2 forLocale(const Locale& locale, UPluralType type, UErrorCode& status);
    221 
    222     /**
    223      * Given a number, returns the keyword of the first rule that applies to
    224      * the number.  This function can be used with isKeyword* functions to
    225      * determine the keyword for default plural rules.
    226      *
    227      * @param number  The number for which the rule has to be determined.
    228      * @return        The keyword of the selected rule.
    229      * @stable ICU 4.0
    230      */
    231     UnicodeString select(int32_t number) const;
    232 
    233     /**
    234      * Given a number, returns the keyword of the first rule that applies to
    235      * the number.  This function can be used with isKeyword* functions to
    236      * determine the keyword for default plural rules.
    237      *
    238      * @param number  The number for which the rule has to be determined.
    239      * @return        The keyword of the selected rule.
    240      * @stable ICU 4.0
    241      */
    242     UnicodeString select(double number) const;
    243 
    244     /**
    245      * Returns a list of all rule keywords used in this <code>PluralRules</code>
    246      * object.  The rule 'other' is always present by default.
    247      *
    248      * @param status Output param set to success/failure code on exit, which
    249      *               must not indicate a failure before the function call.
    250      * @return       StringEnumeration with the keywords.
    251      *               The caller must delete the object.
    252      * @stable ICU 4.0
    253      */
    254     StringEnumeration* getKeywords(UErrorCode& status) const;
    255 
    256     /**
    257      * Returns a unique value for this keyword if it exists, else the constant
    258      * UPLRULES_NO_UNIQUE_VALUE.
    259      *
    260      * @param keyword The keyword.
    261      * @return        The unique value that generates the keyword, or
    262      *                UPLRULES_NO_UNIQUE_VALUE if the keyword is undefined or there is no
    263      *                unique value that generates this keyword.
    264      * @stable ICU 4.8
    265      */
    266     double getUniqueKeywordValue(const UnicodeString& keyword);
    267 
    268     /**
    269      * Returns all the values for which select() would return the keyword.  If
    270      * the keyword is unknown, returns no values, but this is not an error.  If
    271      * the number of values is unlimited, returns no values and -1 as the
    272      * count.
    273      *
    274      * The number of returned values is typically small.
    275      *
    276      * @param keyword      The keyword.
    277      * @param dest         Array into which to put the returned values.  May
    278      *                     be NULL if destCapacity is 0.
    279      * @param destCapacity The capacity of the array, must be at least 0.
    280      * @param status       The error code.
    281      * @return             The count of values available, or -1.  This count
    282      *                     can be larger than destCapacity, but no more than
    283      *                     destCapacity values will be written.
    284      * @stable ICU 4.8
    285      */
    286     int32_t getAllKeywordValues(const UnicodeString &keyword,
    287                                 double *dest, int32_t destCapacity,
    288                                 UErrorCode& status);
    289 
    290     /**
    291      * Returns sample values for which select() would return the keyword.  If
    292      * the keyword is unknown, returns no values, but this is not an error.
    293      *
    294      * The number of returned values is typically small.
    295      *
    296      * @param keyword      The keyword.
    297      * @param dest         Array into which to put the returned values.  May
    298      *                     be NULL if destCapacity is 0.
    299      * @param destCapacity The capacity of the array, must be at least 0.
    300      * @param status       The error code.
    301      * @return             The count of values written.
    302      *                     If more than destCapacity samples are available, then
    303      *                     only destCapacity are written, and destCapacity is returned as the count,
    304      *                     rather than setting a U_BUFFER_OVERFLOW_ERROR.
    305      *                     (The actual number of keyword values could be unlimited.)
    306      * @stable ICU 4.8
    307      */
    308     int32_t getSamples(const UnicodeString &keyword,
    309                        double *dest, int32_t destCapacity,
    310                        UErrorCode& status);
    311 
    312     /**
    313      * Returns TRUE if the given keyword is defined in this
    314      * <code>PluralRules</code> object.
    315      *
    316      * @param keyword  the input keyword.
    317      * @return         TRUE if the input keyword is defined.
    318      *                 Otherwise, return FALSE.
    319      * @stable ICU 4.0
    320      */
    321     UBool isKeyword(const UnicodeString& keyword) const;
    322 
    323 
    324     /**
    325      * Returns keyword for default plural form.
    326      *
    327      * @return         keyword for default plural form.
    328      * @stable ICU 4.0
    329      */
    330     UnicodeString getKeywordOther() const;
    331 
    332     /**
    333      * Compares the equality of two PluralRules objects.
    334      *
    335      * @param other The other PluralRules object to be compared with.
    336      * @return      True if the given PluralRules is the same as this
    337      *              PluralRules; false otherwise.
    338      * @stable ICU 4.0
    339      */
    340     virtual UBool operator==(const PluralRules& other) const;
    341 
    342     /**
    343      * Compares the inequality of two PluralRules objects.
    344      *
    345      * @param other The PluralRules object to be compared with.
    346      * @return      True if the given PluralRules is not the same as this
    347      *              PluralRules; false otherwise.
    348      * @stable ICU 4.0
    349      */
    350     UBool operator!=(const PluralRules& other) const  {return !operator==(other);}
    351 
    352 
    353     /**
    354      * ICU "poor man's RTTI", returns a UClassID for this class.
    355      *
    356      * @stable ICU 4.0
    357      *
    358     */
    359     static UClassID U_EXPORT2 getStaticClassID(void);
    360 
    361     /**
    362      * ICU "poor man's RTTI", returns a UClassID for the actual class.
    363      *
    364      * @stable ICU 4.0
    365      */
    366     virtual UClassID getDynamicClassID() const;
    367 
    368 
    369 private:
    370     RuleChain  *mRules;
    371     RuleParser *mParser;
    372     double     *mSamples;
    373     int32_t    *mSampleInfo;
    374     int32_t    mSampleInfoCount;
    375 
    376     PluralRules();   // default constructor not implemented
    377     int32_t getRepeatLimit() const;
    378     void parseDescription(UnicodeString& ruleData, RuleChain& rules, UErrorCode &status);
    379     void getNextLocale(const UnicodeString& localeData, int32_t* curIndex, UnicodeString& localeName);
    380     void addRules(RuleChain& rules);
    381     int32_t getNumberValue(const UnicodeString& token) const;
    382     UnicodeString getRuleFromResource(const Locale& locale, UPluralType type, UErrorCode& status);
    383 
    384     static const int32_t MAX_SAMPLES = 3;
    385 
    386     int32_t getSamplesInternal(const UnicodeString &keyword, double *dest,
    387                                int32_t destCapacity, UBool includeUnlimited,
    388                                UErrorCode& status);
    389     int32_t getKeywordIndex(const UnicodeString& keyword,
    390                             UErrorCode& status) const;
    391     void initSamples(UErrorCode& status);
    392 
    393 };
    394 
    395 U_NAMESPACE_END
    396 
    397 #endif /* #if !UCONFIG_NO_FORMATTING */
    398 
    399 #endif // _PLURRULE
    400 //eof
    401