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