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