• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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 #ifndef U_HIDE_DRAFT_API
205     /**
206      * Provides access to the predefined <code>PluralRules</code> for a given
207      * locale and the plural type.
208      *
209      * @param locale  The locale for which a <code>PluralRules</code> object is
210      *                returned.
211      * @param type    The plural type (e.g., cardinal or ordinal).
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        The predefined <code>PluralRules</code> object pointer for
215      *                this locale. If there's no predefined rules for this locale,
216      *                the rules for the closest parent in the locale hierarchy
217      *                that has one will  be returned.  The final fallback always
218      *                returns the default 'other' rules.
219      * @draft ICU 50
220      */
221     static PluralRules* U_EXPORT2 forLocale(const Locale& locale, UPluralType type, UErrorCode& status);
222 #endif /* U_HIDE_DRAFT_API */
223 
224     /**
225      * Given a number, returns the keyword of the first rule that applies to
226      * the number.  This function can be used with isKeyword* functions to
227      * determine the keyword for default plural rules.
228      *
229      * @param number  The number for which the rule has to be determined.
230      * @return        The keyword of the selected rule.
231      * @stable ICU 4.0
232      */
233     UnicodeString select(int32_t number) const;
234 
235     /**
236      * Given a number, returns the keyword of the first rule that applies to
237      * the number.  This function can be used with isKeyword* functions to
238      * determine the keyword for default plural rules.
239      *
240      * @param number  The number for which the rule has to be determined.
241      * @return        The keyword of the selected rule.
242      * @stable ICU 4.0
243      */
244     UnicodeString select(double number) const;
245 
246     /**
247      * Returns a list of all rule keywords used in this <code>PluralRules</code>
248      * object.  The rule 'other' is always present by default.
249      *
250      * @param status Output param set to success/failure code on exit, which
251      *               must not indicate a failure before the function call.
252      * @return       StringEnumeration with the keywords.
253      *               The caller must delete the object.
254      * @stable ICU 4.0
255      */
256     StringEnumeration* getKeywords(UErrorCode& status) const;
257 
258     /**
259      * Returns a unique value for this keyword if it exists, else the constant
260      * UPLRULES_NO_UNIQUE_VALUE.
261      *
262      * @param keyword The keyword.
263      * @return        The unique value that generates the keyword, or
264      *                UPLRULES_NO_UNIQUE_VALUE if the keyword is undefined or there is no
265      *                unique value that generates this keyword.
266      * @stable ICU 4.8
267      */
268     double getUniqueKeywordValue(const UnicodeString& keyword);
269 
270     /**
271      * Returns all the values for which select() would return the keyword.  If
272      * the keyword is unknown, returns no values, but this is not an error.  If
273      * the number of values is unlimited, returns no values and -1 as the
274      * count.
275      *
276      * The number of returned values is typically small.
277      *
278      * @param keyword      The keyword.
279      * @param dest         Array into which to put the returned values.  May
280      *                     be NULL if destCapacity is 0.
281      * @param destCapacity The capacity of the array, must be at least 0.
282      * @param status       The error code.
283      * @return             The count of values available, or -1.  This count
284      *                     can be larger than destCapacity, but no more than
285      *                     destCapacity values will be written.
286      * @stable ICU 4.8
287      */
288     int32_t getAllKeywordValues(const UnicodeString &keyword,
289                                 double *dest, int32_t destCapacity,
290                                 UErrorCode& status);
291 
292     /**
293      * Returns sample values for which select() would return the keyword.  If
294      * the keyword is unknown, returns no values, but this is not an error.
295      *
296      * The number of returned values is typically small.
297      *
298      * @param keyword      The keyword.
299      * @param dest         Array into which to put the returned values.  May
300      *                     be NULL if destCapacity is 0.
301      * @param destCapacity The capacity of the array, must be at least 0.
302      * @param status       The error code.
303      * @return             The count of values written.
304      *                     If more than destCapacity samples are available, then
305      *                     only destCapacity are written, and destCapacity is returned as the count,
306      *                     rather than setting a U_BUFFER_OVERFLOW_ERROR.
307      *                     (The actual number of keyword values could be unlimited.)
308      * @stable ICU 4.8
309      */
310     int32_t getSamples(const UnicodeString &keyword,
311                        double *dest, int32_t destCapacity,
312                        UErrorCode& status);
313 
314     /**
315      * Returns TRUE if the given keyword is defined in this
316      * <code>PluralRules</code> object.
317      *
318      * @param keyword  the input keyword.
319      * @return         TRUE if the input keyword is defined.
320      *                 Otherwise, return FALSE.
321      * @stable ICU 4.0
322      */
323     UBool isKeyword(const UnicodeString& keyword) const;
324 
325 
326     /**
327      * Returns keyword for default plural form.
328      *
329      * @return         keyword for default plural form.
330      * @stable ICU 4.0
331      */
332     UnicodeString getKeywordOther() const;
333 
334     /**
335      * Compares the equality of two PluralRules objects.
336      *
337      * @param other The other PluralRules object to be compared with.
338      * @return      True if the given PluralRules is the same as this
339      *              PluralRules; false otherwise.
340      * @stable ICU 4.0
341      */
342     virtual UBool operator==(const PluralRules& other) const;
343 
344     /**
345      * Compares the inequality of two PluralRules objects.
346      *
347      * @param other The PluralRules object to be compared with.
348      * @return      True if the given PluralRules is not the same as this
349      *              PluralRules; false otherwise.
350      * @stable ICU 4.0
351      */
352     UBool operator!=(const PluralRules& other) const  {return !operator==(other);}
353 
354 
355     /**
356      * ICU "poor man's RTTI", returns a UClassID for this class.
357      *
358      * @stable ICU 4.0
359      *
360     */
361     static UClassID U_EXPORT2 getStaticClassID(void);
362 
363     /**
364      * ICU "poor man's RTTI", returns a UClassID for the actual class.
365      *
366      * @stable ICU 4.0
367      */
368     virtual UClassID getDynamicClassID() const;
369 
370 
371 private:
372     RuleChain  *mRules;
373     RuleParser *mParser;
374     double     *mSamples;
375     int32_t    *mSampleInfo;
376     int32_t    mSampleInfoCount;
377 
378     PluralRules();   // default constructor not implemented
379     int32_t getRepeatLimit() const;
380     void parseDescription(UnicodeString& ruleData, RuleChain& rules, UErrorCode &status);
381     void getNextLocale(const UnicodeString& localeData, int32_t* curIndex, UnicodeString& localeName);
382     void addRules(RuleChain& rules);
383     int32_t getNumberValue(const UnicodeString& token) const;
384     UnicodeString getRuleFromResource(const Locale& locale, UPluralType type, UErrorCode& status);
385 
386     static const int32_t MAX_SAMPLES = 3;
387 
388     int32_t getSamplesInternal(const UnicodeString &keyword, double *dest,
389                                int32_t destCapacity, UBool includeUnlimited,
390                                UErrorCode& status);
391     int32_t getKeywordIndex(const UnicodeString& keyword,
392                             UErrorCode& status) const;
393     void initSamples(UErrorCode& status);
394 
395 };
396 
397 U_NAMESPACE_END
398 
399 #endif /* #if !UCONFIG_NO_FORMATTING */
400 
401 #endif // _PLURRULE
402 //eof
403