• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &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  */
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