2 ******************************************************************************
3 * Copyright (C) 2015, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ******************************************************************************
7 * File pluralmap.h - PluralMap class that maps plural categories to values.
8 ******************************************************************************
11 #ifndef __PLURAL_MAP_H__
12 #define __PLURAL_MAP_H__
14 #include "unicode/uobject.h"
21 class U_COMMON_API PluralMapBase
: public UMemory
{
24 * The names of all the plural categories. NONE is not an actual plural
25 * category, but rather represents the absense of a plural category.
39 * Converts a category name such as "zero", "one", "two", "few", "many"
40 * or "other" to a category enum. Returns NONE for an unrecognized
43 static Category
toCategory(const char *categoryName
);
46 * Converts a category name such as "zero", "one", "two", "few", "many"
47 * or "other" to a category enum. Returns NONE for urecongized
50 static Category
toCategory(const UnicodeString
&categoryName
);
53 * Converts a category to a name.
54 * Passing NONE or CATEGORY_COUNT for category returns NULL.
56 static const char *getCategoryName(Category category
);
60 * A Map of plural categories to values. It maintains ownership of the
63 * Type T is the value type. T must provide the followng:
64 * 1) Default constructor
66 * 3) Assignment operator
67 * 4) Must extend UMemory
70 class PluralMap
: public PluralMapBase
{
73 * Other category is maps to a copy of the default value.
75 PluralMap() : fOtherVariant() {
80 * Other category is mapped to otherVariant.
82 PluralMap(const T
&otherVariant
) : fOtherVariant(otherVariant
) {
86 PluralMap(const PluralMap
<T
> &other
) : fOtherVariant(other
.fOtherVariant
) {
87 fVariants
[0] = &fOtherVariant
;
88 for (int32_t i
= 1; i
< UPRV_LENGTHOF(fVariants
); ++i
) {
89 fVariants
[i
] = other
.fVariants
[i
] ?
90 new T(*other
.fVariants
[i
]) : NULL
;
94 PluralMap
<T
> &operator=(const PluralMap
<T
> &other
) {
98 for (int32_t i
= 0; i
< UPRV_LENGTHOF(fVariants
); ++i
) {
99 if (fVariants
[i
] != NULL
&& other
.fVariants
[i
] != NULL
) {
100 *fVariants
[i
] = *other
.fVariants
[i
];
101 } else if (fVariants
[i
] != NULL
) {
104 } else if (other
.fVariants
[i
] != NULL
) {
105 fVariants
[i
] = new T(*other
.fVariants
[i
]);
114 for (int32_t i
= 1; i
< UPRV_LENGTHOF(fVariants
); ++i
) {
120 * Removes all mappings and makes 'other' point to the default value.
124 for (int32_t i
= 1; i
< UPRV_LENGTHOF(fVariants
); ++i
) {
131 * Iterates through the mappings in this instance, set index to NONE
132 * prior to using. Call next repeatedly to get the values until it
133 * returns NULL. Each time next returns, caller may pass index
134 * to getCategoryName() to get the name of the plural category.
135 * When this function returns NULL, index is CATEGORY_COUNT
137 const T
*next(Category
&index
) const {
140 for (; idx
< UPRV_LENGTHOF(fVariants
); ++idx
) {
141 if (fVariants
[idx
] != NULL
) {
142 index
= static_cast<Category
>(idx
);
143 return fVariants
[idx
];
146 index
= static_cast<Category
>(idx
);
151 * non const version of next.
153 T
*nextMutable(Category
&index
) {
154 const T
*result
= next(index
);
155 return const_cast<T
*>(result
);
159 * Returns the 'other' variant.
160 * Same as calling get(OTHER).
162 const T
&getOther() const {
167 * Returns the value associated with a category.
168 * If no value found, or v is NONE or CATEGORY_COUNT, falls
169 * back to returning the value for the 'other' category.
171 const T
&get(Category v
) const {
173 if (index
< 0 || index
>= UPRV_LENGTHOF(fVariants
) || fVariants
[index
] == NULL
) {
174 return *fVariants
[0];
176 return *fVariants
[index
];
180 * Convenience routine to get the value by category name. Otherwise
181 * works just like get(Category).
183 const T
&get(const char *category
) const {
184 return get(toCategory(category
));
188 * Convenience routine to get the value by category name as a
189 * UnicodeString. Otherwise works just like get(category).
191 const T
&get(const UnicodeString
&category
) const {
192 return get(toCategory(category
));
196 * Returns a pointer to the value associated with a category
197 * that caller can safely modify. If the value was defaulting to the 'other'
198 * variant because no explicit value was stored, this method creates a
199 * new value using the default constructor at the returned pointer.
201 * @param category the category with the value to change.
202 * @param status error returned here if index is NONE or CATEGORY_COUNT
203 * or memory could not be allocated, or any other error happens.
207 UErrorCode
&status
) {
208 return getMutable(category
, NULL
, status
);
212 * Convenience routine to get a mutable pointer to a value by category name.
213 * Otherwise works just like getMutable(Category, UErrorCode &).
214 * reports an error if the category name is invalid.
217 const char *category
,
218 UErrorCode
&status
) {
219 return getMutable(toCategory(category
), NULL
, status
);
223 * Just like getMutable(Category, UErrorCode &) but copies defaultValue to
224 * returned pointer if it was defaulting to the 'other' variant
225 * because no explicit value was stored.
227 T
*getMutableWithDefault(
229 const T
&defaultValue
,
230 UErrorCode
&status
) {
231 return getMutable(category
, &defaultValue
, status
);
235 * Returns TRUE if this object equals rhs.
238 const PluralMap
<T
> &rhs
,
239 UBool (*eqFunc
)(const T
&, const T
&)) const {
240 for (int32_t i
= 0; i
< UPRV_LENGTHOF(fVariants
); ++i
) {
241 if (fVariants
[i
] == rhs
.fVariants
[i
]) {
244 if (fVariants
[i
] == NULL
|| rhs
.fVariants
[i
] == NULL
) {
247 if (!eqFunc(*fVariants
[i
], *rhs
.fVariants
[i
])) {
260 const T
*defaultValue
,
261 UErrorCode
&status
) {
262 if (U_FAILURE(status
)) {
265 int32_t index
= category
;
266 if (index
< 0 || index
>= UPRV_LENGTHOF(fVariants
)) {
267 status
= U_ILLEGAL_ARGUMENT_ERROR
;
270 if (fVariants
[index
] == NULL
) {
271 fVariants
[index
] = defaultValue
== NULL
?
272 new T() : new T(*defaultValue
);
274 if (!fVariants
[index
]) {
275 status
= U_MEMORY_ALLOCATION_ERROR
;
277 return fVariants
[index
];
280 void initializeNew() {
281 fVariants
[0] = &fOtherVariant
;
282 for (int32_t i
= 1; i
< UPRV_LENGTHOF(fVariants
); ++i
) {