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