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 #if 0
73
74 /**
75 * \cond
76 * Export an explicit template instantiation. See datefmt.h
77 * (When building DLLs for Windows this is required.)
78 */
79 #if U_PLATFORM == U_PF_WINDOWS && !defined(U_IN_DOXYGEN) && !defined(U_STATIC_IMPLEMENTATION)
80 } // namespace icu::number
81 U_NAMESPACE_END
82
83 template struct U_I18N_API std::atomic< U_NAMESPACE_QUALIFIER number::impl::NumberRangeFormatterImpl*>;
84
85 U_NAMESPACE_BEGIN
86 namespace number { // icu::number
87 #endif
88 /** \endcond */
89
90 #endif
91
92 // Other helper classes would go here, but there are none.
93
94 namespace impl { // icu::number::impl
95
96 // Do not enclose entire MacroProps with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
97 /** @internal */
98 struct U_I18N_API RangeMacroProps : public UMemory {
99 /** @internal */
100 UnlocalizedNumberFormatter formatter1; // = NumberFormatter::with();
101
102 /** @internal */
103 UnlocalizedNumberFormatter formatter2; // = NumberFormatter::with();
104
105 /** @internal */
106 bool singleFormatter = true;
107
108 /** @internal */
109 UNumberRangeCollapse collapse = UNUM_RANGE_COLLAPSE_AUTO;
110
111 /** @internal */
112 UNumberRangeIdentityFallback identityFallback = UNUM_IDENTITY_FALLBACK_APPROXIMATELY;
113
114 /** @internal */
115 Locale locale;
116
117 // NOTE: Uses default copy and move constructors.
118
119 /**
120 * Check all members for errors.
121 * @internal
122 */
copyErrorToRangeMacroProps123 bool copyErrorTo(UErrorCode &status) const {
124 return formatter1.copyErrorTo(status) || formatter2.copyErrorTo(status);
125 }
126 };
127
128 } // namespace impl
129
130 /**
131 * An abstract base class for specifying settings related to number formatting. This class is implemented by
132 * {@link UnlocalizedNumberRangeFormatter} and {@link LocalizedNumberRangeFormatter}. This class is not intended for
133 * public subclassing.
134 */
135 template<typename Derived>
136 class U_I18N_API NumberRangeFormatterSettings {
137 public:
138 /**
139 * Sets the NumberFormatter instance to use for the numbers in the range. The same formatter is applied to both
140 * sides of the range.
141 * <p>
142 * The NumberFormatter instances must not have a locale applied yet; the locale specified on the
143 * NumberRangeFormatter will be used.
144 *
145 * @param formatter
146 * The formatter to use for both numbers in the range.
147 * @return The fluent chain.
148 * @stable ICU 63
149 */
150 Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) const &;
151
152 /**
153 * Overload of numberFormatterBoth() for use on an rvalue reference.
154 *
155 * @param formatter
156 * The formatter to use for both numbers in the range.
157 * @return The fluent chain.
158 * @see #numberFormatterBoth
159 * @stable ICU 63
160 */
161 Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) &&;
162
163 /**
164 * Overload of numberFormatterBoth() for use on an rvalue reference.
165 *
166 * @param formatter
167 * The formatter to use for both numbers in the range.
168 * @return The fluent chain.
169 * @see #numberFormatterBoth
170 * @stable ICU 63
171 */
172 Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) const &;
173
174 /**
175 * Overload of numberFormatterBoth() for use on an rvalue reference.
176 *
177 * @param formatter
178 * The formatter to use for both numbers in the range.
179 * @return The fluent chain.
180 * @see #numberFormatterBoth
181 * @stable ICU 63
182 */
183 Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) &&;
184
185 /**
186 * Sets the NumberFormatter instance to use for the first number in the range.
187 * <p>
188 * The NumberFormatter instances must not have a locale applied yet; the locale specified on the
189 * NumberRangeFormatter will be used.
190 *
191 * @param formatterFirst
192 * The formatter to use for the first number in the range.
193 * @return The fluent chain.
194 * @stable ICU 63
195 */
196 Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) const &;
197
198 /**
199 * Overload of numberFormatterFirst() for use on an rvalue reference.
200 *
201 * @param formatterFirst
202 * The formatter to use for the first number in the range.
203 * @return The fluent chain.
204 * @see #numberFormatterFirst
205 * @stable ICU 63
206 */
207 Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) &&;
208
209 /**
210 * Overload of numberFormatterFirst() for use on an rvalue reference.
211 *
212 * @param formatterFirst
213 * The formatter to use for the first number in the range.
214 * @return The fluent chain.
215 * @see #numberFormatterFirst
216 * @stable ICU 63
217 */
218 Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) const &;
219
220 /**
221 * Overload of numberFormatterFirst() for use on an rvalue reference.
222 *
223 * @param formatterFirst
224 * The formatter to use for the first number in the range.
225 * @return The fluent chain.
226 * @see #numberFormatterFirst
227 * @stable ICU 63
228 */
229 Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) &&;
230
231 /**
232 * Sets the NumberFormatter instance to use for the second number in the range.
233 * <p>
234 * The NumberFormatter instances must not have a locale applied yet; the locale specified on the
235 * NumberRangeFormatter will be used.
236 *
237 * @param formatterSecond
238 * The formatter to use for the second number in the range.
239 * @return The fluent chain.
240 * @stable ICU 63
241 */
242 Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) const &;
243
244 /**
245 * Overload of numberFormatterSecond() for use on an rvalue reference.
246 *
247 * @param formatterSecond
248 * The formatter to use for the second number in the range.
249 * @return The fluent chain.
250 * @see #numberFormatterSecond
251 * @stable ICU 63
252 */
253 Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) &&;
254
255 /**
256 * Overload of numberFormatterSecond() for use on an rvalue reference.
257 *
258 * @param formatterSecond
259 * The formatter to use for the second number in the range.
260 * @return The fluent chain.
261 * @see #numberFormatterSecond
262 * @stable ICU 63
263 */
264 Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) const &;
265
266 /**
267 * Overload of numberFormatterSecond() for use on an rvalue reference.
268 *
269 * @param formatterSecond
270 * The formatter to use for the second number in the range.
271 * @return The fluent chain.
272 * @see #numberFormatterSecond
273 * @stable ICU 63
274 */
275 Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) &&;
276
277 /**
278 * Sets the aggressiveness of "collapsing" fields across the range separator. Possible values:
279 * <p>
280 * <ul>
281 * <li>ALL: "3-5K miles"</li>
282 * <li>UNIT: "3K - 5K miles"</li>
283 * <li>NONE: "3K miles - 5K miles"</li>
284 * <li>AUTO: usually UNIT or NONE, depending on the locale and formatter settings</li>
285 * </ul>
286 * <p>
287 * The default value is AUTO.
288 *
289 * @param collapse
290 * The collapsing strategy to use for this range.
291 * @return The fluent chain.
292 * @stable ICU 63
293 */
294 Derived collapse(UNumberRangeCollapse collapse) const &;
295
296 /**
297 * Overload of collapse() for use on an rvalue reference.
298 *
299 * @param collapse
300 * The collapsing strategy to use for this range.
301 * @return The fluent chain.
302 * @see #collapse
303 * @stable ICU 63
304 */
305 Derived collapse(UNumberRangeCollapse collapse) &&;
306
307 /**
308 * Sets the behavior when the two sides of the range are the same. This could happen if the same two numbers are
309 * passed to the formatFormattableRange function, or if different numbers are passed to the function but they
310 * become the same after rounding rules are applied. Possible values:
311 * <p>
312 * <ul>
313 * <li>SINGLE_VALUE: "5 miles"</li>
314 * <li>APPROXIMATELY_OR_SINGLE_VALUE: "~5 miles" or "5 miles", depending on whether the number was the same before
315 * rounding was applied</li>
316 * <li>APPROXIMATELY: "~5 miles"</li>
317 * <li>RANGE: "5-5 miles" (with collapse=UNIT)</li>
318 * </ul>
319 * <p>
320 * The default value is APPROXIMATELY.
321 *
322 * @param identityFallback
323 * The strategy to use when formatting two numbers that end up being the same.
324 * @return The fluent chain.
325 * @stable ICU 63
326 */
327 Derived identityFallback(UNumberRangeIdentityFallback identityFallback) const &;
328
329 /**
330 * Overload of identityFallback() for use on an rvalue reference.
331 *
332 * @param identityFallback
333 * The strategy to use when formatting two numbers that end up being the same.
334 * @return The fluent chain.
335 * @see #identityFallback
336 * @stable ICU 63
337 */
338 Derived identityFallback(UNumberRangeIdentityFallback identityFallback) &&;
339
340 /**
341 * Returns the current (Un)LocalizedNumberRangeFormatter as a LocalPointer
342 * wrapping a heap-allocated copy of the current object.
343 *
344 * This is equivalent to new-ing the move constructor with a value object
345 * as the argument.
346 *
347 * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped
348 * nullptr on failure.
349 * @stable ICU 64
350 */
351 LocalPointer<Derived> clone() const &;
352
353 /**
354 * Overload of clone for use on an rvalue reference.
355 *
356 * @return A wrapped (Un)LocalizedNumberRangeFormatter pointer, or a wrapped
357 * nullptr on failure.
358 * @stable ICU 64
359 */
360 LocalPointer<Derived> clone() &&;
361
362 /**
363 * Sets the UErrorCode if an error occurred in the fluent chain.
364 * Preserves older error codes in the outErrorCode.
365 * @return true if U_FAILURE(outErrorCode)
366 * @stable ICU 63
367 */
copyErrorTo(UErrorCode & outErrorCode)368 UBool copyErrorTo(UErrorCode &outErrorCode) const {
369 if (U_FAILURE(outErrorCode)) {
370 // Do not overwrite the older error code
371 return true;
372 }
373 fMacros.copyErrorTo(outErrorCode);
374 return U_FAILURE(outErrorCode);
375 }
376
377 // NOTE: Uses default copy and move constructors.
378
379 private:
380 impl::RangeMacroProps fMacros;
381
382 // Don't construct me directly! Use (Un)LocalizedNumberFormatter.
383 NumberRangeFormatterSettings() = default;
384
385 friend class LocalizedNumberRangeFormatter;
386 friend class UnlocalizedNumberRangeFormatter;
387 };
388
389 // Explicit instantiations in source/i18n/numrange_fluent.cpp.
390 // (MSVC treats imports/exports of explicit instantiations differently.)
391 #ifndef _MSC_VER
392 extern template class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>;
393 extern template class NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>;
394 #endif
395
396 /**
397 * A NumberRangeFormatter that does not yet have a locale. In order to format, a locale must be specified.
398 *
399 * Instances of this class are immutable and thread-safe.
400 *
401 * @see NumberRangeFormatter
402 * @stable ICU 63
403 */
404 class U_I18N_API UnlocalizedNumberRangeFormatter
405 : public NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>, public UMemory {
406
407 public:
408 /**
409 * Associate the given locale with the number range formatter. The locale is used for picking the
410 * appropriate symbols, formats, and other data for number display.
411 *
412 * @param locale
413 * The locale to use when loading data for number formatting.
414 * @return The fluent chain.
415 * @stable ICU 63
416 */
417 LocalizedNumberRangeFormatter locale(const icu::Locale &locale) const &;
418
419 /**
420 * Overload of locale() for use on an rvalue reference.
421 *
422 * @param locale
423 * The locale to use when loading data for number formatting.
424 * @return The fluent chain.
425 * @see #locale
426 * @stable ICU 63
427 */
428 LocalizedNumberRangeFormatter locale(const icu::Locale &locale) &&;
429
430 /**
431 * Default constructor: puts the formatter into a valid but undefined state.
432 *
433 * @stable ICU 63
434 */
435 UnlocalizedNumberRangeFormatter() = default;
436
437 /**
438 * Returns a copy of this UnlocalizedNumberRangeFormatter.
439 * @stable ICU 63
440 */
441 UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter &other);
442
443 /**
444 * Move constructor:
445 * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state.
446 * @stable ICU 63
447 */
448 UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&& src) noexcept;
449
450 /**
451 * Copy assignment operator.
452 * @stable ICU 63
453 */
454 UnlocalizedNumberRangeFormatter& operator=(const UnlocalizedNumberRangeFormatter& other);
455
456 /**
457 * Move assignment operator:
458 * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state.
459 * @stable ICU 63
460 */
461 UnlocalizedNumberRangeFormatter& operator=(UnlocalizedNumberRangeFormatter&& src) noexcept;
462
463 private:
464 explicit UnlocalizedNumberRangeFormatter(
465 const NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>& other);
466
467 explicit UnlocalizedNumberRangeFormatter(
468 NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>&& src) noexcept;
469
470 // To give the fluent setters access to this class's constructor:
471 friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>;
472
473 // To give NumberRangeFormatter::with() access to this class's constructor:
474 friend class NumberRangeFormatter;
475 };
476
477 /**
478 * A NumberRangeFormatter that has a locale associated with it; this means .formatRange() methods are available.
479 *
480 * Instances of this class are immutable and thread-safe.
481 *
482 * @see NumberFormatter
483 * @stable ICU 63
484 */
485 class U_I18N_API LocalizedNumberRangeFormatter
486 : public NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>, public UMemory {
487 public:
488 /**
489 * Format the given Formattables to a string using the settings specified in the NumberRangeFormatter fluent setting
490 * chain.
491 *
492 * @param first
493 * The first number in the range, usually to the left in LTR locales.
494 * @param second
495 * The second number in the range, usually to the right in LTR locales.
496 * @param status
497 * Set if an error occurs while formatting.
498 * @return A FormattedNumberRange object; call .toString() to get the string.
499 * @stable ICU 63
500 */
501 FormattedNumberRange formatFormattableRange(
502 const Formattable& first, const Formattable& second, UErrorCode& status) const;
503
504 /**
505 * Default constructor: puts the formatter into a valid but undefined state.
506 *
507 * @stable ICU 63
508 */
509 LocalizedNumberRangeFormatter() = default;
510
511 /**
512 * Returns a copy of this LocalizedNumberRangeFormatter.
513 * @stable ICU 63
514 */
515 LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter &other);
516
517 /**
518 * Move constructor:
519 * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state.
520 * @stable ICU 63
521 */
522 LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&& src) noexcept;
523
524 /**
525 * Copy assignment operator.
526 * @stable ICU 63
527 */
528 LocalizedNumberRangeFormatter& operator=(const LocalizedNumberRangeFormatter& other);
529
530 /**
531 * Move assignment operator:
532 * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state.
533 * @stable ICU 63
534 */
535 LocalizedNumberRangeFormatter& operator=(LocalizedNumberRangeFormatter&& src) noexcept;
536
537 #ifndef U_HIDE_INTERNAL_API
538
539 /**
540 * @param results
541 * The results object. This method will mutate it to save the results.
542 * @param equalBeforeRounding
543 * Whether the number was equal before copying it into a DecimalQuantity.
544 * Used for determining the identity fallback behavior.
545 * @param status
546 * Set if an error occurs while formatting.
547 * @internal
548 */
549 void formatImpl(impl::UFormattedNumberRangeData& results, bool equalBeforeRounding,
550 UErrorCode& status) const;
551
552 #endif /* U_HIDE_INTERNAL_API */
553
554 /**
555 * Destruct this LocalizedNumberRangeFormatter, cleaning up any memory it might own.
556 * @stable ICU 63
557 */
558 ~LocalizedNumberRangeFormatter();
559
560 private:
561 std::atomic<impl::NumberRangeFormatterImpl*> fAtomicFormatter = {};
562
563 const impl::NumberRangeFormatterImpl* getFormatter(UErrorCode& stauts) const;
564
565 explicit LocalizedNumberRangeFormatter(
566 const NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>& other);
567
568 explicit LocalizedNumberRangeFormatter(
569 NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>&& src) noexcept;
570
571 LocalizedNumberRangeFormatter(const impl::RangeMacroProps ¯os, const Locale &locale);
572
573 LocalizedNumberRangeFormatter(impl::RangeMacroProps &¯os, const Locale &locale);
574
575 // To give the fluent setters access to this class's constructor:
576 friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>;
577 friend class NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>;
578
579 // To give UnlocalizedNumberRangeFormatter::locale() access to this class's constructor:
580 friend class UnlocalizedNumberRangeFormatter;
581 };
582
583 /**
584 * The result of a number range formatting operation. This class allows the result to be exported in several data types,
585 * including a UnicodeString and a FieldPositionIterator.
586 *
587 * Instances of this class are immutable and thread-safe.
588 *
589 * @stable ICU 63
590 */
591 class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue {
592 public:
593 // Copybrief: this method is older than the parent method
594 /**
595 * @copybrief FormattedValue::toString()
596 *
597 * For more information, see FormattedValue::toString()
598 *
599 * @stable ICU 63
600 */
601 UnicodeString toString(UErrorCode& status) const override;
602
603 // Copydoc: this method is new in ICU 64
604 /** @copydoc FormattedValue::toTempString() */
605 UnicodeString toTempString(UErrorCode& status) const override;
606
607 // Copybrief: this method is older than the parent method
608 /**
609 * @copybrief FormattedValue::appendTo()
610 *
611 * For more information, see FormattedValue::appendTo()
612 *
613 * @stable ICU 63
614 */
615 Appendable &appendTo(Appendable &appendable, UErrorCode& status) const override;
616
617 // Copydoc: this method is new in ICU 64
618 /** @copydoc FormattedValue::nextPosition() */
619 UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const override;
620
621 /**
622 * Extracts the formatted range as a pair of decimal numbers. This endpoint
623 * is useful for obtaining the exact number being printed after scaling
624 * and rounding have been applied by the number range formatting pipeline.
625 *
626 * The syntax of the unformatted numbers is a "numeric string"
627 * as defined in the Decimal Arithmetic Specification, available at
628 * http://speleotrove.com/decimal
629 *
630 * Example C++17 call site:
631 *
632 * auto [ first, second ] = range.getDecimalNumbers<std::string>(status);
633 *
634 * @tparam StringClass A string class compatible with StringByteSink;
635 * for example, std::string.
636 * @param status Set if an error occurs.
637 * @return A pair of StringClasses containing the numeric strings.
638 * @stable ICU 68
639 */
640 template<typename StringClass>
641 inline std::pair<StringClass, StringClass> getDecimalNumbers(UErrorCode& status) const;
642
643 /**
644 * Returns whether the pair of numbers was successfully formatted as a range or whether an identity fallback was
645 * used. For example, if the first and second number were the same either before or after rounding occurred, an
646 * identity fallback was used.
647 *
648 * @return An indication the resulting identity situation in the formatted number range.
649 * @stable ICU 63
650 * @see UNumberRangeIdentityFallback
651 */
652 UNumberRangeIdentityResult getIdentityResult(UErrorCode& status) const;
653
654 /**
655 * Default constructor; makes an empty FormattedNumberRange.
656 * @stable ICU 70
657 */
FormattedNumberRange()658 FormattedNumberRange()
659 : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {}
660
661 /**
662 * Copying not supported; use move constructor instead.
663 */
664 FormattedNumberRange(const FormattedNumberRange&) = delete;
665
666 /**
667 * Copying not supported; use move assignment instead.
668 */
669 FormattedNumberRange& operator=(const FormattedNumberRange&) = delete;
670
671 /**
672 * Move constructor:
673 * Leaves the source FormattedNumberRange in an undefined state.
674 * @stable ICU 63
675 */
676 FormattedNumberRange(FormattedNumberRange&& src) noexcept;
677
678 /**
679 * Move assignment:
680 * Leaves the source FormattedNumberRange in an undefined state.
681 * @stable ICU 63
682 */
683 FormattedNumberRange& operator=(FormattedNumberRange&& src) noexcept;
684
685 /**
686 * Destruct an instance of FormattedNumberRange, cleaning up any memory it might own.
687 * @stable ICU 63
688 */
689 ~FormattedNumberRange();
690
691 private:
692 // Can't use LocalPointer because UFormattedNumberRangeData is forward-declared
693 const impl::UFormattedNumberRangeData *fData;
694
695 // Error code for the terminal methods
696 UErrorCode fErrorCode;
697
698 /**
699 * Internal constructor from data type. Adopts the data pointer.
700 */
FormattedNumberRange(impl::UFormattedNumberRangeData * results)701 explicit FormattedNumberRange(impl::UFormattedNumberRangeData *results)
702 : fData(results), fErrorCode(U_ZERO_ERROR) {}
703
FormattedNumberRange(UErrorCode errorCode)704 explicit FormattedNumberRange(UErrorCode errorCode)
705 : fData(nullptr), fErrorCode(errorCode) {}
706
707 void getDecimalNumbers(ByteSink& sink1, ByteSink& sink2, UErrorCode& status) const;
708
709 const impl::UFormattedNumberRangeData* getData(UErrorCode& status) const;
710
711 // To allow PluralRules to access the underlying data
712 friend class ::icu::PluralRules;
713
714 // To give LocalizedNumberRangeFormatter format methods access to this class's constructor:
715 friend class LocalizedNumberRangeFormatter;
716
717 // To give C API access to internals
718 friend struct impl::UFormattedNumberRangeImpl;
719 };
720
721 // inline impl of @stable ICU 68 method
722 template<typename StringClass>
getDecimalNumbers(UErrorCode & status)723 std::pair<StringClass, StringClass> FormattedNumberRange::getDecimalNumbers(UErrorCode& status) const {
724 StringClass str1;
725 StringClass str2;
726 StringByteSink<StringClass> sink1(&str1);
727 StringByteSink<StringClass> sink2(&str2);
728 getDecimalNumbers(sink1, sink2, status);
729 return std::make_pair(str1, str2);
730 }
731
732 /**
733 * See the main description in numberrangeformatter.h for documentation and examples.
734 *
735 * @stable ICU 63
736 */
737 class U_I18N_API NumberRangeFormatter final {
738 public:
739 /**
740 * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is not currently
741 * known at the call site.
742 *
743 * @return An {@link UnlocalizedNumberRangeFormatter}, to be used for chaining.
744 * @stable ICU 63
745 */
746 static UnlocalizedNumberRangeFormatter with();
747
748 /**
749 * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is known at the call
750 * site.
751 *
752 * @param locale
753 * The locale from which to load formats and symbols for number range formatting.
754 * @return A {@link LocalizedNumberRangeFormatter}, to be used for chaining.
755 * @stable ICU 63
756 */
757 static LocalizedNumberRangeFormatter withLocale(const Locale &locale);
758
759 /**
760 * Use factory methods instead of the constructor to create a NumberFormatter.
761 */
762 NumberRangeFormatter() = delete;
763 };
764
765 } // namespace number
766 U_NAMESPACE_END
767
768 #endif /* #if !UCONFIG_NO_FORMATTING */
769
770 #endif /* U_SHOW_CPLUSPLUS_API */
771
772 #endif // __NUMBERRANGEFORMATTER_H__
773
774