// © 2018 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING // Allow implicit conversion from char16_t* to UnicodeString for this file: // Helpful in toString methods and elsewhere. #define UNISTR_FROM_STRING_EXPLICIT #include "numparse_types.h" #include "number_decimalquantity.h" #include "putilimp.h" #include <cmath> using namespace icu; using namespace icu::number; using namespace icu::number::impl; using namespace icu::numparse; using namespace icu::numparse::impl; ParsedNumber::ParsedNumber() { clear(); } void ParsedNumber::clear() { quantity.bogus = true; charEnd = 0; flags = 0; prefix.setToBogus(); suffix.setToBogus(); currencyCode[0] = 0; } void ParsedNumber::setCharsConsumed(const StringSegment& segment) { charEnd = segment.getOffset(); } void ParsedNumber::postProcess() { if (!quantity.bogus && 0 != (flags & FLAG_NEGATIVE)) { quantity.negate(); } } bool ParsedNumber::success() const { return charEnd > 0 && 0 == (flags & FLAG_FAIL); } bool ParsedNumber::seenNumber() const { return !quantity.bogus || 0 != (flags & FLAG_NAN) || 0 != (flags & FLAG_INFINITY); } double ParsedNumber::getDouble() const { bool sawNaN = 0 != (flags & FLAG_NAN); bool sawInfinity = 0 != (flags & FLAG_INFINITY); // Check for NaN, infinity, and -0.0 if (sawNaN) { // Can't use NAN or std::nan because the byte pattern is platform-dependent; // MSVC sets the sign bit, but Clang and GCC do not return uprv_getNaN(); } if (sawInfinity) { if (0 != (flags & FLAG_NEGATIVE)) { return -INFINITY; } else { return INFINITY; } } U_ASSERT(!quantity.bogus); if (quantity.isZero() && quantity.isNegative()) { return -0.0; } if (quantity.fitsInLong()) { return static_cast<double>(quantity.toLong()); } else { return quantity.toDouble(); } } void ParsedNumber::populateFormattable(Formattable& output, parse_flags_t parseFlags) const { bool sawNaN = 0 != (flags & FLAG_NAN); bool sawInfinity = 0 != (flags & FLAG_INFINITY); bool integerOnly = 0 != (parseFlags & PARSE_FLAG_INTEGER_ONLY); // Check for NaN, infinity, and -0.0 if (sawNaN) { // Can't use NAN or std::nan because the byte pattern is platform-dependent; // MSVC sets the sign bit, but Clang and GCC do not output.setDouble(uprv_getNaN()); return; } if (sawInfinity) { if (0 != (flags & FLAG_NEGATIVE)) { output.setDouble(-INFINITY); return; } else { output.setDouble(INFINITY); return; } } U_ASSERT(!quantity.bogus); if (quantity.isZero() && quantity.isNegative() && !integerOnly) { output.setDouble(-0.0); return; } // All other numbers output.adoptDecimalQuantity(new DecimalQuantity(quantity)); } bool ParsedNumber::isBetterThan(const ParsedNumber& other) { // Favor results with strictly more characters consumed. return charEnd > other.charEnd; } #endif /* #if !UCONFIG_NO_FORMATTING */