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