intl/icu/source/i18n/unum.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /*
michael@0 2 *******************************************************************************
michael@0 3 * Copyright (C) 1996-2013, International Business Machines
michael@0 4 * Corporation and others. All Rights Reserved.
michael@0 5 *******************************************************************************
michael@0 6 * Modification History:
michael@0 7 *
michael@0 8 * Date Name Description
michael@0 9 * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes
michael@0 10 *******************************************************************************
michael@0 11 */
michael@0 12
michael@0 13 #include "unicode/utypes.h"
michael@0 14
michael@0 15 #if !UCONFIG_NO_FORMATTING
michael@0 16
michael@0 17 #include "unicode/unum.h"
michael@0 18
michael@0 19 #include "unicode/uloc.h"
michael@0 20 #include "unicode/numfmt.h"
michael@0 21 #include "unicode/decimfmt.h"
michael@0 22 #include "unicode/rbnf.h"
michael@0 23 #include "unicode/ustring.h"
michael@0 24 #include "unicode/fmtable.h"
michael@0 25 #include "unicode/dcfmtsym.h"
michael@0 26 #include "unicode/curramt.h"
michael@0 27 #include "unicode/localpointer.h"
michael@0 28 #include "uassert.h"
michael@0 29 #include "cpputils.h"
michael@0 30 #include "cstring.h"
michael@0 31
michael@0 32
michael@0 33 U_NAMESPACE_USE
michael@0 34
michael@0 35
michael@0 36 U_CAPI UNumberFormat* U_EXPORT2
michael@0 37 unum_open( UNumberFormatStyle style,
michael@0 38 const UChar* pattern,
michael@0 39 int32_t patternLength,
michael@0 40 const char* locale,
michael@0 41 UParseError* parseErr,
michael@0 42 UErrorCode* status) {
michael@0 43 if(U_FAILURE(*status)) {
michael@0 44 return NULL;
michael@0 45 }
michael@0 46
michael@0 47 NumberFormat *retVal = NULL;
michael@0 48
michael@0 49 switch(style) {
michael@0 50 case UNUM_DECIMAL:
michael@0 51 case UNUM_CURRENCY:
michael@0 52 case UNUM_PERCENT:
michael@0 53 case UNUM_SCIENTIFIC:
michael@0 54 retVal = NumberFormat::createInstance(Locale(locale), style, *status);
michael@0 55 break;
michael@0 56
michael@0 57 case UNUM_PATTERN_DECIMAL: {
michael@0 58 UParseError tErr;
michael@0 59 /* UnicodeString can handle the case when patternLength = -1. */
michael@0 60 const UnicodeString pat(pattern, patternLength);
michael@0 61
michael@0 62 if(parseErr==NULL){
michael@0 63 parseErr = &tErr;
michael@0 64 }
michael@0 65
michael@0 66 DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status);
michael@0 67 if(syms == NULL) {
michael@0 68 *status = U_MEMORY_ALLOCATION_ERROR;
michael@0 69 return NULL;
michael@0 70 }
michael@0 71 if (U_FAILURE(*status)) {
michael@0 72 delete syms;
michael@0 73 return NULL;
michael@0 74 }
michael@0 75
michael@0 76 retVal = new DecimalFormat(pat, syms, *parseErr, *status);
michael@0 77 if(retVal == NULL) {
michael@0 78 delete syms;
michael@0 79 }
michael@0 80 } break;
michael@0 81
michael@0 82 #if U_HAVE_RBNF
michael@0 83 case UNUM_PATTERN_RULEBASED: {
michael@0 84 UParseError tErr;
michael@0 85 /* UnicodeString can handle the case when patternLength = -1. */
michael@0 86 const UnicodeString pat(pattern, patternLength);
michael@0 87
michael@0 88 if(parseErr==NULL){
michael@0 89 parseErr = &tErr;
michael@0 90 }
michael@0 91
michael@0 92 retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status);
michael@0 93 } break;
michael@0 94
michael@0 95 case UNUM_SPELLOUT:
michael@0 96 retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
michael@0 97 break;
michael@0 98
michael@0 99 case UNUM_ORDINAL:
michael@0 100 retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status);
michael@0 101 break;
michael@0 102
michael@0 103 case UNUM_DURATION:
michael@0 104 retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status);
michael@0 105 break;
michael@0 106
michael@0 107 case UNUM_NUMBERING_SYSTEM:
michael@0 108 retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status);
michael@0 109 break;
michael@0 110 #endif
michael@0 111
michael@0 112 default:
michael@0 113 *status = U_UNSUPPORTED_ERROR;
michael@0 114 return NULL;
michael@0 115 }
michael@0 116
michael@0 117 if(retVal == NULL && U_SUCCESS(*status)) {
michael@0 118 *status = U_MEMORY_ALLOCATION_ERROR;
michael@0 119 }
michael@0 120
michael@0 121 return reinterpret_cast<UNumberFormat *>(retVal);
michael@0 122 }
michael@0 123
michael@0 124 U_CAPI void U_EXPORT2
michael@0 125 unum_close(UNumberFormat* fmt)
michael@0 126 {
michael@0 127 delete (NumberFormat*) fmt;
michael@0 128 }
michael@0 129
michael@0 130 U_CAPI UNumberFormat* U_EXPORT2
michael@0 131 unum_clone(const UNumberFormat *fmt,
michael@0 132 UErrorCode *status)
michael@0 133 {
michael@0 134 if(U_FAILURE(*status))
michael@0 135 return 0;
michael@0 136
michael@0 137 Format *res = 0;
michael@0 138 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
michael@0 139 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
michael@0 140 if (df != NULL) {
michael@0 141 res = df->clone();
michael@0 142 } else {
michael@0 143 const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
michael@0 144 U_ASSERT(rbnf != NULL);
michael@0 145 res = rbnf->clone();
michael@0 146 }
michael@0 147
michael@0 148 if(res == 0) {
michael@0 149 *status = U_MEMORY_ALLOCATION_ERROR;
michael@0 150 return 0;
michael@0 151 }
michael@0 152
michael@0 153 return (UNumberFormat*) res;
michael@0 154 }
michael@0 155
michael@0 156 U_CAPI int32_t U_EXPORT2
michael@0 157 unum_format( const UNumberFormat* fmt,
michael@0 158 int32_t number,
michael@0 159 UChar* result,
michael@0 160 int32_t resultLength,
michael@0 161 UFieldPosition *pos,
michael@0 162 UErrorCode* status)
michael@0 163 {
michael@0 164 return unum_formatInt64(fmt, number, result, resultLength, pos, status);
michael@0 165 }
michael@0 166
michael@0 167 U_CAPI int32_t U_EXPORT2
michael@0 168 unum_formatInt64(const UNumberFormat* fmt,
michael@0 169 int64_t number,
michael@0 170 UChar* result,
michael@0 171 int32_t resultLength,
michael@0 172 UFieldPosition *pos,
michael@0 173 UErrorCode* status)
michael@0 174 {
michael@0 175 if(U_FAILURE(*status))
michael@0 176 return -1;
michael@0 177
michael@0 178 UnicodeString res;
michael@0 179 if(!(result==NULL && resultLength==0)) {
michael@0 180 // NULL destination for pure preflighting: empty dummy string
michael@0 181 // otherwise, alias the destination buffer
michael@0 182 res.setTo(result, 0, resultLength);
michael@0 183 }
michael@0 184
michael@0 185 FieldPosition fp;
michael@0 186
michael@0 187 if(pos != 0)
michael@0 188 fp.setField(pos->field);
michael@0 189
michael@0 190 ((const NumberFormat*)fmt)->format(number, res, fp, *status);
michael@0 191
michael@0 192 if(pos != 0) {
michael@0 193 pos->beginIndex = fp.getBeginIndex();
michael@0 194 pos->endIndex = fp.getEndIndex();
michael@0 195 }
michael@0 196
michael@0 197 return res.extract(result, resultLength, *status);
michael@0 198 }
michael@0 199
michael@0 200 U_CAPI int32_t U_EXPORT2
michael@0 201 unum_formatDouble( const UNumberFormat* fmt,
michael@0 202 double number,
michael@0 203 UChar* result,
michael@0 204 int32_t resultLength,
michael@0 205 UFieldPosition *pos, /* 0 if ignore */
michael@0 206 UErrorCode* status)
michael@0 207 {
michael@0 208
michael@0 209 if(U_FAILURE(*status)) return -1;
michael@0 210
michael@0 211 UnicodeString res;
michael@0 212 if(!(result==NULL && resultLength==0)) {
michael@0 213 // NULL destination for pure preflighting: empty dummy string
michael@0 214 // otherwise, alias the destination buffer
michael@0 215 res.setTo(result, 0, resultLength);
michael@0 216 }
michael@0 217
michael@0 218 FieldPosition fp;
michael@0 219
michael@0 220 if(pos != 0)
michael@0 221 fp.setField(pos->field);
michael@0 222
michael@0 223 ((const NumberFormat*)fmt)->format(number, res, fp, *status);
michael@0 224
michael@0 225 if(pos != 0) {
michael@0 226 pos->beginIndex = fp.getBeginIndex();
michael@0 227 pos->endIndex = fp.getEndIndex();
michael@0 228 }
michael@0 229
michael@0 230 return res.extract(result, resultLength, *status);
michael@0 231 }
michael@0 232
michael@0 233
michael@0 234 U_CAPI int32_t U_EXPORT2
michael@0 235 unum_formatDecimal(const UNumberFormat* fmt,
michael@0 236 const char * number,
michael@0 237 int32_t length,
michael@0 238 UChar* result,
michael@0 239 int32_t resultLength,
michael@0 240 UFieldPosition *pos, /* 0 if ignore */
michael@0 241 UErrorCode* status) {
michael@0 242
michael@0 243 if(U_FAILURE(*status)) {
michael@0 244 return -1;
michael@0 245 }
michael@0 246 if ((result == NULL && resultLength != 0) || resultLength < 0) {
michael@0 247 *status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 248 return -1;
michael@0 249 }
michael@0 250
michael@0 251 FieldPosition fp;
michael@0 252 if(pos != 0) {
michael@0 253 fp.setField(pos->field);
michael@0 254 }
michael@0 255
michael@0 256 if (length < 0) {
michael@0 257 length = uprv_strlen(number);
michael@0 258 }
michael@0 259 StringPiece numSP(number, length);
michael@0 260 Formattable numFmtbl(numSP, *status);
michael@0 261
michael@0 262 UnicodeString resultStr;
michael@0 263 if (resultLength > 0) {
michael@0 264 // Alias the destination buffer.
michael@0 265 resultStr.setTo(result, 0, resultLength);
michael@0 266 }
michael@0 267 ((const NumberFormat*)fmt)->format(numFmtbl, resultStr, fp, *status);
michael@0 268 if(pos != 0) {
michael@0 269 pos->beginIndex = fp.getBeginIndex();
michael@0 270 pos->endIndex = fp.getEndIndex();
michael@0 271 }
michael@0 272 return resultStr.extract(result, resultLength, *status);
michael@0 273 }
michael@0 274
michael@0 275
michael@0 276
michael@0 277
michael@0 278 U_CAPI int32_t U_EXPORT2
michael@0 279 unum_formatDoubleCurrency(const UNumberFormat* fmt,
michael@0 280 double number,
michael@0 281 UChar* currency,
michael@0 282 UChar* result,
michael@0 283 int32_t resultLength,
michael@0 284 UFieldPosition* pos, /* ignored if 0 */
michael@0 285 UErrorCode* status) {
michael@0 286 if (U_FAILURE(*status)) return -1;
michael@0 287
michael@0 288 UnicodeString res;
michael@0 289 if (!(result==NULL && resultLength==0)) {
michael@0 290 // NULL destination for pure preflighting: empty dummy string
michael@0 291 // otherwise, alias the destination buffer
michael@0 292 res.setTo(result, 0, resultLength);
michael@0 293 }
michael@0 294
michael@0 295 FieldPosition fp;
michael@0 296 if (pos != 0) {
michael@0 297 fp.setField(pos->field);
michael@0 298 }
michael@0 299 CurrencyAmount *tempCurrAmnt = new CurrencyAmount(number, currency, *status);
michael@0 300 // Check for null pointer.
michael@0 301 if (tempCurrAmnt == NULL) {
michael@0 302 *status = U_MEMORY_ALLOCATION_ERROR;
michael@0 303 return -1;
michael@0 304 }
michael@0 305 Formattable n(tempCurrAmnt);
michael@0 306 ((const NumberFormat*)fmt)->format(n, res, fp, *status);
michael@0 307
michael@0 308 if (pos != 0) {
michael@0 309 pos->beginIndex = fp.getBeginIndex();
michael@0 310 pos->endIndex = fp.getEndIndex();
michael@0 311 }
michael@0 312
michael@0 313 return res.extract(result, resultLength, *status);
michael@0 314 }
michael@0 315
michael@0 316 static void
michael@0 317 parseRes(Formattable& res,
michael@0 318 const UNumberFormat* fmt,
michael@0 319 const UChar* text,
michael@0 320 int32_t textLength,
michael@0 321 int32_t *parsePos /* 0 = start */,
michael@0 322 UErrorCode *status)
michael@0 323 {
michael@0 324 if(U_FAILURE(*status))
michael@0 325 return;
michael@0 326
michael@0 327 const UnicodeString src((UBool)(textLength == -1), text, textLength);
michael@0 328 ParsePosition pp;
michael@0 329
michael@0 330 if(parsePos != 0)
michael@0 331 pp.setIndex(*parsePos);
michael@0 332
michael@0 333 ((const NumberFormat*)fmt)->parse(src, res, pp);
michael@0 334
michael@0 335 if(pp.getErrorIndex() != -1) {
michael@0 336 *status = U_PARSE_ERROR;
michael@0 337 if(parsePos != 0) {
michael@0 338 *parsePos = pp.getErrorIndex();
michael@0 339 }
michael@0 340 } else if(parsePos != 0) {
michael@0 341 *parsePos = pp.getIndex();
michael@0 342 }
michael@0 343 }
michael@0 344
michael@0 345 U_CAPI int32_t U_EXPORT2
michael@0 346 unum_parse( const UNumberFormat* fmt,
michael@0 347 const UChar* text,
michael@0 348 int32_t textLength,
michael@0 349 int32_t *parsePos /* 0 = start */,
michael@0 350 UErrorCode *status)
michael@0 351 {
michael@0 352 Formattable res;
michael@0 353 parseRes(res, fmt, text, textLength, parsePos, status);
michael@0 354 return res.getLong(*status);
michael@0 355 }
michael@0 356
michael@0 357 U_CAPI int64_t U_EXPORT2
michael@0 358 unum_parseInt64( const UNumberFormat* fmt,
michael@0 359 const UChar* text,
michael@0 360 int32_t textLength,
michael@0 361 int32_t *parsePos /* 0 = start */,
michael@0 362 UErrorCode *status)
michael@0 363 {
michael@0 364 Formattable res;
michael@0 365 parseRes(res, fmt, text, textLength, parsePos, status);
michael@0 366 return res.getInt64(*status);
michael@0 367 }
michael@0 368
michael@0 369 U_CAPI double U_EXPORT2
michael@0 370 unum_parseDouble( const UNumberFormat* fmt,
michael@0 371 const UChar* text,
michael@0 372 int32_t textLength,
michael@0 373 int32_t *parsePos /* 0 = start */,
michael@0 374 UErrorCode *status)
michael@0 375 {
michael@0 376 Formattable res;
michael@0 377 parseRes(res, fmt, text, textLength, parsePos, status);
michael@0 378 return res.getDouble(*status);
michael@0 379 }
michael@0 380
michael@0 381 U_CAPI int32_t U_EXPORT2
michael@0 382 unum_parseDecimal(const UNumberFormat* fmt,
michael@0 383 const UChar* text,
michael@0 384 int32_t textLength,
michael@0 385 int32_t *parsePos /* 0 = start */,
michael@0 386 char *outBuf,
michael@0 387 int32_t outBufLength,
michael@0 388 UErrorCode *status)
michael@0 389 {
michael@0 390 if (U_FAILURE(*status)) {
michael@0 391 return -1;
michael@0 392 }
michael@0 393 if ((outBuf == NULL && outBufLength != 0) || outBufLength < 0) {
michael@0 394 *status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 395 return -1;
michael@0 396 }
michael@0 397 Formattable res;
michael@0 398 parseRes(res, fmt, text, textLength, parsePos, status);
michael@0 399 StringPiece sp = res.getDecimalNumber(*status);
michael@0 400 if (U_FAILURE(*status)) {
michael@0 401 return -1;
michael@0 402 } else if (sp.size() > outBufLength) {
michael@0 403 *status = U_BUFFER_OVERFLOW_ERROR;
michael@0 404 } else if (sp.size() == outBufLength) {
michael@0 405 uprv_strncpy(outBuf, sp.data(), sp.size());
michael@0 406 *status = U_STRING_NOT_TERMINATED_WARNING;
michael@0 407 } else {
michael@0 408 U_ASSERT(outBufLength > 0);
michael@0 409 uprv_strcpy(outBuf, sp.data());
michael@0 410 }
michael@0 411 return sp.size();
michael@0 412 }
michael@0 413
michael@0 414 U_CAPI double U_EXPORT2
michael@0 415 unum_parseDoubleCurrency(const UNumberFormat* fmt,
michael@0 416 const UChar* text,
michael@0 417 int32_t textLength,
michael@0 418 int32_t* parsePos, /* 0 = start */
michael@0 419 UChar* currency,
michael@0 420 UErrorCode* status) {
michael@0 421 double doubleVal = 0.0;
michael@0 422 currency[0] = 0;
michael@0 423 if (U_FAILURE(*status)) {
michael@0 424 return doubleVal;
michael@0 425 }
michael@0 426 const UnicodeString src((UBool)(textLength == -1), text, textLength);
michael@0 427 ParsePosition pp;
michael@0 428 if (parsePos != NULL) {
michael@0 429 pp.setIndex(*parsePos);
michael@0 430 }
michael@0 431 *status = U_PARSE_ERROR; // assume failure, reset if succeed
michael@0 432 LocalPointer<CurrencyAmount> currAmt(((const NumberFormat*)fmt)->parseCurrency(src, pp));
michael@0 433 if (pp.getErrorIndex() != -1) {
michael@0 434 if (parsePos != NULL) {
michael@0 435 *parsePos = pp.getErrorIndex();
michael@0 436 }
michael@0 437 } else {
michael@0 438 if (parsePos != NULL) {
michael@0 439 *parsePos = pp.getIndex();
michael@0 440 }
michael@0 441 if (pp.getIndex() > 0) {
michael@0 442 *status = U_ZERO_ERROR;
michael@0 443 u_strcpy(currency, currAmt->getISOCurrency());
michael@0 444 doubleVal = currAmt->getNumber().getDouble(*status);
michael@0 445 }
michael@0 446 }
michael@0 447 return doubleVal;
michael@0 448 }
michael@0 449
michael@0 450 U_CAPI const char* U_EXPORT2
michael@0 451 unum_getAvailable(int32_t index)
michael@0 452 {
michael@0 453 return uloc_getAvailable(index);
michael@0 454 }
michael@0 455
michael@0 456 U_CAPI int32_t U_EXPORT2
michael@0 457 unum_countAvailable()
michael@0 458 {
michael@0 459 return uloc_countAvailable();
michael@0 460 }
michael@0 461
michael@0 462 U_CAPI int32_t U_EXPORT2
michael@0 463 unum_getAttribute(const UNumberFormat* fmt,
michael@0 464 UNumberFormatAttribute attr)
michael@0 465 {
michael@0 466 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
michael@0 467 if ( attr == UNUM_LENIENT_PARSE ) {
michael@0 468 // Supported for all subclasses
michael@0 469 return nf->isLenient();
michael@0 470 }
michael@0 471
michael@0 472 // The remaining attributea are only supported for DecimalFormat
michael@0 473 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
michael@0 474 if (df != NULL) {
michael@0 475 UErrorCode ignoredStatus = U_ZERO_ERROR;
michael@0 476 return df->getAttribute( attr, ignoredStatus );
michael@0 477 }
michael@0 478
michael@0 479 return -1;
michael@0 480 }
michael@0 481
michael@0 482 U_CAPI void U_EXPORT2
michael@0 483 unum_setAttribute( UNumberFormat* fmt,
michael@0 484 UNumberFormatAttribute attr,
michael@0 485 int32_t newValue)
michael@0 486 {
michael@0 487 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
michael@0 488 if ( attr == UNUM_LENIENT_PARSE ) {
michael@0 489 // Supported for all subclasses
michael@0 490 // keep this here as the class may not be a DecimalFormat
michael@0 491 return nf->setLenient(newValue != 0);
michael@0 492 }
michael@0 493 // The remaining attributea are only supported for DecimalFormat
michael@0 494 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
michael@0 495 if (df != NULL) {
michael@0 496 UErrorCode ignoredStatus = U_ZERO_ERROR;
michael@0 497 df->setAttribute(attr, newValue, ignoredStatus);
michael@0 498 }
michael@0 499 }
michael@0 500
michael@0 501 U_CAPI double U_EXPORT2
michael@0 502 unum_getDoubleAttribute(const UNumberFormat* fmt,
michael@0 503 UNumberFormatAttribute attr)
michael@0 504 {
michael@0 505 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
michael@0 506 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
michael@0 507 if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) {
michael@0 508 return df->getRoundingIncrement();
michael@0 509 } else {
michael@0 510 return -1.0;
michael@0 511 }
michael@0 512 }
michael@0 513
michael@0 514 U_CAPI void U_EXPORT2
michael@0 515 unum_setDoubleAttribute( UNumberFormat* fmt,
michael@0 516 UNumberFormatAttribute attr,
michael@0 517 double newValue)
michael@0 518 {
michael@0 519 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
michael@0 520 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
michael@0 521 if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) {
michael@0 522 df->setRoundingIncrement(newValue);
michael@0 523 }
michael@0 524 }
michael@0 525
michael@0 526 U_CAPI int32_t U_EXPORT2
michael@0 527 unum_getTextAttribute(const UNumberFormat* fmt,
michael@0 528 UNumberFormatTextAttribute tag,
michael@0 529 UChar* result,
michael@0 530 int32_t resultLength,
michael@0 531 UErrorCode* status)
michael@0 532 {
michael@0 533 if(U_FAILURE(*status))
michael@0 534 return -1;
michael@0 535
michael@0 536 UnicodeString res;
michael@0 537 if(!(result==NULL && resultLength==0)) {
michael@0 538 // NULL destination for pure preflighting: empty dummy string
michael@0 539 // otherwise, alias the destination buffer
michael@0 540 res.setTo(result, 0, resultLength);
michael@0 541 }
michael@0 542
michael@0 543 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
michael@0 544 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
michael@0 545 if (df != NULL) {
michael@0 546 switch(tag) {
michael@0 547 case UNUM_POSITIVE_PREFIX:
michael@0 548 df->getPositivePrefix(res);
michael@0 549 break;
michael@0 550
michael@0 551 case UNUM_POSITIVE_SUFFIX:
michael@0 552 df->getPositiveSuffix(res);
michael@0 553 break;
michael@0 554
michael@0 555 case UNUM_NEGATIVE_PREFIX:
michael@0 556 df->getNegativePrefix(res);
michael@0 557 break;
michael@0 558
michael@0 559 case UNUM_NEGATIVE_SUFFIX:
michael@0 560 df->getNegativeSuffix(res);
michael@0 561 break;
michael@0 562
michael@0 563 case UNUM_PADDING_CHARACTER:
michael@0 564 res = df->getPadCharacterString();
michael@0 565 break;
michael@0 566
michael@0 567 case UNUM_CURRENCY_CODE:
michael@0 568 res = UnicodeString(df->getCurrency());
michael@0 569 break;
michael@0 570
michael@0 571 default:
michael@0 572 *status = U_UNSUPPORTED_ERROR;
michael@0 573 return -1;
michael@0 574 }
michael@0 575 } else {
michael@0 576 const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
michael@0 577 U_ASSERT(rbnf != NULL);
michael@0 578 if (tag == UNUM_DEFAULT_RULESET) {
michael@0 579 res = rbnf->getDefaultRuleSetName();
michael@0 580 } else if (tag == UNUM_PUBLIC_RULESETS) {
michael@0 581 int32_t count = rbnf->getNumberOfRuleSetNames();
michael@0 582 for (int i = 0; i < count; ++i) {
michael@0 583 res += rbnf->getRuleSetName(i);
michael@0 584 res += (UChar)0x003b; // semicolon
michael@0 585 }
michael@0 586 } else {
michael@0 587 *status = U_UNSUPPORTED_ERROR;
michael@0 588 return -1;
michael@0 589 }
michael@0 590 }
michael@0 591
michael@0 592 return res.extract(result, resultLength, *status);
michael@0 593 }
michael@0 594
michael@0 595 U_CAPI void U_EXPORT2
michael@0 596 unum_setTextAttribute( UNumberFormat* fmt,
michael@0 597 UNumberFormatTextAttribute tag,
michael@0 598 const UChar* newValue,
michael@0 599 int32_t newValueLength,
michael@0 600 UErrorCode *status)
michael@0 601 {
michael@0 602 if(U_FAILURE(*status))
michael@0 603 return;
michael@0 604
michael@0 605 UnicodeString val(newValue, newValueLength);
michael@0 606 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
michael@0 607 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
michael@0 608 if (df != NULL) {
michael@0 609 switch(tag) {
michael@0 610 case UNUM_POSITIVE_PREFIX:
michael@0 611 df->setPositivePrefix(val);
michael@0 612 break;
michael@0 613
michael@0 614 case UNUM_POSITIVE_SUFFIX:
michael@0 615 df->setPositiveSuffix(val);
michael@0 616 break;
michael@0 617
michael@0 618 case UNUM_NEGATIVE_PREFIX:
michael@0 619 df->setNegativePrefix(val);
michael@0 620 break;
michael@0 621
michael@0 622 case UNUM_NEGATIVE_SUFFIX:
michael@0 623 df->setNegativeSuffix(val);
michael@0 624 break;
michael@0 625
michael@0 626 case UNUM_PADDING_CHARACTER:
michael@0 627 df->setPadCharacter(val);
michael@0 628 break;
michael@0 629
michael@0 630 case UNUM_CURRENCY_CODE:
michael@0 631 df->setCurrency(val.getTerminatedBuffer(), *status);
michael@0 632 break;
michael@0 633
michael@0 634 default:
michael@0 635 *status = U_UNSUPPORTED_ERROR;
michael@0 636 break;
michael@0 637 }
michael@0 638 } else {
michael@0 639 RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf);
michael@0 640 U_ASSERT(rbnf != NULL);
michael@0 641 if (tag == UNUM_DEFAULT_RULESET) {
michael@0 642 rbnf->setDefaultRuleSet(val, *status);
michael@0 643 } else {
michael@0 644 *status = U_UNSUPPORTED_ERROR;
michael@0 645 }
michael@0 646 }
michael@0 647 }
michael@0 648
michael@0 649 U_CAPI int32_t U_EXPORT2
michael@0 650 unum_toPattern( const UNumberFormat* fmt,
michael@0 651 UBool isPatternLocalized,
michael@0 652 UChar* result,
michael@0 653 int32_t resultLength,
michael@0 654 UErrorCode* status)
michael@0 655 {
michael@0 656 if(U_FAILURE(*status))
michael@0 657 return -1;
michael@0 658
michael@0 659 UnicodeString pat;
michael@0 660 if(!(result==NULL && resultLength==0)) {
michael@0 661 // NULL destination for pure preflighting: empty dummy string
michael@0 662 // otherwise, alias the destination buffer
michael@0 663 pat.setTo(result, 0, resultLength);
michael@0 664 }
michael@0 665
michael@0 666 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
michael@0 667 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
michael@0 668 if (df != NULL) {
michael@0 669 if(isPatternLocalized)
michael@0 670 df->toLocalizedPattern(pat);
michael@0 671 else
michael@0 672 df->toPattern(pat);
michael@0 673 } else {
michael@0 674 const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
michael@0 675 U_ASSERT(rbnf != NULL);
michael@0 676 pat = rbnf->getRules();
michael@0 677 }
michael@0 678 return pat.extract(result, resultLength, *status);
michael@0 679 }
michael@0 680
michael@0 681 U_CAPI int32_t U_EXPORT2
michael@0 682 unum_getSymbol(const UNumberFormat *fmt,
michael@0 683 UNumberFormatSymbol symbol,
michael@0 684 UChar *buffer,
michael@0 685 int32_t size,
michael@0 686 UErrorCode *status)
michael@0 687 {
michael@0 688 if(status==NULL || U_FAILURE(*status)) {
michael@0 689 return 0;
michael@0 690 }
michael@0 691 if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) {
michael@0 692 *status=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 693 return 0;
michael@0 694 }
michael@0 695 const NumberFormat *nf = reinterpret_cast<const NumberFormat *>(fmt);
michael@0 696 const DecimalFormat *dcf = dynamic_cast<const DecimalFormat *>(nf);
michael@0 697 if (dcf == NULL) {
michael@0 698 *status = U_UNSUPPORTED_ERROR;
michael@0 699 return 0;
michael@0 700 }
michael@0 701
michael@0 702 return dcf->
michael@0 703 getDecimalFormatSymbols()->
michael@0 704 getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol).
michael@0 705 extract(buffer, size, *status);
michael@0 706 }
michael@0 707
michael@0 708 U_CAPI void U_EXPORT2
michael@0 709 unum_setSymbol(UNumberFormat *fmt,
michael@0 710 UNumberFormatSymbol symbol,
michael@0 711 const UChar *value,
michael@0 712 int32_t length,
michael@0 713 UErrorCode *status)
michael@0 714 {
michael@0 715 if(status==NULL || U_FAILURE(*status)) {
michael@0 716 return;
michael@0 717 }
michael@0 718 if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) {
michael@0 719 *status=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 720 return;
michael@0 721 }
michael@0 722 NumberFormat *nf = reinterpret_cast<NumberFormat *>(fmt);
michael@0 723 DecimalFormat *dcf = dynamic_cast<DecimalFormat *>(nf);
michael@0 724 if (dcf == NULL) {
michael@0 725 *status = U_UNSUPPORTED_ERROR;
michael@0 726 return;
michael@0 727 }
michael@0 728
michael@0 729 DecimalFormatSymbols symbols(*dcf->getDecimalFormatSymbols());
michael@0 730 symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol,
michael@0 731 UnicodeString(value, length)); /* UnicodeString can handle the case when length = -1. */
michael@0 732 dcf->setDecimalFormatSymbols(symbols);
michael@0 733 }
michael@0 734
michael@0 735 U_CAPI void U_EXPORT2
michael@0 736 unum_applyPattern( UNumberFormat *fmt,
michael@0 737 UBool localized,
michael@0 738 const UChar *pattern,
michael@0 739 int32_t patternLength,
michael@0 740 UParseError *parseError,
michael@0 741 UErrorCode* status)
michael@0 742 {
michael@0 743 UErrorCode tStatus = U_ZERO_ERROR;
michael@0 744 UParseError tParseError;
michael@0 745
michael@0 746 if(parseError == NULL){
michael@0 747 parseError = &tParseError;
michael@0 748 }
michael@0 749
michael@0 750 if(status==NULL){
michael@0 751 status = &tStatus;
michael@0 752 }
michael@0 753
michael@0 754 int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
michael@0 755 const UnicodeString pat((UChar*)pattern, len, len);
michael@0 756
michael@0 757 // Verify if the object passed is a DecimalFormat object
michael@0 758 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
michael@0 759 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
michael@0 760 if (df != NULL) {
michael@0 761 if(localized) {
michael@0 762 df->applyLocalizedPattern(pat,*parseError, *status);
michael@0 763 } else {
michael@0 764 df->applyPattern(pat,*parseError, *status);
michael@0 765 }
michael@0 766 } else {
michael@0 767 *status = U_UNSUPPORTED_ERROR;
michael@0 768 return;
michael@0 769 }
michael@0 770 }
michael@0 771
michael@0 772 U_CAPI const char* U_EXPORT2
michael@0 773 unum_getLocaleByType(const UNumberFormat *fmt,
michael@0 774 ULocDataLocaleType type,
michael@0 775 UErrorCode* status)
michael@0 776 {
michael@0 777 if (fmt == NULL) {
michael@0 778 if (U_SUCCESS(*status)) {
michael@0 779 *status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 780 }
michael@0 781 return NULL;
michael@0 782 }
michael@0 783 return ((const Format*)fmt)->getLocaleID(type, *status);
michael@0 784 }
michael@0 785
michael@0 786 U_INTERNAL UFormattable * U_EXPORT2
michael@0 787 unum_parseToUFormattable(const UNumberFormat* fmt,
michael@0 788 UFormattable *result,
michael@0 789 const UChar* text,
michael@0 790 int32_t textLength,
michael@0 791 int32_t* parsePos, /* 0 = start */
michael@0 792 UErrorCode* status) {
michael@0 793 UFormattable *newFormattable = NULL;
michael@0 794 if (U_FAILURE(*status)) return result;
michael@0 795 if (fmt == NULL || (text==NULL && textLength!=0)) {
michael@0 796 *status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 797 return result;
michael@0 798 }
michael@0 799 if (result == NULL) { // allocate if not allocated.
michael@0 800 newFormattable = result = ufmt_open(status);
michael@0 801 }
michael@0 802 parseRes(*(Formattable::fromUFormattable(result)), fmt, text, textLength, parsePos, status);
michael@0 803 if (U_FAILURE(*status) && newFormattable != NULL) {
michael@0 804 ufmt_close(newFormattable);
michael@0 805 result = NULL; // deallocate if there was a parse error
michael@0 806 }
michael@0 807 return result;
michael@0 808 }
michael@0 809
michael@0 810 U_INTERNAL int32_t U_EXPORT2
michael@0 811 unum_formatUFormattable(const UNumberFormat* fmt,
michael@0 812 const UFormattable *number,
michael@0 813 UChar *result,
michael@0 814 int32_t resultLength,
michael@0 815 UFieldPosition *pos, /* ignored if 0 */
michael@0 816 UErrorCode *status) {
michael@0 817 if (U_FAILURE(*status)) {
michael@0 818 return 0;
michael@0 819 }
michael@0 820 if (fmt == NULL || number==NULL ||
michael@0 821 (result==NULL ? resultLength!=0 : resultLength<0)) {
michael@0 822 *status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 823 return 0;
michael@0 824 }
michael@0 825 UnicodeString res(result, 0, resultLength);
michael@0 826
michael@0 827 FieldPosition fp;
michael@0 828
michael@0 829 if(pos != 0)
michael@0 830 fp.setField(pos->field);
michael@0 831
michael@0 832 ((const NumberFormat*)fmt)->format(*(Formattable::fromUFormattable(number)), res, fp, *status);
michael@0 833
michael@0 834 if(pos != 0) {
michael@0 835 pos->beginIndex = fp.getBeginIndex();
michael@0 836 pos->endIndex = fp.getEndIndex();
michael@0 837 }
michael@0 838
michael@0 839 return res.extract(result, resultLength, *status);
michael@0 840 }
michael@0 841
michael@0 842 #endif /* #if !UCONFIG_NO_FORMATTING */

mercurial