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