tor-browser

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

scientificnumberformatter.cpp (9762B)


      1 // © 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 **********************************************************************
      5 * Copyright (c) 2014, International Business Machines
      6 * Corporation and others.  All Rights Reserved.
      7 **********************************************************************
      8 */
      9 #include "unicode/utypes.h"
     10 
     11 #if !UCONFIG_NO_FORMATTING
     12 
     13 #include "unicode/scientificnumberformatter.h"
     14 #include "unicode/dcfmtsym.h"
     15 #include "unicode/fpositer.h"
     16 #include "unicode/utf16.h"
     17 #include "unicode/uniset.h"
     18 #include "unicode/decimfmt.h"
     19 #include "static_unicode_sets.h"
     20 
     21 U_NAMESPACE_BEGIN
     22 
     23 static const char16_t kSuperscriptDigits[] = {
     24        0x2070,
     25        0xB9,
     26        0xB2,
     27        0xB3,
     28        0x2074,
     29        0x2075,
     30        0x2076,
     31        0x2077,
     32        0x2078,
     33        0x2079};
     34 
     35 static const char16_t kSuperscriptPlusSign = 0x207A;
     36 static const char16_t kSuperscriptMinusSign = 0x207B;
     37 
     38 static UBool copyAsSuperscript(
     39        const UnicodeString &s,
     40        int32_t beginIndex,
     41        int32_t endIndex,
     42        UnicodeString &result,
     43        UErrorCode &status) {
     44    if (U_FAILURE(status)) {
     45        return false;
     46    }
     47    for (int32_t i = beginIndex; i < endIndex;) {
     48        UChar32 c = s.char32At(i);
     49        int32_t digit = u_charDigitValue(c);
     50        if (digit < 0) {
     51            status = U_INVALID_CHAR_FOUND;
     52            return false;
     53        }
     54        result.append(kSuperscriptDigits[digit]);
     55        i += U16_LENGTH(c);
     56    }
     57    return true;
     58 }
     59 
     60 ScientificNumberFormatter *ScientificNumberFormatter::createSuperscriptInstance(
     61            DecimalFormat *fmtToAdopt, UErrorCode &status) {
     62    return createInstance(fmtToAdopt, new SuperscriptStyle(), status);
     63 }
     64 
     65 ScientificNumberFormatter *ScientificNumberFormatter::createSuperscriptInstance(
     66            const Locale &locale, UErrorCode &status) {
     67    return createInstance(
     68            static_cast<DecimalFormat *>(
     69                    DecimalFormat::createScientificInstance(locale, status)),
     70            new SuperscriptStyle(),
     71            status);
     72 }
     73 
     74 ScientificNumberFormatter *ScientificNumberFormatter::createMarkupInstance(
     75        DecimalFormat *fmtToAdopt,
     76        const UnicodeString &beginMarkup,
     77        const UnicodeString &endMarkup,
     78        UErrorCode &status) {
     79    return createInstance(
     80            fmtToAdopt,
     81            new MarkupStyle(beginMarkup, endMarkup),
     82            status);
     83 }
     84 
     85 ScientificNumberFormatter *ScientificNumberFormatter::createMarkupInstance(
     86        const Locale &locale,
     87        const UnicodeString &beginMarkup,
     88        const UnicodeString &endMarkup,
     89        UErrorCode &status) {
     90    return createInstance(
     91            static_cast<DecimalFormat *>(
     92                    DecimalFormat::createScientificInstance(locale, status)),
     93            new MarkupStyle(beginMarkup, endMarkup),
     94            status);
     95 }
     96 
     97 ScientificNumberFormatter *ScientificNumberFormatter::createInstance(
     98            DecimalFormat *fmtToAdopt,
     99            Style *styleToAdopt,
    100            UErrorCode &status) {
    101    LocalPointer<DecimalFormat> fmt(fmtToAdopt);
    102    LocalPointer<Style> style(styleToAdopt);
    103    if (U_FAILURE(status)) {
    104        return nullptr;
    105    }
    106    ScientificNumberFormatter *result =
    107            new ScientificNumberFormatter(
    108                    fmt.getAlias(),
    109                    style.getAlias(),
    110                    status);
    111    if (result == nullptr) {
    112        status = U_MEMORY_ALLOCATION_ERROR;
    113        return nullptr;
    114    }
    115    fmt.orphan();
    116    style.orphan();
    117    if (U_FAILURE(status)) {
    118        delete result;
    119        return nullptr;
    120    }
    121    return result;
    122 }
    123 
    124 ScientificNumberFormatter::SuperscriptStyle *ScientificNumberFormatter::SuperscriptStyle::clone() const {
    125    return new ScientificNumberFormatter::SuperscriptStyle(*this);
    126 }
    127 
    128 UnicodeString &ScientificNumberFormatter::SuperscriptStyle::format(
    129        const UnicodeString &original,
    130        FieldPositionIterator &fpi,
    131        const UnicodeString &preExponent,
    132        UnicodeString &appendTo,
    133        UErrorCode &status) const {
    134    if (U_FAILURE(status)) {
    135        return appendTo;
    136    }
    137    FieldPosition fp;
    138    int32_t copyFromOffset = 0;
    139    while (fpi.next(fp)) {
    140        switch (fp.getField()) {
    141        case UNUM_EXPONENT_SYMBOL_FIELD:
    142            appendTo.append(
    143                    original,
    144                    copyFromOffset,
    145                    fp.getBeginIndex() - copyFromOffset);
    146            copyFromOffset = fp.getEndIndex();
    147            appendTo.append(preExponent);
    148            break;
    149        case UNUM_EXPONENT_SIGN_FIELD:
    150            {
    151                using namespace icu::numparse::impl;
    152                int32_t beginIndex = fp.getBeginIndex();
    153                int32_t endIndex = fp.getEndIndex();
    154                UChar32 aChar = original.char32At(beginIndex);
    155                if (unisets::get(unisets::MINUS_SIGN)->contains(aChar)) {
    156                    appendTo.append(
    157                            original,
    158                            copyFromOffset,
    159                            beginIndex - copyFromOffset);
    160                    appendTo.append(kSuperscriptMinusSign);
    161                } else if (unisets::get(unisets::PLUS_SIGN)->contains(aChar)) {
    162                    appendTo.append(
    163                           original,
    164                           copyFromOffset,
    165                           beginIndex - copyFromOffset);
    166                    appendTo.append(kSuperscriptPlusSign);
    167                } else {
    168                    status = U_INVALID_CHAR_FOUND;
    169                    return appendTo;
    170                }
    171                copyFromOffset = endIndex;
    172            }
    173            break;
    174        case UNUM_EXPONENT_FIELD:
    175            appendTo.append(
    176                    original,
    177                    copyFromOffset,
    178                    fp.getBeginIndex() - copyFromOffset);
    179            if (!copyAsSuperscript(
    180                    original,
    181                    fp.getBeginIndex(),
    182                    fp.getEndIndex(),
    183                    appendTo,
    184                    status)) {
    185              return appendTo;
    186            }
    187            copyFromOffset = fp.getEndIndex();
    188            break;
    189        default:
    190            break;
    191        }
    192    }
    193    appendTo.append(
    194            original, copyFromOffset, original.length() - copyFromOffset);
    195    return appendTo;
    196 }
    197 
    198 ScientificNumberFormatter::MarkupStyle *ScientificNumberFormatter::MarkupStyle::clone() const {
    199    return new ScientificNumberFormatter::MarkupStyle(*this);
    200 }
    201 
    202 UnicodeString &ScientificNumberFormatter::MarkupStyle::format(
    203        const UnicodeString &original,
    204        FieldPositionIterator &fpi,
    205        const UnicodeString &preExponent,
    206        UnicodeString &appendTo,
    207        UErrorCode &status) const {
    208    if (U_FAILURE(status)) {
    209        return appendTo;
    210    }
    211    FieldPosition fp;
    212    int32_t copyFromOffset = 0;
    213    while (fpi.next(fp)) {
    214        switch (fp.getField()) {
    215        case UNUM_EXPONENT_SYMBOL_FIELD:
    216            appendTo.append(
    217                    original,
    218                    copyFromOffset,
    219                    fp.getBeginIndex() - copyFromOffset);
    220            copyFromOffset = fp.getEndIndex();
    221            appendTo.append(preExponent);
    222            appendTo.append(fBeginMarkup);
    223            break;
    224        case UNUM_EXPONENT_FIELD:
    225            appendTo.append(
    226                    original,
    227                    copyFromOffset,
    228                    fp.getEndIndex() - copyFromOffset);
    229            copyFromOffset = fp.getEndIndex();
    230            appendTo.append(fEndMarkup);
    231            break;
    232        default:
    233            break;
    234        }
    235    }
    236    appendTo.append(
    237            original, copyFromOffset, original.length() - copyFromOffset);
    238    return appendTo;
    239 }
    240 
    241 ScientificNumberFormatter::ScientificNumberFormatter(
    242        DecimalFormat *fmtToAdopt, Style *styleToAdopt, UErrorCode &status)
    243        : fPreExponent(),
    244          fDecimalFormat(fmtToAdopt),
    245          fStyle(styleToAdopt) {
    246    if (U_FAILURE(status)) {
    247        return;
    248    }
    249    if (fDecimalFormat == nullptr || fStyle == nullptr) {
    250        status = U_ILLEGAL_ARGUMENT_ERROR;
    251        return;
    252    }
    253    const DecimalFormatSymbols *sym = fDecimalFormat->getDecimalFormatSymbols();
    254    if (sym == nullptr) {
    255        status = U_ILLEGAL_ARGUMENT_ERROR;
    256        return;
    257    }
    258    getPreExponent(*sym, fPreExponent);
    259 }
    260 
    261 ScientificNumberFormatter::ScientificNumberFormatter(
    262        const ScientificNumberFormatter &other)
    263        : UObject(other),
    264          fPreExponent(other.fPreExponent),
    265          fDecimalFormat(nullptr),
    266          fStyle(nullptr) {
    267    fDecimalFormat = static_cast<DecimalFormat *>(
    268            other.fDecimalFormat->clone());
    269    fStyle = other.fStyle->clone();
    270 }
    271 
    272 ScientificNumberFormatter::~ScientificNumberFormatter() {
    273    delete fDecimalFormat;
    274    delete fStyle;
    275 }
    276 
    277 UnicodeString &ScientificNumberFormatter::format(
    278        const Formattable &number,
    279        UnicodeString &appendTo,
    280        UErrorCode &status) const {
    281    if (U_FAILURE(status)) {
    282        return appendTo;
    283    }
    284    UnicodeString original;
    285    FieldPositionIterator fpi;
    286    fDecimalFormat->format(number, original, &fpi, status);
    287    return fStyle->format(
    288            original,
    289            fpi,
    290            fPreExponent,
    291            appendTo,
    292            status);
    293 }
    294 
    295 void ScientificNumberFormatter::getPreExponent(
    296        const DecimalFormatSymbols &dfs, UnicodeString &preExponent) {
    297    preExponent.append(dfs.getConstSymbol(
    298            DecimalFormatSymbols::kExponentMultiplicationSymbol));
    299    preExponent.append(dfs.getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol));
    300    preExponent.append(dfs.getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol));
    301 }
    302 
    303 U_NAMESPACE_END
    304 
    305 #endif /* !UCONFIG_NO_FORMATTING */