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