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