• 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
197 
198 } UNumberRangeIdentityResult;
199 
200 
201 #ifndef U_HIDE_DRAFT_API
202 
203 struct UNumberRangeFormatter;
204 /**
205  * C-compatible version of icu::number::LocalizedNumberRangeFormatter.
206  *
207  * NOTE: This is a C-compatible API; C++ users should build against numberrangeformatter.h instead.
208  *
209  * @draft ICU 68
210  */
211 typedef struct UNumberRangeFormatter UNumberRangeFormatter;
212 
213 
214 struct UFormattedNumberRange;
215 /**
216  * C-compatible version of icu::number::FormattedNumberRange.
217  *
218  * NOTE: This is a C-compatible API; C++ users should build against numberrangeformatter.h instead.
219  *
220  * @draft ICU 68
221  */
222 typedef struct UFormattedNumberRange UFormattedNumberRange;
223 
224 
225 /**
226  * Creates a new UNumberFormatter for the given skeleton string, collapse option, identity fallback
227  * option, and locale. This is currently the only method for creating a new UNumberRangeFormatter.
228  *
229  * Objects of type UNumberRangeFormatter returned by this method are threadsafe.
230  *
231  * For more details on skeleton strings, see the documentation in numberrangeformatter.h. For more
232  * details on the usage of this API, see the documentation at the top of unumberrangeformatter.h.
233  *
234  * NOTE: This is a C-compatible API; C++ users should build against numberrangeformatter.h instead.
235  *
236  * @param skeleton The skeleton string, like u"percent precision-integer"
237  * @param skeletonLen The number of UChars in the skeleton string, or -1 if it is NUL-terminated.
238  * @param collapse Option for how to merge affixes (if unsure, use UNUM_RANGE_COLLAPSE_AUTO)
239  * @param identityFallback Option for resolving when both sides of the range are equal.
240  * @param locale The NUL-terminated locale ID.
241  * @param perror A parse error struct populated if an error occurs when parsing. Can be NULL.
242  *               If no error occurs, perror->offset will be set to -1.
243  * @param ec Set if an error occurs.
244  * @draft ICU 68
245  */
246 U_CAPI UNumberRangeFormatter* U_EXPORT2
247 unumrf_openForSkeletonWithCollapseAndIdentityFallback(
248     const UChar* skeleton,
249     int32_t skeletonLen,
250     UNumberRangeCollapse collapse,
251     UNumberRangeIdentityFallback identityFallback,
252     const char* locale,
253     UParseError* perror,
254     UErrorCode* ec);
255 
256 
257 /**
258  * Creates an object to hold the result of a UNumberRangeFormatter
259  * operation. The object can be used repeatedly; it is cleared whenever
260  * passed to a format function.
261  *
262  * @param ec Set if an error occurs.
263  * @draft ICU 68
264  */
265 U_CAPI UFormattedNumberRange* U_EXPORT2
266 unumrf_openResult(UErrorCode* ec);
267 
268 
269 /**
270  * Uses a UNumberRangeFormatter to format a range of doubles.
271  *
272  * The UNumberRangeFormatter can be shared between threads. Each thread should have its own local
273  * UFormattedNumberRange, however, for storing the result of the formatting operation.
274  *
275  * NOTE: This is a C-compatible API; C++ users should build against numberrangeformatter.h instead.
276  *
277  * @param uformatter A formatter object; see unumberrangeformatter.h.
278  * @param first The first (usually smaller) number in the range.
279  * @param second The second (usually larger) number in the range.
280  * @param uresult The object that will be mutated to store the result; see unumrf_openResult.
281  * @param ec Set if an error occurs.
282  * @draft ICU 68
283  */
284 U_CAPI void U_EXPORT2
285 unumrf_formatDoubleRange(
286     const UNumberRangeFormatter* uformatter,
287     double first,
288     double second,
289     UFormattedNumberRange* uresult,
290     UErrorCode* ec);
291 
292 
293 /**
294  * Uses a UNumberRangeFormatter to format a range of decimal numbers.
295  *
296  * With a decimal number string, you can specify an input with arbitrary precision.
297  *
298  * The UNumberRangeFormatter can be shared between threads. Each thread should have its own local
299  * UFormattedNumberRange, however, for storing the result of the formatting operation.
300  *
301  * NOTE: This is a C-compatible API; C++ users should build against numberrangeformatter.h instead.
302  *
303  * @param uformatter A formatter object; see unumberrangeformatter.h.
304  * @param first The first (usually smaller) number in the range.
305  * @param firstLen The length of the first decimal number string.
306  * @param second The second (usually larger) number in the range.
307  * @param secondLen The length of the second decimal number string.
308  * @param uresult The object that will be mutated to store the result; see unumrf_openResult.
309  * @param ec Set if an error occurs.
310  * @draft ICU 68
311  */
312 U_CAPI void U_EXPORT2
313 unumrf_formatDecimalRange(
314     const UNumberRangeFormatter* uformatter,
315     const char* first,
316     int32_t firstLen,
317     const char* second,
318     int32_t secondLen,
319     UFormattedNumberRange* uresult,
320     UErrorCode* ec);
321 
322 
323 /**
324  * Returns a representation of a UFormattedNumberRange as a UFormattedValue,
325  * which can be subsequently passed to any API requiring that type.
326  *
327  * The returned object is owned by the UFormattedNumberRange and is valid
328  * only as long as the UFormattedNumber is present and unchanged in memory.
329  *
330  * You can think of this method as a cast between types.
331  *
332  * @param uresult The object containing the formatted number range.
333  * @param ec Set if an error occurs.
334  * @return A UFormattedValue owned by the input object.
335  * @draft ICU 68
336  */
337 U_CAPI const UFormattedValue* U_EXPORT2
338 unumrf_resultAsValue(const UFormattedNumberRange* uresult, UErrorCode* ec);
339 
340 
341 /**
342  * Extracts the identity result from a UFormattedNumberRange.
343  *
344  * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead.
345  *
346  * @param uresult The object containing the formatted number range.
347  * @param ec Set if an error occurs.
348  * @return The identity result; see UNumberRangeIdentityResult.
349  * @draft ICU 68
350  */
351 U_CAPI UNumberRangeIdentityResult U_EXPORT2
352 unumrf_resultGetIdentityResult(
353     const UFormattedNumberRange* uresult,
354     UErrorCode* ec);
355 
356 
357 /**
358  * Extracts the first formatted number as a decimal number. This endpoint
359  * is useful for obtaining the exact number being printed after scaling
360  * and rounding have been applied by the number range formatting pipeline.
361  *
362  * The syntax of the unformatted number is a "numeric string"
363  * as defined in the Decimal Arithmetic Specification, available at
364  * http://speleotrove.com/decimal
365  *
366  * @param  uresult       The input object containing the formatted number range.
367  * @param  dest          the 8-bit char buffer into which the decimal number is placed
368  * @param  destCapacity  The size, in chars, of the destination buffer.  May be zero
369  *                       for precomputing the required size.
370  * @param  ec            receives any error status.
371  *                       If U_BUFFER_OVERFLOW_ERROR: Returns number of chars for
372  *                       preflighting.
373  * @return Number of chars in the data.  Does not include a trailing NUL.
374  * @draft ICU 68
375  */
376 U_CAPI int32_t U_EXPORT2
377 unumrf_resultGetFirstDecimalNumber(
378     const UFormattedNumberRange* uresult,
379     char* dest,
380     int32_t destCapacity,
381     UErrorCode* ec);
382 
383 
384 /**
385  * Extracts the second formatted number as a decimal number. This endpoint
386  * is useful for obtaining the exact number being printed after scaling
387  * and rounding have been applied by the number range formatting pipeline.
388  *
389  * The syntax of the unformatted number is a "numeric string"
390  * as defined in the Decimal Arithmetic Specification, available at
391  * http://speleotrove.com/decimal
392  *
393  * @param  uresult       The input object containing the formatted number range.
394  * @param  dest          the 8-bit char buffer into which the decimal number is placed
395  * @param  destCapacity  The size, in chars, of the destination buffer.  May be zero
396  *                       for precomputing the required size.
397  * @param  ec            receives any error status.
398  *                       If U_BUFFER_OVERFLOW_ERROR: Returns number of chars for
399  *                       preflighting.
400  * @return Number of chars in the data.  Does not include a trailing NUL.
401  * @draft ICU 68
402  */
403 U_CAPI int32_t U_EXPORT2
404 unumrf_resultGetSecondDecimalNumber(
405     const UFormattedNumberRange* uresult,
406     char* dest,
407     int32_t destCapacity,
408     UErrorCode* ec);
409 
410 
411 /**
412  * Releases the UNumberFormatter created by unumf_openForSkeletonAndLocale().
413  *
414  * @param uformatter An object created by unumf_openForSkeletonAndLocale().
415  * @draft ICU 68
416  */
417 U_CAPI void U_EXPORT2
418 unumrf_close(UNumberRangeFormatter* uformatter);
419 
420 
421 /**
422  * Releases the UFormattedNumber created by unumf_openResult().
423  *
424  * @param uresult An object created by unumf_openResult().
425  * @draft ICU 68
426  */
427 U_CAPI void U_EXPORT2
428 unumrf_closeResult(UFormattedNumberRange* uresult);
429 
430 
431 #if U_SHOW_CPLUSPLUS_API
432 U_NAMESPACE_BEGIN
433 
434 /**
435  * \class LocalUNumberRangeFormatterPointer
436  * "Smart pointer" class; closes a UNumberFormatter via unumf_close().
437  * For most methods see the LocalPointerBase base class.
438  *
439  * Usage:
440  * <pre>
441  * LocalUNumberRangeFormatterPointer uformatter(
442  *     unumrf_openForSkeletonCollapseIdentityFallbackAndLocaleWithError(...));
443  * // no need to explicitly call unumrf_close()
444  * </pre>
445  *
446  * @see LocalPointerBase
447  * @see LocalPointer
448  * @draft ICU 68
449  */
450 U_DEFINE_LOCAL_OPEN_POINTER(LocalUNumberRangeFormatterPointer, UNumberRangeFormatter, unumrf_close);
451 
452 /**
453  * \class LocalUFormattedNumberPointer
454  * "Smart pointer" class; closes a UFormattedNumber via unumf_closeResult().
455  * For most methods see the LocalPointerBase base class.
456  *
457  * Usage:
458  * <pre>
459  * LocalUFormattedNumberRangePointer uresult(unumrf_openResult(...));
460  * // no need to explicitly call unumrf_closeResult()
461  * </pre>
462  *
463  * @see LocalPointerBase
464  * @see LocalPointer
465  * @draft ICU 68
466  */
467 U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattedNumberRangePointer, UFormattedNumberRange, unumrf_closeResult);
468 
469 U_NAMESPACE_END
470 #endif // U_SHOW_CPLUSPLUS_API
471 
472 #endif // U_HIDE_DRAFT_API
473 
474 #endif /* #if !UCONFIG_NO_FORMATTING */
475 #endif //__UNUMBERRANGEFORMATTER_H__
476