]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ******************************************************************************* | |
57a6839d | 3 | * Copyright (C) 1996-2014, 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 | 26 | #include "unicode/curramt.h" |
4388f060 | 27 | #include "unicode/localpointer.h" |
57a6839d | 28 | #include "unicode/udisplaycontext.h" |
374ca955 | 29 | #include "uassert.h" |
b75a7d8f | 30 | #include "cpputils.h" |
729e4ab9 | 31 | #include "cstring.h" |
b75a7d8f | 32 | |
b75a7d8f | 33 | |
374ca955 | 34 | U_NAMESPACE_USE |
b75a7d8f A |
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, | |
4388f060 A |
43 | UErrorCode* status) { |
44 | if(U_FAILURE(*status)) { | |
45 | return NULL; | |
374ca955 A |
46 | } |
47 | ||
4388f060 | 48 | NumberFormat *retVal = NULL; |
374ca955 A |
49 | |
50 | switch(style) { | |
51 | case UNUM_DECIMAL: | |
374ca955 | 52 | case UNUM_CURRENCY: |
374ca955 | 53 | case UNUM_PERCENT: |
374ca955 | 54 | case UNUM_SCIENTIFIC: |
57a6839d A |
55 | case UNUM_CURRENCY_ISO: |
56 | case UNUM_CURRENCY_PLURAL: | |
57 | case UNUM_CURRENCY_ACCOUNTING: | |
4388f060 | 58 | retVal = NumberFormat::createInstance(Locale(locale), style, *status); |
b75a7d8f A |
59 | break; |
60 | ||
374ca955 A |
61 | case UNUM_PATTERN_DECIMAL: { |
62 | UParseError tErr; | |
63 | /* UnicodeString can handle the case when patternLength = -1. */ | |
64 | const UnicodeString pat(pattern, patternLength); | |
374ca955 A |
65 | |
66 | if(parseErr==NULL){ | |
67 | parseErr = &tErr; | |
68 | } | |
69 | ||
4388f060 A |
70 | DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status); |
71 | if(syms == NULL) { | |
374ca955 | 72 | *status = U_MEMORY_ALLOCATION_ERROR; |
4388f060 | 73 | return NULL; |
374ca955 | 74 | } |
729e4ab9 A |
75 | if (U_FAILURE(*status)) { |
76 | delete syms; | |
4388f060 | 77 | return NULL; |
729e4ab9 | 78 | } |
374ca955 | 79 | |
4388f060 A |
80 | retVal = new DecimalFormat(pat, syms, *parseErr, *status); |
81 | if(retVal == NULL) { | |
374ca955 A |
82 | delete syms; |
83 | } | |
4388f060 | 84 | } break; |
374ca955 | 85 | |
b75a7d8f | 86 | #if U_HAVE_RBNF |
374ca955 A |
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 | ||
4388f060 | 96 | retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status); |
374ca955 A |
97 | } break; |
98 | ||
99 | case UNUM_SPELLOUT: | |
4388f060 | 100 | retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status); |
374ca955 | 101 | break; |
b75a7d8f | 102 | |
374ca955 | 103 | case UNUM_ORDINAL: |
4388f060 | 104 | retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status); |
374ca955 | 105 | break; |
b75a7d8f | 106 | |
374ca955 | 107 | case UNUM_DURATION: |
4388f060 | 108 | retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status); |
374ca955 | 109 | break; |
729e4ab9 A |
110 | |
111 | case UNUM_NUMBERING_SYSTEM: | |
4388f060 | 112 | retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status); |
729e4ab9 | 113 | break; |
374ca955 A |
114 | #endif |
115 | ||
116 | default: | |
117 | *status = U_UNSUPPORTED_ERROR; | |
4388f060 | 118 | return NULL; |
374ca955 | 119 | } |
b75a7d8f | 120 | |
4388f060 | 121 | if(retVal == NULL && U_SUCCESS(*status)) { |
b75a7d8f | 122 | *status = U_MEMORY_ALLOCATION_ERROR; |
374ca955 | 123 | } |
b75a7d8f | 124 | |
4388f060 | 125 | return reinterpret_cast<UNumberFormat *>(retVal); |
b75a7d8f A |
126 | } |
127 | ||
128 | U_CAPI void U_EXPORT2 | |
129 | unum_close(UNumberFormat* fmt) | |
130 | { | |
374ca955 | 131 | delete (NumberFormat*) fmt; |
b75a7d8f A |
132 | } |
133 | ||
134 | U_CAPI UNumberFormat* U_EXPORT2 | |
135 | unum_clone(const UNumberFormat *fmt, | |
136 | UErrorCode *status) | |
137 | { | |
374ca955 A |
138 | if(U_FAILURE(*status)) |
139 | return 0; | |
140 | ||
141 | Format *res = 0; | |
729e4ab9 A |
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(); | |
374ca955 | 146 | } else { |
729e4ab9 A |
147 | const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); |
148 | U_ASSERT(rbnf != NULL); | |
149 | res = rbnf->clone(); | |
374ca955 | 150 | } |
b75a7d8f | 151 | |
374ca955 A |
152 | if(res == 0) { |
153 | *status = U_MEMORY_ALLOCATION_ERROR; | |
154 | return 0; | |
155 | } | |
156 | ||
157 | return (UNumberFormat*) res; | |
b75a7d8f A |
158 | } |
159 | ||
160 | U_CAPI int32_t U_EXPORT2 | |
161 | unum_format( const UNumberFormat* fmt, | |
374ca955 | 162 | int32_t number, |
b75a7d8f | 163 | UChar* result, |
374ca955 | 164 | int32_t resultLength, |
b75a7d8f | 165 | UFieldPosition *pos, |
374ca955 | 166 | UErrorCode* status) |
b75a7d8f | 167 | { |
374ca955 A |
168 | return unum_formatInt64(fmt, number, result, resultLength, pos, status); |
169 | } | |
b75a7d8f | 170 | |
374ca955 A |
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 | ||
51004dcb A |
194 | ((const NumberFormat*)fmt)->format(number, res, fp, *status); |
195 | ||
374ca955 A |
196 | if(pos != 0) { |
197 | pos->beginIndex = fp.getBeginIndex(); | |
198 | pos->endIndex = fp.getEndIndex(); | |
199 | } | |
200 | ||
201 | return res.extract(result, resultLength, *status); | |
b75a7d8f A |
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 | ||
51004dcb | 227 | ((const NumberFormat*)fmt)->format(number, res, fp, *status); |
b75a7d8f A |
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 | ||
729e4ab9 | 237 | |
51004dcb | 238 | U_CAPI int32_t U_EXPORT2 |
729e4ab9 A |
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 | ||
46f4442e | 282 | U_CAPI int32_t U_EXPORT2 |
374ca955 A |
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 | } | |
46f4442e A |
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); | |
374ca955 A |
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 */, | |
374ca955 A |
326 | UErrorCode *status) |
327 | { | |
328 | if(U_FAILURE(*status)) | |
329 | return; | |
330 | ||
4388f060 | 331 | const UnicodeString src((UBool)(textLength == -1), text, textLength); |
374ca955 A |
332 | ParsePosition pp; |
333 | ||
334 | if(parsePos != 0) | |
335 | pp.setIndex(*parsePos); | |
336 | ||
4388f060 | 337 | ((const NumberFormat*)fmt)->parse(src, res, pp); |
374ca955 | 338 | |
46f4442e A |
339 | if(pp.getErrorIndex() != -1) { |
340 | *status = U_PARSE_ERROR; | |
341 | if(parsePos != 0) { | |
374ca955 | 342 | *parsePos = pp.getErrorIndex(); |
374ca955 | 343 | } |
46f4442e A |
344 | } else if(parsePos != 0) { |
345 | *parsePos = pp.getIndex(); | |
374ca955 A |
346 | } |
347 | } | |
348 | ||
b75a7d8f A |
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 | { | |
374ca955 | 356 | Formattable res; |
4388f060 | 357 | parseRes(res, fmt, text, textLength, parsePos, status); |
374ca955 A |
358 | return res.getLong(*status); |
359 | } | |
b75a7d8f | 360 | |
374ca955 A |
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; | |
4388f060 | 369 | parseRes(res, fmt, text, textLength, parsePos, status); |
374ca955 | 370 | return res.getInt64(*status); |
b75a7d8f A |
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 | { | |
374ca955 | 380 | Formattable res; |
4388f060 | 381 | parseRes(res, fmt, text, textLength, parsePos, status); |
374ca955 A |
382 | return res.getDouble(*status); |
383 | } | |
b75a7d8f | 384 | |
729e4ab9 A |
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; | |
4388f060 | 402 | parseRes(res, fmt, text, textLength, parsePos, status); |
729e4ab9 A |
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 { | |
4388f060 | 412 | U_ASSERT(outBufLength > 0); |
729e4ab9 A |
413 | uprv_strcpy(outBuf, sp.data()); |
414 | } | |
415 | return sp.size(); | |
416 | } | |
417 | ||
46f4442e | 418 | U_CAPI double U_EXPORT2 |
374ca955 A |
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) { | |
4388f060 | 425 | double doubleVal = 0.0; |
374ca955 | 426 | currency[0] = 0; |
4388f060 A |
427 | if (U_FAILURE(*status)) { |
428 | return doubleVal; | |
b75a7d8f | 429 | } |
4388f060 A |
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; | |
b75a7d8f A |
452 | } |
453 | ||
454 | U_CAPI const char* U_EXPORT2 | |
455 | unum_getAvailable(int32_t index) | |
456 | { | |
374ca955 | 457 | return uloc_getAvailable(index); |
b75a7d8f A |
458 | } |
459 | ||
460 | U_CAPI int32_t U_EXPORT2 | |
461 | unum_countAvailable() | |
462 | { | |
374ca955 | 463 | return uloc_countAvailable(); |
b75a7d8f A |
464 | } |
465 | ||
466 | U_CAPI int32_t U_EXPORT2 | |
467 | unum_getAttribute(const UNumberFormat* fmt, | |
468 | UNumberFormatAttribute attr) | |
469 | { | |
729e4ab9 | 470 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
4388f060 A |
471 | if ( attr == UNUM_LENIENT_PARSE ) { |
472 | // Supported for all subclasses | |
473 | return nf->isLenient(); | |
474 | } | |
51004dcb | 475 | |
4388f060 | 476 | // The remaining attributea are only supported for DecimalFormat |
729e4ab9 A |
477 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); |
478 | if (df != NULL) { | |
51004dcb A |
479 | UErrorCode ignoredStatus = U_ZERO_ERROR; |
480 | return df->getAttribute( attr, ignoredStatus ); | |
b75a7d8f | 481 | } |
374ca955 | 482 | |
b75a7d8f A |
483 | return -1; |
484 | } | |
485 | ||
486 | U_CAPI void U_EXPORT2 | |
487 | unum_setAttribute( UNumberFormat* fmt, | |
488 | UNumberFormatAttribute attr, | |
489 | int32_t newValue) | |
490 | { | |
729e4ab9 | 491 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); |
4388f060 A |
492 | if ( attr == UNUM_LENIENT_PARSE ) { |
493 | // Supported for all subclasses | |
51004dcb | 494 | // keep this here as the class may not be a DecimalFormat |
4388f060 A |
495 | return nf->setLenient(newValue != 0); |
496 | } | |
497 | // The remaining attributea are only supported for DecimalFormat | |
729e4ab9 A |
498 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); |
499 | if (df != NULL) { | |
51004dcb A |
500 | UErrorCode ignoredStatus = U_ZERO_ERROR; |
501 | df->setAttribute(attr, newValue, ignoredStatus); | |
b75a7d8f A |
502 | } |
503 | } | |
504 | ||
505 | U_CAPI double U_EXPORT2 | |
506 | unum_getDoubleAttribute(const UNumberFormat* fmt, | |
507 | UNumberFormatAttribute attr) | |
508 | { | |
729e4ab9 A |
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(); | |
374ca955 A |
513 | } else { |
514 | return -1.0; | |
515 | } | |
b75a7d8f A |
516 | } |
517 | ||
518 | U_CAPI void U_EXPORT2 | |
519 | unum_setDoubleAttribute( UNumberFormat* fmt, | |
520 | UNumberFormatAttribute attr, | |
521 | double newValue) | |
522 | { | |
729e4ab9 A |
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); | |
374ca955 | 527 | } |
b75a7d8f A |
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 | { | |
374ca955 A |
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 | } | |
b75a7d8f | 546 | |
729e4ab9 A |
547 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
548 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |
549 | if (df != NULL) { | |
374ca955 A |
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 { | |
729e4ab9 A |
580 | const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); |
581 | U_ASSERT(rbnf != NULL); | |
374ca955 A |
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 | } | |
b75a7d8f | 595 | |
374ca955 | 596 | return res.extract(result, resultLength, *status); |
b75a7d8f A |
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 | { | |
374ca955 A |
606 | if(U_FAILURE(*status)) |
607 | return; | |
729e4ab9 | 608 | |
4388f060 | 609 | UnicodeString val(newValue, newValueLength); |
729e4ab9 A |
610 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); |
611 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); | |
612 | if (df != NULL) { | |
374ca955 A |
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: | |
4388f060 | 631 | df->setPadCharacter(val); |
374ca955 A |
632 | break; |
633 | ||
634 | case UNUM_CURRENCY_CODE: | |
4388f060 | 635 | df->setCurrency(val.getTerminatedBuffer(), *status); |
374ca955 A |
636 | break; |
637 | ||
638 | default: | |
639 | *status = U_UNSUPPORTED_ERROR; | |
640 | break; | |
641 | } | |
642 | } else { | |
729e4ab9 A |
643 | RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf); |
644 | U_ASSERT(rbnf != NULL); | |
374ca955 | 645 | if (tag == UNUM_DEFAULT_RULESET) { |
4388f060 | 646 | rbnf->setDefaultRuleSet(val, *status); |
374ca955 | 647 | } else { |
729e4ab9 | 648 | *status = U_UNSUPPORTED_ERROR; |
374ca955 A |
649 | } |
650 | } | |
b75a7d8f A |
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 | { | |
374ca955 A |
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 | } | |
b75a7d8f | 669 | |
729e4ab9 A |
670 | const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); |
671 | const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); | |
672 | if (df != NULL) { | |
374ca955 A |
673 | if(isPatternLocalized) |
674 | df->toLocalizedPattern(pat); | |
675 | else | |
676 | df->toPattern(pat); | |
677 | } else { | |
729e4ab9 A |
678 | const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); |
679 | U_ASSERT(rbnf != NULL); | |
680 | pat = rbnf->getRules(); | |
374ca955 A |
681 | } |
682 | return pat.extract(result, resultLength, *status); | |
b75a7d8f A |
683 | } |
684 | ||
685 | U_CAPI int32_t U_EXPORT2 | |
374ca955 | 686 | unum_getSymbol(const UNumberFormat *fmt, |
b75a7d8f A |
687 | UNumberFormatSymbol symbol, |
688 | UChar *buffer, | |
689 | int32_t size, | |
374ca955 A |
690 | UErrorCode *status) |
691 | { | |
692 | if(status==NULL || U_FAILURE(*status)) { | |
693 | return 0; | |
694 | } | |
4388f060 | 695 | if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) { |
374ca955 A |
696 | *status=U_ILLEGAL_ARGUMENT_ERROR; |
697 | return 0; | |
698 | } | |
729e4ab9 A |
699 | const NumberFormat *nf = reinterpret_cast<const NumberFormat *>(fmt); |
700 | const DecimalFormat *dcf = dynamic_cast<const DecimalFormat *>(nf); | |
701 | if (dcf == NULL) { | |
374ca955 A |
702 | *status = U_UNSUPPORTED_ERROR; |
703 | return 0; | |
704 | } | |
b75a7d8f | 705 | |
729e4ab9 | 706 | return dcf-> |
b75a7d8f A |
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, | |
374ca955 | 717 | UErrorCode *status) |
b75a7d8f | 718 | { |
374ca955 A |
719 | if(status==NULL || U_FAILURE(*status)) { |
720 | return; | |
721 | } | |
4388f060 | 722 | if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) { |
374ca955 A |
723 | *status=U_ILLEGAL_ARGUMENT_ERROR; |
724 | return; | |
725 | } | |
729e4ab9 A |
726 | NumberFormat *nf = reinterpret_cast<NumberFormat *>(fmt); |
727 | DecimalFormat *dcf = dynamic_cast<DecimalFormat *>(nf); | |
728 | if (dcf == NULL) { | |
374ca955 A |
729 | *status = U_UNSUPPORTED_ERROR; |
730 | return; | |
731 | } | |
732 | ||
729e4ab9 | 733 | DecimalFormatSymbols symbols(*dcf->getDecimalFormatSymbols()); |
374ca955 A |
734 | symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol, |
735 | UnicodeString(value, length)); /* UnicodeString can handle the case when length = -1. */ | |
729e4ab9 | 736 | dcf->setDecimalFormatSymbols(symbols); |
b75a7d8f | 737 | } |
b75a7d8f A |
738 | |
739 | U_CAPI void U_EXPORT2 | |
729e4ab9 | 740 | unum_applyPattern( UNumberFormat *fmt, |
b75a7d8f A |
741 | UBool localized, |
742 | const UChar *pattern, | |
743 | int32_t patternLength, | |
744 | UParseError *parseError, | |
745 | UErrorCode* status) | |
746 | { | |
374ca955 A |
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); | |
729e4ab9 | 760 | |
374ca955 | 761 | // Verify if the object passed is a DecimalFormat object |
729e4ab9 A |
762 | NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); |
763 | DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); | |
764 | if (df != NULL) { | |
374ca955 | 765 | if(localized) { |
729e4ab9 | 766 | df->applyLocalizedPattern(pat,*parseError, *status); |
374ca955 | 767 | } else { |
729e4ab9 | 768 | df->applyPattern(pat,*parseError, *status); |
374ca955 A |
769 | } |
770 | } else { | |
771 | *status = U_UNSUPPORTED_ERROR; | |
b75a7d8f | 772 | return; |
374ca955 A |
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); | |
b75a7d8f A |
788 | } |
789 | ||
57a6839d A |
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 | ||
b75a7d8f | 865 | #endif /* #if !UCONFIG_NO_FORMATTING */ |