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