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