xref: /aosp_15_r20/external/cronet/third_party/icu/source/i18n/unicode/numberrangeformatter.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 #include "unicode/unumberrangeformatter.h"
20 
21 /**
22  * \file
23  * \brief C++ API: Library for localized formatting of number, currency, and unit ranges.
24  *
25  * The main entrypoint to the formatting of ranges of numbers, including currencies and other units of measurement.
26  * <p>
27  * Usage example:
28  * <p>
29  * <pre>
30  * NumberRangeFormatter::with()
31  *     .identityFallback(UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE)
32  *     .numberFormatterFirst(NumberFormatter::with().adoptUnit(MeasureUnit::createMeter()))
33  *     .numberFormatterSecond(NumberFormatter::with().adoptUnit(MeasureUnit::createKilometer()))
34  *     .locale("en-GB")
35  *     .formatFormattableRange(750, 1.2, status)
36  *     .toString(status);
37  * // => "750 m - 1.2 km"
38  * </pre>
39  * <p>
40  * Like NumberFormatter, NumberRangeFormatter instances (i.e., LocalizedNumberRangeFormatter
41  * and UnlocalizedNumberRangeFormatter) are immutable and thread-safe. This API is based on the
42  * <em>fluent</em> design pattern popularized by libraries such as Google's Guava.
43  *
44  * @author Shane Carr
45  */
46 
47 
48 U_NAMESPACE_BEGIN
49 
50 // Forward declarations:
51 class PluralRules;
52 
53 namespace number {  // icu::number
54 
55 // Forward declarations:
56 class UnlocalizedNumberRangeFormatter;
57 class LocalizedNumberRangeFormatter;
58 class FormattedNumberRange;
59 
60 namespace impl {
61 
62 // Forward declarations:
63 struct RangeMacroProps;
64 class DecimalQuantity;
65 class UFormattedNumberRangeData;
66 class NumberRangeFormatterImpl;
67 struct UFormattedNumberRangeImpl;
68 
69 } // namespace impl
70 
71 
72 #if 0
73 
74 /**
75  * \cond
76  * Export an explicit template instantiation. See datefmt.h
77  * (When building DLLs for Windows this is required.)
78  */
79 #if U_PLATFORM == U_PF_WINDOWS && !defined(U_IN_DOXYGEN) && !defined(U_STATIC_IMPLEMENTATION)
80 } // namespace icu::number
81 U_NAMESPACE_END
82 
83 template struct U_I18N_API std::atomic< U_NAMESPACE_QUALIFIER number::impl::NumberRangeFormatterImpl*>;
84 
85 U_NAMESPACE_BEGIN
86 namespace number {  // icu::number
87 #endif
88 /** \endcond */
89 
90 #endif
91 
92 // Other helper classes would go here, but there are none.
93 
94 namespace impl {  // icu::number::impl
95 
96 // Do not enclose entire MacroProps with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
97 /** @internal */
98 struct U_I18N_API RangeMacroProps : public UMemory {
99     /** @internal */
100     UnlocalizedNumberFormatter formatter1; // = NumberFormatter::with();
101 
102     /** @internal */
103     UnlocalizedNumberFormatter formatter2; // = NumberFormatter::with();
104 
105     /** @internal */
106     bool singleFormatter = true;
107 
108     /** @internal */
109     UNumberRangeCollapse collapse = UNUM_RANGE_COLLAPSE_AUTO;
110 
111     /** @internal */
112     UNumberRangeIdentityFallback identityFallback = UNUM_IDENTITY_FALLBACK_APPROXIMATELY;
113 
114     /** @internal */
115     Locale locale;
116 
117     // NOTE: Uses default copy and move constructors.
118 
119     /**
120      * Check all members for errors.
121      * @internal
122      */
copyErrorToRangeMacroProps123     bool copyErrorTo(UErrorCode &status) const {
124         return formatter1.copyErrorTo(status) || formatter2.copyErrorTo(status);
125     }
126 };
127 
128 } // namespace impl
129 
130 /**
131  * An abstract base class for specifying settings related to number formatting. This class is implemented by
132  * {@link UnlocalizedNumberRangeFormatter} and {@link LocalizedNumberRangeFormatter}. This class is not intended for
133  * public subclassing.
134  */
135 template<typename Derived>
136 class U_I18N_API NumberRangeFormatterSettings {
137   public:
138     /**
139      * Sets the NumberFormatter instance to use for the numbers in the range. The same formatter is applied to both
140      * sides of the range.
141      * <p>
142      * The NumberFormatter instances must not have a locale applied yet; the locale specified on the
143      * NumberRangeFormatter will be used.
144      *
145      * @param formatter
146      *            The formatter to use for both numbers in the range.
147      * @return The fluent chain.
148      * @stable ICU 63
149      */
150     Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) const &;
151 
152     /**
153      * Overload of numberFormatterBoth() for use on an rvalue reference.
154      *
155      * @param formatter
156      *            The formatter to use for both numbers in the range.
157      * @return The fluent chain.
158      * @see #numberFormatterBoth
159      * @stable ICU 63
160      */
161     Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) &&;
162 
163     /**
164      * Overload of numberFormatterBoth() for use on an rvalue reference.
165      *
166      * @param formatter
167      *            The formatter to use for both numbers in the range.
168      * @return The fluent chain.
169      * @see #numberFormatterBoth
170      * @stable ICU 63
171      */
172     Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) const &;
173 
174     /**
175      * Overload of numberFormatterBoth() for use on an rvalue reference.
176      *
177      * @param formatter
178      *            The formatter to use for both numbers in the range.
179      * @return The fluent chain.
180      * @see #numberFormatterBoth
181      * @stable ICU 63
182      */
183     Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) &&;
184 
185     /**
186      * Sets the NumberFormatter instance to use for the first number in the range.
187      * <p>
188      * The NumberFormatter instances must not have a locale applied yet; the locale specified on the
189      * NumberRangeFormatter will be used.
190      *
191      * @param formatterFirst
192      *            The formatter to use for the first number in the range.
193      * @return The fluent chain.
194      * @stable ICU 63
195      */
196     Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) const &;
197 
198     /**
199      * Overload of numberFormatterFirst() for use on an rvalue reference.
200      *
201      * @param formatterFirst
202      *            The formatter to use for the first number in the range.
203      * @return The fluent chain.
204      * @see #numberFormatterFirst
205      * @stable ICU 63
206      */
207     Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) &&;
208 
209     /**
210      * Overload of numberFormatterFirst() for use on an rvalue reference.
211      *
212      * @param formatterFirst
213      *            The formatter to use for the first number in the range.
214      * @return The fluent chain.
215      * @see #numberFormatterFirst
216      * @stable ICU 63
217      */
218     Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) const &;
219 
220     /**
221      * Overload of numberFormatterFirst() for use on an rvalue reference.
222      *
223      * @param formatterFirst
224      *            The formatter to use for the first number in the range.
225      * @return The fluent chain.
226      * @see #numberFormatterFirst
227      * @stable ICU 63
228      */
229     Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) &&;
230 
231     /**
232      * Sets the NumberFormatter instance to use for the second number in the range.
233      * <p>
234      * The NumberFormatter instances must not have a locale applied yet; the locale specified on the
235      * NumberRangeFormatter will be used.
236      *
237      * @param formatterSecond
238      *            The formatter to use for the second number in the range.
239      * @return The fluent chain.
240      * @stable ICU 63
241      */
242     Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) const &;
243 
244     /**
245      * Overload of numberFormatterSecond() for use on an rvalue reference.
246      *
247      * @param formatterSecond
248      *            The formatter to use for the second number in the range.
249      * @return The fluent chain.
250      * @see #numberFormatterSecond
251      * @stable ICU 63
252      */
253     Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) &&;
254 
255     /**
256      * Overload of numberFormatterSecond() for use on an rvalue reference.
257      *
258      * @param formatterSecond
259      *            The formatter to use for the second number in the range.
260      * @return The fluent chain.
261      * @see #numberFormatterSecond
262      * @stable ICU 63
263      */
264     Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) const &;
265 
266     /**
267      * Overload of numberFormatterSecond() for use on an rvalue reference.
268      *
269      * @param formatterSecond
270      *            The formatter to use for the second number in the range.
271      * @return The fluent chain.
272      * @see #numberFormatterSecond
273      * @stable ICU 63
274      */
275     Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) &&;
276 
277     /**
278      * Sets the aggressiveness of "collapsing" fields across the range separator. Possible values:
279      * <p>
280      * <ul>
281      * <li>ALL: "3-5K miles"</li>
282      * <li>UNIT: "3K - 5K miles"</li>
283      * <li>NONE: "3K miles - 5K miles"</li>
284      * <li>AUTO: usually UNIT or NONE, depending on the locale and formatter settings</li>
285      * </ul>
286      * <p>
287      * The default value is AUTO.
288      *
289      * @param collapse
290      *            The collapsing strategy to use for this range.
291      * @return The fluent chain.
292      * @stable ICU 63
293      */
294     Derived collapse(UNumberRangeCollapse collapse) const &;
295 
296     /**
297      * Overload of collapse() for use on an rvalue reference.
298      *
299      * @param collapse
300      *            The collapsing strategy to use for this range.
301      * @return The fluent chain.
302      * @see #collapse
303      * @stable ICU 63
304      */
305     Derived collapse(UNumberRangeCollapse collapse) &&;
306 
307     /**
308      * Sets the behavior when the two sides of the range are the same. This could happen if the same two numbers are
309      * passed to the formatFormattableRange function, or if different numbers are passed to the function but they
310      * become the same after rounding rules are applied. Possible values:
311      * <p>
312      * <ul>
313      * <li>SINGLE_VALUE: "5 miles"</li>
314      * <li>APPROXIMATELY_OR_SINGLE_VALUE: "~5 miles" or "5 miles", depending on whether the number was the same before
315      * rounding was applied</li>
316      * <li>APPROXIMATELY: "~5 miles"</li>
317      * <li>RANGE: "5-5 miles" (with collapse=UNIT)</li>
318      * </ul>
319      * <p>
320      * The default value is APPROXIMATELY.
321      *
322      * @param identityFallback
323      *            The strategy to use when formatting two numbers that end up being the same.
324      * @return The fluent chain.
325      * @stable ICU 63
326      */
327     Derived identityFallback(UNumberRangeIdentityFallback identityFallback) const &;
328 
329     /**
330      * Overload of identityFallback() for use on an rvalue reference.
331      *
332      * @param identityFallback
333      *            The strategy to use when formatting two numbers that end up being the same.
334      * @return The fluent chain.
335      * @see #identityFallback
336      * @stable ICU 63
337      */
338     Derived identityFallback(UNumberRangeIdentityFallback identityFallback) &&;
339 
340     /**
341      * Returns the current (Un)LocalizedNumberRangeFormatter as a LocalPointer
342      * wrapping a heap-allocated copy of the current object.
343      *
344      * This is equivalent to new-ing the move constructor with a value object
345      * as the argument.
346      *
347      * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped
348      *         nullptr on failure.
349      * @stable ICU 64
350      */
351     LocalPointer<Derived> clone() const &;
352 
353     /**
354      * Overload of clone for use on an rvalue reference.
355      *
356      * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped
357      *         nullptr on failure.
358      * @stable ICU 64
359      */
360     LocalPointer<Derived> clone() &&;
361 
362     /**
363      * Sets the UErrorCode if an error occurred in the fluent chain.
364      * Preserves older error codes in the outErrorCode.
365      * @return true if U_FAILURE(outErrorCode)
366      * @stable ICU 63
367      */
copyErrorTo(UErrorCode & outErrorCode)368     UBool copyErrorTo(UErrorCode &outErrorCode) const {
369         if (U_FAILURE(outErrorCode)) {
370             // Do not overwrite the older error code
371             return true;
372         }
373         fMacros.copyErrorTo(outErrorCode);
374         return U_FAILURE(outErrorCode);
375     }
376 
377     // NOTE: Uses default copy and move constructors.
378 
379   private:
380     impl::RangeMacroProps fMacros;
381 
382     // Don't construct me directly!  Use (Un)LocalizedNumberFormatter.
383     NumberRangeFormatterSettings() = default;
384 
385     friend class LocalizedNumberRangeFormatter;
386     friend class UnlocalizedNumberRangeFormatter;
387 };
388 
389 // Explicit instantiations in source/i18n/numrange_fluent.cpp.
390 // (MSVC treats imports/exports of explicit instantiations differently.)
391 #ifndef _MSC_VER
392 extern template class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>;
393 extern template class NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>;
394 #endif
395 
396 /**
397  * A NumberRangeFormatter that does not yet have a locale. In order to format, a locale must be specified.
398  *
399  * Instances of this class are immutable and thread-safe.
400  *
401  * @see NumberRangeFormatter
402  * @stable ICU 63
403  */
404 class U_I18N_API UnlocalizedNumberRangeFormatter
405         : public NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>, public UMemory {
406 
407   public:
408     /**
409      * Associate the given locale with the number range formatter. The locale is used for picking the
410      * appropriate symbols, formats, and other data for number display.
411      *
412      * @param locale
413      *            The locale to use when loading data for number formatting.
414      * @return The fluent chain.
415      * @stable ICU 63
416      */
417     LocalizedNumberRangeFormatter locale(const icu::Locale &locale) const &;
418 
419     /**
420      * Overload of locale() for use on an rvalue reference.
421      *
422      * @param locale
423      *            The locale to use when loading data for number formatting.
424      * @return The fluent chain.
425      * @see #locale
426      * @stable ICU 63
427      */
428     LocalizedNumberRangeFormatter locale(const icu::Locale &locale) &&;
429 
430     /**
431      * Default constructor: puts the formatter into a valid but undefined state.
432      *
433      * @stable ICU 63
434      */
435     UnlocalizedNumberRangeFormatter() = default;
436 
437     /**
438      * Returns a copy of this UnlocalizedNumberRangeFormatter.
439      * @stable ICU 63
440      */
441     UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter &other);
442 
443     /**
444      * Move constructor:
445      * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state.
446      * @stable ICU 63
447      */
448     UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&& src) noexcept;
449 
450     /**
451      * Copy assignment operator.
452      * @stable ICU 63
453      */
454     UnlocalizedNumberRangeFormatter& operator=(const UnlocalizedNumberRangeFormatter& other);
455 
456     /**
457      * Move assignment operator:
458      * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state.
459      * @stable ICU 63
460      */
461     UnlocalizedNumberRangeFormatter& operator=(UnlocalizedNumberRangeFormatter&& src) noexcept;
462 
463   private:
464     explicit UnlocalizedNumberRangeFormatter(
465             const NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>& other);
466 
467     explicit UnlocalizedNumberRangeFormatter(
468             NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>&& src) noexcept;
469 
470     // To give the fluent setters access to this class's constructor:
471     friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>;
472 
473     // To give NumberRangeFormatter::with() access to this class's constructor:
474     friend class NumberRangeFormatter;
475 };
476 
477 /**
478  * A NumberRangeFormatter that has a locale associated with it; this means .formatRange() methods are available.
479  *
480  * Instances of this class are immutable and thread-safe.
481  *
482  * @see NumberFormatter
483  * @stable ICU 63
484  */
485 class U_I18N_API LocalizedNumberRangeFormatter
486         : public NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>, public UMemory {
487   public:
488     /**
489      * Format the given Formattables to a string using the settings specified in the NumberRangeFormatter fluent setting
490      * chain.
491      *
492      * @param first
493      *            The first number in the range, usually to the left in LTR locales.
494      * @param second
495      *            The second number in the range, usually to the right in LTR locales.
496      * @param status
497      *            Set if an error occurs while formatting.
498      * @return A FormattedNumberRange object; call .toString() to get the string.
499      * @stable ICU 63
500      */
501     FormattedNumberRange formatFormattableRange(
502         const Formattable& first, const Formattable& second, UErrorCode& status) const;
503 
504     /**
505      * Default constructor: puts the formatter into a valid but undefined state.
506      *
507      * @stable ICU 63
508      */
509     LocalizedNumberRangeFormatter() = default;
510 
511     /**
512      * Returns a copy of this LocalizedNumberRangeFormatter.
513      * @stable ICU 63
514      */
515     LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter &other);
516 
517     /**
518      * Move constructor:
519      * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state.
520      * @stable ICU 63
521      */
522     LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&& src) noexcept;
523 
524     /**
525      * Copy assignment operator.
526      * @stable ICU 63
527      */
528     LocalizedNumberRangeFormatter& operator=(const LocalizedNumberRangeFormatter& other);
529 
530     /**
531      * Move assignment operator:
532      * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state.
533      * @stable ICU 63
534      */
535     LocalizedNumberRangeFormatter& operator=(LocalizedNumberRangeFormatter&& src) noexcept;
536 
537 #ifndef U_HIDE_INTERNAL_API
538 
539     /**
540      * @param results
541      *            The results object. This method will mutate it to save the results.
542      * @param equalBeforeRounding
543      *            Whether the number was equal before copying it into a DecimalQuantity.
544      *            Used for determining the identity fallback behavior.
545      * @param status
546      *            Set if an error occurs while formatting.
547      * @internal
548      */
549     void formatImpl(impl::UFormattedNumberRangeData& results, bool equalBeforeRounding,
550                     UErrorCode& status) const;
551 
552 #endif  /* U_HIDE_INTERNAL_API */
553 
554     /**
555      * Destruct this LocalizedNumberRangeFormatter, cleaning up any memory it might own.
556      * @stable ICU 63
557      */
558     ~LocalizedNumberRangeFormatter();
559 
560   private:
561     std::atomic<impl::NumberRangeFormatterImpl*> fAtomicFormatter = {};
562 
563     const impl::NumberRangeFormatterImpl* getFormatter(UErrorCode& stauts) const;
564 
565     explicit LocalizedNumberRangeFormatter(
566         const NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>& other);
567 
568     explicit LocalizedNumberRangeFormatter(
569         NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>&& src) noexcept;
570 
571     LocalizedNumberRangeFormatter(const impl::RangeMacroProps &macros, const Locale &locale);
572 
573     LocalizedNumberRangeFormatter(impl::RangeMacroProps &&macros, const Locale &locale);
574 
575     // To give the fluent setters access to this class's constructor:
576     friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>;
577     friend class NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>;
578 
579     // To give UnlocalizedNumberRangeFormatter::locale() access to this class's constructor:
580     friend class UnlocalizedNumberRangeFormatter;
581 };
582 
583 /**
584  * The result of a number range formatting operation. This class allows the result to be exported in several data types,
585  * including a UnicodeString and a FieldPositionIterator.
586  *
587  * Instances of this class are immutable and thread-safe.
588  *
589  * @stable ICU 63
590  */
591 class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue {
592   public:
593     // Copybrief: this method is older than the parent method
594     /**
595      * @copybrief FormattedValue::toString()
596      *
597      * For more information, see FormattedValue::toString()
598      *
599      * @stable ICU 63
600      */
601     UnicodeString toString(UErrorCode& status) const override;
602 
603     // Copydoc: this method is new in ICU 64
604     /** @copydoc FormattedValue::toTempString() */
605     UnicodeString toTempString(UErrorCode& status) const override;
606 
607     // Copybrief: this method is older than the parent method
608     /**
609      * @copybrief FormattedValue::appendTo()
610      *
611      * For more information, see FormattedValue::appendTo()
612      *
613      * @stable ICU 63
614      */
615     Appendable &appendTo(Appendable &appendable, UErrorCode& status) const override;
616 
617     // Copydoc: this method is new in ICU 64
618     /** @copydoc FormattedValue::nextPosition() */
619     UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const override;
620 
621     /**
622      * Extracts the formatted range as a pair of decimal numbers. This endpoint
623      * is useful for obtaining the exact number being printed after scaling
624      * and rounding have been applied by the number range formatting pipeline.
625      *
626      * The syntax of the unformatted numbers is a "numeric string"
627      * as defined in the Decimal Arithmetic Specification, available at
628      * http://speleotrove.com/decimal
629      *
630      * Example C++17 call site:
631      *
632      *     auto [ first, second ] = range.getDecimalNumbers<std::string>(status);
633      *
634      * @tparam StringClass A string class compatible with StringByteSink;
635      *         for example, std::string.
636      * @param status Set if an error occurs.
637      * @return A pair of StringClasses containing the numeric strings.
638      * @stable ICU 68
639      */
640     template<typename StringClass>
641     inline std::pair<StringClass, StringClass> getDecimalNumbers(UErrorCode& status) const;
642 
643     /**
644      * Returns whether the pair of numbers was successfully formatted as a range or whether an identity fallback was
645      * used. For example, if the first and second number were the same either before or after rounding occurred, an
646      * identity fallback was used.
647      *
648      * @return An indication the resulting identity situation in the formatted number range.
649      * @stable ICU 63
650      * @see UNumberRangeIdentityFallback
651      */
652     UNumberRangeIdentityResult getIdentityResult(UErrorCode& status) const;
653 
654     /**
655      * Default constructor; makes an empty FormattedNumberRange.
656      * @stable ICU 70
657      */
FormattedNumberRange()658     FormattedNumberRange()
659         : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {}
660 
661     /**
662      * Copying not supported; use move constructor instead.
663      */
664     FormattedNumberRange(const FormattedNumberRange&) = delete;
665 
666     /**
667      * Copying not supported; use move assignment instead.
668      */
669     FormattedNumberRange& operator=(const FormattedNumberRange&) = delete;
670 
671     /**
672      * Move constructor:
673      * Leaves the source FormattedNumberRange in an undefined state.
674      * @stable ICU 63
675      */
676     FormattedNumberRange(FormattedNumberRange&& src) noexcept;
677 
678     /**
679      * Move assignment:
680      * Leaves the source FormattedNumberRange in an undefined state.
681      * @stable ICU 63
682      */
683     FormattedNumberRange& operator=(FormattedNumberRange&& src) noexcept;
684 
685     /**
686      * Destruct an instance of FormattedNumberRange, cleaning up any memory it might own.
687      * @stable ICU 63
688      */
689     ~FormattedNumberRange();
690 
691   private:
692     // Can't use LocalPointer because UFormattedNumberRangeData is forward-declared
693     const impl::UFormattedNumberRangeData *fData;
694 
695     // Error code for the terminal methods
696     UErrorCode fErrorCode;
697 
698     /**
699      * Internal constructor from data type. Adopts the data pointer.
700      */
FormattedNumberRange(impl::UFormattedNumberRangeData * results)701     explicit FormattedNumberRange(impl::UFormattedNumberRangeData *results)
702         : fData(results), fErrorCode(U_ZERO_ERROR) {}
703 
FormattedNumberRange(UErrorCode errorCode)704     explicit FormattedNumberRange(UErrorCode errorCode)
705         : fData(nullptr), fErrorCode(errorCode) {}
706 
707     void getDecimalNumbers(ByteSink& sink1, ByteSink& sink2, UErrorCode& status) const;
708 
709     const impl::UFormattedNumberRangeData* getData(UErrorCode& status) const;
710 
711     // To allow PluralRules to access the underlying data
712     friend class ::icu::PluralRules;
713 
714     // To give LocalizedNumberRangeFormatter format methods access to this class's constructor:
715     friend class LocalizedNumberRangeFormatter;
716 
717     // To give C API access to internals
718     friend struct impl::UFormattedNumberRangeImpl;
719 };
720 
721 // inline impl of @stable ICU 68 method
722 template<typename StringClass>
getDecimalNumbers(UErrorCode & status)723 std::pair<StringClass, StringClass> FormattedNumberRange::getDecimalNumbers(UErrorCode& status) const {
724     StringClass str1;
725     StringClass str2;
726     StringByteSink<StringClass> sink1(&str1);
727     StringByteSink<StringClass> sink2(&str2);
728     getDecimalNumbers(sink1, sink2, status);
729     return std::make_pair(str1, str2);
730 }
731 
732 /**
733  * See the main description in numberrangeformatter.h for documentation and examples.
734  *
735  * @stable ICU 63
736  */
737 class U_I18N_API NumberRangeFormatter final {
738   public:
739     /**
740      * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is not currently
741      * known at the call site.
742      *
743      * @return An {@link UnlocalizedNumberRangeFormatter}, to be used for chaining.
744      * @stable ICU 63
745      */
746     static UnlocalizedNumberRangeFormatter with();
747 
748     /**
749      * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is known at the call
750      * site.
751      *
752      * @param locale
753      *            The locale from which to load formats and symbols for number range formatting.
754      * @return A {@link LocalizedNumberRangeFormatter}, to be used for chaining.
755      * @stable ICU 63
756      */
757     static LocalizedNumberRangeFormatter withLocale(const Locale &locale);
758 
759     /**
760      * Use factory methods instead of the constructor to create a NumberFormatter.
761      */
762     NumberRangeFormatter() = delete;
763 };
764 
765 }  // namespace number
766 U_NAMESPACE_END
767 
768 #endif /* #if !UCONFIG_NO_FORMATTING */
769 
770 #endif /* U_SHOW_CPLUSPLUS_API */
771 
772 #endif // __NUMBERRANGEFORMATTER_H__
773 
774