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