numparse_parsednumber.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // © 2018 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. #include "unicode/utypes.h"
  4. #if !UCONFIG_NO_FORMATTING
  5. // Allow implicit conversion from char16_t* to UnicodeString for this file:
  6. // Helpful in toString methods and elsewhere.
  7. #define UNISTR_FROM_STRING_EXPLICIT
  8. #include "numparse_types.h"
  9. #include "number_decimalquantity.h"
  10. #include "string_segment.h"
  11. #include "putilimp.h"
  12. #include <cmath>
  13. using namespace icu;
  14. using namespace icu::number;
  15. using namespace icu::number::impl;
  16. using namespace icu::numparse;
  17. using namespace icu::numparse::impl;
  18. ParsedNumber::ParsedNumber() {
  19. clear();
  20. }
  21. void ParsedNumber::clear() {
  22. quantity.bogus = true;
  23. charEnd = 0;
  24. flags = 0;
  25. prefix.setToBogus();
  26. suffix.setToBogus();
  27. currencyCode[0] = 0;
  28. }
  29. void ParsedNumber::setCharsConsumed(const StringSegment& segment) {
  30. charEnd = segment.getOffset();
  31. }
  32. void ParsedNumber::postProcess() {
  33. if (!quantity.bogus && 0 != (flags & FLAG_NEGATIVE)) {
  34. quantity.negate();
  35. }
  36. }
  37. bool ParsedNumber::success() const {
  38. return charEnd > 0 && 0 == (flags & FLAG_FAIL);
  39. }
  40. bool ParsedNumber::seenNumber() const {
  41. return !quantity.bogus || 0 != (flags & FLAG_NAN) || 0 != (flags & FLAG_INFINITY);
  42. }
  43. double ParsedNumber::getDouble(UErrorCode& status) const {
  44. bool sawNaN = 0 != (flags & FLAG_NAN);
  45. bool sawInfinity = 0 != (flags & FLAG_INFINITY);
  46. // Check for NaN, infinity, and -0.0
  47. if (sawNaN) {
  48. // Can't use NAN or std::nan because the byte pattern is platform-dependent;
  49. // MSVC sets the sign bit, but Clang and GCC do not
  50. return uprv_getNaN();
  51. }
  52. if (sawInfinity) {
  53. if (0 != (flags & FLAG_NEGATIVE)) {
  54. return -INFINITY;
  55. } else {
  56. return INFINITY;
  57. }
  58. }
  59. if (quantity.bogus) {
  60. status = U_INVALID_STATE_ERROR;
  61. return 0.0;
  62. }
  63. if (quantity.isZeroish() && quantity.isNegative()) {
  64. return -0.0;
  65. }
  66. if (quantity.fitsInLong()) {
  67. return static_cast<double>(quantity.toLong());
  68. } else {
  69. return quantity.toDouble();
  70. }
  71. }
  72. void ParsedNumber::populateFormattable(Formattable& output, parse_flags_t parseFlags) const {
  73. bool sawNaN = 0 != (flags & FLAG_NAN);
  74. bool sawInfinity = 0 != (flags & FLAG_INFINITY);
  75. bool integerOnly = 0 != (parseFlags & PARSE_FLAG_INTEGER_ONLY);
  76. // Check for NaN, infinity, and -0.0
  77. if (sawNaN) {
  78. // Can't use NAN or std::nan because the byte pattern is platform-dependent;
  79. // MSVC sets the sign bit, but Clang and GCC do not
  80. output.setDouble(uprv_getNaN());
  81. return;
  82. }
  83. if (sawInfinity) {
  84. if (0 != (flags & FLAG_NEGATIVE)) {
  85. output.setDouble(-INFINITY);
  86. return;
  87. } else {
  88. output.setDouble(INFINITY);
  89. return;
  90. }
  91. }
  92. U_ASSERT(!quantity.bogus);
  93. if (quantity.isZeroish() && quantity.isNegative() && !integerOnly) {
  94. output.setDouble(-0.0);
  95. return;
  96. }
  97. // All other numbers
  98. output.adoptDecimalQuantity(new DecimalQuantity(quantity));
  99. }
  100. bool ParsedNumber::isBetterThan(const ParsedNumber& other) {
  101. // Favor results with strictly more characters consumed.
  102. return charEnd > other.charEnd;
  103. }
  104. #endif /* #if !UCONFIG_NO_FORMATTING */