#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:
enum Category {
NONE = -1,
OTHER,
ZERO,
ONE,
TWO,
FEW,
MANY,
CATEGORY_COUNT
};
static Category toCategory(const char *categoryName);
static Category toCategory(const UnicodeString &categoryName);
static const char *getCategoryName(Category category);
};
template<typename T>
class PluralMap : public PluralMapBase {
public:
PluralMap() : fOtherVariant() {
initializeNew();
}
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 {
}
}
return *this;
}
~PluralMap() {
for (int32_t i = 1; i < UPRV_LENGTHOF(fVariants); ++i) {
delete fVariants[i];
}
}
void clear() {
*fVariants[0] = T();
for (int32_t i = 1; i < UPRV_LENGTHOF(fVariants); ++i) {
delete fVariants[i];
fVariants[i] = NULL;
}
}
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;
}
T *nextMutable(Category &index) {
const T *result = next(index);
return const_cast<T *>(result);
}
const T &getOther() const {
return get(OTHER);
}
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];
}
const T &get(const char *category) const {
return get(toCategory(category));
}
const T &get(const UnicodeString &category) const {
return get(toCategory(category));
}
T *getMutable(
Category category,
UErrorCode &status) {
return getMutable(category, NULL, status);
}
T *getMutable(
const char *category,
UErrorCode &status) {
return getMutable(toCategory(category), NULL, status);
}
T *getMutableWithDefault(
Category category,
const T &defaultValue,
UErrorCode &status) {
return getMutable(category, &defaultValue, status);
}
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