Home | History | Annotate | Download | only in unicode
      1 /*
      2 *******************************************************************************
      3 * Copyright (C) 2008-2010, 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 
     30 U_NAMESPACE_BEGIN
     31 
     32 class Hashtable;
     33 class RuleChain;
     34 class RuleParser;
     35 
     36 /**
     37  * Defines rules for mapping positive long values onto a small set of
     38  * keywords. Rules are constructed from a text description, consisting
     39  * of a series of keywords and conditions.  The {@link #select} method
     40  * examines each condition in order and returns the keyword for the
     41  * first condition that matches the number.  If none match,
     42  * default rule(other) is returned.
     43  *
     44  * Examples:<pre>
     45  *   "one: n is 1; few: n in 2..4"</pre>
     46  *  This defines two rules, for 'one' and 'few'.  The condition for
     47  *  'one' is "n is 1" which means that the number must be equal to
     48  *  1 for this condition to pass.  The condition for 'few' is
     49  *  "n in 2..4" which means that the number must be between 2 and
     50  *  4 inclusive for this condition to pass.  All other numbers
     51  *  are assigned the keyword "other" by the default rule.
     52  *  </p><pre>
     53  *    "zero: n is 0; one: n is 1; zero: n mod 100 in 1..19"</pre>
     54  *  This illustrates that the same keyword can be defined multiple times.
     55  *  Each rule is examined in order, and the first keyword whose condition
     56  *  passes is the one returned.  Also notes that a modulus is applied
     57  *  to n in the last rule.  Thus its condition holds for 119, 219, 319...
     58  *  </p><pre>
     59  *    "one: n is 1; few: n mod 10 in 2..4 and n mod 100 not in 12..14"</pre>
     60  *  This illustrates conjunction and negation.  The condition for 'few'
     61  *  has two parts, both of which must be met: "n mod 10 in 2..4" and
     62  *  "n mod 100 not in 12..14".  The first part applies a modulus to n
     63  *  before the test as in the previous example.  The second part applies
     64  *  a different modulus and also uses negation, thus it matches all
     65  *  numbers _not_ in 12, 13, 14, 112, 113, 114, 212, 213, 214...
     66  *  </p>
     67  *  <p>
     68  * Syntax:<pre>
     69  * \code
     70  * rules         = rule (';' rule)*
     71  * rule          = keyword ':' condition
     72  * keyword       = <identifier>
     73  * condition     = and_condition ('or' and_condition)*
     74  * and_condition = relation ('and' relation)*
     75  * relation      = is_relation | in_relation | within_relation | 'n' <EOL>
     76  * is_relation   = expr 'is' ('not')? value
     77  * in_relation   = expr ('not')? 'in' range
     78  * within_relation = expr ('not')? 'within' range
     79  * expr          = 'n' ('mod' value)?
     80  * value         = digit+
     81  * digit         = 0|1|2|3|4|5|6|7|8|9
     82  * range         = value'..'value
     83  * \endcode
     84  * </pre></p>
     85  * <p>
     86  *  The difference between 'in' and 'within' is that 'in' only includes
     87  *  integers in the specified range, while 'within' includes all values.</p>
     88  *  <p>
     89  *  Keywords
     90  *  could be defined by users or from ICU locale data. There are 6
     91  *  predefined values in ICU - 'zero', 'one', 'two', 'few', 'many' and
     92  *  'other'. Callers need to check the value of keyword returned by
     93  *  {@link #select} method.
     94  *  </p>
     95  *
     96  * Examples:<pre>
     97  * UnicodeString keyword = pl->select(number);
     98  * if (keyword== UnicodeString("one") {
     99  *     ...
    100  * }
    101  * else if ( ... )
    102  * </pre>
    103  * <strong>Note:</strong><br>
    104  *  <p>
    105  *   ICU defines plural rules for many locales based on CLDR <i>Language Plural Rules</i>.
    106  *   For these predefined rules, see CLDR page at
    107  *    http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
    108  * </p>
    109  */
    110 class U_I18N_API PluralRules : public UObject {
    111 public:
    112 
    113     /**
    114      * Constructor.
    115      * @param status  Output param set to success/failure code on exit, which
    116      *                must not indicate a failure before the function call.
    117      *
    118      * @stable ICU 4.0
    119      */
    120     PluralRules(UErrorCode& status);
    121 
    122     /**
    123      * Copy constructor.
    124      * @stable ICU 4.0
    125      */
    126     PluralRules(const PluralRules& other);
    127 
    128     /**
    129      * Destructor.
    130      * @stable ICU 4.0
    131      */
    132     virtual ~PluralRules();
    133 
    134     /**
    135      * Clone
    136      * @stable ICU 4.0
    137      */
    138     PluralRules* clone() const;
    139 
    140     /**
    141       * Assignment operator.
    142       * @stable ICU 4.0
    143       */
    144     PluralRules& operator=(const PluralRules&);
    145 
    146     /**
    147      * Creates a PluralRules from a description if it is parsable, otherwise
    148      * returns null.
    149      *
    150      * @param description rule description
    151      * @param status      Output param set to success/failure code on exit, which
    152      *                    must not indicate a failure before the function call.
    153      * @return            new PluralRules pointer. NULL if there is an error.
    154      * @stable ICU 4.0
    155      */
    156     static PluralRules* U_EXPORT2 createRules(const UnicodeString& description,
    157                                               UErrorCode& status);
    158 
    159     /**
    160      * The default rules that accept any number.
    161      *
    162      * @param status  Output param set to success/failure code on exit, which
    163      *                must not indicate a failure before the function call.
    164      * @return        new PluralRules pointer. NULL if there is an error.
    165      * @stable ICU 4.0
    166      */
    167     static PluralRules* U_EXPORT2 createDefaultRules(UErrorCode& status);
    168 
    169     /**
    170      * Provides access to the predefined <code>PluralRules</code> for a given
    171      * locale.
    172      *
    173      * @param locale  The locale for which a <code>PluralRules</code> object is
    174      *                returned.
    175      * @param status  Output param set to success/failure code on exit, which
    176      *                must not indicate a failure before the function call.
    177      * @return        The predefined <code>PluralRules</code> object pointer for
    178      *                this locale. If there's no predefined rules for this locale,
    179      *                the rules for the closest parent in the locale hierarchy
    180      *                that has one will  be returned.  The final fallback always
    181      *                returns the default 'other' rules.
    182      * @stable ICU 4.0
    183      */
    184     static PluralRules* U_EXPORT2 forLocale(const Locale& locale, UErrorCode& status);
    185 
    186     /**
    187      * Given a number, returns the keyword of the first rule that applies to
    188      * the number.  This function can be used with isKeyword* functions to
    189      * determine the keyword for default plural rules.
    190      *
    191      * @param number  The number for which the rule has to be determined.
    192      * @return        The keyword of the selected rule.
    193      * @stable ICU 4.0
    194      */
    195     UnicodeString select(int32_t number) const;
    196 
    197     /**
    198      * Given a number, returns the keyword of the first rule that applies to
    199      * the number.  This function can be used with isKeyword* functions to
    200      * determine the keyword for default plural rules.
    201      *
    202      * @param number  The number for which the rule has to be determined.
    203      * @return        The keyword of the selected rule.
    204      * @stable ICU 4.0
    205      */
    206     UnicodeString select(double number) const;
    207 
    208     /**
    209      * Returns a list of all rule keywords used in this <code>PluralRules</code>
    210      * object.  The rule 'other' is always present by default.
    211      *
    212      * @param status Output param set to success/failure code on exit, which
    213      *               must not indicate a failure before the function call.
    214      * @return       StringEnumeration with the keywords.
    215      *               The caller must delete the object.
    216      * @stable ICU 4.0
    217      */
    218     StringEnumeration* getKeywords(UErrorCode& status) const;
    219 
    220     /**
    221      * Returns TRUE if the given keyword is defined in this
    222      * <code>PluralRules</code> object.
    223      *
    224      * @param keyword  the input keyword.
    225      * @return         TRUE if the input keyword is defined.
    226      *                 Otherwise, return FALSE.
    227      * @stable ICU 4.0
    228      */
    229     UBool isKeyword(const UnicodeString& keyword) const;
    230 
    231 
    232     /**
    233      * Returns keyword for default plural form.
    234      *
    235      * @return         keyword for default plural form.
    236      * @internal 4.0
    237      * @stable ICU 4.0
    238      */
    239     UnicodeString getKeywordOther() const;
    240 
    241     /**
    242      * Compares the equality of two PluralRules objects.
    243      *
    244      * @param other The other PluralRules object to be compared with.
    245      * @return      True if the given PluralRules is the same as this
    246      *              PluralRules; false otherwise.
    247      * @stable ICU 4.0
    248      */
    249     virtual UBool operator==(const PluralRules& other) const;
    250 
    251     /**
    252      * Compares the inequality of two PluralRules objects.
    253      *
    254      * @param other The PluralRules object to be compared with.
    255      * @return      True if the given PluralRules is not the same as this
    256      *              PluralRules; false otherwise.
    257      * @stable ICU 4.0
    258      */
    259     UBool operator!=(const PluralRules& other) const  {return !operator==(other);}
    260 
    261 
    262     /**
    263      * ICU "poor man's RTTI", returns a UClassID for this class.
    264      *
    265      * @stable ICU 4.0
    266      *
    267     */
    268     static UClassID U_EXPORT2 getStaticClassID(void);
    269 
    270     /**
    271      * ICU "poor man's RTTI", returns a UClassID for the actual class.
    272      *
    273      * @stable ICU 4.0
    274      */
    275     virtual UClassID getDynamicClassID() const;
    276 
    277 
    278 private:
    279     Hashtable       *fLocaleStringsHash;
    280     UnicodeString   mLocaleName;
    281     RuleChain       *mRules;
    282     RuleParser      *mParser;
    283 
    284     PluralRules();   // default constructor not implemented
    285     int32_t getRepeatLimit() const;
    286     void parseDescription(UnicodeString& ruleData, RuleChain& rules, UErrorCode &status);
    287     void getNextLocale(const UnicodeString& localeData, int32_t* curIndex, UnicodeString& localeName);
    288     void addRules(RuleChain& rules);
    289     int32_t getNumberValue(const UnicodeString& token) const;
    290     UnicodeString getRuleFromResource(const Locale& locale, UErrorCode& status);
    291 
    292 };
    293 
    294 U_NAMESPACE_END
    295 
    296 #endif /* #if !UCONFIG_NO_FORMATTING */
    297 
    298 #endif // _PLURRULE
    299 //eof
    300