tor-browser

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

number_multiplier.cpp (4619B)


      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 "number_decnum.h"
     13 #include "number_types.h"
     14 #include "number_multiplier.h"
     15 #include "numparse_validators.h"
     16 #include "number_utils.h"
     17 #include "decNumber.h"
     18 
     19 using namespace icu;
     20 using namespace icu::number;
     21 using namespace icu::number::impl;
     22 using namespace icu::numparse::impl;
     23 
     24 
     25 Scale::Scale(int32_t magnitude, DecNum* arbitraryToAdopt)
     26        : fMagnitude(magnitude), fArbitrary(arbitraryToAdopt), fError(U_ZERO_ERROR) {
     27    if (fArbitrary != nullptr) {
     28        // Attempt to convert the DecNum to a magnitude multiplier.
     29        fArbitrary->normalize();
     30        if (fArbitrary->getRawDecNumber()->digits == 1 && fArbitrary->getRawDecNumber()->lsu[0] == 1 &&
     31            !fArbitrary->isNegative()) {
     32            // Success!
     33            fMagnitude += fArbitrary->getRawDecNumber()->exponent;
     34            delete fArbitrary;
     35            fArbitrary = nullptr;
     36        }
     37    }
     38 }
     39 
     40 Scale::Scale(const Scale& other)
     41        : fMagnitude(other.fMagnitude), fArbitrary(nullptr), fError(other.fError) {
     42    if (other.fArbitrary != nullptr) {
     43        UErrorCode localStatus = U_ZERO_ERROR;
     44        fArbitrary = new DecNum(*other.fArbitrary, localStatus);
     45    }
     46 }
     47 
     48 Scale& Scale::operator=(const Scale& other) {
     49    if (this == &other) { return *this; }  // self-assignment: no-op
     50    fMagnitude = other.fMagnitude;
     51    if (other.fArbitrary != nullptr) {
     52        UErrorCode localStatus = U_ZERO_ERROR;
     53        fArbitrary = new DecNum(*other.fArbitrary, localStatus);
     54    } else {
     55        fArbitrary = nullptr;
     56    }
     57    fError = other.fError;
     58    return *this;
     59 }
     60 
     61 Scale::Scale(Scale&& src) noexcept
     62        : fMagnitude(src.fMagnitude), fArbitrary(src.fArbitrary), fError(src.fError) {
     63    // Take ownership away from src if necessary
     64    src.fArbitrary = nullptr;
     65 }
     66 
     67 Scale& Scale::operator=(Scale&& src) noexcept {
     68    fMagnitude = src.fMagnitude;
     69    delete fArbitrary;
     70    fArbitrary = src.fArbitrary;
     71    fError = src.fError;
     72    // Take ownership away from src if necessary
     73    src.fArbitrary = nullptr;
     74    return *this;
     75 }
     76 
     77 Scale::~Scale() {
     78    delete fArbitrary;
     79 }
     80 
     81 
     82 Scale Scale::none() {
     83    return {0, nullptr};
     84 }
     85 
     86 Scale Scale::powerOfTen(int32_t power) {
     87    return {power, nullptr};
     88 }
     89 
     90 Scale Scale::byDecimal(StringPiece multiplicand) {
     91    UErrorCode localError = U_ZERO_ERROR;
     92    LocalPointer<DecNum> decnum(new DecNum(), localError);
     93    if (U_FAILURE(localError)) {
     94        return {localError};
     95    }
     96    decnum->setTo(multiplicand, localError);
     97    if (U_FAILURE(localError)) {
     98        return {localError};
     99    }
    100    return {0, decnum.orphan()};
    101 }
    102 
    103 Scale Scale::byDouble(double multiplicand) {
    104    UErrorCode localError = U_ZERO_ERROR;
    105    LocalPointer<DecNum> decnum(new DecNum(), localError);
    106    if (U_FAILURE(localError)) {
    107        return {localError};
    108    }
    109    decnum->setTo(multiplicand, localError);
    110    if (U_FAILURE(localError)) {
    111        return {localError};
    112    }
    113    return {0, decnum.orphan()};
    114 }
    115 
    116 Scale Scale::byDoubleAndPowerOfTen(double multiplicand, int32_t power) {
    117    UErrorCode localError = U_ZERO_ERROR;
    118    LocalPointer<DecNum> decnum(new DecNum(), localError);
    119    if (U_FAILURE(localError)) {
    120        return {localError};
    121    }
    122    decnum->setTo(multiplicand, localError);
    123    if (U_FAILURE(localError)) {
    124        return {localError};
    125    }
    126    return {power, decnum.orphan()};
    127 }
    128 
    129 void Scale::applyTo(impl::DecimalQuantity& quantity) const {
    130    quantity.adjustMagnitude(fMagnitude);
    131    if (fArbitrary != nullptr) {
    132        UErrorCode localStatus = U_ZERO_ERROR;
    133        quantity.multiplyBy(*fArbitrary, localStatus);
    134    }
    135 }
    136 
    137 void Scale::applyReciprocalTo(impl::DecimalQuantity& quantity) const {
    138    quantity.adjustMagnitude(-fMagnitude);
    139    if (fArbitrary != nullptr) {
    140        UErrorCode localStatus = U_ZERO_ERROR;
    141        quantity.divideBy(*fArbitrary, localStatus);
    142    }
    143 }
    144 
    145 
    146 void
    147 MultiplierFormatHandler::setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent) {
    148    fMultiplier = multiplier;
    149    fParent = parent;
    150 }
    151 
    152 void MultiplierFormatHandler::processQuantity(DecimalQuantity& quantity, MicroProps& micros,
    153                                              UErrorCode& status) const {
    154    fParent->processQuantity(quantity, micros, status);
    155    fMultiplier.applyTo(quantity);
    156 }
    157 
    158 #endif /* #if !UCONFIG_NO_FORMATTING */