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