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 20 /** 21 * \file 22 * \brief C++ API: Library for localized formatting of number, currency, and unit ranges. 23 * 24 * The main entrypoint to the formatting of ranges of numbers, including currencies and other units of measurement. 25 * <p> 26 * Usage example: 27 * <p> 28 * <pre> 29 * NumberRangeFormatter::with() 30 * .identityFallback(UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE) 31 * .numberFormatterFirst(NumberFormatter::with().adoptUnit(MeasureUnit::createMeter())) 32 * .numberFormatterSecond(NumberFormatter::with().adoptUnit(MeasureUnit::createKilometer())) 33 * .locale("en-GB") 34 * .formatRange(750, 1.2, status) 35 * .toString(status); 36 * // => "750 m - 1.2 km" 37 * </pre> 38 * <p> 39 * Like NumberFormatter, NumberRangeFormatter instances (i.e., LocalizedNumberRangeFormatter 40 * and UnlocalizedNumberRangeFormatter) are immutable and thread-safe. This API is based on the 41 * <em>fluent</em> design pattern popularized by libraries such as Google's Guava. 42 * 43 * @author Shane Carr 44 */ 45 46 47 /** 48 * Defines how to merge fields that are identical across the range sign. 49 * 50 * @stable ICU 63 51 */ 52 typedef enum UNumberRangeCollapse { 53 /** 54 * Use locale data and heuristics to determine how much of the string to collapse. Could end up collapsing none, 55 * some, or all repeated pieces in a locale-sensitive way. 56 * 57 * The heuristics used for this option are subject to change over time. 58 * 59 * @stable ICU 63 60 */ 61 UNUM_RANGE_COLLAPSE_AUTO, 62 63 /** 64 * Do not collapse any part of the number. Example: "3.2 thousand kilograms – 5.3 thousand kilograms" 65 * 66 * @stable ICU 63 67 */ 68 UNUM_RANGE_COLLAPSE_NONE, 69 70 /** 71 * Collapse the unit part of the number, but not the notation, if present. Example: "3.2 thousand – 5.3 thousand 72 * kilograms" 73 * 74 * @stable ICU 63 75 */ 76 UNUM_RANGE_COLLAPSE_UNIT, 77 78 /** 79 * Collapse any field that is equal across the range sign. May introduce ambiguity on the magnitude of the 80 * number. Example: "3.2 – 5.3 thousand kilograms" 81 * 82 * @stable ICU 63 83 */ 84 UNUM_RANGE_COLLAPSE_ALL 85 } UNumberRangeCollapse; 86 87 /** 88 * Defines the behavior when the two numbers in the range are identical after rounding. To programmatically detect 89 * when the identity fallback is used, compare the lower and upper BigDecimals via FormattedNumber. 90 * 91 * @stable ICU 63 92 * @see NumberRangeFormatter 93 */ 94 typedef enum UNumberRangeIdentityFallback { 95 /** 96 * Show the number as a single value rather than a range. Example: "$5" 97 * 98 * @stable ICU 63 99 */ 100 UNUM_IDENTITY_FALLBACK_SINGLE_VALUE, 101 102 /** 103 * Show the number using a locale-sensitive approximation pattern. If the numbers were the same before rounding, 104 * show the single value. Example: "~$5" or "$5" 105 * 106 * @stable ICU 63 107 */ 108 UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, 109 110 /** 111 * Show the number using a locale-sensitive approximation pattern. Use the range pattern always, even if the 112 * inputs are the same. Example: "~$5" 113 * 114 * @stable ICU 63 115 */ 116 UNUM_IDENTITY_FALLBACK_APPROXIMATELY, 117 118 /** 119 * Show the number as the range of two equal values. Use the range pattern always, even if the inputs are the 120 * same. Example (with RangeCollapse.NONE): "$5 – $5" 121 * 122 * @stable ICU 63 123 */ 124 UNUM_IDENTITY_FALLBACK_RANGE 125 } UNumberRangeIdentityFallback; 126 127 /** 128 * Used in the result class FormattedNumberRange to indicate to the user whether the numbers formatted in the range 129 * were equal or not, and whether or not the identity fallback was applied. 130 * 131 * @stable ICU 63 132 * @see NumberRangeFormatter 133 */ 134 typedef enum UNumberRangeIdentityResult { 135 /** 136 * Used to indicate that the two numbers in the range were equal, even before any rounding rules were applied. 137 * 138 * @stable ICU 63 139 * @see NumberRangeFormatter 140 */ 141 UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING, 142 143 /** 144 * Used to indicate that the two numbers in the range were equal, but only after rounding rules were applied. 145 * 146 * @stable ICU 63 147 * @see NumberRangeFormatter 148 */ 149 UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING, 150 151 /** 152 * Used to indicate that the two numbers in the range were not equal, even after rounding rules were applied. 153 * 154 * @stable ICU 63 155 * @see NumberRangeFormatter 156 */ 157 UNUM_IDENTITY_RESULT_NOT_EQUAL, 158 159 #ifndef U_HIDE_INTERNAL_API 160 /** 161 * The number of entries in this enum. 162 * @internal 163 */ 164 UNUM_IDENTITY_RESULT_COUNT 165 #endif 166 167 } UNumberRangeIdentityResult; 168 169 U_NAMESPACE_BEGIN 170 171 namespace number { // icu::number 172 173 // Forward declarations: 174 class UnlocalizedNumberRangeFormatter; 175 class LocalizedNumberRangeFormatter; 176 class FormattedNumberRange; 177 178 namespace impl { 179 180 // Forward declarations: 181 struct RangeMacroProps; 182 class DecimalQuantity; 183 class UFormattedNumberRangeData; 184 class NumberRangeFormatterImpl; 185 186 } // namespace impl 187 188 /** 189 * \cond 190 * Export an explicit template instantiation. See datefmt.h 191 * (When building DLLs for Windows this is required.) 192 */ 193 #if U_PLATFORM == U_PF_WINDOWS && !defined(U_IN_DOXYGEN) 194 } // namespace icu::number 195 U_NAMESPACE_END 196 197 template struct U_I18N_API std::atomic< U_NAMESPACE_QUALIFIER number::impl::NumberRangeFormatterImpl*>; 198 199 U_NAMESPACE_BEGIN 200 namespace number { // icu::number 201 #endif 202 /** \endcond */ 203 204 // Other helper classes would go here, but there are none. 205 206 namespace impl { // icu::number::impl 207 208 // Do not enclose entire MacroProps with #ifndef U_HIDE_INTERNAL_API, needed for a protected field 209 /** @internal */ 210 struct U_I18N_API RangeMacroProps : public UMemory { 211 /** @internal */ 212 UnlocalizedNumberFormatter formatter1; // = NumberFormatter::with(); 213 214 /** @internal */ 215 UnlocalizedNumberFormatter formatter2; // = NumberFormatter::with(); 216 217 /** @internal */ 218 bool singleFormatter = true; 219 220 /** @internal */ 221 UNumberRangeCollapse collapse = UNUM_RANGE_COLLAPSE_AUTO; 222 223 /** @internal */ 224 UNumberRangeIdentityFallback identityFallback = UNUM_IDENTITY_FALLBACK_APPROXIMATELY; 225 226 /** @internal */ 227 Locale locale; 228 229 // NOTE: Uses default copy and move constructors. 230 231 /** 232 * Check all members for errors. 233 * @internal 234 */ 235 bool copyErrorTo(UErrorCode &status) const { 236 return formatter1.copyErrorTo(status) || formatter2.copyErrorTo(status); 237 } 238 }; 239 240 } // namespace impl 241 242 /** 243 * An abstract base class for specifying settings related to number formatting. This class is implemented by 244 * {@link UnlocalizedNumberRangeFormatter} and {@link LocalizedNumberRangeFormatter}. This class is not intended for 245 * public subclassing. 246 */ 247 template<typename Derived> 248 class U_I18N_API NumberRangeFormatterSettings { 249 public: 250 /** 251 * Sets the NumberFormatter instance to use for the numbers in the range. The same formatter is applied to both 252 * sides of the range. 253 * <p> 254 * The NumberFormatter instances must not have a locale applied yet; the locale specified on the 255 * NumberRangeFormatter will be used. 256 * 257 * @param formatter 258 * The formatter to use for both numbers in the range. 259 * @return The fluent chain. 260 * @stable ICU 63 261 */ 262 Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) const &; 263 264 /** 265 * Overload of numberFormatterBoth() for use on an rvalue reference. 266 * 267 * @param formatter 268 * The formatter to use for both numbers in the range. 269 * @return The fluent chain. 270 * @see #numberFormatterBoth 271 * @stable ICU 63 272 */ 273 Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) &&; 274 275 /** 276 * Overload of numberFormatterBoth() for use on an rvalue reference. 277 * 278 * @param formatter 279 * The formatter to use for both numbers in the range. 280 * @return The fluent chain. 281 * @see #numberFormatterBoth 282 * @stable ICU 63 283 */ 284 Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) const &; 285 286 /** 287 * Overload of numberFormatterBoth() for use on an rvalue reference. 288 * 289 * @param formatter 290 * The formatter to use for both numbers in the range. 291 * @return The fluent chain. 292 * @see #numberFormatterBoth 293 * @stable ICU 63 294 */ 295 Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) &&; 296 297 /** 298 * Sets the NumberFormatter instance to use for the first number in the range. 299 * <p> 300 * The NumberFormatter instances must not have a locale applied yet; the locale specified on the 301 * NumberRangeFormatter will be used. 302 * 303 * @param formatterFirst 304 * The formatter to use for the first number in the range. 305 * @return The fluent chain. 306 * @stable ICU 63 307 */ 308 Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) const &; 309 310 /** 311 * Overload of numberFormatterFirst() for use on an rvalue reference. 312 * 313 * @param formatterFirst 314 * The formatter to use for the first number in the range. 315 * @return The fluent chain. 316 * @see #numberFormatterFirst 317 * @stable ICU 63 318 */ 319 Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) &&; 320 321 /** 322 * Overload of numberFormatterFirst() for use on an rvalue reference. 323 * 324 * @param formatterFirst 325 * The formatter to use for the first number in the range. 326 * @return The fluent chain. 327 * @see #numberFormatterFirst 328 * @stable ICU 63 329 */ 330 Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) const &; 331 332 /** 333 * Overload of numberFormatterFirst() for use on an rvalue reference. 334 * 335 * @param formatterFirst 336 * The formatter to use for the first number in the range. 337 * @return The fluent chain. 338 * @see #numberFormatterFirst 339 * @stable ICU 63 340 */ 341 Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) &&; 342 343 /** 344 * Sets the NumberFormatter instance to use for the second number in the range. 345 * <p> 346 * The NumberFormatter instances must not have a locale applied yet; the locale specified on the 347 * NumberRangeFormatter will be used. 348 * 349 * @param formatterSecond 350 * The formatter to use for the second number in the range. 351 * @return The fluent chain. 352 * @stable ICU 63 353 */ 354 Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) const &; 355 356 /** 357 * Overload of numberFormatterSecond() for use on an rvalue reference. 358 * 359 * @param formatterSecond 360 * The formatter to use for the second number in the range. 361 * @return The fluent chain. 362 * @see #numberFormatterSecond 363 * @stable ICU 63 364 */ 365 Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) &&; 366 367 /** 368 * Overload of numberFormatterSecond() for use on an rvalue reference. 369 * 370 * @param formatterSecond 371 * The formatter to use for the second number in the range. 372 * @return The fluent chain. 373 * @see #numberFormatterSecond 374 * @stable ICU 63 375 */ 376 Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) const &; 377 378 /** 379 * Overload of numberFormatterSecond() for use on an rvalue reference. 380 * 381 * @param formatterSecond 382 * The formatter to use for the second number in the range. 383 * @return The fluent chain. 384 * @see #numberFormatterSecond 385 * @stable ICU 63 386 */ 387 Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) &&; 388 389 /** 390 * Sets the aggressiveness of "collapsing" fields across the range separator. Possible values: 391 * <p> 392 * <ul> 393 * <li>ALL: "3-5K miles"</li> 394 * <li>UNIT: "3K - 5K miles"</li> 395 * <li>NONE: "3K miles - 5K miles"</li> 396 * <li>AUTO: usually UNIT or NONE, depending on the locale and formatter settings</li> 397 * </ul> 398 * <p> 399 * The default value is AUTO. 400 * 401 * @param collapse 402 * The collapsing strategy to use for this range. 403 * @return The fluent chain. 404 * @stable ICU 63 405 */ 406 Derived collapse(UNumberRangeCollapse collapse) const &; 407 408 /** 409 * Overload of collapse() for use on an rvalue reference. 410 * 411 * @param collapse 412 * The collapsing strategy to use for this range. 413 * @return The fluent chain. 414 * @see #collapse 415 * @stable ICU 63 416 */ 417 Derived collapse(UNumberRangeCollapse collapse) &&; 418 419 /** 420 * Sets the behavior when the two sides of the range are the same. This could happen if the same two numbers are 421 * passed to the formatRange function, or if different numbers are passed to the function but they become the same 422 * after rounding rules are applied. Possible values: 423 * <p> 424 * <ul> 425 * <li>SINGLE_VALUE: "5 miles"</li> 426 * <li>APPROXIMATELY_OR_SINGLE_VALUE: "~5 miles" or "5 miles", depending on whether the number was the same before 427 * rounding was applied</li> 428 * <li>APPROXIMATELY: "~5 miles"</li> 429 * <li>RANGE: "5-5 miles" (with collapse=UNIT)</li> 430 * </ul> 431 * <p> 432 * The default value is APPROXIMATELY. 433 * 434 * @param identityFallback 435 * The strategy to use when formatting two numbers that end up being the same. 436 * @return The fluent chain. 437 * @stable ICU 63 438 */ 439 Derived identityFallback(UNumberRangeIdentityFallback identityFallback) const &; 440 441 /** 442 * Overload of identityFallback() for use on an rvalue reference. 443 * 444 * @param identityFallback 445 * The strategy to use when formatting two numbers that end up being the same. 446 * @return The fluent chain. 447 * @see #identityFallback 448 * @stable ICU 63 449 */ 450 Derived identityFallback(UNumberRangeIdentityFallback identityFallback) &&; 451 452 #ifndef U_HIDE_DRAFT_API 453 /** 454 * Returns the current (Un)LocalizedNumberRangeFormatter as a LocalPointer 455 * wrapping a heap-allocated copy of the current object. 456 * 457 * This is equivalent to new-ing the move constructor with a value object 458 * as the argument. 459 * 460 * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped 461 * nullptr on failure. 462 * @draft ICU 64 463 */ 464 LocalPointer<Derived> clone() const &; 465 466 /** 467 * Overload of clone for use on an rvalue reference. 468 * 469 * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped 470 * nullptr on failure. 471 * @draft ICU 64 472 */ 473 LocalPointer<Derived> clone() &&; 474 #endif /* U_HIDE_DRAFT_API */ 475 476 /** 477 * Sets the UErrorCode if an error occurred in the fluent chain. 478 * Preserves older error codes in the outErrorCode. 479 * @return TRUE if U_FAILURE(outErrorCode) 480 * @stable ICU 63 481 */ 482 UBool copyErrorTo(UErrorCode &outErrorCode) const { 483 if (U_FAILURE(outErrorCode)) { 484 // Do not overwrite the older error code 485 return TRUE; 486 } 487 fMacros.copyErrorTo(outErrorCode); 488 return U_FAILURE(outErrorCode); 489 } 490 491 // NOTE: Uses default copy and move constructors. 492 493 private: 494 impl::RangeMacroProps fMacros; 495 496 // Don't construct me directly! Use (Un)LocalizedNumberFormatter. 497 NumberRangeFormatterSettings() = default; 498 499 friend class LocalizedNumberRangeFormatter; 500 friend class UnlocalizedNumberRangeFormatter; 501 }; 502 503 /** 504 * A NumberRangeFormatter that does not yet have a locale. In order to format, a locale must be specified. 505 * 506 * Instances of this class are immutable and thread-safe. 507 * 508 * @see NumberRangeFormatter 509 * @stable ICU 63 510 */ 511 class U_I18N_API UnlocalizedNumberRangeFormatter 512 : public NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>, public UMemory { 513 514 public: 515 /** 516 * Associate the given locale with the number range formatter. The locale is used for picking the 517 * appropriate symbols, formats, and other data for number display. 518 * 519 * @param locale 520 * The locale to use when loading data for number formatting. 521 * @return The fluent chain. 522 * @stable ICU 63 523 */ 524 LocalizedNumberRangeFormatter locale(const icu::Locale &locale) const &; 525 526 /** 527 * Overload of locale() for use on an rvalue reference. 528 * 529 * @param locale 530 * The locale to use when loading data for number formatting. 531 * @return The fluent chain. 532 * @see #locale 533 * @stable ICU 63 534 */ 535 LocalizedNumberRangeFormatter locale(const icu::Locale &locale) &&; 536 537 /** 538 * Default constructor: puts the formatter into a valid but undefined state. 539 * 540 * @stable ICU 63 541 */ 542 UnlocalizedNumberRangeFormatter() = default; 543 544 /** 545 * Returns a copy of this UnlocalizedNumberRangeFormatter. 546 * @stable ICU 63 547 */ 548 UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter &other); 549 550 /** 551 * Move constructor: 552 * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state. 553 * @stable ICU 63 554 */ 555 UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&& src) U_NOEXCEPT; 556 557 /** 558 * Copy assignment operator. 559 * @stable ICU 63 560 */ 561 UnlocalizedNumberRangeFormatter& operator=(const UnlocalizedNumberRangeFormatter& other); 562 563 /** 564 * Move assignment operator: 565 * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state. 566 * @stable ICU 63 567 */ 568 UnlocalizedNumberRangeFormatter& operator=(UnlocalizedNumberRangeFormatter&& src) U_NOEXCEPT; 569 570 private: 571 explicit UnlocalizedNumberRangeFormatter( 572 const NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>& other); 573 574 explicit UnlocalizedNumberRangeFormatter( 575 NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>&& src) U_NOEXCEPT; 576 577 // To give the fluent setters access to this class's constructor: 578 friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>; 579 580 // To give NumberRangeFormatter::with() access to this class's constructor: 581 friend class NumberRangeFormatter; 582 }; 583 584 /** 585 * A NumberRangeFormatter that has a locale associated with it; this means .formatRange() methods are available. 586 * 587 * Instances of this class are immutable and thread-safe. 588 * 589 * @see NumberFormatter 590 * @stable ICU 63 591 */ 592 class U_I18N_API LocalizedNumberRangeFormatter 593 : public NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>, public UMemory { 594 public: 595 /** 596 * Format the given Formattables to a string using the settings specified in the NumberRangeFormatter fluent setting 597 * chain. 598 * 599 * @param first 600 * The first number in the range, usually to the left in LTR locales. 601 * @param second 602 * The second number in the range, usually to the right in LTR locales. 603 * @param status 604 * Set if an error occurs while formatting. 605 * @return A FormattedNumberRange object; call .toString() to get the string. 606 * @stable ICU 63 607 */ 608 FormattedNumberRange formatFormattableRange( 609 const Formattable& first, const Formattable& second, UErrorCode& status) const; 610 611 /** 612 * Default constructor: puts the formatter into a valid but undefined state. 613 * 614 * @stable ICU 63 615 */ 616 LocalizedNumberRangeFormatter() = default; 617 618 /** 619 * Returns a copy of this LocalizedNumberRangeFormatter. 620 * @stable ICU 63 621 */ 622 LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter &other); 623 624 /** 625 * Move constructor: 626 * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state. 627 * @stable ICU 63 628 */ 629 LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT; 630 631 /** 632 * Copy assignment operator. 633 * @stable ICU 63 634 */ 635 LocalizedNumberRangeFormatter& operator=(const LocalizedNumberRangeFormatter& other); 636 637 /** 638 * Move assignment operator: 639 * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state. 640 * @stable ICU 63 641 */ 642 LocalizedNumberRangeFormatter& operator=(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT; 643 644 #ifndef U_HIDE_INTERNAL_API 645 646 /** 647 * @param results 648 * The results object. This method will mutate it to save the results. 649 * @param equalBeforeRounding 650 * Whether the number was equal before copying it into a DecimalQuantity. 651 * Used for determining the identity fallback behavior. 652 * @param status 653 * Set if an error occurs while formatting. 654 * @internal 655 */ 656 void formatImpl(impl::UFormattedNumberRangeData& results, bool equalBeforeRounding, 657 UErrorCode& status) const; 658 659 #endif /* U_HIDE_INTERNAL_API */ 660 661 /** 662 * Destruct this LocalizedNumberRangeFormatter, cleaning up any memory it might own. 663 * @stable ICU 63 664 */ 665 ~LocalizedNumberRangeFormatter(); 666 667 private: 668 std::atomic<impl::NumberRangeFormatterImpl*> fAtomicFormatter = {}; 669 670 const impl::NumberRangeFormatterImpl* getFormatter(UErrorCode& stauts) const; 671 672 explicit LocalizedNumberRangeFormatter( 673 const NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>& other); 674 675 explicit LocalizedNumberRangeFormatter( 676 NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>&& src) U_NOEXCEPT; 677 678 LocalizedNumberRangeFormatter(const impl::RangeMacroProps ¯os, const Locale &locale); 679 680 LocalizedNumberRangeFormatter(impl::RangeMacroProps &¯os, const Locale &locale); 681 682 void clear(); 683 684 // To give the fluent setters access to this class's constructor: 685 friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>; 686 friend class NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>; 687 688 // To give UnlocalizedNumberRangeFormatter::locale() access to this class's constructor: 689 friend class UnlocalizedNumberRangeFormatter; 690 }; 691 692 /** 693 * The result of a number range formatting operation. This class allows the result to be exported in several data types, 694 * including a UnicodeString and a FieldPositionIterator. 695 * 696 * Instances of this class are immutable and thread-safe. 697 * 698 * @stable ICU 63 699 */ 700 class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue { 701 public: 702 // Copybrief: this method is older than the parent method 703 /** 704 * @copybrief FormattedValue::toString() 705 * 706 * For more information, see FormattedValue::toString() 707 * 708 * @stable ICU 63 709 */ 710 UnicodeString toString(UErrorCode& status) const U_OVERRIDE; 711 712 // Copydoc: this method is new in ICU 64 713 /** @copydoc FormattedValue::toTempString() */ 714 UnicodeString toTempString(UErrorCode& status) const U_OVERRIDE; 715 716 // Copybrief: this method is older than the parent method 717 /** 718 * @copybrief FormattedValue::appendTo() 719 * 720 * For more information, see FormattedValue::appendTo() 721 * 722 * @stable ICU 63 723 */ 724 Appendable &appendTo(Appendable &appendable, UErrorCode& status) const U_OVERRIDE; 725 726 // Copydoc: this method is new in ICU 64 727 /** @copydoc FormattedValue::nextPosition() */ 728 UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE; 729 730 #ifndef U_HIDE_DRAFT_API 731 /** 732 * Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the given 733 * <em>field</em> in the output string. This allows you to determine the locations of, for example, 734 * the integer part, fraction part, or symbols. 735 * 736 * If both sides of the range have the same field, the field will occur twice, once before the 737 * range separator and once after the range separator, if applicable. 738 * 739 * If a field occurs just once, calling this method will find that occurrence and return it. If a 740 * field occurs multiple times, this method may be called repeatedly with the following pattern: 741 * 742 * <pre> 743 * FieldPosition fpos(UNUM_INTEGER_FIELD); 744 * while (formattedNumberRange.nextFieldPosition(fpos, status)) { 745 * // do something with fpos. 746 * } 747 * </pre> 748 * 749 * This method is useful if you know which field to query. If you want all available field position 750 * information, use #getAllFieldPositions(). 751 * 752 * @param fieldPosition 753 * Input+output variable. See {@link FormattedNumber#nextFieldPosition}. 754 * @param status 755 * Set if an error occurs while populating the FieldPosition. 756 * @return TRUE if a new occurrence of the field was found; FALSE otherwise. 757 * @draft ICU 63 758 * @see UNumberFormatFields 759 */ 760 UBool nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const; 761 762 /** 763 * Export the formatted number range to a FieldPositionIterator. This allows you to determine which characters in 764 * the output string correspond to which <em>fields</em>, such as the integer part, fraction part, and sign. 765 * 766 * If information on only one field is needed, use #nextFieldPosition() instead. 767 * 768 * @param iterator 769 * The FieldPositionIterator to populate with all of the fields present in the formatted number. 770 * @param status 771 * Set if an error occurs while populating the FieldPositionIterator. 772 * @draft ICU 63 773 * @see UNumberFormatFields 774 */ 775 void getAllFieldPositions(FieldPositionIterator &iterator, UErrorCode &status) const; 776 777 /** 778 * Export the first formatted number as a decimal number. This endpoint 779 * is useful for obtaining the exact number being printed after scaling 780 * and rounding have been applied by the number range formatting pipeline. 781 * 782 * The syntax of the unformatted number is a "numeric string" 783 * as defined in the Decimal Arithmetic Specification, available at 784 * http://speleotrove.com/decimal 785 * 786 * @return A decimal representation of the first formatted number. 787 * @draft ICU 63 788 * @see NumberRangeFormatter 789 * @see #getSecondDecimal 790 */ 791 UnicodeString getFirstDecimal(UErrorCode& status) const; 792 793 /** 794 * Export the second formatted number as a decimal number. This endpoint 795 * is useful for obtaining the exact number being printed after scaling 796 * and rounding have been applied by the number range formatting pipeline. 797 * 798 * The syntax of the unformatted number is a "numeric string" 799 * as defined in the Decimal Arithmetic Specification, available at 800 * http://speleotrove.com/decimal 801 * 802 * @return A decimal representation of the second formatted number. 803 * @draft ICU 63 804 * @see NumberRangeFormatter 805 * @see #getFirstDecimal 806 */ 807 UnicodeString getSecondDecimal(UErrorCode& status) const; 808 #endif // U_HIDE_DRAFT_API 809 810 /** 811 * Returns whether the pair of numbers was successfully formatted as a range or whether an identity fallback was 812 * used. For example, if the first and second number were the same either before or after rounding occurred, an 813 * identity fallback was used. 814 * 815 * @return An indication the resulting identity situation in the formatted number range. 816 * @stable ICU 63 817 * @see UNumberRangeIdentityFallback 818 */ 819 UNumberRangeIdentityResult getIdentityResult(UErrorCode& status) const; 820 821 /** 822 * Copying not supported; use move constructor instead. 823 */ 824 FormattedNumberRange(const FormattedNumberRange&) = delete; 825 826 /** 827 * Copying not supported; use move assignment instead. 828 */ 829 FormattedNumberRange& operator=(const FormattedNumberRange&) = delete; 830 831 /** 832 * Move constructor: 833 * Leaves the source FormattedNumberRange in an undefined state. 834 * @stable ICU 63 835 */ 836 FormattedNumberRange(FormattedNumberRange&& src) U_NOEXCEPT; 837 838 /** 839 * Move assignment: 840 * Leaves the source FormattedNumberRange in an undefined state. 841 * @stable ICU 63 842 */ 843 FormattedNumberRange& operator=(FormattedNumberRange&& src) U_NOEXCEPT; 844 845 /** 846 * Destruct an instance of FormattedNumberRange, cleaning up any memory it might own. 847 * @stable ICU 63 848 */ 849 ~FormattedNumberRange(); 850 851 private: 852 // Can't use LocalPointer because UFormattedNumberRangeData is forward-declared 853 const impl::UFormattedNumberRangeData *fData; 854 855 // Error code for the terminal methods 856 UErrorCode fErrorCode; 857 858 /** 859 * Internal constructor from data type. Adopts the data pointer. 860 */ 861 explicit FormattedNumberRange(impl::UFormattedNumberRangeData *results) 862 : fData(results), fErrorCode(U_ZERO_ERROR) {} 863 864 explicit FormattedNumberRange(UErrorCode errorCode) 865 : fData(nullptr), fErrorCode(errorCode) {} 866 867 void getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, UErrorCode& status) const; 868 869 // To give LocalizedNumberRangeFormatter format methods access to this class's constructor: 870 friend class LocalizedNumberRangeFormatter; 871 }; 872 873 /** 874 * See the main description in numberrangeformatter.h for documentation and examples. 875 * 876 * @stable ICU 63 877 */ 878 class U_I18N_API NumberRangeFormatter final { 879 public: 880 /** 881 * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is not currently 882 * known at the call site. 883 * 884 * @return An {@link UnlocalizedNumberRangeFormatter}, to be used for chaining. 885 * @stable ICU 63 886 */ 887 static UnlocalizedNumberRangeFormatter with(); 888 889 /** 890 * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is known at the call 891 * site. 892 * 893 * @param locale 894 * The locale from which to load formats and symbols for number range formatting. 895 * @return A {@link LocalizedNumberRangeFormatter}, to be used for chaining. 896 * @stable ICU 63 897 */ 898 static LocalizedNumberRangeFormatter withLocale(const Locale &locale); 899 900 /** 901 * Use factory methods instead of the constructor to create a NumberFormatter. 902 */ 903 NumberRangeFormatter() = delete; 904 }; 905 906 } // namespace number 907 U_NAMESPACE_END 908 909 #endif /* #if !UCONFIG_NO_FORMATTING */ 910 911 #endif /* U_SHOW_CPLUSPLUS_API */ 912 913 #endif // __NUMBERRANGEFORMATTER_H__ 914 915