• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2020 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 
4 #ifndef __UNUMBERRANGEFORMATTER_H__
5 #define __UNUMBERRANGEFORMATTER_H__
6 
7 #include "unicode/utypes.h"
8 
9 #if !UCONFIG_NO_FORMATTING
10 
11 #include "unicode/parseerr.h"
12 #include "unicode/ufieldpositer.h"
13 #include "unicode/umisc.h"
14 #include "unicode/uformattedvalue.h"
15 #include "unicode/uformattable.h"
16 
17 
18 /**
19  * \file
20  * \brief C-compatible API for localized number range formatting.
21  *
22  * This is the C-compatible version of the NumberRangeFormatter API. C++ users
23  * should include unicode/numberrangeformatter.h and use the proper C++ APIs.
24  *
25  * First create a UNumberRangeFormatter, which is immutable, and then format to
26  * a UFormattedNumberRange.
27  *
28  * Example code:
29  * <pre>
30  * // Setup:
31  * UErrorCode ec = U_ZERO_ERROR;
32  * UNumberRangeFormatter* uformatter = unumrf_openForSkeletonCollapseIdentityFallbackAndLocaleWithError(
33  *     u"currency/USD precision-integer",
34  *     -1,
35  *     UNUM_RANGE_COLLAPSE_AUTO,
36  *     UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
37  *     "en-US",
38  *     NULL,
39  *     &ec);
40  * UFormattedNumberRange* uresult = unumrf_openResult(&ec);
41  * if (U_FAILURE(ec)) { return; }
42  *
43  * // Format a double range:
44  * unumrf_formatDoubleRange(uformatter, 3.0, 5.0, uresult, &ec);
45  * if (U_FAILURE(ec)) { return; }
46  *
47  * // Get the result string:
48  * int32_t len;
49  * const UChar* str = ufmtval_getString(unumrf_resultAsValue(uresult, &ec), &len, &ec);
50  * if (U_FAILURE(ec)) { return; }
51  * // str should equal "$3 – $5"
52  *
53  * // Cleanup:
54  * unumf_close(uformatter);
55  * unumf_closeResult(uresult);
56  * </pre>
57  *
58  * If you are a C++ user linking against the C libraries, you can use the LocalPointer versions of these
59  * APIs. The following example uses LocalPointer with the decimal number and field position APIs:
60  *
61  * <pre>
62  * // Setup:
63  * LocalUNumberRangeFormatterPointer uformatter(
64  *     unumrf_openForSkeletonCollapseIdentityFallbackAndLocaleWithError(...));
65  * LocalUFormattedNumberRangePointer uresult(unumrf_openResult(&ec));
66  * if (U_FAILURE(ec)) { return; }
67  *
68  * // Format a double number range:
69  * unumrf_formatDoubleRange(uformatter.getAlias(), 3.0, 5.0, uresult.getAlias(), &ec);
70  * if (U_FAILURE(ec)) { return; }
71  *
72  * // No need to do any cleanup since we are using LocalPointer.
73  * </pre>
74  *
75  * You can also get field positions. For more information, see uformattedvalue.h.
76  */
77 
78 /**
79  * Defines how to merge fields that are identical across the range sign.
80  *
81  * @stable ICU 63
82  */
83 typedef enum UNumberRangeCollapse {
84     /**
85      * Use locale data and heuristics to determine how much of the string to collapse. Could end up collapsing none,
86      * some, or all repeated pieces in a locale-sensitive way.
87      *
88      * The heuristics used for this option are subject to change over time.
89      *
90      * @stable ICU 63
91      */
92     UNUM_RANGE_COLLAPSE_AUTO,
93 
94     /**
95      * Do not collapse any part of the number. Example: "3.2 thousand kilograms – 5.3 thousand kilograms"
96      *
97      * @stable ICU 63
98      */
99     UNUM_RANGE_COLLAPSE_NONE,
100 
101     /**
102      * Collapse the unit part of the number, but not the notation, if present. Example: "3.2 thousand – 5.3 thousand
103      * kilograms"
104      *
105      * @stable ICU 63
106      */
107     UNUM_RANGE_COLLAPSE_UNIT,
108 
109     /**
110      * Collapse any field that is equal across the range sign. May introduce ambiguity on the magnitude of the
111      * number. Example: "3.2 – 5.3 thousand kilograms"
112      *
113      * @stable ICU 63
114      */
115     UNUM_RANGE_COLLAPSE_ALL
116 } UNumberRangeCollapse;
117 
118 /**
119  * Defines the behavior when the two numbers in the range are identical after rounding. To programmatically detect
120  * when the identity fallback is used, compare the lower and upper BigDecimals via FormattedNumber.
121  *
122  * @stable ICU 63
123  * @see NumberRangeFormatter
124  */
125 typedef enum UNumberRangeIdentityFallback {
126     /**
127      * Show the number as a single value rather than a range. Example: "$5"
128      *
129      * @stable ICU 63
130      */
131     UNUM_IDENTITY_FALLBACK_SINGLE_VALUE,
132 
133     /**
134      * Show the number using a locale-sensitive approximation pattern. If the numbers were the same before rounding,
135      * show the single value. Example: "~$5" or "$5"
136      *
137      * @stable ICU 63
138      */
139     UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE,
140 
141     /**
142      * Show the number using a locale-sensitive approximation pattern. Use the range pattern always, even if the
143      * inputs are the same. Example: "~$5"
144      *
145      * @stable ICU 63
146      */
147     UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
148 
149     /**
150      * Show the number as the range of two equal values. Use the range pattern always, even if the inputs are the
151      * same. Example (with RangeCollapse.NONE): "$5 – $5"
152      *
153      * @stable ICU 63
154      */
155     UNUM_IDENTITY_FALLBACK_RANGE
156 } UNumberRangeIdentityFallback;
157 
158 /**
159  * Used in the result class FormattedNumberRange to indicate to the user whether the numbers formatted in the range
160  * were equal or not, and whether or not the identity fallback was applied.
161  *
162  * @stable ICU 63
163  * @see NumberRangeFormatter
164  */
165 typedef enum UNumberRangeIdentityResult {
166     /**
167      * Used to indicate that the two numbers in the range were equal, even before any rounding rules were applied.
168      *
169      * @stable ICU 63
170      * @see NumberRangeFormatter
171      */
172     UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING,
173 
174     /**
175      * Used to indicate that the two numbers in the range were equal, but only after rounding rules were applied.
176      *
177      * @stable ICU 63
178      * @see NumberRangeFormatter
179      */
180     UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING,
181 
182     /**
183      * Used to indicate that the two numbers in the range were not equal, even after rounding rules were applied.
184      *
185      * @stable ICU 63
186      * @see NumberRangeFormatter
187      */
188     UNUM_IDENTITY_RESULT_NOT_EQUAL,
189 
190 #ifndef U_HIDE_INTERNAL_API
191     /**
192      * The number of entries in this enum.
193      * @internal
194      */
195     UNUM_IDENTITY_RESULT_COUNT
196 #endif  /* U_HIDE_INTERNAL_API */
197 
198 } UNumberRangeIdentityResult;
199 
200 
201 struct UNumberRangeFormatter;
202 /**
203  * C-compatible version of icu::number::LocalizedNumberRangeFormatter.
204  *
205  * NOTE: This is a C-compatible API; C++ users should build against numberrangeformatter.h instead.
206  *
207  * @stable ICU 68
208  */
209 typedef struct UNumberRangeFormatter UNumberRangeFormatter;
210 
211 
212 struct UFormattedNumberRange;
213 /**
214  * C-compatible version of icu::number::FormattedNumberRange.
215  *
216  * NOTE: This is a C-compatible API; C++ users should build against numberrangeformatter.h instead.
217  *
218  * @stable ICU 68
219  */
220 typedef struct UFormattedNumberRange UFormattedNumberRange;
221 
222 
223 /**
224  * Creates a new UNumberFormatter for the given skeleton string, collapse option, identity fallback
225  * option, and locale. This is currently the only method for creating a new UNumberRangeFormatter.
226  *
227  * Objects of type UNumberRangeFormatter returned by this method are threadsafe.
228  *
229  * For more details on skeleton strings, see the documentation in numberrangeformatter.h. For more
230  * details on the usage of this API, see the documentation at the top of unumberrangeformatter.h.
231  *
232  * NOTE: This is a C-compatible API; C++ users should build against numberrangeformatter.h instead.
233  *
234  * @param skeleton The skeleton string, like u"percent precision-integer"
235  * @param skeletonLen The number of UChars in the skeleton string, or -1 if it is NUL-terminated.
236  * @param collapse Option for how to merge affixes (if unsure, use UNUM_RANGE_COLLAPSE_AUTO)
237  * @param identityFallback Option for resolving when both sides of the range are equal.
238  * @param locale The NUL-terminated locale ID.
239  * @param perror A parse error struct populated if an error occurs when parsing. Can be NULL.
240  *               If no error occurs, perror->offset will be set to -1.
241  * @param ec Set if an error occurs.
242  * @stable ICU 68
243  */
244 U_CAPI UNumberRangeFormatter* U_EXPORT2
245 unumrf_openForSkeletonWithCollapseAndIdentityFallback(
246     const UChar* skeleton,
247     int32_t skeletonLen,
248     UNumberRangeCollapse collapse,
249     UNumberRangeIdentityFallback identityFallback,
250     const char* locale,
251     UParseError* perror,
252     UErrorCode* ec);
253 
254 
255 /**
256  * Creates an object to hold the result of a UNumberRangeFormatter
257  * operation. The object can be used repeatedly; it is cleared whenever
258  * passed to a format function.
259  *
260  * @param ec Set if an error occurs.
261  * @stable ICU 68
262  */
263 U_CAPI UFormattedNumberRange* U_EXPORT2
264 unumrf_openResult(UErrorCode* ec);
265 
266 
267 /**
268  * Uses a UNumberRangeFormatter to format a range of doubles.
269  *
270  * The UNumberRangeFormatter can be shared between threads. Each thread should have its own local
271  * UFormattedNumberRange, however, for storing the result of the formatting operation.
272  *
273  * NOTE: This is a C-compatible API; C++ users should build against numberrangeformatter.h instead.
274  *
275  * @param uformatter A formatter object; see unumberrangeformatter.h.
276  * @param first The first (usually smaller) number in the range.
277  * @param second The second (usually larger) number in the range.
278  * @param uresult The object that will be mutated to store the result; see unumrf_openResult.
279  * @param ec Set if an error occurs.
280  * @stable ICU 68
281  */
282 U_CAPI void U_EXPORT2
283 unumrf_formatDoubleRange(
284     const UNumberRangeFormatter* uformatter,
285     double first,
286     double second,
287     UFormattedNumberRange* uresult,
288     UErrorCode* ec);
289 
290 
291 /**
292  * Uses a UNumberRangeFormatter to format a range of decimal numbers.
293  *
294  * With a decimal number string, you can specify an input with arbitrary precision.
295  *
296  * The UNumberRangeFormatter can be shared between threads. Each thread should have its own local
297  * UFormattedNumberRange, however, for storing the result of the formatting operation.
298  *
299  * NOTE: This is a C-compatible API; C++ users should build against numberrangeformatter.h instead.
300  *
301  * @param uformatter A formatter object; see unumberrangeformatter.h.
302  * @param first The first (usually smaller) number in the range.
303  * @param firstLen The length of the first decimal number string.
304  * @param second The second (usually larger) number in the range.
305  * @param secondLen The length of the second decimal number string.
306  * @param uresult The object that will be mutated to store the result; see unumrf_openResult.
307  * @param ec Set if an error occurs.
308  * @stable ICU 68
309  */
310 U_CAPI void U_EXPORT2
311 unumrf_formatDecimalRange(
312     const UNumberRangeFormatter* uformatter,
313     const char* first,
314     int32_t firstLen,
315     const char* second,
316     int32_t secondLen,
317     UFormattedNumberRange* uresult,
318     UErrorCode* ec);
319 
320 
321 /**
322  * Returns a representation of a UFormattedNumberRange as a UFormattedValue,
323  * which can be subsequently passed to any API requiring that type.
324  *
325  * The returned object is owned by the UFormattedNumberRange and is valid
326  * only as long as the UFormattedNumber is present and unchanged in memory.
327  *
328  * You can think of this method as a cast between types.
329  *
330  * @param uresult The object containing the formatted number range.
331  * @param ec Set if an error occurs.
332  * @return A UFormattedValue owned by the input object.
333  * @stable ICU 68
334  */
335 U_CAPI const UFormattedValue* U_EXPORT2
336 unumrf_resultAsValue(const UFormattedNumberRange* uresult, UErrorCode* ec);
337 
338 
339 /**
340  * Extracts the identity result from a UFormattedNumberRange.
341  *
342  * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead.
343  *
344  * @param uresult The object containing the formatted number range.
345  * @param ec Set if an error occurs.
346  * @return The identity result; see UNumberRangeIdentityResult.
347  * @stable ICU 68
348  */
349 U_CAPI UNumberRangeIdentityResult U_EXPORT2
350 unumrf_resultGetIdentityResult(
351     const UFormattedNumberRange* uresult,
352     UErrorCode* ec);
353 
354 
355 /**
356  * Extracts the first formatted number as a decimal number. This endpoint
357  * is useful for obtaining the exact number being printed after scaling
358  * and rounding have been applied by the number range formatting pipeline.
359  *
360  * The syntax of the unformatted number is a "numeric string"
361  * as defined in the Decimal Arithmetic Specification, available at
362  * http://speleotrove.com/decimal
363  *
364  * @param  uresult       The input object containing the formatted number range.
365  * @param  dest          the 8-bit char buffer into which the decimal number is placed
366  * @param  destCapacity  The size, in chars, of the destination buffer.  May be zero
367  *                       for precomputing the required size.
368  * @param  ec            receives any error status.
369  *                       If U_BUFFER_OVERFLOW_ERROR: Returns number of chars for
370  *                       preflighting.
371  * @return Number of chars in the data.  Does not include a trailing NUL.
372  * @stable ICU 68
373  */
374 U_CAPI int32_t U_EXPORT2
375 unumrf_resultGetFirstDecimalNumber(
376     const UFormattedNumberRange* uresult,
377     char* dest,
378     int32_t destCapacity,
379     UErrorCode* ec);
380 
381 
382 /**
383  * Extracts the second formatted number as a decimal number. This endpoint
384  * is useful for obtaining the exact number being printed after scaling
385  * and rounding have been applied by the number range formatting pipeline.
386  *
387  * The syntax of the unformatted number is a "numeric string"
388  * as defined in the Decimal Arithmetic Specification, available at
389  * http://speleotrove.com/decimal
390  *
391  * @param  uresult       The input object containing the formatted number range.
392  * @param  dest          the 8-bit char buffer into which the decimal number is placed
393  * @param  destCapacity  The size, in chars, of the destination buffer.  May be zero
394  *                       for precomputing the required size.
395  * @param  ec            receives any error status.
396  *                       If U_BUFFER_OVERFLOW_ERROR: Returns number of chars for
397  *                       preflighting.
398  * @return Number of chars in the data.  Does not include a trailing NUL.
399  * @stable ICU 68
400  */
401 U_CAPI int32_t U_EXPORT2
402 unumrf_resultGetSecondDecimalNumber(
403     const UFormattedNumberRange* uresult,
404     char* dest,
405     int32_t destCapacity,
406     UErrorCode* ec);
407 
408 
409 /**
410  * Releases the UNumberFormatter created by unumf_openForSkeletonAndLocale().
411  *
412  * @param uformatter An object created by unumf_openForSkeletonAndLocale().
413  * @stable ICU 68
414  */
415 U_CAPI void U_EXPORT2
416 unumrf_close(UNumberRangeFormatter* uformatter);
417 
418 
419 /**
420  * Releases the UFormattedNumber created by unumf_openResult().
421  *
422  * @param uresult An object created by unumf_openResult().
423  * @stable ICU 68
424  */
425 U_CAPI void U_EXPORT2
426 unumrf_closeResult(UFormattedNumberRange* uresult);
427 
428 
429 #if U_SHOW_CPLUSPLUS_API
430 U_NAMESPACE_BEGIN
431 
432 /**
433  * \class LocalUNumberRangeFormatterPointer
434  * "Smart pointer" class; closes a UNumberFormatter via unumf_close().
435  * For most methods see the LocalPointerBase base class.
436  *
437  * Usage:
438  * <pre>
439  * LocalUNumberRangeFormatterPointer uformatter(
440  *     unumrf_openForSkeletonCollapseIdentityFallbackAndLocaleWithError(...));
441  * // no need to explicitly call unumrf_close()
442  * </pre>
443  *
444  * @see LocalPointerBase
445  * @see LocalPointer
446  * @stable ICU 68
447  */
448 U_DEFINE_LOCAL_OPEN_POINTER(LocalUNumberRangeFormatterPointer, UNumberRangeFormatter, unumrf_close);
449 
450 /**
451  * \class LocalUFormattedNumberPointer
452  * "Smart pointer" class; closes a UFormattedNumber via unumf_closeResult().
453  * For most methods see the LocalPointerBase base class.
454  *
455  * Usage:
456  * <pre>
457  * LocalUFormattedNumberRangePointer uresult(unumrf_openResult(...));
458  * // no need to explicitly call unumrf_closeResult()
459  * </pre>
460  *
461  * @see LocalPointerBase
462  * @see LocalPointer
463  * @stable ICU 68
464  */
465 U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattedNumberRangePointer, UFormattedNumberRange, unumrf_closeResult);
466 
467 U_NAMESPACE_END
468 #endif // U_SHOW_CPLUSPLUS_API
469 
470 #endif /* #if !UCONFIG_NO_FORMATTING */
471 #endif //__UNUMBERRANGEFORMATTER_H__
472