tor-browser

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

pluralmap.h (8721B)


      1 // © 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 ******************************************************************************
      5 * Copyright (C) 2015, International Business Machines Corporation and
      6 * others. All Rights Reserved.
      7 ******************************************************************************
      8 *
      9 * File pluralmap.h - PluralMap class that maps plural categories to values.
     10 ******************************************************************************
     11 */
     12 
     13 #ifndef __PLURAL_MAP_H__
     14 #define __PLURAL_MAP_H__
     15 
     16 #include "unicode/uobject.h"
     17 #include "cmemory.h"
     18 
     19 U_NAMESPACE_BEGIN
     20 
     21 class UnicodeString;
     22 
     23 class U_COMMON_API PluralMapBase : public UMemory {
     24 public:
     25    /**
     26     * The names of all the plural categories. NONE is not an actual plural
     27     * category, but rather represents the absence of a plural category.
     28     */
     29    enum Category {
     30        NONE = -1,
     31        OTHER,
     32        ZERO,
     33        ONE,
     34        TWO,
     35        FEW,
     36        MANY,
     37        CATEGORY_COUNT
     38    };
     39 
     40    /**
     41     * Converts a category name such as "zero", "one", "two", "few", "many"
     42     * or "other" to a category enum. Returns NONE for an unrecognized
     43     * category name.
     44     */
     45    static Category toCategory(const char *categoryName);
     46 
     47    /**
     48     * Converts a category name such as "zero", "one", "two", "few", "many"
     49     * or "other" to a category enum.  Returns NONE for unrecognized
     50     * category name.
     51     */
     52    static Category toCategory(const UnicodeString &categoryName);
     53 
     54    /**
     55     * Converts a category to a name.
     56     * Passing NONE or CATEGORY_COUNT for category returns nullptr.
     57     */
     58    static const char *getCategoryName(Category category);
     59 };
     60 
     61 /**
     62 * A Map of plural categories to values. It maintains ownership of the
     63 * values.
     64 *
     65 * Type T is the value type. T must provide the following:
     66 * 1) Default constructor
     67 * 2) Copy constructor
     68 * 3) Assignment operator
     69 * 4) Must extend UMemory
     70 */
     71 template<typename T>
     72 class PluralMap : public PluralMapBase {
     73 public:
     74    /**
     75     * Other category is maps to a copy of the default value.
     76     */
     77    PluralMap() : fOtherVariant() {
     78        initializeNew();
     79    }
     80 
     81    /**
     82     * Other category is mapped to otherVariant.
     83     */
     84    PluralMap(const T &otherVariant) : fOtherVariant(otherVariant) {
     85        initializeNew();
     86    }
     87 
     88    PluralMap(const PluralMap<T> &other) : fOtherVariant(other.fOtherVariant) {
     89        fVariants[0] = &fOtherVariant;
     90        for (int32_t i = 1; i < UPRV_LENGTHOF(fVariants); ++i) {
     91            fVariants[i] = other.fVariants[i] ?
     92                    new T(*other.fVariants[i]) : nullptr;
     93        }
     94    }
     95 
     96    PluralMap<T> &operator=(const PluralMap<T> &other) {
     97        if (this == &other) {
     98            return *this;
     99        }
    100        for (int32_t i = 0; i < UPRV_LENGTHOF(fVariants); ++i) {
    101            if (fVariants[i] != nullptr && other.fVariants[i] != nullptr) {
    102                *fVariants[i] = *other.fVariants[i];
    103            } else if (fVariants[i] != nullptr) {
    104                delete fVariants[i];
    105                fVariants[i] = nullptr;
    106            } else if (other.fVariants[i] != nullptr) {
    107                fVariants[i] = new T(*other.fVariants[i]);
    108            } else {
    109                // do nothing
    110            }
    111        }
    112        return *this;
    113    }
    114 
    115    ~PluralMap() {
    116        for (int32_t i = 1; i < UPRV_LENGTHOF(fVariants); ++i) {
    117            delete fVariants[i];
    118        }
    119    }
    120 
    121    /**
    122     * Removes all mappings and makes 'other' point to the default value.
    123     */
    124    void clear() {
    125        *fVariants[0] = T();
    126        for (int32_t i = 1; i < UPRV_LENGTHOF(fVariants); ++i) {
    127            delete fVariants[i];
    128            fVariants[i] = nullptr;
    129        }
    130    }
    131 
    132    /**
    133     * Iterates through the mappings in this instance, set index to NONE
    134     * prior to using. Call next repeatedly to get the values until it
    135     * returns nullptr. Each time next returns, caller may pass index
    136     * to getCategoryName() to get the name of the plural category.
    137     * When this function returns nullptr, index is CATEGORY_COUNT
    138     */
    139    const T *next(Category &index) const {
    140        int32_t idx = index;
    141        ++idx;
    142        for (; idx < UPRV_LENGTHOF(fVariants); ++idx) {
    143            if (fVariants[idx] != nullptr) {
    144                index = static_cast<Category>(idx);
    145                return fVariants[idx];
    146            }
    147        }
    148        index = static_cast<Category>(idx);
    149        return nullptr;
    150    }
    151 
    152    /**
    153     * non const version of next.
    154     */
    155    T *nextMutable(Category &index) {
    156        const T *result = next(index);
    157        return const_cast<T *>(result);
    158    }
    159 
    160    /**
    161     * Returns the 'other' variant.
    162     * Same as calling get(OTHER).
    163     */
    164    const T &getOther() const {
    165        return get(OTHER);
    166    }
    167 
    168    /**
    169     * Returns the value associated with a category.
    170     * If no value found, or v is NONE or CATEGORY_COUNT, falls
    171     * back to returning the value for the 'other' category.
    172     */
    173    const T &get(Category v) const {
    174        int32_t index = v;
    175        if (index < 0 || index >= UPRV_LENGTHOF(fVariants) || fVariants[index] == nullptr) {
    176            return *fVariants[0];
    177        }
    178        return *fVariants[index];
    179    }
    180 
    181    /**
    182     * Convenience routine to get the value by category name. Otherwise
    183     * works just like get(Category).
    184     */
    185    const T &get(const char *category) const {
    186        return get(toCategory(category));
    187    }
    188 
    189    /**
    190     * Convenience routine to get the value by category name as a
    191     * UnicodeString. Otherwise works just like get(category).
    192     */
    193    const T &get(const UnicodeString &category) const {
    194        return get(toCategory(category));
    195    }
    196 
    197    /**
    198     * Returns a pointer to the value associated with a category
    199     * that caller can safely modify. If the value was defaulting to the 'other'
    200     * variant because no explicit value was stored, this method creates a
    201     * new value using the default constructor at the returned pointer.
    202     *
    203     * @param category the category with the value to change.
    204     * @param status error returned here if index is NONE or CATEGORY_COUNT
    205     *  or memory could not be allocated, or any other error happens.
    206     */
    207    T *getMutable(
    208            Category category,
    209            UErrorCode &status) {
    210        return getMutable(category, nullptr, status);
    211    }
    212 
    213    /**
    214     * Convenience routine to get a mutable pointer to a value by category name.
    215     * Otherwise works just like getMutable(Category, UErrorCode &).
    216     * reports an error if the category name is invalid.
    217     */
    218    T *getMutable(
    219            const char *category,
    220            UErrorCode &status) {
    221        return getMutable(toCategory(category), nullptr, status);
    222    }
    223 
    224    /**
    225     * Just like getMutable(Category, UErrorCode &) but copies defaultValue to
    226     * returned pointer if it was defaulting to the 'other' variant
    227     * because no explicit value was stored.
    228     */
    229    T *getMutableWithDefault(
    230            Category category,
    231            const T &defaultValue,
    232            UErrorCode &status) {
    233        return getMutable(category, &defaultValue, status);
    234    }
    235 
    236    /**
    237     * Returns true if this object equals rhs.
    238     */
    239    UBool equals(
    240            const PluralMap<T> &rhs,
    241            UBool (*eqFunc)(const T &, const T &)) const {
    242        for (int32_t i = 0; i < UPRV_LENGTHOF(fVariants); ++i) {
    243            if (fVariants[i] == rhs.fVariants[i]) {
    244                continue;
    245            }
    246            if (fVariants[i] == nullptr || rhs.fVariants[i] == nullptr) {
    247                return false;
    248            }
    249            if (!eqFunc(*fVariants[i], *rhs.fVariants[i])) {
    250                return false;
    251            }
    252        }
    253        return true;
    254    }
    255 
    256 private:
    257    T fOtherVariant;
    258    T* fVariants[6];
    259 
    260    T *getMutable(
    261            Category category,
    262            const T *defaultValue,
    263            UErrorCode &status) {
    264        if (U_FAILURE(status)) {
    265            return nullptr;
    266        }
    267        int32_t index = category;
    268        if (index < 0 || index >= UPRV_LENGTHOF(fVariants)) {
    269            status = U_ILLEGAL_ARGUMENT_ERROR;
    270            return nullptr;
    271        }
    272        if (fVariants[index] == nullptr) {
    273            fVariants[index] = defaultValue == nullptr ?
    274                    new T() : new T(*defaultValue);
    275        }
    276        if (!fVariants[index]) {
    277            status = U_MEMORY_ALLOCATION_ERROR;
    278        }
    279        return fVariants[index];
    280    }
    281 
    282    void initializeNew() {
    283        fVariants[0] = &fOtherVariant;
    284        for (int32_t i = 1; i < UPRV_LENGTHOF(fVariants); ++i) {
    285            fVariants[i] = nullptr;
    286        }
    287    }
    288 };
    289 
    290 U_NAMESPACE_END
    291 
    292 #endif