• 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 #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 /**
390  * A NumberRangeFormatter that does not yet have a locale. In order to format, a locale must be specified.
391  *
392  * Instances of this class are immutable and thread-safe.
393  *
394  * @see NumberRangeFormatter
395  * @stable ICU 63
396  */
397 class U_I18N_API UnlocalizedNumberRangeFormatter
398         : public NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>, public UMemory {
399 
400   public:
401     /**
402      * Associate the given locale with the number range formatter. The locale is used for picking the
403      * appropriate symbols, formats, and other data for number display.
404      *
405      * @param locale
406      *            The locale to use when loading data for number formatting.
407      * @return The fluent chain.
408      * @stable ICU 63
409      */
410     LocalizedNumberRangeFormatter locale(const icu::Locale &locale) const &;
411 
412     /**
413      * Overload of locale() for use on an rvalue reference.
414      *
415      * @param locale
416      *            The locale to use when loading data for number formatting.
417      * @return The fluent chain.
418      * @see #locale
419      * @stable ICU 63
420      */
421     LocalizedNumberRangeFormatter locale(const icu::Locale &locale) &&;
422 
423     /**
424      * Default constructor: puts the formatter into a valid but undefined state.
425      *
426      * @stable ICU 63
427      */
428     UnlocalizedNumberRangeFormatter() = default;
429 
430     /**
431      * Returns a copy of this UnlocalizedNumberRangeFormatter.
432      * @stable ICU 63
433      */
434     UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter &other);
435 
436     /**
437      * Move constructor:
438      * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state.
439      * @stable ICU 63
440      */
441     UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&& src) U_NOEXCEPT;
442 
443     /**
444      * Copy assignment operator.
445      * @stable ICU 63
446      */
447     UnlocalizedNumberRangeFormatter& operator=(const UnlocalizedNumberRangeFormatter& other);
448 
449     /**
450      * Move assignment operator:
451      * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state.
452      * @stable ICU 63
453      */
454     UnlocalizedNumberRangeFormatter& operator=(UnlocalizedNumberRangeFormatter&& src) U_NOEXCEPT;
455 
456   private:
457     explicit UnlocalizedNumberRangeFormatter(
458             const NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>& other);
459 
460     explicit UnlocalizedNumberRangeFormatter(
461             NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>&& src) U_NOEXCEPT;
462 
463     // To give the fluent setters access to this class's constructor:
464     friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>;
465 
466     // To give NumberRangeFormatter::with() access to this class's constructor:
467     friend class NumberRangeFormatter;
468 };
469 
470 /**
471  * A NumberRangeFormatter that has a locale associated with it; this means .formatRange() methods are available.
472  *
473  * Instances of this class are immutable and thread-safe.
474  *
475  * @see NumberFormatter
476  * @stable ICU 63
477  */
478 class U_I18N_API LocalizedNumberRangeFormatter
479         : public NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>, public UMemory {
480   public:
481     /**
482      * Format the given Formattables to a string using the settings specified in the NumberRangeFormatter fluent setting
483      * chain.
484      *
485      * @param first
486      *            The first number in the range, usually to the left in LTR locales.
487      * @param second
488      *            The second number in the range, usually to the right in LTR locales.
489      * @param status
490      *            Set if an error occurs while formatting.
491      * @return A FormattedNumberRange object; call .toString() to get the string.
492      * @stable ICU 63
493      */
494     FormattedNumberRange formatFormattableRange(
495         const Formattable& first, const Formattable& second, UErrorCode& status) const;
496 
497     /**
498      * Default constructor: puts the formatter into a valid but undefined state.
499      *
500      * @stable ICU 63
501      */
502     LocalizedNumberRangeFormatter() = default;
503 
504     /**
505      * Returns a copy of this LocalizedNumberRangeFormatter.
506      * @stable ICU 63
507      */
508     LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter &other);
509 
510     /**
511      * Move constructor:
512      * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state.
513      * @stable ICU 63
514      */
515     LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT;
516 
517     /**
518      * Copy assignment operator.
519      * @stable ICU 63
520      */
521     LocalizedNumberRangeFormatter& operator=(const LocalizedNumberRangeFormatter& other);
522 
523     /**
524      * Move assignment operator:
525      * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state.
526      * @stable ICU 63
527      */
528     LocalizedNumberRangeFormatter& operator=(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT;
529 
530 #ifndef U_HIDE_INTERNAL_API
531 
532     /**
533      * @param results
534      *            The results object. This method will mutate it to save the results.
535      * @param equalBeforeRounding
536      *            Whether the number was equal before copying it into a DecimalQuantity.
537      *            Used for determining the identity fallback behavior.
538      * @param status
539      *            Set if an error occurs while formatting.
540      * @internal
541      */
542     void formatImpl(impl::UFormattedNumberRangeData& results, bool equalBeforeRounding,
543                     UErrorCode& status) const;
544 
545 #endif  /* U_HIDE_INTERNAL_API */
546 
547     /**
548      * Destruct this LocalizedNumberRangeFormatter, cleaning up any memory it might own.
549      * @stable ICU 63
550      */
551     ~LocalizedNumberRangeFormatter();
552 
553   private:
554     std::atomic<impl::NumberRangeFormatterImpl*> fAtomicFormatter = {};
555 
556     const impl::NumberRangeFormatterImpl* getFormatter(UErrorCode& stauts) const;
557 
558     explicit LocalizedNumberRangeFormatter(
559         const NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>& other);
560 
561     explicit LocalizedNumberRangeFormatter(
562         NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>&& src) U_NOEXCEPT;
563 
564     LocalizedNumberRangeFormatter(const impl::RangeMacroProps &macros, const Locale &locale);
565 
566     LocalizedNumberRangeFormatter(impl::RangeMacroProps &&macros, const Locale &locale);
567 
568     void clear();
569 
570     // To give the fluent setters access to this class's constructor:
571     friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>;
572     friend class NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>;
573 
574     // To give UnlocalizedNumberRangeFormatter::locale() access to this class's constructor:
575     friend class UnlocalizedNumberRangeFormatter;
576 };
577 
578 /**
579  * The result of a number range formatting operation. This class allows the result to be exported in several data types,
580  * including a UnicodeString and a FieldPositionIterator.
581  *
582  * Instances of this class are immutable and thread-safe.
583  *
584  * @stable ICU 63
585  */
586 class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue {
587   public:
588     // Copybrief: this method is older than the parent method
589     /**
590      * @copybrief FormattedValue::toString()
591      *
592      * For more information, see FormattedValue::toString()
593      *
594      * @stable ICU 63
595      */
596     UnicodeString toString(UErrorCode& status) const U_OVERRIDE;
597 
598     // Copydoc: this method is new in ICU 64
599     /** @copydoc FormattedValue::toTempString() */
600     UnicodeString toTempString(UErrorCode& status) const U_OVERRIDE;
601 
602     // Copybrief: this method is older than the parent method
603     /**
604      * @copybrief FormattedValue::appendTo()
605      *
606      * For more information, see FormattedValue::appendTo()
607      *
608      * @stable ICU 63
609      */
610     Appendable &appendTo(Appendable &appendable, UErrorCode& status) const U_OVERRIDE;
611 
612     // Copydoc: this method is new in ICU 64
613     /** @copydoc FormattedValue::nextPosition() */
614     UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE;
615 
616 #ifndef U_HIDE_DRAFT_API
617     /**
618      * Extracts the formatted range as a pair of decimal numbers. This endpoint
619      * is useful for obtaining the exact number being printed after scaling
620      * and rounding have been applied by the number range formatting pipeline.
621      *
622      * The syntax of the unformatted numbers is a "numeric string"
623      * as defined in the Decimal Arithmetic Specification, available at
624      * http://speleotrove.com/decimal
625      *
626      * Example C++17 call site:
627      *
628      *     auto [ first, second ] = range.getDecimalNumbers<std::string>(status);
629      *
630      * @tparam StringClass A string class compatible with StringByteSink;
631      *         for example, std::string.
632      * @param status Set if an error occurs.
633      * @return A pair of StringClasses containing the numeric strings.
634      * @draft ICU 68
635      */
636     template<typename StringClass>
637     inline std::pair<StringClass, StringClass> getDecimalNumbers(UErrorCode& status) const;
638 #endif // U_HIDE_DRAFT_API
639 
640     /**
641      * Returns whether the pair of numbers was successfully formatted as a range or whether an identity fallback was
642      * used. For example, if the first and second number were the same either before or after rounding occurred, an
643      * identity fallback was used.
644      *
645      * @return An indication the resulting identity situation in the formatted number range.
646      * @stable ICU 63
647      * @see UNumberRangeIdentityFallback
648      */
649     UNumberRangeIdentityResult getIdentityResult(UErrorCode& status) const;
650 
651     /**
652      * Copying not supported; use move constructor instead.
653      */
654     FormattedNumberRange(const FormattedNumberRange&) = delete;
655 
656     /**
657      * Copying not supported; use move assignment instead.
658      */
659     FormattedNumberRange& operator=(const FormattedNumberRange&) = delete;
660 
661     /**
662      * Move constructor:
663      * Leaves the source FormattedNumberRange in an undefined state.
664      * @stable ICU 63
665      */
666     FormattedNumberRange(FormattedNumberRange&& src) U_NOEXCEPT;
667 
668     /**
669      * Move assignment:
670      * Leaves the source FormattedNumberRange in an undefined state.
671      * @stable ICU 63
672      */
673     FormattedNumberRange& operator=(FormattedNumberRange&& src) U_NOEXCEPT;
674 
675     /**
676      * Destruct an instance of FormattedNumberRange, cleaning up any memory it might own.
677      * @stable ICU 63
678      */
679     ~FormattedNumberRange();
680 
681   private:
682     // Can't use LocalPointer because UFormattedNumberRangeData is forward-declared
683     const impl::UFormattedNumberRangeData *fData;
684 
685     // Error code for the terminal methods
686     UErrorCode fErrorCode;
687 
688     /**
689      * Internal constructor from data type. Adopts the data pointer.
690      */
FormattedNumberRange(impl::UFormattedNumberRangeData * results)691     explicit FormattedNumberRange(impl::UFormattedNumberRangeData *results)
692         : fData(results), fErrorCode(U_ZERO_ERROR) {}
693 
FormattedNumberRange(UErrorCode errorCode)694     explicit FormattedNumberRange(UErrorCode errorCode)
695         : fData(nullptr), fErrorCode(errorCode) {}
696 
697     void getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, UErrorCode& status) const;
698 
699     void getDecimalNumbers(ByteSink& sink1, ByteSink& sink2, UErrorCode& status) const;
700 
701     const impl::UFormattedNumberRangeData* getData(UErrorCode& status) const;
702 
703     // To allow PluralRules to access the underlying data
704     friend class ::icu::PluralRules;
705 
706     // To give LocalizedNumberRangeFormatter format methods access to this class's constructor:
707     friend class LocalizedNumberRangeFormatter;
708 
709     // To give C API access to internals
710     friend struct impl::UFormattedNumberRangeImpl;
711 };
712 
713 #ifndef U_HIDE_DRAFT_API
714 // inline impl of @draft ICU 68 method
715 template<typename StringClass>
getDecimalNumbers(UErrorCode & status)716 std::pair<StringClass, StringClass> FormattedNumberRange::getDecimalNumbers(UErrorCode& status) const {
717     StringClass str1;
718     StringClass str2;
719     StringByteSink<StringClass> sink1(&str1);
720     StringByteSink<StringClass> sink2(&str2);
721     getDecimalNumbers(sink1, sink2, status);
722     return std::make_pair(str1, str2);
723 }
724 #endif // U_HIDE_DRAFT_API
725 
726 /**
727  * See the main description in numberrangeformatter.h for documentation and examples.
728  *
729  * @stable ICU 63
730  */
731 class U_I18N_API NumberRangeFormatter final {
732   public:
733     /**
734      * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is not currently
735      * known at the call site.
736      *
737      * @return An {@link UnlocalizedNumberRangeFormatter}, to be used for chaining.
738      * @stable ICU 63
739      */
740     static UnlocalizedNumberRangeFormatter with();
741 
742     /**
743      * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is known at the call
744      * site.
745      *
746      * @param locale
747      *            The locale from which to load formats and symbols for number range formatting.
748      * @return A {@link LocalizedNumberRangeFormatter}, to be used for chaining.
749      * @stable ICU 63
750      */
751     static LocalizedNumberRangeFormatter withLocale(const Locale &locale);
752 
753     /**
754      * Use factory methods instead of the constructor to create a NumberFormatter.
755      */
756     NumberRangeFormatter() = delete;
757 };
758 
759 }  // namespace number
760 U_NAMESPACE_END
761 
762 #endif /* #if !UCONFIG_NO_FORMATTING */
763 
764 #endif /* U_SHOW_CPLUSPLUS_API */
765 
766 #endif // __NUMBERRANGEFORMATTER_H__
767 
768