Line data Source code
1 : // © 2016 and later: Unicode, Inc. and others.
2 : // License & terms of use: http://www.unicode.org/copyright.html
3 : /*
4 : *******************************************************************************
5 : * Copyright (C) 2007-2014, International Business Machines Corporation and
6 : * others. All Rights Reserved.
7 : *******************************************************************************
8 : *
9 :
10 : * File PLURFMT.H
11 : ********************************************************************************
12 : */
13 :
14 : #ifndef PLURFMT
15 : #define PLURFMT
16 :
17 : #include "unicode/utypes.h"
18 :
19 : /**
20 : * \file
21 : * \brief C++ API: PluralFormat object
22 : */
23 :
24 : #if !UCONFIG_NO_FORMATTING
25 :
26 : #include "unicode/messagepattern.h"
27 : #include "unicode/numfmt.h"
28 : #include "unicode/plurrule.h"
29 :
30 : U_NAMESPACE_BEGIN
31 :
32 : class Hashtable;
33 : class NFRule;
34 :
35 : /**
36 : * <p>
37 : * <code>PluralFormat</code> supports the creation of internationalized
38 : * messages with plural inflection. It is based on <i>plural
39 : * selection</i>, i.e. the caller specifies messages for each
40 : * plural case that can appear in the user's language and the
41 : * <code>PluralFormat</code> selects the appropriate message based on
42 : * the number.
43 : * </p>
44 : * <h4>The Problem of Plural Forms in Internationalized Messages</h4>
45 : * <p>
46 : * Different languages have different ways to inflect
47 : * plurals. Creating internationalized messages that include plural
48 : * forms is only feasible when the framework is able to handle plural
49 : * forms of <i>all</i> languages correctly. <code>ChoiceFormat</code>
50 : * doesn't handle this well, because it attaches a number interval to
51 : * each message and selects the message whose interval contains a
52 : * given number. This can only handle a finite number of
53 : * intervals. But in some languages, like Polish, one plural case
54 : * applies to infinitely many intervals (e.g., the plural case applies to
55 : * numbers ending with 2, 3, or 4 except those ending with 12, 13, or
56 : * 14). Thus <code>ChoiceFormat</code> is not adequate.
57 : * </p><p>
58 : * <code>PluralFormat</code> deals with this by breaking the problem
59 : * into two parts:
60 : * <ul>
61 : * <li>It uses <code>PluralRules</code> that can define more complex
62 : * conditions for a plural case than just a single interval. These plural
63 : * rules define both what plural cases exist in a language, and to
64 : * which numbers these cases apply.
65 : * <li>It provides predefined plural rules for many languages. Thus, the programmer
66 : * need not worry about the plural cases of a language and
67 : * does not have to define the plural cases; they can simply
68 : * use the predefined keywords. The whole plural formatting of messages can
69 : * be done using localized patterns from resource bundles. For predefined plural
70 : * rules, see the CLDR <i>Language Plural Rules</i> page at
71 : * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
72 : * </ul>
73 : * </p>
74 : * <h4>Usage of <code>PluralFormat</code></h4>
75 : * <p>Note: Typically, plural formatting is done via <code>MessageFormat</code>
76 : * with a <code>plural</code> argument type,
77 : * rather than using a stand-alone <code>PluralFormat</code>.
78 : * </p><p>
79 : * This discussion assumes that you use <code>PluralFormat</code> with
80 : * a predefined set of plural rules. You can create one using one of
81 : * the constructors that takes a <code>locale</code> object. To
82 : * specify the message pattern, you can either pass it to the
83 : * constructor or set it explicitly using the
84 : * <code>applyPattern()</code> method. The <code>format()</code>
85 : * method takes a number object and selects the message of the
86 : * matching plural case. This message will be returned.
87 : * </p>
88 : * <h5>Patterns and Their Interpretation</h5>
89 : * <p>
90 : * The pattern text defines the message output for each plural case of the
91 : * specified locale. Syntax:
92 : * <pre>
93 : * pluralStyle = [offsetValue] (selector '{' message '}')+
94 : * offsetValue = "offset:" number
95 : * selector = explicitValue | keyword
96 : * explicitValue = '=' number // adjacent, no white space in between
97 : * keyword = [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+
98 : * message: see {@link MessageFormat}
99 : * </pre>
100 : * Pattern_White_Space between syntax elements is ignored, except
101 : * between the {curly braces} and their sub-message,
102 : * and between the '=' and the number of an explicitValue.
103 : *
104 : * </p><p>
105 : * There are 6 predefined casekeyword in CLDR/ICU - 'zero', 'one', 'two', 'few', 'many' and
106 : * 'other'. You always have to define a message text for the default plural case
107 : * <code>other</code> which is contained in every rule set.
108 : * If you do not specify a message text for a particular plural case, the
109 : * message text of the plural case <code>other</code> gets assigned to this
110 : * plural case.
111 : * </p><p>
112 : * When formatting, the input number is first matched against the explicitValue clauses.
113 : * If there is no exact-number match, then a keyword is selected by calling
114 : * the <code>PluralRules</code> with the input number <em>minus the offset</em>.
115 : * (The offset defaults to 0 if it is omitted from the pattern string.)
116 : * If there is no clause with that keyword, then the "other" clauses is returned.
117 : * </p><p>
118 : * An unquoted pound sign (<code>#</code>) in the selected sub-message
119 : * itself (i.e., outside of arguments nested in the sub-message)
120 : * is replaced by the input number minus the offset.
121 : * The number-minus-offset value is formatted using a
122 : * <code>NumberFormat</code> for the <code>PluralFormat</code>'s locale. If you
123 : * need special number formatting, you have to use a <code>MessageFormat</code>
124 : * and explicitly specify a <code>NumberFormat</code> argument.
125 : * <strong>Note:</strong> That argument is formatting without subtracting the offset!
126 : * If you need a custom format and have a non-zero offset, then you need to pass the
127 : * number-minus-offset value as a separate parameter.
128 : * </p>
129 : * For a usage example, see the {@link MessageFormat} class documentation.
130 : *
131 : * <h4>Defining Custom Plural Rules</h4>
132 : * <p>If you need to use <code>PluralFormat</code> with custom rules, you can
133 : * create a <code>PluralRules</code> object and pass it to
134 : * <code>PluralFormat</code>'s constructor. If you also specify a locale in this
135 : * constructor, this locale will be used to format the number in the message
136 : * texts.
137 : * </p><p>
138 : * For more information about <code>PluralRules</code>, see
139 : * {@link PluralRules}.
140 : * </p>
141 : *
142 : * ported from Java
143 : * @stable ICU 4.0
144 : */
145 :
146 : class U_I18N_API PluralFormat : public Format {
147 : public:
148 :
149 : /**
150 : * Creates a new cardinal-number <code>PluralFormat</code> for the default locale.
151 : * This locale will be used to get the set of plural rules and for standard
152 : * number formatting.
153 : * @param status output param set to success/failure code on exit, which
154 : * must not indicate a failure before the function call.
155 : * @stable ICU 4.0
156 : */
157 : PluralFormat(UErrorCode& status);
158 :
159 : /**
160 : * Creates a new cardinal-number <code>PluralFormat</code> for a given locale.
161 : * @param locale the <code>PluralFormat</code> will be configured with
162 : * rules for this locale. This locale will also be used for
163 : * standard number formatting.
164 : * @param status output param set to success/failure code on exit, which
165 : * must not indicate a failure before the function call.
166 : * @stable ICU 4.0
167 : */
168 : PluralFormat(const Locale& locale, UErrorCode& status);
169 :
170 : /**
171 : * Creates a new <code>PluralFormat</code> for a given set of rules.
172 : * The standard number formatting will be done using the default locale.
173 : * @param rules defines the behavior of the <code>PluralFormat</code>
174 : * object.
175 : * @param status output param set to success/failure code on exit, which
176 : * must not indicate a failure before the function call.
177 : * @stable ICU 4.0
178 : */
179 : PluralFormat(const PluralRules& rules, UErrorCode& status);
180 :
181 : /**
182 : * Creates a new <code>PluralFormat</code> for a given set of rules.
183 : * The standard number formatting will be done using the given locale.
184 : * @param locale the default number formatting will be done using this
185 : * locale.
186 : * @param rules defines the behavior of the <code>PluralFormat</code>
187 : * object.
188 : * @param status output param set to success/failure code on exit, which
189 : * must not indicate a failure before the function call.
190 : * @stable ICU 4.0
191 : * <p>
192 : * <h4>Sample code</h4>
193 : * \snippet samples/plurfmtsample/plurfmtsample.cpp PluralFormatExample1
194 : * \snippet samples/plurfmtsample/plurfmtsample.cpp PluralFormatExample
195 : * <p>
196 : */
197 : PluralFormat(const Locale& locale, const PluralRules& rules, UErrorCode& status);
198 :
199 : /**
200 : * Creates a new <code>PluralFormat</code> for the plural type.
201 : * The standard number formatting will be done using the given locale.
202 : * @param locale the default number formatting will be done using this
203 : * locale.
204 : * @param type The plural type (e.g., cardinal or ordinal).
205 : * @param status output param set to success/failure code on exit, which
206 : * must not indicate a failure before the function call.
207 : * @stable ICU 50
208 : */
209 : PluralFormat(const Locale& locale, UPluralType type, UErrorCode& status);
210 :
211 : /**
212 : * Creates a new cardinal-number <code>PluralFormat</code> for a given pattern string.
213 : * The default locale will be used to get the set of plural rules and for
214 : * standard number formatting.
215 : * @param pattern the pattern for this <code>PluralFormat</code>.
216 : * errors are returned to status if the pattern is invalid.
217 : * @param status output param set to success/failure code on exit, which
218 : * must not indicate a failure before the function call.
219 : * @stable ICU 4.0
220 : */
221 : PluralFormat(const UnicodeString& pattern, UErrorCode& status);
222 :
223 : /**
224 : * Creates a new cardinal-number <code>PluralFormat</code> for a given pattern string and
225 : * locale.
226 : * The locale will be used to get the set of plural rules and for
227 : * standard number formatting.
228 : * @param locale the <code>PluralFormat</code> will be configured with
229 : * rules for this locale. This locale will also be used for
230 : * standard number formatting.
231 : * @param pattern the pattern for this <code>PluralFormat</code>.
232 : * errors are returned to status if the pattern is invalid.
233 : * @param status output param set to success/failure code on exit, which
234 : * must not indicate a failure before the function call.
235 : * @stable ICU 4.0
236 : */
237 : PluralFormat(const Locale& locale, const UnicodeString& pattern, UErrorCode& status);
238 :
239 : /**
240 : * Creates a new <code>PluralFormat</code> for a given set of rules, a
241 : * pattern and a locale.
242 : * @param rules defines the behavior of the <code>PluralFormat</code>
243 : * object.
244 : * @param pattern the pattern for this <code>PluralFormat</code>.
245 : * errors are returned to status if the pattern is invalid.
246 : * @param status output param set to success/failure code on exit, which
247 : * must not indicate a failure before the function call.
248 : * @stable ICU 4.0
249 : */
250 : PluralFormat(const PluralRules& rules,
251 : const UnicodeString& pattern,
252 : UErrorCode& status);
253 :
254 : /**
255 : * Creates a new <code>PluralFormat</code> for a given set of rules, a
256 : * pattern and a locale.
257 : * @param locale the <code>PluralFormat</code> will be configured with
258 : * rules for this locale. This locale will also be used for
259 : * standard number formatting.
260 : * @param rules defines the behavior of the <code>PluralFormat</code>
261 : * object.
262 : * @param pattern the pattern for this <code>PluralFormat</code>.
263 : * errors are returned to status if the pattern is invalid.
264 : * @param status output param set to success/failure code on exit, which
265 : * must not indicate a failure before the function call.
266 : * @stable ICU 4.0
267 : */
268 : PluralFormat(const Locale& locale,
269 : const PluralRules& rules,
270 : const UnicodeString& pattern,
271 : UErrorCode& status);
272 :
273 : /**
274 : * Creates a new <code>PluralFormat</code> for a plural type, a
275 : * pattern and a locale.
276 : * @param locale the <code>PluralFormat</code> will be configured with
277 : * rules for this locale. This locale will also be used for
278 : * standard number formatting.
279 : * @param type The plural type (e.g., cardinal or ordinal).
280 : * @param pattern the pattern for this <code>PluralFormat</code>.
281 : * errors are returned to status if the pattern is invalid.
282 : * @param status output param set to success/failure code on exit, which
283 : * must not indicate a failure before the function call.
284 : * @stable ICU 50
285 : */
286 : PluralFormat(const Locale& locale,
287 : UPluralType type,
288 : const UnicodeString& pattern,
289 : UErrorCode& status);
290 :
291 : /**
292 : * copy constructor.
293 : * @stable ICU 4.0
294 : */
295 : PluralFormat(const PluralFormat& other);
296 :
297 : /**
298 : * Destructor.
299 : * @stable ICU 4.0
300 : */
301 : virtual ~PluralFormat();
302 :
303 : /**
304 : * Sets the pattern used by this plural format.
305 : * The method parses the pattern and creates a map of format strings
306 : * for the plural rules.
307 : * Patterns and their interpretation are specified in the class description.
308 : *
309 : * @param pattern the pattern for this plural format
310 : * errors are returned to status if the pattern is invalid.
311 : * @param status output param set to success/failure code on exit, which
312 : * must not indicate a failure before the function call.
313 : * @stable ICU 4.0
314 : */
315 : void applyPattern(const UnicodeString& pattern, UErrorCode& status);
316 :
317 :
318 : using Format::format;
319 :
320 : /**
321 : * Formats a plural message for a given number.
322 : *
323 : * @param number a number for which the plural message should be formatted
324 : * for. If no pattern has been applied to this
325 : * <code>PluralFormat</code> object yet, the formatted number
326 : * will be returned.
327 : * @param status output param set to success/failure code on exit, which
328 : * must not indicate a failure before the function call.
329 : * @return the string containing the formatted plural message.
330 : * @stable ICU 4.0
331 : */
332 : UnicodeString format(int32_t number, UErrorCode& status) const;
333 :
334 : /**
335 : * Formats a plural message for a given number.
336 : *
337 : * @param number a number for which the plural message should be formatted
338 : * for. If no pattern has been applied to this
339 : * PluralFormat object yet, the formatted number
340 : * will be returned.
341 : * @param status output param set to success or failure code on exit, which
342 : * must not indicate a failure before the function call.
343 : * @return the string containing the formatted plural message.
344 : * @stable ICU 4.0
345 : */
346 : UnicodeString format(double number, UErrorCode& status) const;
347 :
348 : /**
349 : * Formats a plural message for a given number.
350 : *
351 : * @param number a number for which the plural message should be formatted
352 : * for. If no pattern has been applied to this
353 : * <code>PluralFormat</code> object yet, the formatted number
354 : * will be returned.
355 : * @param appendTo output parameter to receive result.
356 : * result is appended to existing contents.
357 : * @param pos On input: an alignment field, if desired.
358 : * On output: the offsets of the alignment field.
359 : * @param status output param set to success/failure code on exit, which
360 : * must not indicate a failure before the function call.
361 : * @return the string containing the formatted plural message.
362 : * @stable ICU 4.0
363 : */
364 : UnicodeString& format(int32_t number,
365 : UnicodeString& appendTo,
366 : FieldPosition& pos,
367 : UErrorCode& status) const;
368 :
369 : /**
370 : * Formats a plural message for a given number.
371 : *
372 : * @param number a number for which the plural message should be formatted
373 : * for. If no pattern has been applied to this
374 : * PluralFormat object yet, the formatted number
375 : * will be returned.
376 : * @param appendTo output parameter to receive result.
377 : * result is appended to existing contents.
378 : * @param pos On input: an alignment field, if desired.
379 : * On output: the offsets of the alignment field.
380 : * @param status output param set to success/failure code on exit, which
381 : * must not indicate a failure before the function call.
382 : * @return the string containing the formatted plural message.
383 : * @stable ICU 4.0
384 : */
385 : UnicodeString& format(double number,
386 : UnicodeString& appendTo,
387 : FieldPosition& pos,
388 : UErrorCode& status) const;
389 :
390 : #ifndef U_HIDE_DEPRECATED_API
391 : /**
392 : * Sets the locale used by this <code>PluraFormat</code> object.
393 : * Note: Calling this method resets this <code>PluraFormat</code> object,
394 : * i.e., a pattern that was applied previously will be removed,
395 : * and the NumberFormat is set to the default number format for
396 : * the locale. The resulting format behaves the same as one
397 : * constructed from {@link #PluralFormat(const Locale& locale, UPluralType type, UErrorCode& status)}
398 : * with UPLURAL_TYPE_CARDINAL.
399 : * @param locale the <code>locale</code> to use to configure the formatter.
400 : * @param status output param set to success/failure code on exit, which
401 : * must not indicate a failure before the function call.
402 : * @deprecated ICU 50 This method clears the pattern and might create
403 : * a different kind of PluralRules instance;
404 : * use one of the constructors to create a new instance instead.
405 : */
406 : void setLocale(const Locale& locale, UErrorCode& status);
407 : #endif /* U_HIDE_DEPRECATED_API */
408 :
409 : /**
410 : * Sets the number format used by this formatter. You only need to
411 : * call this if you want a different number format than the default
412 : * formatter for the locale.
413 : * @param format the number format to use.
414 : * @param status output param set to success/failure code on exit, which
415 : * must not indicate a failure before the function call.
416 : * @stable ICU 4.0
417 : */
418 : void setNumberFormat(const NumberFormat* format, UErrorCode& status);
419 :
420 : /**
421 : * Assignment operator
422 : *
423 : * @param other the PluralFormat object to copy from.
424 : * @stable ICU 4.0
425 : */
426 : PluralFormat& operator=(const PluralFormat& other);
427 :
428 : /**
429 : * Return true if another object is semantically equal to this one.
430 : *
431 : * @param other the PluralFormat object to be compared with.
432 : * @return true if other is semantically equal to this.
433 : * @stable ICU 4.0
434 : */
435 : virtual UBool operator==(const Format& other) const;
436 :
437 : /**
438 : * Return true if another object is semantically unequal to this one.
439 : *
440 : * @param other the PluralFormat object to be compared with.
441 : * @return true if other is semantically unequal to this.
442 : * @stable ICU 4.0
443 : */
444 : virtual UBool operator!=(const Format& other) const;
445 :
446 : /**
447 : * Clones this Format object polymorphically. The caller owns the
448 : * result and should delete it when done.
449 : * @stable ICU 4.0
450 : */
451 : virtual Format* clone(void) const;
452 :
453 : /**
454 : * Formats a plural message for a number taken from a Formattable object.
455 : *
456 : * @param obj The object containing a number for which the
457 : * plural message should be formatted.
458 : * The object must be of a numeric type.
459 : * @param appendTo output parameter to receive result.
460 : * Result is appended to existing contents.
461 : * @param pos On input: an alignment field, if desired.
462 : * On output: the offsets of the alignment field.
463 : * @param status output param filled with success/failure status.
464 : * @return Reference to 'appendTo' parameter.
465 : * @stable ICU 4.0
466 : */
467 : UnicodeString& format(const Formattable& obj,
468 : UnicodeString& appendTo,
469 : FieldPosition& pos,
470 : UErrorCode& status) const;
471 :
472 : /**
473 : * Returns the pattern from applyPattern() or constructor().
474 : *
475 : * @param appendTo output parameter to receive result.
476 : * Result is appended to existing contents.
477 : * @return the UnicodeString with inserted pattern.
478 : * @stable ICU 4.0
479 : */
480 : UnicodeString& toPattern(UnicodeString& appendTo);
481 :
482 : /**
483 : * This method is not yet supported by <code>PluralFormat</code>.
484 : * <P>
485 : * Before calling, set parse_pos.index to the offset you want to start
486 : * parsing at in the source. After calling, parse_pos.index is the end of
487 : * the text you parsed. If error occurs, index is unchanged.
488 : * <P>
489 : * When parsing, leading whitespace is discarded (with a successful parse),
490 : * while trailing whitespace is left as is.
491 : * <P>
492 : * See Format::parseObject() for more.
493 : *
494 : * @param source The string to be parsed into an object.
495 : * @param result Formattable to be set to the parse result.
496 : * If parse fails, return contents are undefined.
497 : * @param parse_pos The position to start parsing at. Upon return
498 : * this param is set to the position after the
499 : * last character successfully parsed. If the
500 : * source is not parsed successfully, this param
501 : * will remain unchanged.
502 : * @stable ICU 4.0
503 : */
504 : virtual void parseObject(const UnicodeString& source,
505 : Formattable& result,
506 : ParsePosition& parse_pos) const;
507 :
508 : /**
509 : * ICU "poor man's RTTI", returns a UClassID for this class.
510 : *
511 : * @stable ICU 4.0
512 : *
513 : */
514 : static UClassID U_EXPORT2 getStaticClassID(void);
515 :
516 : /**
517 : * ICU "poor man's RTTI", returns a UClassID for the actual class.
518 : *
519 : * @stable ICU 4.0
520 : */
521 : virtual UClassID getDynamicClassID() const;
522 :
523 : #if (defined(__xlC__) && (__xlC__ < 0x0C00)) || (U_PLATFORM == U_PF_OS390) || (U_PLATFORM ==U_PF_OS400)
524 : // Work around a compiler bug on xlC 11.1 on AIX 7.1 that would
525 : // prevent PluralSelectorAdapter from implementing private PluralSelector.
526 : // xlC error message:
527 : // 1540-0300 (S) The "private" member "class icu_49::PluralFormat::PluralSelector" cannot be accessed.
528 : public:
529 : #else
530 : private:
531 : #endif
532 : /**
533 : * @internal
534 : */
535 0 : class U_I18N_API PluralSelector : public UMemory {
536 : public:
537 : virtual ~PluralSelector();
538 : /**
539 : * Given a number, returns the appropriate PluralFormat keyword.
540 : *
541 : * @param context worker object for the selector.
542 : * @param number The number to be plural-formatted.
543 : * @param ec Error code.
544 : * @return The selected PluralFormat keyword.
545 : * @internal
546 : */
547 : virtual UnicodeString select(void *context, double number, UErrorCode& ec) const = 0;
548 : };
549 :
550 : /**
551 : * @internal
552 : */
553 : class U_I18N_API PluralSelectorAdapter : public PluralSelector {
554 : public:
555 0 : PluralSelectorAdapter() : pluralRules(NULL) {
556 0 : }
557 :
558 : virtual ~PluralSelectorAdapter();
559 :
560 : virtual UnicodeString select(void *context, double number, UErrorCode& /*ec*/) const; /**< @internal */
561 :
562 : void reset();
563 :
564 : PluralRules* pluralRules;
565 : };
566 :
567 : #if defined(__xlC__)
568 : // End of xlC bug workaround, keep remaining definitions private.
569 : private:
570 : #endif
571 : Locale locale;
572 : MessagePattern msgPattern;
573 : NumberFormat* numberFormat;
574 : double offset;
575 : PluralSelectorAdapter pluralRulesWrapper;
576 :
577 : PluralFormat(); // default constructor not implemented
578 : void init(const PluralRules* rules, UPluralType type, UErrorCode& status);
579 : /**
580 : * Copies dynamically allocated values (pointer fields).
581 : * Others are copied using their copy constructors and assignment operators.
582 : */
583 : void copyObjects(const PluralFormat& other);
584 :
585 : UnicodeString& format(const Formattable& numberObject, double number,
586 : UnicodeString& appendTo,
587 : FieldPosition& pos,
588 : UErrorCode& status) const; /**< @internal */
589 :
590 : /**
591 : * Finds the PluralFormat sub-message for the given number, or the "other" sub-message.
592 : * @param pattern A MessagePattern.
593 : * @param partIndex the index of the first PluralFormat argument style part.
594 : * @param selector the PluralSelector for mapping the number (minus offset) to a keyword.
595 : * @param context worker object for the selector.
596 : * @param number a number to be matched to one of the PluralFormat argument's explicit values,
597 : * or mapped via the PluralSelector.
598 : * @param ec ICU error code.
599 : * @return the sub-message start part index.
600 : */
601 : static int32_t findSubMessage(
602 : const MessagePattern& pattern, int32_t partIndex,
603 : const PluralSelector& selector, void *context, double number, UErrorCode& ec); /**< @internal */
604 :
605 : void parseType(const UnicodeString& source, const NFRule *rbnfLenientScanner,
606 : Formattable& result, FieldPosition& pos) const;
607 :
608 : friend class MessageFormat;
609 : friend class NFRule;
610 : };
611 :
612 : U_NAMESPACE_END
613 :
614 : #endif /* #if !UCONFIG_NO_FORMATTING */
615 :
616 : #endif // _PLURFMT
617 : //eof
|