Home | History | Annotate | Download | only in unicode
      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