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