| Index: source/common/pluralmap.h
|
| diff --git a/source/common/pluralmap.h b/source/common/pluralmap.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..63ccf8d31d14f9b016aab65dfe4d1d7256f46097
|
| --- /dev/null
|
| +++ b/source/common/pluralmap.h
|
| @@ -0,0 +1,290 @@
|
| +/*
|
| +******************************************************************************
|
| +* 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
|
|
|