1 | // © 2018 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html |
3 | |
4 | #ifndef __NUMBERRANGEFORMATTER_H__ |
5 | #define __NUMBERRANGEFORMATTER_H__ |
6 | |
7 | #include "unicode/utypes.h" |
8 | |
9 | #if U_SHOW_CPLUSPLUS_API |
10 | |
11 | #if !UCONFIG_NO_FORMATTING |
12 | |
13 | #include <atomic> |
14 | #include "unicode/appendable.h" |
15 | #include "unicode/fieldpos.h" |
16 | #include "unicode/formattedvalue.h" |
17 | #include "unicode/fpositer.h" |
18 | #include "unicode/numberformatter.h" |
19 | |
20 | /** |
21 | * \file |
22 | * \brief C++ API: Library for localized formatting of number, currency, and unit ranges. |
23 | * |
24 | * The main entrypoint to the formatting of ranges of numbers, including currencies and other units of measurement. |
25 | * <p> |
26 | * Usage example: |
27 | * <p> |
28 | * <pre> |
29 | * NumberRangeFormatter::with() |
30 | * .identityFallback(UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE) |
31 | * .numberFormatterFirst(NumberFormatter::with().adoptUnit(MeasureUnit::createMeter())) |
32 | * .numberFormatterSecond(NumberFormatter::with().adoptUnit(MeasureUnit::createKilometer())) |
33 | * .locale("en-GB") |
34 | * .formatRange(750, 1.2, status) |
35 | * .toString(status); |
36 | * // => "750 m - 1.2 km" |
37 | * </pre> |
38 | * <p> |
39 | * Like NumberFormatter, NumberRangeFormatter instances (i.e., LocalizedNumberRangeFormatter |
40 | * and UnlocalizedNumberRangeFormatter) are immutable and thread-safe. This API is based on the |
41 | * <em>fluent</em> design pattern popularized by libraries such as Google's Guava. |
42 | * |
43 | * @author Shane Carr |
44 | */ |
45 | |
46 | |
47 | /** |
48 | * Defines how to merge fields that are identical across the range sign. |
49 | * |
50 | * @stable ICU 63 |
51 | */ |
52 | typedef enum UNumberRangeCollapse { |
53 | /** |
54 | * Use locale data and heuristics to determine how much of the string to collapse. Could end up collapsing none, |
55 | * some, or all repeated pieces in a locale-sensitive way. |
56 | * |
57 | * The heuristics used for this option are subject to change over time. |
58 | * |
59 | * @stable ICU 63 |
60 | */ |
61 | UNUM_RANGE_COLLAPSE_AUTO, |
62 | |
63 | /** |
64 | * Do not collapse any part of the number. Example: "3.2 thousand kilograms – 5.3 thousand kilograms" |
65 | * |
66 | * @stable ICU 63 |
67 | */ |
68 | UNUM_RANGE_COLLAPSE_NONE, |
69 | |
70 | /** |
71 | * Collapse the unit part of the number, but not the notation, if present. Example: "3.2 thousand – 5.3 thousand |
72 | * kilograms" |
73 | * |
74 | * @stable ICU 63 |
75 | */ |
76 | UNUM_RANGE_COLLAPSE_UNIT, |
77 | |
78 | /** |
79 | * Collapse any field that is equal across the range sign. May introduce ambiguity on the magnitude of the |
80 | * number. Example: "3.2 – 5.3 thousand kilograms" |
81 | * |
82 | * @stable ICU 63 |
83 | */ |
84 | UNUM_RANGE_COLLAPSE_ALL |
85 | } UNumberRangeCollapse; |
86 | |
87 | /** |
88 | * Defines the behavior when the two numbers in the range are identical after rounding. To programmatically detect |
89 | * when the identity fallback is used, compare the lower and upper BigDecimals via FormattedNumber. |
90 | * |
91 | * @stable ICU 63 |
92 | * @see NumberRangeFormatter |
93 | */ |
94 | typedef enum UNumberRangeIdentityFallback { |
95 | /** |
96 | * Show the number as a single value rather than a range. Example: "$5" |
97 | * |
98 | * @stable ICU 63 |
99 | */ |
100 | UNUM_IDENTITY_FALLBACK_SINGLE_VALUE, |
101 | |
102 | /** |
103 | * Show the number using a locale-sensitive approximation pattern. If the numbers were the same before rounding, |
104 | * show the single value. Example: "~$5" or "$5" |
105 | * |
106 | * @stable ICU 63 |
107 | */ |
108 | UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, |
109 | |
110 | /** |
111 | * Show the number using a locale-sensitive approximation pattern. Use the range pattern always, even if the |
112 | * inputs are the same. Example: "~$5" |
113 | * |
114 | * @stable ICU 63 |
115 | */ |
116 | UNUM_IDENTITY_FALLBACK_APPROXIMATELY, |
117 | |
118 | /** |
119 | * Show the number as the range of two equal values. Use the range pattern always, even if the inputs are the |
120 | * same. Example (with RangeCollapse.NONE): "$5 – $5" |
121 | * |
122 | * @stable ICU 63 |
123 | */ |
124 | UNUM_IDENTITY_FALLBACK_RANGE |
125 | } UNumberRangeIdentityFallback; |
126 | |
127 | /** |
128 | * Used in the result class FormattedNumberRange to indicate to the user whether the numbers formatted in the range |
129 | * were equal or not, and whether or not the identity fallback was applied. |
130 | * |
131 | * @stable ICU 63 |
132 | * @see NumberRangeFormatter |
133 | */ |
134 | typedef enum UNumberRangeIdentityResult { |
135 | /** |
136 | * Used to indicate that the two numbers in the range were equal, even before any rounding rules were applied. |
137 | * |
138 | * @stable ICU 63 |
139 | * @see NumberRangeFormatter |
140 | */ |
141 | UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING, |
142 | |
143 | /** |
144 | * Used to indicate that the two numbers in the range were equal, but only after rounding rules were applied. |
145 | * |
146 | * @stable ICU 63 |
147 | * @see NumberRangeFormatter |
148 | */ |
149 | UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING, |
150 | |
151 | /** |
152 | * Used to indicate that the two numbers in the range were not equal, even after rounding rules were applied. |
153 | * |
154 | * @stable ICU 63 |
155 | * @see NumberRangeFormatter |
156 | */ |
157 | UNUM_IDENTITY_RESULT_NOT_EQUAL, |
158 | |
159 | #ifndef U_HIDE_INTERNAL_API |
160 | /** |
161 | * The number of entries in this enum. |
162 | * @internal |
163 | */ |
164 | UNUM_IDENTITY_RESULT_COUNT |
165 | #endif |
166 | |
167 | } UNumberRangeIdentityResult; |
168 | |
169 | U_NAMESPACE_BEGIN |
170 | |
171 | namespace number { // icu::number |
172 | |
173 | // Forward declarations: |
174 | class UnlocalizedNumberRangeFormatter; |
175 | class LocalizedNumberRangeFormatter; |
176 | class FormattedNumberRange; |
177 | |
178 | namespace impl { |
179 | |
180 | // Forward declarations: |
181 | struct RangeMacroProps; |
182 | class DecimalQuantity; |
183 | class UFormattedNumberRangeData; |
184 | class NumberRangeFormatterImpl; |
185 | |
186 | } // namespace impl |
187 | |
188 | /** |
189 | * \cond |
190 | * Export an explicit template instantiation. See datefmt.h |
191 | * (When building DLLs for Windows this is required.) |
192 | */ |
193 | #if U_PLATFORM == U_PF_WINDOWS && !defined(U_IN_DOXYGEN) |
194 | } // namespace icu::number |
195 | U_NAMESPACE_END |
196 | |
197 | template struct U_I18N_API std::atomic< U_NAMESPACE_QUALIFIER number::impl::NumberRangeFormatterImpl*>; |
198 | |
199 | U_NAMESPACE_BEGIN |
200 | namespace number { // icu::number |
201 | #endif |
202 | /** \endcond */ |
203 | |
204 | // Other helper classes would go here, but there are none. |
205 | |
206 | namespace impl { // icu::number::impl |
207 | |
208 | // Do not enclose entire MacroProps with #ifndef U_HIDE_INTERNAL_API, needed for a protected field |
209 | /** @internal */ |
210 | struct U_I18N_API RangeMacroProps : public UMemory { |
211 | /** @internal */ |
212 | UnlocalizedNumberFormatter formatter1; // = NumberFormatter::with(); |
213 | |
214 | /** @internal */ |
215 | UnlocalizedNumberFormatter formatter2; // = NumberFormatter::with(); |
216 | |
217 | /** @internal */ |
218 | bool singleFormatter = true; |
219 | |
220 | /** @internal */ |
221 | UNumberRangeCollapse collapse = UNUM_RANGE_COLLAPSE_AUTO; |
222 | |
223 | /** @internal */ |
224 | UNumberRangeIdentityFallback identityFallback = UNUM_IDENTITY_FALLBACK_APPROXIMATELY; |
225 | |
226 | /** @internal */ |
227 | Locale locale; |
228 | |
229 | // NOTE: Uses default copy and move constructors. |
230 | |
231 | /** |
232 | * Check all members for errors. |
233 | * @internal |
234 | */ |
235 | bool copyErrorTo(UErrorCode &status) const { |
236 | return formatter1.copyErrorTo(status) || formatter2.copyErrorTo(status); |
237 | } |
238 | }; |
239 | |
240 | } // namespace impl |
241 | |
242 | /** |
243 | * An abstract base class for specifying settings related to number formatting. This class is implemented by |
244 | * {@link UnlocalizedNumberRangeFormatter} and {@link LocalizedNumberRangeFormatter}. This class is not intended for |
245 | * public subclassing. |
246 | */ |
247 | template<typename Derived> |
248 | class U_I18N_API NumberRangeFormatterSettings { |
249 | public: |
250 | /** |
251 | * Sets the NumberFormatter instance to use for the numbers in the range. The same formatter is applied to both |
252 | * sides of the range. |
253 | * <p> |
254 | * The NumberFormatter instances must not have a locale applied yet; the locale specified on the |
255 | * NumberRangeFormatter will be used. |
256 | * |
257 | * @param formatter |
258 | * The formatter to use for both numbers in the range. |
259 | * @return The fluent chain. |
260 | * @stable ICU 63 |
261 | */ |
262 | Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) const &; |
263 | |
264 | /** |
265 | * Overload of numberFormatterBoth() for use on an rvalue reference. |
266 | * |
267 | * @param formatter |
268 | * The formatter to use for both numbers in the range. |
269 | * @return The fluent chain. |
270 | * @see #numberFormatterBoth |
271 | * @stable ICU 63 |
272 | */ |
273 | Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) &&; |
274 | |
275 | /** |
276 | * Overload of numberFormatterBoth() for use on an rvalue reference. |
277 | * |
278 | * @param formatter |
279 | * The formatter to use for both numbers in the range. |
280 | * @return The fluent chain. |
281 | * @see #numberFormatterBoth |
282 | * @stable ICU 63 |
283 | */ |
284 | Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) const &; |
285 | |
286 | /** |
287 | * Overload of numberFormatterBoth() for use on an rvalue reference. |
288 | * |
289 | * @param formatter |
290 | * The formatter to use for both numbers in the range. |
291 | * @return The fluent chain. |
292 | * @see #numberFormatterBoth |
293 | * @stable ICU 63 |
294 | */ |
295 | Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) &&; |
296 | |
297 | /** |
298 | * Sets the NumberFormatter instance to use for the first number in the range. |
299 | * <p> |
300 | * The NumberFormatter instances must not have a locale applied yet; the locale specified on the |
301 | * NumberRangeFormatter will be used. |
302 | * |
303 | * @param formatterFirst |
304 | * The formatter to use for the first number in the range. |
305 | * @return The fluent chain. |
306 | * @stable ICU 63 |
307 | */ |
308 | Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) const &; |
309 | |
310 | /** |
311 | * Overload of numberFormatterFirst() for use on an rvalue reference. |
312 | * |
313 | * @param formatterFirst |
314 | * The formatter to use for the first number in the range. |
315 | * @return The fluent chain. |
316 | * @see #numberFormatterFirst |
317 | * @stable ICU 63 |
318 | */ |
319 | Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) &&; |
320 | |
321 | /** |
322 | * Overload of numberFormatterFirst() for use on an rvalue reference. |
323 | * |
324 | * @param formatterFirst |
325 | * The formatter to use for the first number in the range. |
326 | * @return The fluent chain. |
327 | * @see #numberFormatterFirst |
328 | * @stable ICU 63 |
329 | */ |
330 | Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) const &; |
331 | |
332 | /** |
333 | * Overload of numberFormatterFirst() for use on an rvalue reference. |
334 | * |
335 | * @param formatterFirst |
336 | * The formatter to use for the first number in the range. |
337 | * @return The fluent chain. |
338 | * @see #numberFormatterFirst |
339 | * @stable ICU 63 |
340 | */ |
341 | Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) &&; |
342 | |
343 | /** |
344 | * Sets the NumberFormatter instance to use for the second number in the range. |
345 | * <p> |
346 | * The NumberFormatter instances must not have a locale applied yet; the locale specified on the |
347 | * NumberRangeFormatter will be used. |
348 | * |
349 | * @param formatterSecond |
350 | * The formatter to use for the second number in the range. |
351 | * @return The fluent chain. |
352 | * @stable ICU 63 |
353 | */ |
354 | Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) const &; |
355 | |
356 | /** |
357 | * Overload of numberFormatterSecond() for use on an rvalue reference. |
358 | * |
359 | * @param formatterSecond |
360 | * The formatter to use for the second number in the range. |
361 | * @return The fluent chain. |
362 | * @see #numberFormatterSecond |
363 | * @stable ICU 63 |
364 | */ |
365 | Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) &&; |
366 | |
367 | /** |
368 | * Overload of numberFormatterSecond() for use on an rvalue reference. |
369 | * |
370 | * @param formatterSecond |
371 | * The formatter to use for the second number in the range. |
372 | * @return The fluent chain. |
373 | * @see #numberFormatterSecond |
374 | * @stable ICU 63 |
375 | */ |
376 | Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) const &; |
377 | |
378 | /** |
379 | * Overload of numberFormatterSecond() for use on an rvalue reference. |
380 | * |
381 | * @param formatterSecond |
382 | * The formatter to use for the second number in the range. |
383 | * @return The fluent chain. |
384 | * @see #numberFormatterSecond |
385 | * @stable ICU 63 |
386 | */ |
387 | Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) &&; |
388 | |
389 | /** |
390 | * Sets the aggressiveness of "collapsing" fields across the range separator. Possible values: |
391 | * <p> |
392 | * <ul> |
393 | * <li>ALL: "3-5K miles"</li> |
394 | * <li>UNIT: "3K - 5K miles"</li> |
395 | * <li>NONE: "3K miles - 5K miles"</li> |
396 | * <li>AUTO: usually UNIT or NONE, depending on the locale and formatter settings</li> |
397 | * </ul> |
398 | * <p> |
399 | * The default value is AUTO. |
400 | * |
401 | * @param collapse |
402 | * The collapsing strategy to use for this range. |
403 | * @return The fluent chain. |
404 | * @stable ICU 63 |
405 | */ |
406 | Derived collapse(UNumberRangeCollapse collapse) const &; |
407 | |
408 | /** |
409 | * Overload of collapse() for use on an rvalue reference. |
410 | * |
411 | * @param collapse |
412 | * The collapsing strategy to use for this range. |
413 | * @return The fluent chain. |
414 | * @see #collapse |
415 | * @stable ICU 63 |
416 | */ |
417 | Derived collapse(UNumberRangeCollapse collapse) &&; |
418 | |
419 | /** |
420 | * Sets the behavior when the two sides of the range are the same. This could happen if the same two numbers are |
421 | * passed to the formatRange function, or if different numbers are passed to the function but they become the same |
422 | * after rounding rules are applied. Possible values: |
423 | * <p> |
424 | * <ul> |
425 | * <li>SINGLE_VALUE: "5 miles"</li> |
426 | * <li>APPROXIMATELY_OR_SINGLE_VALUE: "~5 miles" or "5 miles", depending on whether the number was the same before |
427 | * rounding was applied</li> |
428 | * <li>APPROXIMATELY: "~5 miles"</li> |
429 | * <li>RANGE: "5-5 miles" (with collapse=UNIT)</li> |
430 | * </ul> |
431 | * <p> |
432 | * The default value is APPROXIMATELY. |
433 | * |
434 | * @param identityFallback |
435 | * The strategy to use when formatting two numbers that end up being the same. |
436 | * @return The fluent chain. |
437 | * @stable ICU 63 |
438 | */ |
439 | Derived identityFallback(UNumberRangeIdentityFallback identityFallback) const &; |
440 | |
441 | /** |
442 | * Overload of identityFallback() for use on an rvalue reference. |
443 | * |
444 | * @param identityFallback |
445 | * The strategy to use when formatting two numbers that end up being the same. |
446 | * @return The fluent chain. |
447 | * @see #identityFallback |
448 | * @stable ICU 63 |
449 | */ |
450 | Derived identityFallback(UNumberRangeIdentityFallback identityFallback) &&; |
451 | |
452 | #ifndef U_HIDE_DRAFT_API |
453 | /** |
454 | * Returns the current (Un)LocalizedNumberRangeFormatter as a LocalPointer |
455 | * wrapping a heap-allocated copy of the current object. |
456 | * |
457 | * This is equivalent to new-ing the move constructor with a value object |
458 | * as the argument. |
459 | * |
460 | * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped |
461 | * nullptr on failure. |
462 | * @draft ICU 64 |
463 | */ |
464 | LocalPointer<Derived> clone() const &; |
465 | |
466 | /** |
467 | * Overload of clone for use on an rvalue reference. |
468 | * |
469 | * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped |
470 | * nullptr on failure. |
471 | * @draft ICU 64 |
472 | */ |
473 | LocalPointer<Derived> clone() &&; |
474 | #endif /* U_HIDE_DRAFT_API */ |
475 | |
476 | /** |
477 | * Sets the UErrorCode if an error occurred in the fluent chain. |
478 | * Preserves older error codes in the outErrorCode. |
479 | * @return TRUE if U_FAILURE(outErrorCode) |
480 | * @stable ICU 63 |
481 | */ |
482 | UBool copyErrorTo(UErrorCode &outErrorCode) const { |
483 | if (U_FAILURE(outErrorCode)) { |
484 | // Do not overwrite the older error code |
485 | return TRUE; |
486 | } |
487 | fMacros.copyErrorTo(outErrorCode); |
488 | return U_FAILURE(outErrorCode); |
489 | } |
490 | |
491 | // NOTE: Uses default copy and move constructors. |
492 | |
493 | private: |
494 | impl::RangeMacroProps fMacros; |
495 | |
496 | // Don't construct me directly! Use (Un)LocalizedNumberFormatter. |
497 | NumberRangeFormatterSettings() = default; |
498 | |
499 | friend class LocalizedNumberRangeFormatter; |
500 | friend class UnlocalizedNumberRangeFormatter; |
501 | }; |
502 | |
503 | /** |
504 | * A NumberRangeFormatter that does not yet have a locale. In order to format, a locale must be specified. |
505 | * |
506 | * Instances of this class are immutable and thread-safe. |
507 | * |
508 | * @see NumberRangeFormatter |
509 | * @stable ICU 63 |
510 | */ |
511 | class U_I18N_API UnlocalizedNumberRangeFormatter |
512 | : public NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>, public UMemory { |
513 | |
514 | public: |
515 | /** |
516 | * Associate the given locale with the number range formatter. The locale is used for picking the |
517 | * appropriate symbols, formats, and other data for number display. |
518 | * |
519 | * @param locale |
520 | * The locale to use when loading data for number formatting. |
521 | * @return The fluent chain. |
522 | * @stable ICU 63 |
523 | */ |
524 | LocalizedNumberRangeFormatter locale(const icu::Locale &locale) const &; |
525 | |
526 | /** |
527 | * Overload of locale() for use on an rvalue reference. |
528 | * |
529 | * @param locale |
530 | * The locale to use when loading data for number formatting. |
531 | * @return The fluent chain. |
532 | * @see #locale |
533 | * @stable ICU 63 |
534 | */ |
535 | LocalizedNumberRangeFormatter locale(const icu::Locale &locale) &&; |
536 | |
537 | /** |
538 | * Default constructor: puts the formatter into a valid but undefined state. |
539 | * |
540 | * @stable ICU 63 |
541 | */ |
542 | UnlocalizedNumberRangeFormatter() = default; |
543 | |
544 | /** |
545 | * Returns a copy of this UnlocalizedNumberRangeFormatter. |
546 | * @stable ICU 63 |
547 | */ |
548 | UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter &other); |
549 | |
550 | /** |
551 | * Move constructor: |
552 | * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state. |
553 | * @stable ICU 63 |
554 | */ |
555 | UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&& src) U_NOEXCEPT; |
556 | |
557 | /** |
558 | * Copy assignment operator. |
559 | * @stable ICU 63 |
560 | */ |
561 | UnlocalizedNumberRangeFormatter& operator=(const UnlocalizedNumberRangeFormatter& other); |
562 | |
563 | /** |
564 | * Move assignment operator: |
565 | * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state. |
566 | * @stable ICU 63 |
567 | */ |
568 | UnlocalizedNumberRangeFormatter& operator=(UnlocalizedNumberRangeFormatter&& src) U_NOEXCEPT; |
569 | |
570 | private: |
571 | explicit UnlocalizedNumberRangeFormatter( |
572 | const NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>& other); |
573 | |
574 | explicit UnlocalizedNumberRangeFormatter( |
575 | NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>&& src) U_NOEXCEPT; |
576 | |
577 | // To give the fluent setters access to this class's constructor: |
578 | friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>; |
579 | |
580 | // To give NumberRangeFormatter::with() access to this class's constructor: |
581 | friend class NumberRangeFormatter; |
582 | }; |
583 | |
584 | /** |
585 | * A NumberRangeFormatter that has a locale associated with it; this means .formatRange() methods are available. |
586 | * |
587 | * Instances of this class are immutable and thread-safe. |
588 | * |
589 | * @see NumberFormatter |
590 | * @stable ICU 63 |
591 | */ |
592 | class U_I18N_API LocalizedNumberRangeFormatter |
593 | : public NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>, public UMemory { |
594 | public: |
595 | /** |
596 | * Format the given Formattables to a string using the settings specified in the NumberRangeFormatter fluent setting |
597 | * chain. |
598 | * |
599 | * @param first |
600 | * The first number in the range, usually to the left in LTR locales. |
601 | * @param second |
602 | * The second number in the range, usually to the right in LTR locales. |
603 | * @param status |
604 | * Set if an error occurs while formatting. |
605 | * @return A FormattedNumberRange object; call .toString() to get the string. |
606 | * @stable ICU 63 |
607 | */ |
608 | FormattedNumberRange formatFormattableRange( |
609 | const Formattable& first, const Formattable& second, UErrorCode& status) const; |
610 | |
611 | /** |
612 | * Default constructor: puts the formatter into a valid but undefined state. |
613 | * |
614 | * @stable ICU 63 |
615 | */ |
616 | LocalizedNumberRangeFormatter() = default; |
617 | |
618 | /** |
619 | * Returns a copy of this LocalizedNumberRangeFormatter. |
620 | * @stable ICU 63 |
621 | */ |
622 | LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter &other); |
623 | |
624 | /** |
625 | * Move constructor: |
626 | * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state. |
627 | * @stable ICU 63 |
628 | */ |
629 | LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT; |
630 | |
631 | /** |
632 | * Copy assignment operator. |
633 | * @stable ICU 63 |
634 | */ |
635 | LocalizedNumberRangeFormatter& operator=(const LocalizedNumberRangeFormatter& other); |
636 | |
637 | /** |
638 | * Move assignment operator: |
639 | * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state. |
640 | * @stable ICU 63 |
641 | */ |
642 | LocalizedNumberRangeFormatter& operator=(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT; |
643 | |
644 | #ifndef U_HIDE_INTERNAL_API |
645 | |
646 | /** |
647 | * @param results |
648 | * The results object. This method will mutate it to save the results. |
649 | * @param equalBeforeRounding |
650 | * Whether the number was equal before copying it into a DecimalQuantity. |
651 | * Used for determining the identity fallback behavior. |
652 | * @param status |
653 | * Set if an error occurs while formatting. |
654 | * @internal |
655 | */ |
656 | void formatImpl(impl::UFormattedNumberRangeData& results, bool equalBeforeRounding, |
657 | UErrorCode& status) const; |
658 | |
659 | #endif /* U_HIDE_INTERNAL_API */ |
660 | |
661 | /** |
662 | * Destruct this LocalizedNumberRangeFormatter, cleaning up any memory it might own. |
663 | * @stable ICU 63 |
664 | */ |
665 | ~LocalizedNumberRangeFormatter(); |
666 | |
667 | private: |
668 | std::atomic<impl::NumberRangeFormatterImpl*> fAtomicFormatter = {}; |
669 | |
670 | const impl::NumberRangeFormatterImpl* getFormatter(UErrorCode& stauts) const; |
671 | |
672 | explicit LocalizedNumberRangeFormatter( |
673 | const NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>& other); |
674 | |
675 | explicit LocalizedNumberRangeFormatter( |
676 | NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>&& src) U_NOEXCEPT; |
677 | |
678 | LocalizedNumberRangeFormatter(const impl::RangeMacroProps ¯os, const Locale &locale); |
679 | |
680 | LocalizedNumberRangeFormatter(impl::RangeMacroProps &¯os, const Locale &locale); |
681 | |
682 | void clear(); |
683 | |
684 | // To give the fluent setters access to this class's constructor: |
685 | friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>; |
686 | friend class NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>; |
687 | |
688 | // To give UnlocalizedNumberRangeFormatter::locale() access to this class's constructor: |
689 | friend class UnlocalizedNumberRangeFormatter; |
690 | }; |
691 | |
692 | /** |
693 | * The result of a number range formatting operation. This class allows the result to be exported in several data types, |
694 | * including a UnicodeString and a FieldPositionIterator. |
695 | * |
696 | * Instances of this class are immutable and thread-safe. |
697 | * |
698 | * @stable ICU 63 |
699 | */ |
700 | class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue { |
701 | public: |
702 | // Copybrief: this method is older than the parent method |
703 | /** |
704 | * @copybrief FormattedValue::toString() |
705 | * |
706 | * For more information, see FormattedValue::toString() |
707 | * |
708 | * @stable ICU 63 |
709 | */ |
710 | UnicodeString toString(UErrorCode& status) const U_OVERRIDE; |
711 | |
712 | // Copydoc: this method is new in ICU 64 |
713 | /** @copydoc FormattedValue::toTempString() */ |
714 | UnicodeString toTempString(UErrorCode& status) const U_OVERRIDE; |
715 | |
716 | // Copybrief: this method is older than the parent method |
717 | /** |
718 | * @copybrief FormattedValue::appendTo() |
719 | * |
720 | * For more information, see FormattedValue::appendTo() |
721 | * |
722 | * @stable ICU 63 |
723 | */ |
724 | Appendable &appendTo(Appendable &appendable, UErrorCode& status) const U_OVERRIDE; |
725 | |
726 | // Copydoc: this method is new in ICU 64 |
727 | /** @copydoc FormattedValue::nextPosition() */ |
728 | UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE; |
729 | |
730 | #ifndef U_HIDE_DRAFT_API |
731 | /** |
732 | * Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the given |
733 | * <em>field</em> in the output string. This allows you to determine the locations of, for example, |
734 | * the integer part, fraction part, or symbols. |
735 | * |
736 | * If both sides of the range have the same field, the field will occur twice, once before the |
737 | * range separator and once after the range separator, if applicable. |
738 | * |
739 | * If a field occurs just once, calling this method will find that occurrence and return it. If a |
740 | * field occurs multiple times, this method may be called repeatedly with the following pattern: |
741 | * |
742 | * <pre> |
743 | * FieldPosition fpos(UNUM_INTEGER_FIELD); |
744 | * while (formattedNumberRange.nextFieldPosition(fpos, status)) { |
745 | * // do something with fpos. |
746 | * } |
747 | * </pre> |
748 | * |
749 | * This method is useful if you know which field to query. If you want all available field position |
750 | * information, use #getAllFieldPositions(). |
751 | * |
752 | * @param fieldPosition |
753 | * Input+output variable. See {@link FormattedNumber#nextFieldPosition}. |
754 | * @param status |
755 | * Set if an error occurs while populating the FieldPosition. |
756 | * @return TRUE if a new occurrence of the field was found; FALSE otherwise. |
757 | * @draft ICU 63 |
758 | * @see UNumberFormatFields |
759 | */ |
760 | UBool nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const; |
761 | |
762 | /** |
763 | * Export the formatted number range to a FieldPositionIterator. This allows you to determine which characters in |
764 | * the output string correspond to which <em>fields</em>, such as the integer part, fraction part, and sign. |
765 | * |
766 | * If information on only one field is needed, use #nextFieldPosition() instead. |
767 | * |
768 | * @param iterator |
769 | * The FieldPositionIterator to populate with all of the fields present in the formatted number. |
770 | * @param status |
771 | * Set if an error occurs while populating the FieldPositionIterator. |
772 | * @draft ICU 63 |
773 | * @see UNumberFormatFields |
774 | */ |
775 | void getAllFieldPositions(FieldPositionIterator &iterator, UErrorCode &status) const; |
776 | |
777 | /** |
778 | * Export the first formatted number as a decimal number. This endpoint |
779 | * is useful for obtaining the exact number being printed after scaling |
780 | * and rounding have been applied by the number range formatting pipeline. |
781 | * |
782 | * The syntax of the unformatted number is a "numeric string" |
783 | * as defined in the Decimal Arithmetic Specification, available at |
784 | * http://speleotrove.com/decimal |
785 | * |
786 | * @return A decimal representation of the first formatted number. |
787 | * @draft ICU 63 |
788 | * @see NumberRangeFormatter |
789 | * @see #getSecondDecimal |
790 | */ |
791 | UnicodeString getFirstDecimal(UErrorCode& status) const; |
792 | |
793 | /** |
794 | * Export the second formatted number as a decimal number. This endpoint |
795 | * is useful for obtaining the exact number being printed after scaling |
796 | * and rounding have been applied by the number range formatting pipeline. |
797 | * |
798 | * The syntax of the unformatted number is a "numeric string" |
799 | * as defined in the Decimal Arithmetic Specification, available at |
800 | * http://speleotrove.com/decimal |
801 | * |
802 | * @return A decimal representation of the second formatted number. |
803 | * @draft ICU 63 |
804 | * @see NumberRangeFormatter |
805 | * @see #getFirstDecimal |
806 | */ |
807 | UnicodeString getSecondDecimal(UErrorCode& status) const; |
808 | #endif // U_HIDE_DRAFT_API |
809 | |
810 | /** |
811 | * Returns whether the pair of numbers was successfully formatted as a range or whether an identity fallback was |
812 | * used. For example, if the first and second number were the same either before or after rounding occurred, an |
813 | * identity fallback was used. |
814 | * |
815 | * @return An indication the resulting identity situation in the formatted number range. |
816 | * @stable ICU 63 |
817 | * @see UNumberRangeIdentityFallback |
818 | */ |
819 | UNumberRangeIdentityResult getIdentityResult(UErrorCode& status) const; |
820 | |
821 | /** |
822 | * Copying not supported; use move constructor instead. |
823 | */ |
824 | FormattedNumberRange(const FormattedNumberRange&) = delete; |
825 | |
826 | /** |
827 | * Copying not supported; use move assignment instead. |
828 | */ |
829 | FormattedNumberRange& operator=(const FormattedNumberRange&) = delete; |
830 | |
831 | /** |
832 | * Move constructor: |
833 | * Leaves the source FormattedNumberRange in an undefined state. |
834 | * @stable ICU 63 |
835 | */ |
836 | FormattedNumberRange(FormattedNumberRange&& src) U_NOEXCEPT; |
837 | |
838 | /** |
839 | * Move assignment: |
840 | * Leaves the source FormattedNumberRange in an undefined state. |
841 | * @stable ICU 63 |
842 | */ |
843 | FormattedNumberRange& operator=(FormattedNumberRange&& src) U_NOEXCEPT; |
844 | |
845 | /** |
846 | * Destruct an instance of FormattedNumberRange, cleaning up any memory it might own. |
847 | * @stable ICU 63 |
848 | */ |
849 | ~FormattedNumberRange(); |
850 | |
851 | private: |
852 | // Can't use LocalPointer because UFormattedNumberRangeData is forward-declared |
853 | const impl::UFormattedNumberRangeData *fData; |
854 | |
855 | // Error code for the terminal methods |
856 | UErrorCode fErrorCode; |
857 | |
858 | /** |
859 | * Internal constructor from data type. Adopts the data pointer. |
860 | */ |
861 | explicit FormattedNumberRange(impl::UFormattedNumberRangeData *results) |
862 | : fData(results), fErrorCode(U_ZERO_ERROR) {} |
863 | |
864 | explicit FormattedNumberRange(UErrorCode errorCode) |
865 | : fData(nullptr), fErrorCode(errorCode) {} |
866 | |
867 | void getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, UErrorCode& status) const; |
868 | |
869 | // To give LocalizedNumberRangeFormatter format methods access to this class's constructor: |
870 | friend class LocalizedNumberRangeFormatter; |
871 | }; |
872 | |
873 | /** |
874 | * See the main description in numberrangeformatter.h for documentation and examples. |
875 | * |
876 | * @stable ICU 63 |
877 | */ |
878 | class U_I18N_API NumberRangeFormatter final { |
879 | public: |
880 | /** |
881 | * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is not currently |
882 | * known at the call site. |
883 | * |
884 | * @return An {@link UnlocalizedNumberRangeFormatter}, to be used for chaining. |
885 | * @stable ICU 63 |
886 | */ |
887 | static UnlocalizedNumberRangeFormatter with(); |
888 | |
889 | /** |
890 | * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is known at the call |
891 | * site. |
892 | * |
893 | * @param locale |
894 | * The locale from which to load formats and symbols for number range formatting. |
895 | * @return A {@link LocalizedNumberRangeFormatter}, to be used for chaining. |
896 | * @stable ICU 63 |
897 | */ |
898 | static LocalizedNumberRangeFormatter withLocale(const Locale &locale); |
899 | |
900 | /** |
901 | * Use factory methods instead of the constructor to create a NumberFormatter. |
902 | */ |
903 | NumberRangeFormatter() = delete; |
904 | }; |
905 | |
906 | } // namespace number |
907 | U_NAMESPACE_END |
908 | |
909 | #endif /* #if !UCONFIG_NO_FORMATTING */ |
910 | |
911 | #endif /* U_SHOW_CPLUSPLUS_API */ |
912 | |
913 | #endif // __NUMBERRANGEFORMATTER_H__ |
914 | |
915 | |