fmtable.cpp 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042
  1. // © 2016 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. /*
  4. *******************************************************************************
  5. * Copyright (C) 1997-2016, International Business Machines Corporation and
  6. * others. All Rights Reserved.
  7. *******************************************************************************
  8. *
  9. * File FMTABLE.CPP
  10. *
  11. * Modification History:
  12. *
  13. * Date Name Description
  14. * 03/25/97 clhuang Initial Implementation.
  15. ********************************************************************************
  16. */
  17. #include "unicode/utypes.h"
  18. #if !UCONFIG_NO_FORMATTING
  19. #include <cstdlib>
  20. #include <math.h>
  21. #include "unicode/fmtable.h"
  22. #include "unicode/ustring.h"
  23. #include "unicode/measure.h"
  24. #include "unicode/curramt.h"
  25. #include "unicode/uformattable.h"
  26. #include "charstr.h"
  27. #include "cmemory.h"
  28. #include "cstring.h"
  29. #include "fmtableimp.h"
  30. #include "number_decimalquantity.h"
  31. // *****************************************************************************
  32. // class Formattable
  33. // *****************************************************************************
  34. U_NAMESPACE_BEGIN
  35. UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable)
  36. using number::impl::DecimalQuantity;
  37. //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
  38. // NOTE: As of 3.0, there are limitations to the UObject API. It does
  39. // not (yet) support cloning, operator=, nor operator==. To
  40. // work around this, I implement some simple inlines here. Later
  41. // these can be modified or removed. [alan]
  42. // NOTE: These inlines assume that all fObjects are in fact instances
  43. // of the Measure class, which is true as of 3.0. [alan]
  44. // Return true if *a == *b.
  45. static inline UBool objectEquals(const UObject* a, const UObject* b) {
  46. // LATER: return *a == *b;
  47. return *((const Measure*) a) == *((const Measure*) b);
  48. }
  49. // Return a clone of *a.
  50. static inline UObject* objectClone(const UObject* a) {
  51. // LATER: return a->clone();
  52. return ((const Measure*) a)->clone();
  53. }
  54. // Return true if *a is an instance of Measure.
  55. static inline UBool instanceOfMeasure(const UObject* a) {
  56. return dynamic_cast<const Measure*>(a) != nullptr;
  57. }
  58. /**
  59. * Creates a new Formattable array and copies the values from the specified
  60. * original.
  61. * @param array the original array
  62. * @param count the original array count
  63. * @return the new Formattable array.
  64. */
  65. static Formattable* createArrayCopy(const Formattable* array, int32_t count) {
  66. Formattable *result = new Formattable[count];
  67. if (result != nullptr) {
  68. for (int32_t i=0; i<count; ++i)
  69. result[i] = array[i]; // Don't memcpy!
  70. }
  71. return result;
  72. }
  73. //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
  74. /**
  75. * Set 'ec' to 'err' only if 'ec' is not already set to a failing UErrorCode.
  76. */
  77. static void setError(UErrorCode& ec, UErrorCode err) {
  78. if (U_SUCCESS(ec)) {
  79. ec = err;
  80. }
  81. }
  82. //
  83. // Common initialization code, shared by constructors.
  84. // Put everything into a known state.
  85. //
  86. void Formattable::init() {
  87. fValue.fInt64 = 0;
  88. fType = kLong;
  89. fDecimalStr = nullptr;
  90. fDecimalQuantity = nullptr;
  91. fBogus.setToBogus();
  92. }
  93. // -------------------------------------
  94. // default constructor.
  95. // Creates a formattable object with a long value 0.
  96. Formattable::Formattable() {
  97. init();
  98. }
  99. // -------------------------------------
  100. // Creates a formattable object with a Date instance.
  101. Formattable::Formattable(UDate date, ISDATE /*isDate*/)
  102. {
  103. init();
  104. fType = kDate;
  105. fValue.fDate = date;
  106. }
  107. // -------------------------------------
  108. // Creates a formattable object with a double value.
  109. Formattable::Formattable(double value)
  110. {
  111. init();
  112. fType = kDouble;
  113. fValue.fDouble = value;
  114. }
  115. // -------------------------------------
  116. // Creates a formattable object with an int32_t value.
  117. Formattable::Formattable(int32_t value)
  118. {
  119. init();
  120. fValue.fInt64 = value;
  121. }
  122. // -------------------------------------
  123. // Creates a formattable object with an int64_t value.
  124. Formattable::Formattable(int64_t value)
  125. {
  126. init();
  127. fType = kInt64;
  128. fValue.fInt64 = value;
  129. }
  130. // -------------------------------------
  131. // Creates a formattable object with a decimal number value from a string.
  132. Formattable::Formattable(StringPiece number, UErrorCode &status) {
  133. init();
  134. setDecimalNumber(number, status);
  135. }
  136. // -------------------------------------
  137. // Creates a formattable object with a UnicodeString instance.
  138. Formattable::Formattable(const UnicodeString& stringToCopy)
  139. {
  140. init();
  141. fType = kString;
  142. fValue.fString = new UnicodeString(stringToCopy);
  143. }
  144. // -------------------------------------
  145. // Creates a formattable object with a UnicodeString* value.
  146. // (adopting semantics)
  147. Formattable::Formattable(UnicodeString* stringToAdopt)
  148. {
  149. init();
  150. fType = kString;
  151. fValue.fString = stringToAdopt;
  152. }
  153. Formattable::Formattable(UObject* objectToAdopt)
  154. {
  155. init();
  156. fType = kObject;
  157. fValue.fObject = objectToAdopt;
  158. }
  159. // -------------------------------------
  160. Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
  161. : UObject(), fType(kArray)
  162. {
  163. init();
  164. fType = kArray;
  165. fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count);
  166. fValue.fArrayAndCount.fCount = count;
  167. }
  168. // -------------------------------------
  169. // copy constructor
  170. Formattable::Formattable(const Formattable &source)
  171. : UObject(*this)
  172. {
  173. init();
  174. *this = source;
  175. }
  176. // -------------------------------------
  177. // assignment operator
  178. Formattable&
  179. Formattable::operator=(const Formattable& source)
  180. {
  181. if (this != &source)
  182. {
  183. // Disposes the current formattable value/setting.
  184. dispose();
  185. // Sets the correct data type for this value.
  186. fType = source.fType;
  187. switch (fType)
  188. {
  189. case kArray:
  190. // Sets each element in the array one by one and records the array count.
  191. fValue.fArrayAndCount.fCount = source.fValue.fArrayAndCount.fCount;
  192. fValue.fArrayAndCount.fArray = createArrayCopy(source.fValue.fArrayAndCount.fArray,
  193. source.fValue.fArrayAndCount.fCount);
  194. break;
  195. case kString:
  196. // Sets the string value.
  197. fValue.fString = new UnicodeString(*source.fValue.fString);
  198. break;
  199. case kDouble:
  200. // Sets the double value.
  201. fValue.fDouble = source.fValue.fDouble;
  202. break;
  203. case kLong:
  204. case kInt64:
  205. // Sets the long value.
  206. fValue.fInt64 = source.fValue.fInt64;
  207. break;
  208. case kDate:
  209. // Sets the Date value.
  210. fValue.fDate = source.fValue.fDate;
  211. break;
  212. case kObject:
  213. fValue.fObject = objectClone(source.fValue.fObject);
  214. break;
  215. }
  216. UErrorCode status = U_ZERO_ERROR;
  217. if (source.fDecimalQuantity != nullptr) {
  218. fDecimalQuantity = new DecimalQuantity(*source.fDecimalQuantity);
  219. }
  220. if (source.fDecimalStr != nullptr) {
  221. fDecimalStr = new CharString(*source.fDecimalStr, status);
  222. if (U_FAILURE(status)) {
  223. delete fDecimalStr;
  224. fDecimalStr = nullptr;
  225. }
  226. }
  227. }
  228. return *this;
  229. }
  230. // -------------------------------------
  231. bool
  232. Formattable::operator==(const Formattable& that) const
  233. {
  234. int32_t i;
  235. if (this == &that) return true;
  236. // Returns false if the data types are different.
  237. if (fType != that.fType) return false;
  238. // Compares the actual data values.
  239. bool equal = true;
  240. switch (fType) {
  241. case kDate:
  242. equal = (fValue.fDate == that.fValue.fDate);
  243. break;
  244. case kDouble:
  245. equal = (fValue.fDouble == that.fValue.fDouble);
  246. break;
  247. case kLong:
  248. case kInt64:
  249. equal = (fValue.fInt64 == that.fValue.fInt64);
  250. break;
  251. case kString:
  252. equal = (*(fValue.fString) == *(that.fValue.fString));
  253. break;
  254. case kArray:
  255. if (fValue.fArrayAndCount.fCount != that.fValue.fArrayAndCount.fCount) {
  256. equal = false;
  257. break;
  258. }
  259. // Checks each element for equality.
  260. for (i=0; i<fValue.fArrayAndCount.fCount; ++i) {
  261. if (fValue.fArrayAndCount.fArray[i] != that.fValue.fArrayAndCount.fArray[i]) {
  262. equal = false;
  263. break;
  264. }
  265. }
  266. break;
  267. case kObject:
  268. if (fValue.fObject == nullptr || that.fValue.fObject == nullptr) {
  269. equal = false;
  270. } else {
  271. equal = objectEquals(fValue.fObject, that.fValue.fObject);
  272. }
  273. break;
  274. }
  275. // TODO: compare digit lists if numeric.
  276. return equal;
  277. }
  278. // -------------------------------------
  279. Formattable::~Formattable()
  280. {
  281. dispose();
  282. }
  283. // -------------------------------------
  284. void Formattable::dispose()
  285. {
  286. // Deletes the data value if necessary.
  287. switch (fType) {
  288. case kString:
  289. delete fValue.fString;
  290. break;
  291. case kArray:
  292. delete[] fValue.fArrayAndCount.fArray;
  293. break;
  294. case kObject:
  295. delete fValue.fObject;
  296. break;
  297. default:
  298. break;
  299. }
  300. fType = kLong;
  301. fValue.fInt64 = 0;
  302. delete fDecimalStr;
  303. fDecimalStr = nullptr;
  304. delete fDecimalQuantity;
  305. fDecimalQuantity = nullptr;
  306. }
  307. Formattable *
  308. Formattable::clone() const {
  309. return new Formattable(*this);
  310. }
  311. // -------------------------------------
  312. // Gets the data type of this Formattable object.
  313. Formattable::Type
  314. Formattable::getType() const
  315. {
  316. return fType;
  317. }
  318. UBool
  319. Formattable::isNumeric() const {
  320. switch (fType) {
  321. case kDouble:
  322. case kLong:
  323. case kInt64:
  324. return true;
  325. default:
  326. return false;
  327. }
  328. }
  329. // -------------------------------------
  330. int32_t
  331. //Formattable::getLong(UErrorCode* status) const
  332. Formattable::getLong(UErrorCode& status) const
  333. {
  334. if (U_FAILURE(status)) {
  335. return 0;
  336. }
  337. switch (fType) {
  338. case Formattable::kLong:
  339. return (int32_t)fValue.fInt64;
  340. case Formattable::kInt64:
  341. if (fValue.fInt64 > INT32_MAX) {
  342. status = U_INVALID_FORMAT_ERROR;
  343. return INT32_MAX;
  344. } else if (fValue.fInt64 < INT32_MIN) {
  345. status = U_INVALID_FORMAT_ERROR;
  346. return INT32_MIN;
  347. } else {
  348. return (int32_t)fValue.fInt64;
  349. }
  350. case Formattable::kDouble:
  351. if (fValue.fDouble > INT32_MAX) {
  352. status = U_INVALID_FORMAT_ERROR;
  353. return INT32_MAX;
  354. } else if (fValue.fDouble < INT32_MIN) {
  355. status = U_INVALID_FORMAT_ERROR;
  356. return INT32_MIN;
  357. } else {
  358. return (int32_t)fValue.fDouble; // loses fraction
  359. }
  360. case Formattable::kObject:
  361. if (fValue.fObject == nullptr) {
  362. status = U_MEMORY_ALLOCATION_ERROR;
  363. return 0;
  364. }
  365. // TODO Later replace this with instanceof call
  366. if (instanceOfMeasure(fValue.fObject)) {
  367. return ((const Measure*) fValue.fObject)->
  368. getNumber().getLong(status);
  369. }
  370. U_FALLTHROUGH;
  371. default:
  372. status = U_INVALID_FORMAT_ERROR;
  373. return 0;
  374. }
  375. }
  376. // -------------------------------------
  377. // Maximum int that can be represented exactly in a double. (53 bits)
  378. // Larger ints may be rounded to a near-by value as not all are representable.
  379. // TODO: move this constant elsewhere, possibly configure it for different
  380. // floating point formats, if any non-standard ones are still in use.
  381. static const int64_t U_DOUBLE_MAX_EXACT_INT = 9007199254740992LL;
  382. int64_t
  383. Formattable::getInt64(UErrorCode& status) const
  384. {
  385. if (U_FAILURE(status)) {
  386. return 0;
  387. }
  388. switch (fType) {
  389. case Formattable::kLong:
  390. case Formattable::kInt64:
  391. return fValue.fInt64;
  392. case Formattable::kDouble:
  393. if (fValue.fDouble > (double)U_INT64_MAX) {
  394. status = U_INVALID_FORMAT_ERROR;
  395. return U_INT64_MAX;
  396. } else if (fValue.fDouble < (double)U_INT64_MIN) {
  397. status = U_INVALID_FORMAT_ERROR;
  398. return U_INT64_MIN;
  399. } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalQuantity != nullptr) {
  400. if (fDecimalQuantity->fitsInLong(true)) {
  401. return fDecimalQuantity->toLong();
  402. } else {
  403. // Unexpected
  404. status = U_INVALID_FORMAT_ERROR;
  405. return fDecimalQuantity->isNegative() ? U_INT64_MIN : U_INT64_MAX;
  406. }
  407. } else {
  408. return (int64_t)fValue.fDouble;
  409. }
  410. case Formattable::kObject:
  411. if (fValue.fObject == nullptr) {
  412. status = U_MEMORY_ALLOCATION_ERROR;
  413. return 0;
  414. }
  415. if (instanceOfMeasure(fValue.fObject)) {
  416. return ((const Measure*) fValue.fObject)->
  417. getNumber().getInt64(status);
  418. }
  419. U_FALLTHROUGH;
  420. default:
  421. status = U_INVALID_FORMAT_ERROR;
  422. return 0;
  423. }
  424. }
  425. // -------------------------------------
  426. double
  427. Formattable::getDouble(UErrorCode& status) const
  428. {
  429. if (U_FAILURE(status)) {
  430. return 0;
  431. }
  432. switch (fType) {
  433. case Formattable::kLong:
  434. case Formattable::kInt64: // loses precision
  435. return (double)fValue.fInt64;
  436. case Formattable::kDouble:
  437. return fValue.fDouble;
  438. case Formattable::kObject:
  439. if (fValue.fObject == nullptr) {
  440. status = U_MEMORY_ALLOCATION_ERROR;
  441. return 0;
  442. }
  443. // TODO Later replace this with instanceof call
  444. if (instanceOfMeasure(fValue.fObject)) {
  445. return ((const Measure*) fValue.fObject)->
  446. getNumber().getDouble(status);
  447. }
  448. U_FALLTHROUGH;
  449. default:
  450. status = U_INVALID_FORMAT_ERROR;
  451. return 0;
  452. }
  453. }
  454. const UObject*
  455. Formattable::getObject() const {
  456. return (fType == kObject) ? fValue.fObject : nullptr;
  457. }
  458. // -------------------------------------
  459. // Sets the value to a double value d.
  460. void
  461. Formattable::setDouble(double d)
  462. {
  463. dispose();
  464. fType = kDouble;
  465. fValue.fDouble = d;
  466. }
  467. // -------------------------------------
  468. // Sets the value to a long value l.
  469. void
  470. Formattable::setLong(int32_t l)
  471. {
  472. dispose();
  473. fType = kLong;
  474. fValue.fInt64 = l;
  475. }
  476. // -------------------------------------
  477. // Sets the value to an int64 value ll.
  478. void
  479. Formattable::setInt64(int64_t ll)
  480. {
  481. dispose();
  482. fType = kInt64;
  483. fValue.fInt64 = ll;
  484. }
  485. // -------------------------------------
  486. // Sets the value to a Date instance d.
  487. void
  488. Formattable::setDate(UDate d)
  489. {
  490. dispose();
  491. fType = kDate;
  492. fValue.fDate = d;
  493. }
  494. // -------------------------------------
  495. // Sets the value to a string value stringToCopy.
  496. void
  497. Formattable::setString(const UnicodeString& stringToCopy)
  498. {
  499. dispose();
  500. fType = kString;
  501. fValue.fString = new UnicodeString(stringToCopy);
  502. }
  503. // -------------------------------------
  504. // Sets the value to an array of Formattable objects.
  505. void
  506. Formattable::setArray(const Formattable* array, int32_t count)
  507. {
  508. dispose();
  509. fType = kArray;
  510. fValue.fArrayAndCount.fArray = createArrayCopy(array, count);
  511. fValue.fArrayAndCount.fCount = count;
  512. }
  513. // -------------------------------------
  514. // Adopts the stringToAdopt value.
  515. void
  516. Formattable::adoptString(UnicodeString* stringToAdopt)
  517. {
  518. dispose();
  519. fType = kString;
  520. fValue.fString = stringToAdopt;
  521. }
  522. // -------------------------------------
  523. // Adopts the array value and its count.
  524. void
  525. Formattable::adoptArray(Formattable* array, int32_t count)
  526. {
  527. dispose();
  528. fType = kArray;
  529. fValue.fArrayAndCount.fArray = array;
  530. fValue.fArrayAndCount.fCount = count;
  531. }
  532. void
  533. Formattable::adoptObject(UObject* objectToAdopt) {
  534. dispose();
  535. fType = kObject;
  536. fValue.fObject = objectToAdopt;
  537. }
  538. // -------------------------------------
  539. UnicodeString&
  540. Formattable::getString(UnicodeString& result, UErrorCode& status) const
  541. {
  542. if (fType != kString) {
  543. setError(status, U_INVALID_FORMAT_ERROR);
  544. result.setToBogus();
  545. } else {
  546. if (fValue.fString == nullptr) {
  547. setError(status, U_MEMORY_ALLOCATION_ERROR);
  548. } else {
  549. result = *fValue.fString;
  550. }
  551. }
  552. return result;
  553. }
  554. // -------------------------------------
  555. const UnicodeString&
  556. Formattable::getString(UErrorCode& status) const
  557. {
  558. if (fType != kString) {
  559. setError(status, U_INVALID_FORMAT_ERROR);
  560. return *getBogus();
  561. }
  562. if (fValue.fString == nullptr) {
  563. setError(status, U_MEMORY_ALLOCATION_ERROR);
  564. return *getBogus();
  565. }
  566. return *fValue.fString;
  567. }
  568. // -------------------------------------
  569. UnicodeString&
  570. Formattable::getString(UErrorCode& status)
  571. {
  572. if (fType != kString) {
  573. setError(status, U_INVALID_FORMAT_ERROR);
  574. return *getBogus();
  575. }
  576. if (fValue.fString == nullptr) {
  577. setError(status, U_MEMORY_ALLOCATION_ERROR);
  578. return *getBogus();
  579. }
  580. return *fValue.fString;
  581. }
  582. // -------------------------------------
  583. const Formattable*
  584. Formattable::getArray(int32_t& count, UErrorCode& status) const
  585. {
  586. if (fType != kArray) {
  587. setError(status, U_INVALID_FORMAT_ERROR);
  588. count = 0;
  589. return nullptr;
  590. }
  591. count = fValue.fArrayAndCount.fCount;
  592. return fValue.fArrayAndCount.fArray;
  593. }
  594. // -------------------------------------
  595. // Gets the bogus string, ensures mondo bogosity.
  596. UnicodeString*
  597. Formattable::getBogus() const
  598. {
  599. return (UnicodeString*)&fBogus; /* cast away const :-( */
  600. }
  601. // --------------------------------------
  602. StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
  603. if (U_FAILURE(status)) {
  604. return "";
  605. }
  606. if (fDecimalStr != nullptr) {
  607. return fDecimalStr->toStringPiece();
  608. }
  609. CharString *decimalStr = internalGetCharString(status);
  610. if(decimalStr == nullptr) {
  611. return ""; // getDecimalNumber returns "" for error cases
  612. } else {
  613. return decimalStr->toStringPiece();
  614. }
  615. }
  616. CharString *Formattable::internalGetCharString(UErrorCode &status) {
  617. if(fDecimalStr == nullptr) {
  618. if (fDecimalQuantity == nullptr) {
  619. // No decimal number for the formattable yet. Which means the value was
  620. // set directly by the user as an int, int64 or double. If the value came
  621. // from parsing, or from the user setting a decimal number, fDecimalNum
  622. // would already be set.
  623. //
  624. LocalPointer<DecimalQuantity> dq(new DecimalQuantity(), status);
  625. if (U_FAILURE(status)) { return nullptr; }
  626. populateDecimalQuantity(*dq, status);
  627. if (U_FAILURE(status)) { return nullptr; }
  628. fDecimalQuantity = dq.orphan();
  629. }
  630. fDecimalStr = new CharString();
  631. if (fDecimalStr == nullptr) {
  632. status = U_MEMORY_ALLOCATION_ERROR;
  633. return nullptr;
  634. }
  635. // Older ICUs called uprv_decNumberToString here, which is not exactly the same as
  636. // DecimalQuantity::toScientificString(). The biggest difference is that uprv_decNumberToString does
  637. // not print scientific notation for magnitudes greater than -5 and smaller than some amount (+5?).
  638. if (fDecimalQuantity->isInfinite()) {
  639. fDecimalStr->append("Infinity", status);
  640. } else if (fDecimalQuantity->isNaN()) {
  641. fDecimalStr->append("NaN", status);
  642. } else if (fDecimalQuantity->isZeroish()) {
  643. fDecimalStr->append("0", -1, status);
  644. } else if (fType==kLong || fType==kInt64 || // use toPlainString for integer types
  645. (fDecimalQuantity->getMagnitude() != INT32_MIN && std::abs(fDecimalQuantity->getMagnitude()) < 5)) {
  646. fDecimalStr->appendInvariantChars(fDecimalQuantity->toPlainString(), status);
  647. } else {
  648. fDecimalStr->appendInvariantChars(fDecimalQuantity->toScientificString(), status);
  649. }
  650. }
  651. return fDecimalStr;
  652. }
  653. void
  654. Formattable::populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const {
  655. if (fDecimalQuantity != nullptr) {
  656. output = *fDecimalQuantity;
  657. return;
  658. }
  659. switch (fType) {
  660. case kDouble:
  661. output.setToDouble(this->getDouble());
  662. output.roundToInfinity();
  663. break;
  664. case kLong:
  665. output.setToInt(this->getLong());
  666. break;
  667. case kInt64:
  668. output.setToLong(this->getInt64());
  669. break;
  670. default:
  671. // The formattable's value is not a numeric type.
  672. status = U_INVALID_STATE_ERROR;
  673. }
  674. }
  675. // ---------------------------------------
  676. void
  677. Formattable::adoptDecimalQuantity(DecimalQuantity *dq) {
  678. if (fDecimalQuantity != nullptr) {
  679. delete fDecimalQuantity;
  680. }
  681. fDecimalQuantity = dq;
  682. if (dq == nullptr) { // allow adoptDigitList(nullptr) to clear
  683. return;
  684. }
  685. // Set the value into the Union of simple type values.
  686. // Cannot use the set() functions because they would delete the fDecimalNum value.
  687. if (fDecimalQuantity->fitsInLong()) {
  688. fValue.fInt64 = fDecimalQuantity->toLong();
  689. if (fValue.fInt64 <= INT32_MAX && fValue.fInt64 >= INT32_MIN) {
  690. fType = kLong;
  691. } else {
  692. fType = kInt64;
  693. }
  694. } else {
  695. fType = kDouble;
  696. fValue.fDouble = fDecimalQuantity->toDouble();
  697. }
  698. }
  699. // ---------------------------------------
  700. void
  701. Formattable::setDecimalNumber(StringPiece numberString, UErrorCode &status) {
  702. if (U_FAILURE(status)) {
  703. return;
  704. }
  705. dispose();
  706. auto* dq = new DecimalQuantity();
  707. dq->setToDecNumber(numberString, status);
  708. adoptDecimalQuantity(dq);
  709. // Note that we do not hang on to the caller's input string.
  710. // If we are asked for the string, we will regenerate one from fDecimalQuantity.
  711. }
  712. #if 0
  713. //----------------------------------------------------
  714. // console I/O
  715. //----------------------------------------------------
  716. #ifdef _DEBUG
  717. #include <iostream>
  718. using namespace std;
  719. #include "unicode/datefmt.h"
  720. #include "unistrm.h"
  721. class FormattableStreamer /* not : public UObject because all methods are static */ {
  722. public:
  723. static void streamOut(ostream& stream, const Formattable& obj);
  724. private:
  725. FormattableStreamer() {} // private - forbid instantiation
  726. };
  727. // This is for debugging purposes only. This will send a displayable
  728. // form of the Formattable object to the output stream.
  729. void
  730. FormattableStreamer::streamOut(ostream& stream, const Formattable& obj)
  731. {
  732. static DateFormat *defDateFormat = 0;
  733. UnicodeString buffer;
  734. switch(obj.getType()) {
  735. case Formattable::kDate :
  736. // Creates a DateFormat instance for formatting the
  737. // Date instance.
  738. if (defDateFormat == 0) {
  739. defDateFormat = DateFormat::createInstance();
  740. }
  741. defDateFormat->format(obj.getDate(), buffer);
  742. stream << buffer;
  743. break;
  744. case Formattable::kDouble :
  745. // Output the double as is.
  746. stream << obj.getDouble() << 'D';
  747. break;
  748. case Formattable::kLong :
  749. // Output the double as is.
  750. stream << obj.getLong() << 'L';
  751. break;
  752. case Formattable::kString:
  753. // Output the double as is. Please see UnicodeString console
  754. // I/O routine for more details.
  755. stream << '"' << obj.getString(buffer) << '"';
  756. break;
  757. case Formattable::kArray:
  758. int32_t i, count;
  759. const Formattable* array;
  760. array = obj.getArray(count);
  761. stream << '[';
  762. // Recursively calling the console I/O routine for each element in the array.
  763. for (i=0; i<count; ++i) {
  764. FormattableStreamer::streamOut(stream, array[i]);
  765. stream << ( (i==(count-1)) ? "" : ", " );
  766. }
  767. stream << ']';
  768. break;
  769. default:
  770. // Not a recognizable Formattable object.
  771. stream << "INVALID_Formattable";
  772. }
  773. stream.flush();
  774. }
  775. #endif
  776. #endif
  777. U_NAMESPACE_END
  778. /* ---- UFormattable implementation ---- */
  779. U_NAMESPACE_USE
  780. U_CAPI UFormattable* U_EXPORT2
  781. ufmt_open(UErrorCode *status) {
  782. if( U_FAILURE(*status) ) {
  783. return nullptr;
  784. }
  785. UFormattable *fmt = (new Formattable())->toUFormattable();
  786. if( fmt == nullptr ) {
  787. *status = U_MEMORY_ALLOCATION_ERROR;
  788. }
  789. return fmt;
  790. }
  791. U_CAPI void U_EXPORT2
  792. ufmt_close(UFormattable *fmt) {
  793. Formattable *obj = Formattable::fromUFormattable(fmt);
  794. delete obj;
  795. }
  796. U_CAPI UFormattableType U_EXPORT2
  797. ufmt_getType(const UFormattable *fmt, UErrorCode *status) {
  798. if(U_FAILURE(*status)) {
  799. return (UFormattableType)UFMT_COUNT;
  800. }
  801. const Formattable *obj = Formattable::fromUFormattable(fmt);
  802. return (UFormattableType)obj->getType();
  803. }
  804. U_CAPI UBool U_EXPORT2
  805. ufmt_isNumeric(const UFormattable *fmt) {
  806. const Formattable *obj = Formattable::fromUFormattable(fmt);
  807. return obj->isNumeric();
  808. }
  809. U_CAPI UDate U_EXPORT2
  810. ufmt_getDate(const UFormattable *fmt, UErrorCode *status) {
  811. const Formattable *obj = Formattable::fromUFormattable(fmt);
  812. return obj->getDate(*status);
  813. }
  814. U_CAPI double U_EXPORT2
  815. ufmt_getDouble(UFormattable *fmt, UErrorCode *status) {
  816. Formattable *obj = Formattable::fromUFormattable(fmt);
  817. return obj->getDouble(*status);
  818. }
  819. U_CAPI int32_t U_EXPORT2
  820. ufmt_getLong(UFormattable *fmt, UErrorCode *status) {
  821. Formattable *obj = Formattable::fromUFormattable(fmt);
  822. return obj->getLong(*status);
  823. }
  824. U_CAPI const void *U_EXPORT2
  825. ufmt_getObject(const UFormattable *fmt, UErrorCode *status) {
  826. const Formattable *obj = Formattable::fromUFormattable(fmt);
  827. const void *ret = obj->getObject();
  828. if( ret==nullptr &&
  829. (obj->getType() != Formattable::kObject) &&
  830. U_SUCCESS( *status )) {
  831. *status = U_INVALID_FORMAT_ERROR;
  832. }
  833. return ret;
  834. }
  835. U_CAPI const char16_t* U_EXPORT2
  836. ufmt_getUChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
  837. Formattable *obj = Formattable::fromUFormattable(fmt);
  838. // avoid bogosity by checking the type first.
  839. if( obj->getType() != Formattable::kString ) {
  840. if( U_SUCCESS(*status) ){
  841. *status = U_INVALID_FORMAT_ERROR;
  842. }
  843. return nullptr;
  844. }
  845. // This should return a valid string
  846. UnicodeString &str = obj->getString(*status);
  847. if( U_SUCCESS(*status) && len != nullptr ) {
  848. *len = str.length();
  849. }
  850. return str.getTerminatedBuffer();
  851. }
  852. U_CAPI int32_t U_EXPORT2
  853. ufmt_getArrayLength(const UFormattable* fmt, UErrorCode *status) {
  854. const Formattable *obj = Formattable::fromUFormattable(fmt);
  855. int32_t count;
  856. (void)obj->getArray(count, *status);
  857. return count;
  858. }
  859. U_CAPI UFormattable * U_EXPORT2
  860. ufmt_getArrayItemByIndex(UFormattable* fmt, int32_t n, UErrorCode *status) {
  861. Formattable *obj = Formattable::fromUFormattable(fmt);
  862. int32_t count;
  863. (void)obj->getArray(count, *status);
  864. if(U_FAILURE(*status)) {
  865. return nullptr;
  866. } else if(n<0 || n>=count) {
  867. setError(*status, U_INDEX_OUTOFBOUNDS_ERROR);
  868. return nullptr;
  869. } else {
  870. return (*obj)[n].toUFormattable(); // returns non-const Formattable
  871. }
  872. }
  873. U_CAPI const char * U_EXPORT2
  874. ufmt_getDecNumChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
  875. if(U_FAILURE(*status)) {
  876. return "";
  877. }
  878. Formattable *obj = Formattable::fromUFormattable(fmt);
  879. CharString *charString = obj->internalGetCharString(*status);
  880. if(U_FAILURE(*status)) {
  881. return "";
  882. }
  883. if(charString == nullptr) {
  884. *status = U_MEMORY_ALLOCATION_ERROR;
  885. return "";
  886. } else {
  887. if(len!=nullptr) {
  888. *len = charString->length();
  889. }
  890. return charString->data();
  891. }
  892. }
  893. U_CAPI int64_t U_EXPORT2
  894. ufmt_getInt64(UFormattable *fmt, UErrorCode *status) {
  895. Formattable *obj = Formattable::fromUFormattable(fmt);
  896. return obj->getInt64(*status);
  897. }
  898. #endif /* #if !UCONFIG_NO_FORMATTING */
  899. //eof