tor-browser

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

number_modifiers.h (11921B)


      1 // © 2017 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 #ifndef __NUMBER_MODIFIERS_H__
      8 #define __NUMBER_MODIFIERS_H__
      9 
     10 #include <algorithm>
     11 #include <cstdint>
     12 #include "unicode/uniset.h"
     13 #include "unicode/simpleformatter.h"
     14 #include "standardplural.h"
     15 #include "formatted_string_builder.h"
     16 #include "number_types.h"
     17 
     18 U_NAMESPACE_BEGIN
     19 namespace number::impl {
     20 
     21 /**
     22 * The canonical implementation of {@link Modifier}, containing a prefix and suffix string.
     23 * TODO: This is not currently being used by real code and could be removed.
     24 */
     25 class U_I18N_API ConstantAffixModifier : public Modifier, public UObject {
     26  public:
     27    ConstantAffixModifier(const UnicodeString &prefix, const UnicodeString &suffix, Field field,
     28                          bool strong)
     29            : fPrefix(prefix), fSuffix(suffix), fField(field), fStrong(strong) {}
     30 
     31    int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
     32                  UErrorCode &status) const override;
     33 
     34    int32_t getPrefixLength() const override;
     35 
     36    int32_t getCodePointCount() const override;
     37 
     38    bool isStrong() const override;
     39 
     40    bool containsField(Field field) const override;
     41 
     42    void getParameters(Parameters& output) const override;
     43 
     44    bool strictEquals(const Modifier& other) const override;
     45 
     46  private:
     47    UnicodeString fPrefix;
     48    UnicodeString fSuffix;
     49    Field fField;
     50    bool fStrong;
     51 };
     52 
     53 /**
     54 * The second primary implementation of {@link Modifier}, this one consuming a {@link SimpleFormatter}
     55 * pattern.
     56 */
     57 class U_I18N_API SimpleModifier : public Modifier, public UMemory {
     58  public:
     59    SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong);
     60 
     61    SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong,
     62                   const Modifier::Parameters parameters);
     63 
     64    // Default constructor for LongNameHandler.h
     65    SimpleModifier();
     66 
     67    int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
     68                  UErrorCode &status) const override;
     69 
     70    int32_t getPrefixLength() const override;
     71 
     72    int32_t getCodePointCount() const override;
     73 
     74    bool isStrong() const override;
     75 
     76    bool containsField(Field field) const override;
     77 
     78    void getParameters(Parameters& output) const override;
     79 
     80    bool strictEquals(const Modifier& other) const override;
     81 
     82    /**
     83     * TODO: This belongs in SimpleFormatterImpl. The only reason I haven't moved it there yet is because
     84     * FormattedStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it.
     85     *
     86     * <p>
     87     * Formats a value that is already stored inside the StringBuilder <code>result</code> between the indices
     88     * <code>startIndex</code> and <code>endIndex</code> by inserting characters before the start index and after the
     89     * end index.
     90     *
     91     * <p>
     92     * This is well-defined only for patterns with exactly one argument.
     93     *
     94     * @param result
     95     *            The StringBuilder containing the value argument.
     96     * @param startIndex
     97     *            The left index of the value within the string builder.
     98     * @param endIndex
     99     *            The right index of the value within the string builder.
    100     * @return The number of characters (UTF-16 code points) that were added to the StringBuilder.
    101     */
    102    int32_t
    103    formatAsPrefixSuffix(FormattedStringBuilder& result, int32_t startIndex, int32_t endIndex,
    104                         UErrorCode& status) const;
    105 
    106    /**
    107     * TODO: Like above, this belongs with the rest of the SimpleFormatterImpl code.
    108     * I put it here so that the SimpleFormatter uses in FormattedStringBuilder are near each other.
    109     *
    110     * <p>
    111     * Applies the compiled two-argument pattern to the FormattedStringBuilder.
    112     *
    113     * <p>
    114     * This method is optimized for the case where the prefix and suffix are often empty, such as
    115     * in the range pattern like "{0}-{1}".
    116     */
    117    static int32_t
    118    formatTwoArgPattern(const SimpleFormatter& compiled, FormattedStringBuilder& result,
    119                        int32_t index, int32_t* outPrefixLength, int32_t* outSuffixLength,
    120                        Field field, UErrorCode& status);
    121 
    122  private:
    123    UnicodeString fCompiledPattern;
    124    Field fField;
    125    bool fStrong = false;
    126    int32_t fPrefixLength = 0;
    127    int32_t fSuffixOffset = -1;
    128    int32_t fSuffixLength = 0;
    129    Modifier::Parameters fParameters;
    130 };
    131 
    132 /**
    133 * An implementation of {@link Modifier} that allows for multiple types of fields in the same modifier. Constructed
    134 * based on the contents of two {@link FormattedStringBuilder} instances (one for the prefix, one for the suffix).
    135 */
    136 class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory {
    137  public:
    138    ConstantMultiFieldModifier(
    139            const FormattedStringBuilder &prefix,
    140            const FormattedStringBuilder &suffix,
    141            bool overwrite,
    142            bool strong,
    143            const Modifier::Parameters parameters)
    144      : fPrefix(prefix),
    145        fSuffix(suffix),
    146        fOverwrite(overwrite),
    147        fStrong(strong),
    148        fParameters(parameters) {}
    149 
    150    ConstantMultiFieldModifier(
    151            const FormattedStringBuilder &prefix,
    152            const FormattedStringBuilder &suffix,
    153            bool overwrite,
    154            bool strong)
    155      : fPrefix(prefix),
    156        fSuffix(suffix),
    157        fOverwrite(overwrite),
    158        fStrong(strong) {}
    159 
    160    int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
    161                  UErrorCode &status) const override;
    162 
    163    int32_t getPrefixLength() const override;
    164 
    165    int32_t getCodePointCount() const override;
    166 
    167    bool isStrong() const override;
    168 
    169    bool containsField(Field field) const override;
    170 
    171    void getParameters(Parameters& output) const override;
    172 
    173    bool strictEquals(const Modifier& other) const override;
    174 
    175  protected:
    176    // NOTE: In Java, these are stored as array pointers. In C++, the FormattedStringBuilder is stored by
    177    // value and is treated internally as immutable.
    178    FormattedStringBuilder fPrefix;
    179    FormattedStringBuilder fSuffix;
    180    bool fOverwrite;
    181    bool fStrong;
    182    Modifier::Parameters fParameters;
    183 };
    184 
    185 /** Identical to {@link ConstantMultiFieldModifier}, but supports currency spacing. */
    186 class U_I18N_API CurrencySpacingEnabledModifier : public ConstantMultiFieldModifier {
    187  public:
    188    /** Safe code path */
    189    CurrencySpacingEnabledModifier(
    190            const FormattedStringBuilder &prefix,
    191            const FormattedStringBuilder &suffix,
    192            bool overwrite,
    193            bool strong,
    194            const DecimalFormatSymbols &symbols,
    195            UErrorCode &status);
    196 
    197    int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
    198                  UErrorCode &status) const override;
    199 
    200    /** Unsafe code path */
    201    static int32_t
    202    applyCurrencySpacing(FormattedStringBuilder &output, int32_t prefixStart, int32_t prefixLen,
    203                         int32_t suffixStart, int32_t suffixLen, const DecimalFormatSymbols &symbols,
    204                         UErrorCode &status);
    205 
    206  private:
    207    UnicodeSet fAfterPrefixUnicodeSet;
    208    UnicodeString fAfterPrefixInsert;
    209    UnicodeSet fBeforeSuffixUnicodeSet;
    210    UnicodeString fBeforeSuffixInsert;
    211 
    212    enum EAffix {
    213        PREFIX, SUFFIX
    214    };
    215 
    216    enum EPosition {
    217        IN_CURRENCY, IN_NUMBER
    218    };
    219 
    220    /** Unsafe code path */
    221    static int32_t applyCurrencySpacingAffix(FormattedStringBuilder &output, int32_t index, EAffix affix,
    222                                             const DecimalFormatSymbols &symbols, UErrorCode &status);
    223 
    224    static UnicodeSet
    225    getUnicodeSet(const DecimalFormatSymbols &symbols, EPosition position, EAffix affix,
    226                  UErrorCode &status);
    227 
    228    static UnicodeString
    229    getInsertString(const DecimalFormatSymbols &symbols, EAffix affix, UErrorCode &status);
    230 };
    231 
    232 /** A Modifier that does not do anything. */
    233 class U_I18N_API EmptyModifier : public Modifier, public UMemory {
    234  public:
    235    explicit EmptyModifier(bool isStrong) : fStrong(isStrong) {}
    236 
    237    int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
    238                  UErrorCode &status) const override {
    239        (void)output;
    240        (void)leftIndex;
    241        (void)rightIndex;
    242        (void)status;
    243        return 0;
    244    }
    245 
    246    int32_t getPrefixLength() const override {
    247        return 0;
    248    }
    249 
    250    int32_t getCodePointCount() const override {
    251        return 0;
    252    }
    253 
    254    bool isStrong() const override {
    255        return fStrong;
    256    }
    257 
    258    bool containsField(Field field) const override {
    259        (void)field;
    260        return false;
    261    }
    262 
    263    void getParameters(Parameters& output) const override {
    264        output.obj = nullptr;
    265    }
    266 
    267    bool strictEquals(const Modifier& other) const override {
    268        return other.getCodePointCount() == 0;
    269    }
    270 
    271  private:
    272    bool fStrong;
    273 };
    274 
    275 /** An adopting Modifier store that varies by signum but not plural form. */
    276 class U_I18N_API AdoptingSignumModifierStore : public UMemory {
    277  public:
    278    virtual ~AdoptingSignumModifierStore();
    279 
    280    AdoptingSignumModifierStore() = default;
    281 
    282    // No copying!
    283    AdoptingSignumModifierStore(const AdoptingSignumModifierStore &other) = delete;
    284    AdoptingSignumModifierStore& operator=(const AdoptingSignumModifierStore& other) = delete;
    285 
    286    // Moving is OK
    287    AdoptingSignumModifierStore(AdoptingSignumModifierStore &&other) noexcept {
    288        *this = std::move(other);
    289    }
    290    AdoptingSignumModifierStore& operator=(AdoptingSignumModifierStore&& other) noexcept;
    291 
    292    /** Take ownership of the Modifier and slot it in at the given Signum. */
    293    void adoptModifier(Signum signum, const Modifier* mod) {
    294        U_ASSERT(mods[signum] == nullptr);
    295        mods[signum] = mod;
    296    }
    297 
    298    inline const Modifier*& operator[](Signum signum) {
    299        return mods[signum];
    300    }
    301    inline Modifier const* operator[](Signum signum) const {
    302        return mods[signum];
    303    }
    304 
    305  private:
    306    const Modifier* mods[SIGNUM_COUNT] = {};
    307 };
    308 
    309 /**
    310 * This implementation of ModifierStore adopts Modifier pointers.
    311 */
    312 class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory {
    313  public:
    314    static constexpr StandardPlural::Form DEFAULT_STANDARD_PLURAL = StandardPlural::OTHER;
    315 
    316    AdoptingModifierStore() = default;
    317 
    318    // No copying!
    319    AdoptingModifierStore(const AdoptingModifierStore &other) = delete;
    320 
    321    // Moving is OK
    322    AdoptingModifierStore(AdoptingModifierStore &&other) = default;
    323 
    324    /** Sets the modifiers for a specific plural form. */
    325    void adoptSignumModifierStore(StandardPlural::Form plural, AdoptingSignumModifierStore other) {
    326        mods[plural] = std::move(other);
    327    }
    328 
    329    /** Sets the modifiers for the default plural form. */
    330    void adoptSignumModifierStoreNoPlural(AdoptingSignumModifierStore other) {
    331        mods[DEFAULT_STANDARD_PLURAL] = std::move(other);
    332    }
    333 
    334    /** Returns a reference to the modifier; no ownership change. */
    335    const Modifier *getModifier(Signum signum, StandardPlural::Form plural) const override {
    336        const Modifier* modifier = mods[plural][signum];
    337        if (modifier == nullptr && plural != DEFAULT_STANDARD_PLURAL) {
    338            modifier = mods[DEFAULT_STANDARD_PLURAL][signum];
    339        }
    340        return modifier;
    341    }
    342 
    343    /** Returns a reference to the modifier; no ownership change. */
    344    const Modifier *getModifierWithoutPlural(Signum signum) const {
    345        return mods[DEFAULT_STANDARD_PLURAL][signum];
    346    }
    347 
    348  private:
    349    // NOTE: mods is zero-initialized (to nullptr)
    350    AdoptingSignumModifierStore mods[StandardPlural::COUNT] = {};
    351 };
    352 
    353 } // namespace number::impl
    354 U_NAMESPACE_END
    355 
    356 
    357 #endif //__NUMBER_MODIFIERS_H__
    358 
    359 #endif /* #if !UCONFIG_NO_FORMATTING */