1 /* 2 ******************************************************************************* 3 * Copyright (C) 2008-2011, 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 * @draft ICU 4.8 34 */ 35 #define UPLRULES_NO_UNIQUE_VALUE ((double)-0.00123456777) 36 37 U_NAMESPACE_BEGIN 38 39 class Hashtable; 40 class RuleChain; 41 class RuleParser; 42 class 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 */ 126 class U_I18N_API PluralRules : public UObject { 127 public: 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 * @draft 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 * @draft 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 * @draft 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 * @internal 4.0 309 * @stable ICU 4.0 310 */ 311 UnicodeString getKeywordOther() const; 312 313 /** 314 * Compares the equality of two PluralRules objects. 315 * 316 * @param other The other PluralRules object to be compared with. 317 * @return True if the given PluralRules is the same as this 318 * PluralRules; false otherwise. 319 * @stable ICU 4.0 320 */ 321 virtual UBool operator==(const PluralRules& other) const; 322 323 /** 324 * Compares the inequality of two PluralRules objects. 325 * 326 * @param other The PluralRules object to be compared with. 327 * @return True if the given PluralRules is not the same as this 328 * PluralRules; false otherwise. 329 * @stable ICU 4.0 330 */ 331 UBool operator!=(const PluralRules& other) const {return !operator==(other);} 332 333 334 /** 335 * ICU "poor man's RTTI", returns a UClassID for this class. 336 * 337 * @stable ICU 4.0 338 * 339 */ 340 static UClassID U_EXPORT2 getStaticClassID(void); 341 342 /** 343 * ICU "poor man's RTTI", returns a UClassID for the actual class. 344 * 345 * @stable ICU 4.0 346 */ 347 virtual UClassID getDynamicClassID() const; 348 349 350 private: 351 RuleChain *mRules; 352 RuleParser *mParser; 353 double *mSamples; 354 int32_t *mSampleInfo; 355 int32_t mSampleInfoCount; 356 357 PluralRules(); // default constructor not implemented 358 int32_t getRepeatLimit() const; 359 void parseDescription(UnicodeString& ruleData, RuleChain& rules, UErrorCode &status); 360 void getNextLocale(const UnicodeString& localeData, int32_t* curIndex, UnicodeString& localeName); 361 void addRules(RuleChain& rules); 362 int32_t getNumberValue(const UnicodeString& token) const; 363 UnicodeString getRuleFromResource(const Locale& locale, UErrorCode& status); 364 365 static const int32_t MAX_SAMPLES = 3; 366 367 int32_t getSamplesInternal(const UnicodeString &keyword, double *dest, 368 int32_t destCapacity, UBool includeUnlimited, 369 UErrorCode& status); 370 int32_t getKeywordIndex(const UnicodeString& keyword, 371 UErrorCode& status) const; 372 void initSamples(UErrorCode& status); 373 374 }; 375 376 U_NAMESPACE_END 377 378 #endif /* #if !UCONFIG_NO_FORMATTING */ 379 380 #endif // _PLURRULE 381 //eof 382