tor-browser

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

number_capi.cpp (13321B)


      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 "fphdlimp.h"
     13 #include "number_utypes.h"
     14 #include "numparse_types.h"
     15 #include "formattedval_impl.h"
     16 #include "number_decnum.h"
     17 #include "unicode/numberformatter.h"
     18 #include "unicode/unumberformatter.h"
     19 #include "unicode/simplenumberformatter.h"
     20 #include "unicode/usimplenumberformatter.h"
     21 
     22 using namespace icu;
     23 using namespace icu::number;
     24 using namespace icu::number::impl;
     25 
     26 
     27 U_NAMESPACE_BEGIN
     28 namespace number::impl {
     29 
     30 /**
     31 * Implementation class for UNumberFormatter. Wraps a LocalizedNumberFormatter.
     32 */
     33 struct UNumberFormatterData : public UMemory,
     34        // Magic number as ASCII == "NFR" (NumberFormatteR)
     35        public IcuCApiHelper<UNumberFormatter, UNumberFormatterData, 0x4E465200> {
     36    LocalizedNumberFormatter fFormatter;
     37 };
     38 
     39 /**
     40 * Implementation class for USimpleNumber. Wraps a SimpleNumberFormatter.
     41 */
     42 struct USimpleNumberData : public UMemory,
     43        // Magic number as ASCII == "SNM" (SimpleNuMber)
     44        public IcuCApiHelper<USimpleNumber, USimpleNumberData, 0x534E4D00> {
     45    SimpleNumber fNumber;
     46 };
     47 
     48 /**
     49 * Implementation class for USimpleNumberFormatter. Wraps a SimpleNumberFormatter.
     50 */
     51 struct USimpleNumberFormatterData : public UMemory,
     52        // Magic number as ASCII == "SNF" (SimpleNumberFormatter)
     53        public IcuCApiHelper<USimpleNumberFormatter, USimpleNumberFormatterData, 0x534E4600> {
     54    SimpleNumberFormatter fFormatter;
     55 };
     56 
     57 struct UFormattedNumberImpl;
     58 
     59 // Magic number as ASCII == "FDN" (FormatteDNumber)
     60 typedef IcuCApiHelper<UFormattedNumber, UFormattedNumberImpl, 0x46444E00> UFormattedNumberApiHelper;
     61 
     62 struct UFormattedNumberImpl : public UFormattedValueImpl, public UFormattedNumberApiHelper {
     63    UFormattedNumberImpl();
     64    ~UFormattedNumberImpl();
     65 
     66    FormattedNumber fImpl;
     67    UFormattedNumberData fData;
     68 
     69    void setTo(FormattedNumber value);
     70 };
     71 
     72 UFormattedNumberImpl::UFormattedNumberImpl()
     73        : fImpl(&fData) {
     74    fFormattedValue = &fImpl;
     75 }
     76 
     77 UFormattedNumberImpl::~UFormattedNumberImpl() {
     78    // Disown the data from fImpl so it doesn't get deleted twice
     79    fImpl.fData = nullptr;
     80 }
     81 
     82 void UFormattedNumberImpl::setTo(FormattedNumber value) {
     83    fData = std::move(*value.fData);
     84 }
     85 
     86 } // namespace number::impl
     87 U_NAMESPACE_END
     88 
     89 
     90 UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(
     91    UFormattedNumber,
     92    UFormattedNumberImpl,
     93    UFormattedNumberApiHelper,
     94    unumf)
     95 
     96 
     97 const DecimalQuantity* icu::number::impl::validateUFormattedNumberToDecimalQuantity(
     98        const UFormattedNumber* uresult, UErrorCode& status) {
     99    const auto* result = UFormattedNumberApiHelper::validate(uresult, status);
    100    if (U_FAILURE(status)) {
    101        return nullptr;
    102    }
    103    return &result->fData.quantity;
    104 }
    105 
    106 
    107 
    108 U_CAPI UNumberFormatter* U_EXPORT2
    109 unumf_openForSkeletonAndLocale(const char16_t* skeleton, int32_t skeletonLen, const char* locale,
    110                               UErrorCode* ec) {
    111    auto* impl = new UNumberFormatterData();
    112    if (impl == nullptr) {
    113        *ec = U_MEMORY_ALLOCATION_ERROR;
    114        return nullptr;
    115    }
    116    // Readonly-alias constructor (first argument is whether we are NUL-terminated)
    117    UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen);
    118    impl->fFormatter = NumberFormatter::forSkeleton(skeletonString, *ec).locale(locale);
    119    return impl->exportForC();
    120 }
    121 
    122 U_CAPI UNumberFormatter* U_EXPORT2
    123 unumf_openForSkeletonAndLocaleWithError(const char16_t* skeleton, int32_t skeletonLen, const char* locale,
    124                                         UParseError* perror, UErrorCode* ec) {
    125    auto* impl = new UNumberFormatterData();
    126    if (impl == nullptr) {
    127        *ec = U_MEMORY_ALLOCATION_ERROR;
    128        return nullptr;
    129    }
    130    // Readonly-alias constructor (first argument is whether we are NUL-terminated)
    131    UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen);
    132    UParseError tempParseError;
    133    impl->fFormatter = NumberFormatter::forSkeleton(skeletonString, (perror == nullptr) ? tempParseError : *perror, *ec).locale(locale);
    134    return impl->exportForC();
    135 }
    136 
    137 U_CAPI void U_EXPORT2
    138 unumf_formatInt(const UNumberFormatter* uformatter, int64_t value, UFormattedNumber* uresult,
    139                UErrorCode* ec) {
    140    const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
    141    auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
    142    if (U_FAILURE(*ec)) { return; }
    143 
    144    result->fData.resetString();
    145    result->fData.quantity.clear();
    146    result->fData.quantity.setToLong(value);
    147    formatter->fFormatter.formatImpl(&result->fData, *ec);
    148 }
    149 
    150 U_CAPI void U_EXPORT2
    151 unumf_formatDouble(const UNumberFormatter* uformatter, double value, UFormattedNumber* uresult,
    152                   UErrorCode* ec) {
    153    const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
    154    auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
    155    if (U_FAILURE(*ec)) { return; }
    156 
    157    result->fData.resetString();
    158    result->fData.quantity.clear();
    159    result->fData.quantity.setToDouble(value);
    160    formatter->fFormatter.formatImpl(&result->fData, *ec);
    161 }
    162 
    163 U_CAPI void U_EXPORT2
    164 unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32_t valueLen,
    165                    UFormattedNumber* uresult, UErrorCode* ec) {
    166    const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec);
    167    auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
    168    if (U_FAILURE(*ec)) { return; }
    169 
    170    result->fData.resetString();
    171    result->fData.quantity.clear();
    172    result->fData.quantity.setToDecNumber({value, valueLen}, *ec);
    173    if (U_FAILURE(*ec)) { return; }
    174    formatter->fFormatter.formatImpl(&result->fData, *ec);
    175 }
    176 
    177 U_CAPI int32_t U_EXPORT2
    178 unumf_resultToString(const UFormattedNumber* uresult, char16_t* buffer, int32_t bufferCapacity,
    179                     UErrorCode* ec) {
    180    const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
    181    if (U_FAILURE(*ec)) { return 0; }
    182 
    183    if (buffer == nullptr ? bufferCapacity != 0 : bufferCapacity < 0) {
    184        *ec = U_ILLEGAL_ARGUMENT_ERROR;
    185        return 0;
    186    }
    187 
    188    return result->fData.toTempString(*ec).extract(buffer, bufferCapacity, *ec);
    189 }
    190 
    191 U_CAPI UBool U_EXPORT2
    192 unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* ufpos, UErrorCode* ec) {
    193    const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
    194    if (U_FAILURE(*ec)) { return false; }
    195 
    196    if (ufpos == nullptr) {
    197        *ec = U_ILLEGAL_ARGUMENT_ERROR;
    198        return false;
    199    }
    200 
    201    FieldPosition fp;
    202    fp.setField(ufpos->field);
    203    fp.setBeginIndex(ufpos->beginIndex);
    204    fp.setEndIndex(ufpos->endIndex);
    205    bool retval = result->fData.nextFieldPosition(fp, *ec);
    206    ufpos->beginIndex = fp.getBeginIndex();
    207    ufpos->endIndex = fp.getEndIndex();
    208    // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
    209    return retval ? true : false;
    210 }
    211 
    212 U_CAPI void U_EXPORT2
    213 unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer,
    214                                 UErrorCode* ec) {
    215    const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
    216    if (U_FAILURE(*ec)) { return; }
    217 
    218    if (ufpositer == nullptr) {
    219        *ec = U_ILLEGAL_ARGUMENT_ERROR;
    220        return;
    221    }
    222 
    223    auto* fpi = reinterpret_cast<FieldPositionIterator*>(ufpositer);
    224    FieldPositionIteratorHandler fpih(fpi, *ec);
    225    result->fData.getAllFieldPositions(fpih, *ec);
    226 }
    227 
    228 U_CAPI int32_t U_EXPORT2
    229 unumf_resultToDecimalNumber(
    230        const UFormattedNumber* uresult,
    231        char* dest,
    232        int32_t destCapacity,
    233        UErrorCode* ec) {
    234    const auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
    235    if (U_FAILURE(*ec)) {
    236        return 0;
    237    }
    238    DecNum decnum;
    239    return result->fData.quantity
    240        .toDecNum(decnum, *ec)
    241        .toCharString(*ec)
    242        .extract(dest, destCapacity, *ec);
    243 }
    244 
    245 U_CAPI void U_EXPORT2
    246 unumf_close(UNumberFormatter* f) {
    247    UErrorCode localStatus = U_ZERO_ERROR;
    248    const UNumberFormatterData* impl = UNumberFormatterData::validate(f, localStatus);
    249    delete impl;
    250 }
    251 
    252 
    253 ///// SIMPLE NUMBER FORMATTER /////
    254 
    255 U_CAPI USimpleNumber* U_EXPORT2
    256 usnum_openForInt64(int64_t value, UErrorCode* ec) {
    257    auto* number = new USimpleNumberData();
    258    if (number == nullptr) {
    259        *ec = U_MEMORY_ALLOCATION_ERROR;
    260        return nullptr;
    261    }
    262    number->fNumber = SimpleNumber::forInt64(value, *ec);
    263    return number->exportForC();
    264 }
    265 
    266 U_CAPI void U_EXPORT2
    267 usnum_setToInt64(USimpleNumber* unumber, int64_t value, UErrorCode* ec) {
    268    auto* number = USimpleNumberData::validate(unumber, *ec);
    269    if (U_FAILURE(*ec)) {
    270        return;
    271    }
    272    number->fNumber = SimpleNumber::forInt64(value, *ec);
    273 }
    274 
    275 U_CAPI void U_EXPORT2
    276 usnum_multiplyByPowerOfTen(USimpleNumber* unumber, int32_t power, UErrorCode* ec) {
    277    auto* number = USimpleNumberData::validate(unumber, *ec);
    278    if (U_FAILURE(*ec)) {
    279        return;
    280    }
    281    number->fNumber.multiplyByPowerOfTen(power, *ec);
    282 }
    283 
    284 U_CAPI void U_EXPORT2
    285 usnum_roundTo(USimpleNumber* unumber, int32_t position, UNumberFormatRoundingMode roundingMode, UErrorCode* ec) {
    286    auto* number = USimpleNumberData::validate(unumber, *ec);
    287    if (U_FAILURE(*ec)) {
    288        return;
    289    }
    290    number->fNumber.roundTo(position, roundingMode, *ec);
    291 }
    292 
    293 U_CAPI void U_EXPORT2
    294 usnum_setMinimumIntegerDigits(USimpleNumber* unumber, int32_t minimumIntegerDigits, UErrorCode* ec) {
    295    auto* number = USimpleNumberData::validate(unumber, *ec);
    296    if (U_FAILURE(*ec)) {
    297        return;
    298    }
    299    number->fNumber.setMinimumIntegerDigits(minimumIntegerDigits, *ec);
    300 }
    301 
    302 U_CAPI void U_EXPORT2
    303 usnum_setMinimumFractionDigits(USimpleNumber* unumber, int32_t minimumFractionDigits, UErrorCode* ec) {
    304    auto* number = USimpleNumberData::validate(unumber, *ec);
    305    if (U_FAILURE(*ec)) {
    306        return;
    307    }
    308    number->fNumber.setMinimumFractionDigits(minimumFractionDigits, *ec);
    309 }
    310 
    311 U_CAPI void U_EXPORT2
    312 usnum_setMaximumIntegerDigits(USimpleNumber* unumber, int32_t maximumIntegerDigits, UErrorCode* ec) {
    313    auto* number = USimpleNumberData::validate(unumber, *ec);
    314    if (U_FAILURE(*ec)) {
    315        return;
    316    }
    317    number->fNumber.setMaximumIntegerDigits(maximumIntegerDigits, *ec);
    318 }
    319 
    320 U_CAPI void U_EXPORT2
    321 usnum_setSign(USimpleNumber* unumber, USimpleNumberSign sign, UErrorCode* ec) {
    322    auto* number = USimpleNumberData::validate(unumber, *ec);
    323    if (U_FAILURE(*ec)) {
    324        return;
    325    }
    326    number->fNumber.setSign(sign, *ec);
    327 }
    328 
    329 U_CAPI USimpleNumberFormatter* U_EXPORT2
    330 usnumf_openForLocale(const char* locale, UErrorCode* ec) {
    331    auto* impl = new USimpleNumberFormatterData();
    332    if (impl == nullptr) {
    333        *ec = U_MEMORY_ALLOCATION_ERROR;
    334        return nullptr;
    335    }
    336    impl->fFormatter = SimpleNumberFormatter::forLocale(locale, *ec);
    337    return impl->exportForC();
    338 }
    339 
    340 U_CAPI USimpleNumberFormatter* U_EXPORT2
    341 usnumf_openForLocaleAndGroupingStrategy(
    342       const char* locale, UNumberGroupingStrategy groupingStrategy, UErrorCode* ec) {
    343    auto* impl = new USimpleNumberFormatterData();
    344    if (impl == nullptr) {
    345        *ec = U_MEMORY_ALLOCATION_ERROR;
    346        return nullptr;
    347    }
    348    impl->fFormatter = SimpleNumberFormatter::forLocaleAndGroupingStrategy(locale, groupingStrategy, *ec);
    349    return impl->exportForC();
    350 }
    351 
    352 U_CAPI void U_EXPORT2
    353 usnumf_format(
    354        const USimpleNumberFormatter* uformatter,
    355        USimpleNumber* unumber,
    356        UFormattedNumber* uresult,
    357        UErrorCode* ec) {
    358    const auto* formatter = USimpleNumberFormatterData::validate(uformatter, *ec);
    359    auto* number = USimpleNumberData::validate(unumber, *ec);
    360    auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
    361    if (U_FAILURE(*ec)) {
    362        return;
    363    }
    364    auto localResult = formatter->fFormatter.format(std::move(number->fNumber), *ec);
    365    if (U_FAILURE(*ec)) {
    366        return;
    367    }
    368    result->setTo(std::move(localResult));
    369 }
    370 
    371 U_CAPI void U_EXPORT2
    372 usnumf_formatInt64(
    373        const USimpleNumberFormatter* uformatter,
    374        int64_t value,
    375        UFormattedNumber* uresult,
    376        UErrorCode* ec) {
    377    const auto* formatter = USimpleNumberFormatterData::validate(uformatter, *ec);
    378    auto* result = UFormattedNumberApiHelper::validate(uresult, *ec);
    379    if (U_FAILURE(*ec)) {
    380        return;
    381    }
    382    auto localResult = formatter->fFormatter.formatInt64(value, *ec);
    383    result->setTo(std::move(localResult)); 
    384 }
    385 
    386 U_CAPI void U_EXPORT2
    387 usnum_close(USimpleNumber* unumber) {
    388    UErrorCode localStatus = U_ZERO_ERROR;
    389    const USimpleNumberData* impl = USimpleNumberData::validate(unumber, localStatus);
    390    delete impl;
    391 }
    392 
    393 U_CAPI void U_EXPORT2
    394 usnumf_close(USimpleNumberFormatter* uformatter) {
    395    UErrorCode localStatus = U_ZERO_ERROR;
    396    const USimpleNumberFormatterData* impl = USimpleNumberFormatterData::validate(uformatter, localStatus);
    397    delete impl;
    398 }
    399 
    400 
    401 #endif /* #if !UCONFIG_NO_FORMATTING */