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