tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

numparse_parsednumber.cpp (3367B)


      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 "string_segment.h"
     15 #include "putilimp.h"
     16 #include <cmath>
     17 
     18 using namespace icu;
     19 using namespace icu::number;
     20 using namespace icu::number::impl;
     21 using namespace icu::numparse;
     22 using namespace icu::numparse::impl;
     23 
     24 
     25 ParsedNumber::ParsedNumber() {
     26    clear();
     27 }
     28 
     29 void ParsedNumber::clear() {
     30    quantity.bogus = true;
     31    charEnd = 0;
     32    flags = 0;
     33    prefix.setToBogus();
     34    suffix.setToBogus();
     35    currencyCode[0] = 0;
     36 }
     37 
     38 void ParsedNumber::setCharsConsumed(const StringSegment& segment) {
     39    charEnd = segment.getOffset();
     40 }
     41 
     42 void ParsedNumber::postProcess() {
     43    if (!quantity.bogus && 0 != (flags & FLAG_NEGATIVE)) {
     44        quantity.negate();
     45    }
     46 }
     47 
     48 bool ParsedNumber::success() const {
     49    return charEnd > 0 && 0 == (flags & FLAG_FAIL);
     50 }
     51 
     52 bool ParsedNumber::seenNumber() const {
     53    return !quantity.bogus || 0 != (flags & FLAG_NAN) || 0 != (flags & FLAG_INFINITY);
     54 }
     55 
     56 double ParsedNumber::getDouble(UErrorCode& status) const {
     57    bool sawNaN = 0 != (flags & FLAG_NAN);
     58    bool sawInfinity = 0 != (flags & FLAG_INFINITY);
     59 
     60    // Check for NaN, infinity, and -0.0
     61    if (sawNaN) {
     62        // Can't use NAN or std::nan because the byte pattern is platform-dependent;
     63        // MSVC sets the sign bit, but Clang and GCC do not
     64        return uprv_getNaN();
     65    }
     66    if (sawInfinity) {
     67        if (0 != (flags & FLAG_NEGATIVE)) {
     68            return -INFINITY;
     69        } else {
     70            return INFINITY;
     71        }
     72    }
     73    if (quantity.bogus) {
     74        status = U_INVALID_STATE_ERROR;
     75        return 0.0;
     76    }
     77    if (quantity.isZeroish() && quantity.isNegative()) {
     78        return -0.0;
     79    }
     80 
     81    if (quantity.fitsInLong()) {
     82        return static_cast<double>(quantity.toLong());
     83    } else {
     84        return quantity.toDouble();
     85    }
     86 }
     87 
     88 void ParsedNumber::populateFormattable(Formattable& output, parse_flags_t parseFlags) const {
     89    bool sawNaN = 0 != (flags & FLAG_NAN);
     90    bool sawInfinity = 0 != (flags & FLAG_INFINITY);
     91    bool integerOnly = 0 != (parseFlags & PARSE_FLAG_INTEGER_ONLY);
     92 
     93    // Check for NaN, infinity, and -0.0
     94    if (sawNaN) {
     95        // Can't use NAN or std::nan because the byte pattern is platform-dependent;
     96        // MSVC sets the sign bit, but Clang and GCC do not
     97        output.setDouble(uprv_getNaN());
     98        return;
     99    }
    100    if (sawInfinity) {
    101        if (0 != (flags & FLAG_NEGATIVE)) {
    102            output.setDouble(-INFINITY);
    103            return;
    104        } else {
    105            output.setDouble(INFINITY);
    106            return;
    107        }
    108    }
    109    U_ASSERT(!quantity.bogus);
    110    if (quantity.isZeroish() && quantity.isNegative() && !integerOnly) {
    111        output.setDouble(-0.0);
    112        return;
    113    }
    114 
    115    // All other numbers
    116    output.adoptDecimalQuantity(new DecimalQuantity(quantity));
    117 }
    118 
    119 bool ParsedNumber::isBetterThan(const ParsedNumber& other) {
    120    // Favor results with strictly more characters consumed.
    121    return charEnd > other.charEnd;
    122 }
    123 
    124 
    125 
    126 #endif /* #if !UCONFIG_NO_FORMATTING */