/src/icu/source/i18n/unicode/numberrangeformatter.h
Line | Count | Source (jump to first uncovered line) |
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 | | * \cond |
73 | | * Export an explicit template instantiation. See datefmt.h |
74 | | * (When building DLLs for Windows this is required.) |
75 | | */ |
76 | | #if U_PLATFORM == U_PF_WINDOWS && !defined(U_IN_DOXYGEN) && !defined(U_STATIC_IMPLEMENTATION) |
77 | | } // namespace icu::number |
78 | | U_NAMESPACE_END |
79 | | |
80 | | template struct U_I18N_API std::atomic< U_NAMESPACE_QUALIFIER number::impl::NumberRangeFormatterImpl*>; |
81 | | |
82 | | U_NAMESPACE_BEGIN |
83 | | namespace number { // icu::number |
84 | | #endif |
85 | | /** \endcond */ |
86 | | |
87 | | // Other helper classes would go here, but there are none. |
88 | | |
89 | | namespace impl { // icu::number::impl |
90 | | |
91 | | // Do not enclose entire MacroProps with #ifndef U_HIDE_INTERNAL_API, needed for a protected field |
92 | | /** @internal */ |
93 | | struct U_I18N_API RangeMacroProps : public UMemory { |
94 | | /** @internal */ |
95 | | UnlocalizedNumberFormatter formatter1; // = NumberFormatter::with(); |
96 | | |
97 | | /** @internal */ |
98 | | UnlocalizedNumberFormatter formatter2; // = NumberFormatter::with(); |
99 | | |
100 | | /** @internal */ |
101 | | bool singleFormatter = true; |
102 | | |
103 | | /** @internal */ |
104 | | UNumberRangeCollapse collapse = UNUM_RANGE_COLLAPSE_AUTO; |
105 | | |
106 | | /** @internal */ |
107 | | UNumberRangeIdentityFallback identityFallback = UNUM_IDENTITY_FALLBACK_APPROXIMATELY; |
108 | | |
109 | | /** @internal */ |
110 | | Locale locale; |
111 | | |
112 | | // NOTE: Uses default copy and move constructors. |
113 | | |
114 | | /** |
115 | | * Check all members for errors. |
116 | | * @internal |
117 | | */ |
118 | 0 | bool copyErrorTo(UErrorCode &status) const { |
119 | 0 | return formatter1.copyErrorTo(status) || formatter2.copyErrorTo(status); |
120 | 0 | } |
121 | | }; |
122 | | |
123 | | } // namespace impl |
124 | | |
125 | | /** |
126 | | * An abstract base class for specifying settings related to number formatting. This class is implemented by |
127 | | * {@link UnlocalizedNumberRangeFormatter} and {@link LocalizedNumberRangeFormatter}. This class is not intended for |
128 | | * public subclassing. |
129 | | */ |
130 | | template<typename Derived> |
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 | | * <p> |
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 | | * <p> |
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 | | * <p> |
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 | | * <p> |
275 | | * <ul> |
276 | | * <li>ALL: "3-5K miles"</li> |
277 | | * <li>UNIT: "3K - 5K miles"</li> |
278 | | * <li>NONE: "3K miles - 5K miles"</li> |
279 | | * <li>AUTO: usually UNIT or NONE, depending on the locale and formatter settings</li> |
280 | | * </ul> |
281 | | * <p> |
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 | | * <p> |
307 | | * <ul> |
308 | | * <li>SINGLE_VALUE: "5 miles"</li> |
309 | | * <li>APPROXIMATELY_OR_SINGLE_VALUE: "~5 miles" or "5 miles", depending on whether the number was the same before |
310 | | * rounding was applied</li> |
311 | | * <li>APPROXIMATELY: "~5 miles"</li> |
312 | | * <li>RANGE: "5-5 miles" (with collapse=UNIT)</li> |
313 | | * </ul> |
314 | | * <p> |
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<Derived> 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<Derived> 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 | | /** |
385 | | * A NumberRangeFormatter that does not yet have a locale. In order to format, a locale must be specified. |
386 | | * |
387 | | * Instances of this class are immutable and thread-safe. |
388 | | * |
389 | | * @see NumberRangeFormatter |
390 | | * @stable ICU 63 |
391 | | */ |
392 | | class U_I18N_API UnlocalizedNumberRangeFormatter |
393 | | : public NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>, public UMemory { |
394 | | |
395 | | public: |
396 | | /** |
397 | | * Associate the given locale with the number range formatter. The locale is used for picking the |
398 | | * appropriate symbols, formats, and other data for number display. |
399 | | * |
400 | | * @param locale |
401 | | * The locale to use when loading data for number formatting. |
402 | | * @return The fluent chain. |
403 | | * @stable ICU 63 |
404 | | */ |
405 | | LocalizedNumberRangeFormatter locale(const icu::Locale &locale) const &; |
406 | | |
407 | | /** |
408 | | * Overload of locale() for use on an rvalue reference. |
409 | | * |
410 | | * @param locale |
411 | | * The locale to use when loading data for number formatting. |
412 | | * @return The fluent chain. |
413 | | * @see #locale |
414 | | * @stable ICU 63 |
415 | | */ |
416 | | LocalizedNumberRangeFormatter locale(const icu::Locale &locale) &&; |
417 | | |
418 | | /** |
419 | | * Default constructor: puts the formatter into a valid but undefined state. |
420 | | * |
421 | | * @stable ICU 63 |
422 | | */ |
423 | | UnlocalizedNumberRangeFormatter() = default; |
424 | | |
425 | | /** |
426 | | * Returns a copy of this UnlocalizedNumberRangeFormatter. |
427 | | * @stable ICU 63 |
428 | | */ |
429 | | UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter &other); |
430 | | |
431 | | /** |
432 | | * Move constructor: |
433 | | * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state. |
434 | | * @stable ICU 63 |
435 | | */ |
436 | | UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&& src) U_NOEXCEPT; |
437 | | |
438 | | /** |
439 | | * Copy assignment operator. |
440 | | * @stable ICU 63 |
441 | | */ |
442 | | UnlocalizedNumberRangeFormatter& operator=(const UnlocalizedNumberRangeFormatter& other); |
443 | | |
444 | | /** |
445 | | * Move assignment operator: |
446 | | * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state. |
447 | | * @stable ICU 63 |
448 | | */ |
449 | | UnlocalizedNumberRangeFormatter& operator=(UnlocalizedNumberRangeFormatter&& src) U_NOEXCEPT; |
450 | | |
451 | | private: |
452 | | explicit UnlocalizedNumberRangeFormatter( |
453 | | const NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>& other); |
454 | | |
455 | | explicit UnlocalizedNumberRangeFormatter( |
456 | | NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>&& src) U_NOEXCEPT; |
457 | | |
458 | | // To give the fluent setters access to this class's constructor: |
459 | | friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>; |
460 | | |
461 | | // To give NumberRangeFormatter::with() access to this class's constructor: |
462 | | friend class NumberRangeFormatter; |
463 | | }; |
464 | | |
465 | | /** |
466 | | * A NumberRangeFormatter that has a locale associated with it; this means .formatRange() methods are available. |
467 | | * |
468 | | * Instances of this class are immutable and thread-safe. |
469 | | * |
470 | | * @see NumberFormatter |
471 | | * @stable ICU 63 |
472 | | */ |
473 | | class U_I18N_API LocalizedNumberRangeFormatter |
474 | | : public NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>, public UMemory { |
475 | | public: |
476 | | /** |
477 | | * Format the given Formattables to a string using the settings specified in the NumberRangeFormatter fluent setting |
478 | | * chain. |
479 | | * |
480 | | * @param first |
481 | | * The first number in the range, usually to the left in LTR locales. |
482 | | * @param second |
483 | | * The second number in the range, usually to the right in LTR locales. |
484 | | * @param status |
485 | | * Set if an error occurs while formatting. |
486 | | * @return A FormattedNumberRange object; call .toString() to get the string. |
487 | | * @stable ICU 63 |
488 | | */ |
489 | | FormattedNumberRange formatFormattableRange( |
490 | | const Formattable& first, const Formattable& second, UErrorCode& status) const; |
491 | | |
492 | | /** |
493 | | * Default constructor: puts the formatter into a valid but undefined state. |
494 | | * |
495 | | * @stable ICU 63 |
496 | | */ |
497 | | LocalizedNumberRangeFormatter() = default; |
498 | | |
499 | | /** |
500 | | * Returns a copy of this LocalizedNumberRangeFormatter. |
501 | | * @stable ICU 63 |
502 | | */ |
503 | | LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter &other); |
504 | | |
505 | | /** |
506 | | * Move constructor: |
507 | | * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state. |
508 | | * @stable ICU 63 |
509 | | */ |
510 | | LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT; |
511 | | |
512 | | /** |
513 | | * Copy assignment operator. |
514 | | * @stable ICU 63 |
515 | | */ |
516 | | LocalizedNumberRangeFormatter& operator=(const LocalizedNumberRangeFormatter& other); |
517 | | |
518 | | /** |
519 | | * Move assignment operator: |
520 | | * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state. |
521 | | * @stable ICU 63 |
522 | | */ |
523 | | LocalizedNumberRangeFormatter& operator=(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT; |
524 | | |
525 | | #ifndef U_HIDE_INTERNAL_API |
526 | | |
527 | | /** |
528 | | * @param results |
529 | | * The results object. This method will mutate it to save the results. |
530 | | * @param equalBeforeRounding |
531 | | * Whether the number was equal before copying it into a DecimalQuantity. |
532 | | * Used for determining the identity fallback behavior. |
533 | | * @param status |
534 | | * Set if an error occurs while formatting. |
535 | | * @internal |
536 | | */ |
537 | | void formatImpl(impl::UFormattedNumberRangeData& results, bool equalBeforeRounding, |
538 | | UErrorCode& status) const; |
539 | | |
540 | | #endif /* U_HIDE_INTERNAL_API */ |
541 | | |
542 | | /** |
543 | | * Destruct this LocalizedNumberRangeFormatter, cleaning up any memory it might own. |
544 | | * @stable ICU 63 |
545 | | */ |
546 | | ~LocalizedNumberRangeFormatter(); |
547 | | |
548 | | private: |
549 | | std::atomic<impl::NumberRangeFormatterImpl*> fAtomicFormatter = {}; |
550 | | |
551 | | const impl::NumberRangeFormatterImpl* getFormatter(UErrorCode& stauts) const; |
552 | | |
553 | | explicit LocalizedNumberRangeFormatter( |
554 | | const NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>& other); |
555 | | |
556 | | explicit LocalizedNumberRangeFormatter( |
557 | | NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>&& src) U_NOEXCEPT; |
558 | | |
559 | | LocalizedNumberRangeFormatter(const impl::RangeMacroProps ¯os, const Locale &locale); |
560 | | |
561 | | LocalizedNumberRangeFormatter(impl::RangeMacroProps &¯os, const Locale &locale); |
562 | | |
563 | | void clear(); |
564 | | |
565 | | // To give the fluent setters access to this class's constructor: |
566 | | friend class NumberRangeFormatterSettings<UnlocalizedNumberRangeFormatter>; |
567 | | friend class NumberRangeFormatterSettings<LocalizedNumberRangeFormatter>; |
568 | | |
569 | | // To give UnlocalizedNumberRangeFormatter::locale() access to this class's constructor: |
570 | | friend class UnlocalizedNumberRangeFormatter; |
571 | | }; |
572 | | |
573 | | /** |
574 | | * The result of a number range formatting operation. This class allows the result to be exported in several data types, |
575 | | * including a UnicodeString and a FieldPositionIterator. |
576 | | * |
577 | | * Instances of this class are immutable and thread-safe. |
578 | | * |
579 | | * @stable ICU 63 |
580 | | */ |
581 | | class U_I18N_API FormattedNumberRange : public UMemory, public FormattedValue { |
582 | | public: |
583 | | // Copybrief: this method is older than the parent method |
584 | | /** |
585 | | * @copybrief FormattedValue::toString() |
586 | | * |
587 | | * For more information, see FormattedValue::toString() |
588 | | * |
589 | | * @stable ICU 63 |
590 | | */ |
591 | | UnicodeString toString(UErrorCode& status) const U_OVERRIDE; |
592 | | |
593 | | // Copydoc: this method is new in ICU 64 |
594 | | /** @copydoc FormattedValue::toTempString() */ |
595 | | UnicodeString toTempString(UErrorCode& status) const U_OVERRIDE; |
596 | | |
597 | | // Copybrief: this method is older than the parent method |
598 | | /** |
599 | | * @copybrief FormattedValue::appendTo() |
600 | | * |
601 | | * For more information, see FormattedValue::appendTo() |
602 | | * |
603 | | * @stable ICU 63 |
604 | | */ |
605 | | Appendable &appendTo(Appendable &appendable, UErrorCode& status) const U_OVERRIDE; |
606 | | |
607 | | // Copydoc: this method is new in ICU 64 |
608 | | /** @copydoc FormattedValue::nextPosition() */ |
609 | | UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const U_OVERRIDE; |
610 | | |
611 | | /** |
612 | | * Extracts the formatted range as a pair of decimal numbers. This endpoint |
613 | | * is useful for obtaining the exact number being printed after scaling |
614 | | * and rounding have been applied by the number range formatting pipeline. |
615 | | * |
616 | | * The syntax of the unformatted numbers is a "numeric string" |
617 | | * as defined in the Decimal Arithmetic Specification, available at |
618 | | * http://speleotrove.com/decimal |
619 | | * |
620 | | * Example C++17 call site: |
621 | | * |
622 | | * auto [ first, second ] = range.getDecimalNumbers<std::string>(status); |
623 | | * |
624 | | * @tparam StringClass A string class compatible with StringByteSink; |
625 | | * for example, std::string. |
626 | | * @param status Set if an error occurs. |
627 | | * @return A pair of StringClasses containing the numeric strings. |
628 | | * @stable ICU 68 |
629 | | */ |
630 | | template<typename StringClass> |
631 | | inline std::pair<StringClass, StringClass> getDecimalNumbers(UErrorCode& status) const; |
632 | | |
633 | | /** |
634 | | * Returns whether the pair of numbers was successfully formatted as a range or whether an identity fallback was |
635 | | * used. For example, if the first and second number were the same either before or after rounding occurred, an |
636 | | * identity fallback was used. |
637 | | * |
638 | | * @return An indication the resulting identity situation in the formatted number range. |
639 | | * @stable ICU 63 |
640 | | * @see UNumberRangeIdentityFallback |
641 | | */ |
642 | | UNumberRangeIdentityResult getIdentityResult(UErrorCode& status) const; |
643 | | |
644 | | #ifndef U_HIDE_DRAFT_API |
645 | | /** |
646 | | * Default constructor; makes an empty FormattedNumberRange. |
647 | | * @draft ICU 70 |
648 | | */ |
649 | | FormattedNumberRange() |
650 | 0 | : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {} |
651 | | #endif |
652 | | |
653 | | /** |
654 | | * Copying not supported; use move constructor instead. |
655 | | */ |
656 | | FormattedNumberRange(const FormattedNumberRange&) = delete; |
657 | | |
658 | | /** |
659 | | * Copying not supported; use move assignment instead. |
660 | | */ |
661 | | FormattedNumberRange& operator=(const FormattedNumberRange&) = delete; |
662 | | |
663 | | /** |
664 | | * Move constructor: |
665 | | * Leaves the source FormattedNumberRange in an undefined state. |
666 | | * @stable ICU 63 |
667 | | */ |
668 | | FormattedNumberRange(FormattedNumberRange&& src) U_NOEXCEPT; |
669 | | |
670 | | /** |
671 | | * Move assignment: |
672 | | * Leaves the source FormattedNumberRange in an undefined state. |
673 | | * @stable ICU 63 |
674 | | */ |
675 | | FormattedNumberRange& operator=(FormattedNumberRange&& src) U_NOEXCEPT; |
676 | | |
677 | | /** |
678 | | * Destruct an instance of FormattedNumberRange, cleaning up any memory it might own. |
679 | | * @stable ICU 63 |
680 | | */ |
681 | | ~FormattedNumberRange(); |
682 | | |
683 | | private: |
684 | | // Can't use LocalPointer because UFormattedNumberRangeData is forward-declared |
685 | | const impl::UFormattedNumberRangeData *fData; |
686 | | |
687 | | // Error code for the terminal methods |
688 | | UErrorCode fErrorCode; |
689 | | |
690 | | /** |
691 | | * Internal constructor from data type. Adopts the data pointer. |
692 | | */ |
693 | | explicit FormattedNumberRange(impl::UFormattedNumberRangeData *results) |
694 | 0 | : fData(results), fErrorCode(U_ZERO_ERROR) {} |
695 | | |
696 | | explicit FormattedNumberRange(UErrorCode errorCode) |
697 | 0 | : fData(nullptr), fErrorCode(errorCode) {} |
698 | | |
699 | | void getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, UErrorCode& status) const; |
700 | | |
701 | | void getDecimalNumbers(ByteSink& sink1, ByteSink& sink2, UErrorCode& status) const; |
702 | | |
703 | | const impl::UFormattedNumberRangeData* getData(UErrorCode& status) const; |
704 | | |
705 | | // To allow PluralRules to access the underlying data |
706 | | friend class ::icu::PluralRules; |
707 | | |
708 | | // To give LocalizedNumberRangeFormatter format methods access to this class's constructor: |
709 | | friend class LocalizedNumberRangeFormatter; |
710 | | |
711 | | // To give C API access to internals |
712 | | friend struct impl::UFormattedNumberRangeImpl; |
713 | | }; |
714 | | |
715 | | // inline impl of @stable ICU 68 method |
716 | | template<typename StringClass> |
717 | | std::pair<StringClass, StringClass> FormattedNumberRange::getDecimalNumbers(UErrorCode& status) const { |
718 | | StringClass str1; |
719 | | StringClass str2; |
720 | | StringByteSink<StringClass> sink1(&str1); |
721 | | StringByteSink<StringClass> sink2(&str2); |
722 | | getDecimalNumbers(sink1, sink2, status); |
723 | | return std::make_pair(str1, str2); |
724 | | } |
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 | | |