unum.cpp 29 KB

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