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