123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- // © 2016 and later: Unicode, Inc. and others.
- // License & terms of use: http://www.unicode.org/copyright.html
- /*
- ******************************************************************************
- * Copyright (C) 2015, International Business Machines Corporation and
- * others. All Rights Reserved.
- ******************************************************************************
- *
- * File pluralmap.h - PluralMap class that maps plural categories to values.
- ******************************************************************************
- */
- #ifndef __PLURAL_MAP_H__
- #define __PLURAL_MAP_H__
- #include "unicode/uobject.h"
- #include "cmemory.h"
- U_NAMESPACE_BEGIN
- class UnicodeString;
- class U_COMMON_API PluralMapBase : public UMemory {
- public:
- /**
- * The names of all the plural categories. NONE is not an actual plural
- * category, but rather represents the absense of a plural category.
- */
- enum Category {
- NONE = -1,
- OTHER,
- ZERO,
- ONE,
- TWO,
- FEW,
- MANY,
- CATEGORY_COUNT
- };
- /**
- * Converts a category name such as "zero", "one", "two", "few", "many"
- * or "other" to a category enum. Returns NONE for an unrecognized
- * category name.
- */
- static Category toCategory(const char *categoryName);
- /**
- * Converts a category name such as "zero", "one", "two", "few", "many"
- * or "other" to a category enum. Returns NONE for urecongized
- * category name.
- */
- static Category toCategory(const UnicodeString &categoryName);
- /**
- * Converts a category to a name.
- * Passing NONE or CATEGORY_COUNT for category returns NULL.
- */
- static const char *getCategoryName(Category category);
- };
- /**
- * A Map of plural categories to values. It maintains ownership of the
- * values.
- *
- * Type T is the value type. T must provide the followng:
- * 1) Default constructor
- * 2) Copy constructor
- * 3) Assignment operator
- * 4) Must extend UMemory
- */
- template<typename T>
- class PluralMap : public PluralMapBase {
- public:
- /**
- * Other category is maps to a copy of the default value.
- */
- PluralMap() : fOtherVariant() {
- initializeNew();
- }
- /**
- * Other category is mapped to otherVariant.
- */
- PluralMap(const T &otherVariant) : fOtherVariant(otherVariant) {
- initializeNew();
- }
- PluralMap(const PluralMap<T> &other) : fOtherVariant(other.fOtherVariant) {
- fVariants[0] = &fOtherVariant;
- for (int32_t i = 1; i < UPRV_LENGTHOF(fVariants); ++i) {
- fVariants[i] = other.fVariants[i] ?
- new T(*other.fVariants[i]) : NULL;
- }
- }
- PluralMap<T> &operator=(const PluralMap<T> &other) {
- if (this == &other) {
- return *this;
- }
- for (int32_t i = 0; i < UPRV_LENGTHOF(fVariants); ++i) {
- if (fVariants[i] != NULL && other.fVariants[i] != NULL) {
- *fVariants[i] = *other.fVariants[i];
- } else if (fVariants[i] != NULL) {
- delete fVariants[i];
- fVariants[i] = NULL;
- } else if (other.fVariants[i] != NULL) {
- fVariants[i] = new T(*other.fVariants[i]);
- } else {
- // do nothing
- }
- }
- return *this;
- }
- ~PluralMap() {
- for (int32_t i = 1; i < UPRV_LENGTHOF(fVariants); ++i) {
- delete fVariants[i];
- }
- }
- /**
- * Removes all mappings and makes 'other' point to the default value.
- */
- void clear() {
- *fVariants[0] = T();
- for (int32_t i = 1; i < UPRV_LENGTHOF(fVariants); ++i) {
- delete fVariants[i];
- fVariants[i] = NULL;
- }
- }
- /**
- * Iterates through the mappings in this instance, set index to NONE
- * prior to using. Call next repeatedly to get the values until it
- * returns NULL. Each time next returns, caller may pass index
- * to getCategoryName() to get the name of the plural category.
- * When this function returns NULL, index is CATEGORY_COUNT
- */
- const T *next(Category &index) const {
- int32_t idx = index;
- ++idx;
- for (; idx < UPRV_LENGTHOF(fVariants); ++idx) {
- if (fVariants[idx] != NULL) {
- index = static_cast<Category>(idx);
- return fVariants[idx];
- }
- }
- index = static_cast<Category>(idx);
- return NULL;
- }
- /**
- * non const version of next.
- */
- T *nextMutable(Category &index) {
- const T *result = next(index);
- return const_cast<T *>(result);
- }
- /**
- * Returns the 'other' variant.
- * Same as calling get(OTHER).
- */
- const T &getOther() const {
- return get(OTHER);
- }
- /**
- * Returns the value associated with a category.
- * If no value found, or v is NONE or CATEGORY_COUNT, falls
- * back to returning the value for the 'other' category.
- */
- const T &get(Category v) const {
- int32_t index = v;
- if (index < 0 || index >= UPRV_LENGTHOF(fVariants) || fVariants[index] == NULL) {
- return *fVariants[0];
- }
- return *fVariants[index];
- }
- /**
- * Convenience routine to get the value by category name. Otherwise
- * works just like get(Category).
- */
- const T &get(const char *category) const {
- return get(toCategory(category));
- }
- /**
- * Convenience routine to get the value by category name as a
- * UnicodeString. Otherwise works just like get(category).
- */
- const T &get(const UnicodeString &category) const {
- return get(toCategory(category));
- }
- /**
- * Returns a pointer to the value associated with a category
- * that caller can safely modify. If the value was defaulting to the 'other'
- * variant because no explicit value was stored, this method creates a
- * new value using the default constructor at the returned pointer.
- *
- * @param category the category with the value to change.
- * @param status error returned here if index is NONE or CATEGORY_COUNT
- * or memory could not be allocated, or any other error happens.
- */
- T *getMutable(
- Category category,
- UErrorCode &status) {
- return getMutable(category, NULL, status);
- }
- /**
- * Convenience routine to get a mutable pointer to a value by category name.
- * Otherwise works just like getMutable(Category, UErrorCode &).
- * reports an error if the category name is invalid.
- */
- T *getMutable(
- const char *category,
- UErrorCode &status) {
- return getMutable(toCategory(category), NULL, status);
- }
- /**
- * Just like getMutable(Category, UErrorCode &) but copies defaultValue to
- * returned pointer if it was defaulting to the 'other' variant
- * because no explicit value was stored.
- */
- T *getMutableWithDefault(
- Category category,
- const T &defaultValue,
- UErrorCode &status) {
- return getMutable(category, &defaultValue, status);
- }
- /**
- * Returns TRUE if this object equals rhs.
- */
- UBool equals(
- const PluralMap<T> &rhs,
- UBool (*eqFunc)(const T &, const T &)) const {
- for (int32_t i = 0; i < UPRV_LENGTHOF(fVariants); ++i) {
- if (fVariants[i] == rhs.fVariants[i]) {
- continue;
- }
- if (fVariants[i] == NULL || rhs.fVariants[i] == NULL) {
- return FALSE;
- }
- if (!eqFunc(*fVariants[i], *rhs.fVariants[i])) {
- return FALSE;
- }
- }
- return TRUE;
- }
- private:
- T fOtherVariant;
- T* fVariants[6];
- T *getMutable(
- Category category,
- const T *defaultValue,
- UErrorCode &status) {
- if (U_FAILURE(status)) {
- return NULL;
- }
- int32_t index = category;
- if (index < 0 || index >= UPRV_LENGTHOF(fVariants)) {
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return NULL;
- }
- if (fVariants[index] == NULL) {
- fVariants[index] = defaultValue == NULL ?
- new T() : new T(*defaultValue);
- }
- if (!fVariants[index]) {
- status = U_MEMORY_ALLOCATION_ERROR;
- }
- return fVariants[index];
- }
- void initializeNew() {
- fVariants[0] = &fOtherVariant;
- for (int32_t i = 1; i < UPRV_LENGTHOF(fVariants); ++i) {
- fVariants[i] = NULL;
- }
- }
- };
- U_NAMESPACE_END
- #endif
|