1 /* 2 ******************************************************************************* 3 * Copyright (C) 2008-2015, 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 FixedDecimal; 42 class VisibleDigitsWithExponent; 43 class RuleChain; 44 class PluralRuleParser; 45 class PluralKeywordEnumeration; 46 class AndConstraint; 47 class SharedPluralRules; 48 49 /** 50 * Defines rules for mapping non-negative numeric values onto a small set of 51 * keywords. Rules are constructed from a text description, consisting 52 * of a series of keywords and conditions. The {@link #select} method 53 * examines each condition in order and returns the keyword for the 54 * first condition that matches the number. If none match, 55 * default rule(other) is returned. 56 * 57 * For more information, details, and tips for writing rules, see the 58 * LDML spec, C.11 Language Plural Rules: 59 * http://www.unicode.org/draft/reports/tr35/tr35.html#Language_Plural_Rules 60 * 61 * Examples:<pre> 62 * "one: n is 1; few: n in 2..4"</pre> 63 * This defines two rules, for 'one' and 'few'. The condition for 64 * 'one' is "n is 1" which means that the number must be equal to 65 * 1 for this condition to pass. The condition for 'few' is 66 * "n in 2..4" which means that the number must be between 2 and 67 * 4 inclusive for this condition to pass. All other numbers 68 * are assigned the keyword "other" by the default rule. 69 * </p><pre> 70 * "zero: n is 0; one: n is 1; zero: n mod 100 in 1..19"</pre> 71 * This illustrates that the same keyword can be defined multiple times. 72 * Each rule is examined in order, and the first keyword whose condition 73 * passes is the one returned. Also notes that a modulus is applied 74 * to n in the last rule. Thus its condition holds for 119, 219, 319... 75 * </p><pre> 76 * "one: n is 1; few: n mod 10 in 2..4 and n mod 100 not in 12..14"</pre> 77 * This illustrates conjunction and negation. The condition for 'few' 78 * has two parts, both of which must be met: "n mod 10 in 2..4" and 79 * "n mod 100 not in 12..14". The first part applies a modulus to n 80 * before the test as in the previous example. The second part applies 81 * a different modulus and also uses negation, thus it matches all 82 * numbers _not_ in 12, 13, 14, 112, 113, 114, 212, 213, 214... 83 * </p> 84 * <p> 85 * Syntax:<pre> 86 * \code 87 * rules = rule (';' rule)* 88 * rule = keyword ':' condition 89 * keyword = <identifier> 90 * condition = and_condition ('or' and_condition)* 91 * and_condition = relation ('and' relation)* 92 * relation = is_relation | in_relation | within_relation | 'n' <EOL> 93 * is_relation = expr 'is' ('not')? value 94 * in_relation = expr ('not')? 'in' range_list 95 * within_relation = expr ('not')? 'within' range 96 * expr = ('n' | 'i' | 'f' | 'v' | 'j') ('mod' value)? 97 * range_list = (range | value) (',' range_list)* 98 * value = digit+ ('.' digit+)? 99 * digit = 0|1|2|3|4|5|6|7|8|9 100 * range = value'..'value 101 * \endcode 102 * </pre></p> 103 * <p> 104 * <p> 105 * The i, f, and v values are defined as follows: 106 * </p> 107 * <ul> 108 * <li>i to be the integer digits.</li> 109 * <li>f to be the visible fractional digits, as an integer.</li> 110 * <li>v to be the number of visible fraction digits.</li> 111 * <li>j is defined to only match integers. That is j is 3 fails if v != 0 (eg for 3.1 or 3.0).</li> 112 * </ul> 113 * <p> 114 * Examples are in the following table: 115 * </p> 116 * <table border='1' style="border-collapse:collapse"> 117 * <tbody> 118 * <tr> 119 * <th>n</th> 120 * <th>i</th> 121 * <th>f</th> 122 * <th>v</th> 123 * </tr> 124 * <tr> 125 * <td>1.0</td> 126 * <td>1</td> 127 * <td align="right">0</td> 128 * <td>1</td> 129 * </tr> 130 * <tr> 131 * <td>1.00</td> 132 * <td>1</td> 133 * <td align="right">0</td> 134 * <td>2</td> 135 * </tr> 136 * <tr> 137 * <td>1.3</td> 138 * <td>1</td> 139 * <td align="right">3</td> 140 * <td>1</td> 141 * </tr> 142 * <tr> 143 * <td>1.03</td> 144 * <td>1</td> 145 * <td align="right">3</td> 146 * <td>2</td> 147 * </tr> 148 * <tr> 149 * <td>1.23</td> 150 * <td>1</td> 151 * <td align="right">23</td> 152 * <td>2</td> 153 * </tr> 154 * </tbody> 155 * </table> 156 * <p> 157 * The difference between 'in' and 'within' is that 'in' only includes integers in the specified range, while 'within' 158 * includes all values. Using 'within' with a range_list consisting entirely of values is the same as using 'in' (it's 159 * not an error). 160 * </p> 161 162 * An "identifier" is a sequence of characters that do not have the 163 * Unicode Pattern_Syntax or Pattern_White_Space properties. 164 * <p> 165 * The difference between 'in' and 'within' is that 'in' only includes 166 * integers in the specified range, while 'within' includes all values. 167 * Using 'within' with a range_list consisting entirely of values is the 168 * same as using 'in' (it's not an error). 169 *</p> 170 * <p> 171 * Keywords 172 * could be defined by users or from ICU locale data. There are 6 173 * predefined values in ICU - 'zero', 'one', 'two', 'few', 'many' and 174 * 'other'. Callers need to check the value of keyword returned by 175 * {@link #select} method. 176 * </p> 177 * 178 * Examples:<pre> 179 * UnicodeString keyword = pl->select(number); 180 * if (keyword== UnicodeString("one") { 181 * ... 182 * } 183 * else if ( ... ) 184 * </pre> 185 * <strong>Note:</strong><br> 186 * <p> 187 * ICU defines plural rules for many locales based on CLDR <i>Language Plural Rules</i>. 188 * For these predefined rules, see CLDR page at 189 * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html 190 * </p> 191 */ 192 class U_I18N_API PluralRules : public UObject { 193 public: 194 195 /** 196 * Constructor. 197 * @param status Output param set to success/failure code on exit, which 198 * must not indicate a failure before the function call. 199 * 200 * @stable ICU 4.0 201 */ 202 PluralRules(UErrorCode& status); 203 204 /** 205 * Copy constructor. 206 * @stable ICU 4.0 207 */ 208 PluralRules(const PluralRules& other); 209 210 /** 211 * Destructor. 212 * @stable ICU 4.0 213 */ 214 virtual ~PluralRules(); 215 216 /** 217 * Clone 218 * @stable ICU 4.0 219 */ 220 PluralRules* clone() const; 221 222 /** 223 * Assignment operator. 224 * @stable ICU 4.0 225 */ 226 PluralRules& operator=(const PluralRules&); 227 228 /** 229 * Creates a PluralRules from a description if it is parsable, otherwise 230 * returns NULL. 231 * 232 * @param description rule description 233 * @param status Output param set to success/failure code on exit, which 234 * must not indicate a failure before the function call. 235 * @return new PluralRules pointer. NULL if there is an error. 236 * @stable ICU 4.0 237 */ 238 static PluralRules* U_EXPORT2 createRules(const UnicodeString& description, 239 UErrorCode& status); 240 241 /** 242 * The default rules that accept any number. 243 * 244 * @param status Output param set to success/failure code on exit, which 245 * must not indicate a failure before the function call. 246 * @return new PluralRules pointer. NULL if there is an error. 247 * @stable ICU 4.0 248 */ 249 static PluralRules* U_EXPORT2 createDefaultRules(UErrorCode& status); 250 251 /** 252 * Provides access to the predefined cardinal-number <code>PluralRules</code> for a given 253 * locale. 254 * Same as forLocale(locale, UPLURAL_TYPE_CARDINAL, status). 255 * 256 * @param locale The locale for which a <code>PluralRules</code> object is 257 * returned. 258 * @param status Output param set to success/failure code on exit, which 259 * must not indicate a failure before the function call. 260 * @return The predefined <code>PluralRules</code> object pointer for 261 * this locale. If there's no predefined rules for this locale, 262 * the rules for the closest parent in the locale hierarchy 263 * that has one will be returned. The final fallback always 264 * returns the default 'other' rules. 265 * @stable ICU 4.0 266 */ 267 static PluralRules* U_EXPORT2 forLocale(const Locale& locale, UErrorCode& status); 268 269 /** 270 * Provides access to the predefined <code>PluralRules</code> for a given 271 * locale and the plural type. 272 * 273 * @param locale The locale for which a <code>PluralRules</code> object is 274 * returned. 275 * @param type The plural type (e.g., cardinal or ordinal). 276 * @param status Output param set to success/failure code on exit, which 277 * must not indicate a failure before the function call. 278 * @return The predefined <code>PluralRules</code> object pointer for 279 * this locale. If there's no predefined rules for this locale, 280 * the rules for the closest parent in the locale hierarchy 281 * that has one will be returned. The final fallback always 282 * returns the default 'other' rules. 283 * @stable ICU 50 284 */ 285 static PluralRules* U_EXPORT2 forLocale(const Locale& locale, UPluralType type, UErrorCode& status); 286 287 #ifndef U_HIDE_INTERNAL_API 288 /** 289 * Return a StringEnumeration over the locales for which there is plurals data. 290 * @return a StringEnumeration over the locales available. 291 * @internal 292 */ 293 static StringEnumeration* U_EXPORT2 getAvailableLocales(UErrorCode &status); 294 295 /** 296 * Returns whether or not there are overrides. 297 * @param locale the locale to check. 298 * @return 299 * @internal 300 */ 301 static UBool hasOverride(const Locale &locale); 302 303 /** 304 * For ICU use only. 305 * creates a SharedPluralRules object 306 * @internal 307 */ 308 static PluralRules* U_EXPORT2 internalForLocale(const Locale& locale, UPluralType type, UErrorCode& status); 309 310 /** 311 * For ICU use only. 312 * Returns handle to the shared, cached PluralRules instance. 313 * Caller must call removeRef() on returned value once it is done with 314 * the shared instance. 315 * @internal 316 */ 317 static const SharedPluralRules* U_EXPORT2 createSharedInstance( 318 const Locale& locale, UPluralType type, UErrorCode& status); 319 320 321 #endif /* U_HIDE_INTERNAL_API */ 322 323 /** 324 * Given a number, returns the keyword of the first rule that applies to 325 * the number. This function can be used with isKeyword* functions to 326 * determine the keyword for default plural rules. 327 * 328 * @param number The number for which the rule has to be determined. 329 * @return The keyword of the selected rule. 330 * @stable ICU 4.0 331 */ 332 UnicodeString select(int32_t number) const; 333 334 /** 335 * Given a number, returns the keyword of the first rule that applies to 336 * the number. This function can be used with isKeyword* functions to 337 * determine the keyword for default plural rules. 338 * 339 * @param number The number for which the rule has to be determined. 340 * @return The keyword of the selected rule. 341 * @stable ICU 4.0 342 */ 343 UnicodeString select(double number) const; 344 345 #ifndef U_HIDE_INTERNAL_API 346 /** 347 * @internal 348 */ 349 UnicodeString select(const FixedDecimal &number) const; 350 /** 351 * @internal 352 */ 353 UnicodeString select(const VisibleDigitsWithExponent &number) const; 354 #endif /* U_HIDE_INTERNAL_API */ 355 356 /** 357 * Returns a list of all rule keywords used in this <code>PluralRules</code> 358 * object. The rule 'other' is always present by default. 359 * 360 * @param status Output param set to success/failure code on exit, which 361 * must not indicate a failure before the function call. 362 * @return StringEnumeration with the keywords. 363 * The caller must delete the object. 364 * @stable ICU 4.0 365 */ 366 StringEnumeration* getKeywords(UErrorCode& status) const; 367 368 #ifndef U_HIDE_DEPRECATED_API 369 /** 370 * Deprecated Function, does not return useful results. 371 * 372 * Originally intended to return a unique value for this keyword if it exists, 373 * else the constant UPLRULES_NO_UNIQUE_VALUE. 374 * 375 * @param keyword The keyword. 376 * @return Stub deprecated function returns UPLRULES_NO_UNIQUE_VALUE always. 377 * @deprecated ICU 55 378 */ 379 double getUniqueKeywordValue(const UnicodeString& keyword); 380 381 /** 382 * Deprecated Function, does not produce useful results. 383 * 384 * Orginally intended to return all the values for which select() would return the keyword. 385 * If the keyword is unknown, returns no values, but this is not an error. If 386 * the number of values is unlimited, returns no values and -1 as the 387 * count. 388 * 389 * The number of returned values is typically small. 390 * 391 * @param keyword The keyword. 392 * @param dest Array into which to put the returned values. May 393 * be NULL if destCapacity is 0. 394 * @param destCapacity The capacity of the array, must be at least 0. 395 * @param status The error code. Deprecated function, always sets U_UNSUPPORTED_ERROR. 396 * @return The count of values available, or -1. This count 397 * can be larger than destCapacity, but no more than 398 * destCapacity values will be written. 399 * @deprecated ICU 55 400 */ 401 int32_t getAllKeywordValues(const UnicodeString &keyword, 402 double *dest, int32_t destCapacity, 403 UErrorCode& status); 404 #endif /* U_HIDE_DEPRECATED_API */ 405 406 /** 407 * Returns sample values for which select() would return the keyword. If 408 * the keyword is unknown, returns no values, but this is not an error. 409 * 410 * The number of returned values is typically small. 411 * 412 * @param keyword The keyword. 413 * @param dest Array into which to put the returned values. May 414 * be NULL if destCapacity is 0. 415 * @param destCapacity The capacity of the array, must be at least 0. 416 * @param status The error code. 417 * @return The count of values written. 418 * If more than destCapacity samples are available, then 419 * only destCapacity are written, and destCapacity is returned as the count, 420 * rather than setting a U_BUFFER_OVERFLOW_ERROR. 421 * (The actual number of keyword values could be unlimited.) 422 * @stable ICU 4.8 423 */ 424 int32_t getSamples(const UnicodeString &keyword, 425 double *dest, int32_t destCapacity, 426 UErrorCode& status); 427 428 /** 429 * Returns TRUE if the given keyword is defined in this 430 * <code>PluralRules</code> object. 431 * 432 * @param keyword the input keyword. 433 * @return TRUE if the input keyword is defined. 434 * Otherwise, return FALSE. 435 * @stable ICU 4.0 436 */ 437 UBool isKeyword(const UnicodeString& keyword) const; 438 439 440 /** 441 * Returns keyword for default plural form. 442 * 443 * @return keyword for default plural form. 444 * @stable ICU 4.0 445 */ 446 UnicodeString getKeywordOther() const; 447 448 #ifndef U_HIDE_INTERNAL_API 449 /** 450 * 451 * @internal 452 */ 453 UnicodeString getRules() const; 454 #endif /* U_HIDE_INTERNAL_API */ 455 456 /** 457 * Compares the equality of two PluralRules objects. 458 * 459 * @param other The other PluralRules object to be compared with. 460 * @return True if the given PluralRules is the same as this 461 * PluralRules; false otherwise. 462 * @stable ICU 4.0 463 */ 464 virtual UBool operator==(const PluralRules& other) const; 465 466 /** 467 * Compares the inequality of two PluralRules objects. 468 * 469 * @param other The PluralRules object to be compared with. 470 * @return True if the given PluralRules is not the same as this 471 * PluralRules; false otherwise. 472 * @stable ICU 4.0 473 */ 474 UBool operator!=(const PluralRules& other) const {return !operator==(other);} 475 476 477 /** 478 * ICU "poor man's RTTI", returns a UClassID for this class. 479 * 480 * @stable ICU 4.0 481 * 482 */ 483 static UClassID U_EXPORT2 getStaticClassID(void); 484 485 /** 486 * ICU "poor man's RTTI", returns a UClassID for the actual class. 487 * 488 * @stable ICU 4.0 489 */ 490 virtual UClassID getDynamicClassID() const; 491 492 493 private: 494 RuleChain *mRules; 495 496 PluralRules(); // default constructor not implemented 497 void parseDescription(const UnicodeString& ruleData, UErrorCode &status); 498 int32_t getNumberValue(const UnicodeString& token) const; 499 UnicodeString getRuleFromResource(const Locale& locale, UPluralType type, UErrorCode& status); 500 RuleChain *rulesForKeyword(const UnicodeString &keyword) const; 501 502 friend class PluralRuleParser; 503 }; 504 505 U_NAMESPACE_END 506 507 #endif /* #if !UCONFIG_NO_FORMATTING */ 508 509 #endif // _PLURRULE 510 //eof 511