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 */
52typedef 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 */
94typedef 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 */
134typedef 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
169U_NAMESPACE_BEGIN
170
171namespace number { // icu::number
172
173// Forward declarations:
174class UnlocalizedNumberRangeFormatter;
175class LocalizedNumberRangeFormatter;
176class FormattedNumberRange;
177
178namespace impl {
179
180// Forward declarations:
181struct RangeMacroProps;
182class DecimalQuantity;
183class UFormattedNumberRangeData;
184class 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
195U_NAMESPACE_END
196
197template struct U_I18N_API std::atomic< U_NAMESPACE_QUALIFIER number::impl::NumberRangeFormatterImpl*>;
198
199U_NAMESPACE_BEGIN
200namespace number { // icu::number
201#endif
202/** \endcond */
203
204// Other helper classes would go here, but there are none.
205
206namespace impl { // icu::number::impl
207
208// Do not enclose entire MacroProps with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
209/** @internal */
210struct 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 */
247template<typename Derived>
248class 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 */
511class 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 */
592class 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 &macros, const Locale &locale);
679
680 LocalizedNumberRangeFormatter(impl::RangeMacroProps &&macros, 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 */
700class 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 */
878class 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
907U_NAMESPACE_END
908
909#endif /* #if !UCONFIG_NO_FORMATTING */
910
911#endif /* U_SHOW_CPLUSPLUS_API */
912
913#endif // __NUMBERRANGEFORMATTER_H__
914
915