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