ICU-3378 Port over getKeywordValuesForLocale API from ICU4J to ICU4C. Add test for this new API. Also add for, internal use, Linked List API for when creating UEnumeration.

X-SVN-Rev: 25527
This commit is contained in:
Michael Ow 2009-03-09 20:39:13 +00:00
parent f2d5519047
commit aa05d999c7
13 changed files with 972 additions and 11 deletions

View File

@ -86,7 +86,8 @@ uarrsort.o brkiter.o ubrk.o brkeng.o dictbe.o triedict.o \
rbbi.o rbbidata.o rbbinode.o rbbirb.o rbbiscan.o rbbisetb.o rbbistbl.o rbbitblb.o \
serv.o servnotf.o servls.o servlk.o servlkf.o servrbf.o servslkf.o \
uidna.o usprep.o punycode.o \
util.o util_props.o parsepos.o locbased.o cwchar.o wintz.o mutex.o dtintrv.o ucnvsel.o propsvec.o
util.o util_props.o parsepos.o locbased.o cwchar.o wintz.o mutex.o dtintrv.o ucnvsel.o propsvec.o \
ulist.o
## Header files to install
HEADERS = $(srcdir)/unicode/*.h unicode/*.h

View File

@ -932,6 +932,14 @@
RelativePath=".\uhash_us.cpp"
>
</File>
<File
RelativePath=".\ulist.c"
>
</File>
<File
RelativePath=".\ulist.h"
>
</File>
<File
RelativePath=".\ustack.cpp"
>

239
icu4c/source/common/ulist.c Normal file
View File

@ -0,0 +1,239 @@
/*
******************************************************************************
* Copyright (C) 2009, International Business Machines
* Corporation and others. All Rights Reserved.
******************************************************************************
*/
#include "ulist.h"
#include "cmemory.h"
#include "cstring.h"
#include "uenumimp.h"
typedef struct UListNode UListNode;
struct UListNode {
void *data;
UListNode *next;
UListNode *previous;
/* When data is created with uprv_malloc, needs to be freed during deleteList function. */
UBool forceDelete;
};
struct UList {
UListNode *curr;
UListNode *head;
UListNode *tail;
int32_t size;
int32_t currentIndex;
};
U_CAPI UList *U_EXPORT2 ulist_createEmptyList(UErrorCode *status) {
UList *newList = NULL;
if (U_FAILURE(*status)) {
return NULL;
}
newList = (UList *)uprv_malloc(sizeof(UList));
if (newList == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
newList->curr = NULL;
newList->head = NULL;
newList->tail = NULL;
newList->size = 0;
newList->currentIndex = -1;
return newList;
}
/*
* Function called by addItemEndList or addItemBeginList when the first item is added to the list.
* This function properly sets the pointers for the first item added.
*/
void ulist_addFirstItem(UList *list, UListNode *newItem) {
newItem->next = NULL;
newItem->previous = NULL;
list->head = newItem;
list->tail = newItem;
list->currentIndex = 0;
}
U_CAPI void U_EXPORT2 ulist_addItemEndList(UList *list, const void *data, UBool forceDelete, UErrorCode *status) {
UListNode *newItem = NULL;
if (U_FAILURE(*status) || list == NULL || data == NULL) {
return;
}
newItem = (UListNode *)uprv_malloc(sizeof(UListNode));
if (newItem == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
return;
}
newItem->data = data;
newItem->forceDelete = forceDelete;
if (list->size == 0) {
ulist_addFirstItem(list, newItem);
} else {
newItem->next = NULL;
newItem->previous = list->tail;
list->tail->next = newItem;
list->tail = newItem;
}
list->size++;
}
U_CAPI void U_EXPORT2 ulist_addItemBeginList(UList *list, const void *data, UBool forceDelete, UErrorCode *status) {
UListNode *newItem = NULL;
if (U_FAILURE(*status) || list == NULL || data == NULL) {
return;
}
newItem = (UListNode *)uprv_malloc(sizeof(UListNode));
if (newItem == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
return;
}
newItem->data = data;
newItem->forceDelete = forceDelete;
if (list->size == 0) {
ulist_addFirstItem(list, newItem);
} else {
newItem->previous = NULL;
newItem->next = list->head;
list->head->previous = newItem;
list->head = newItem;
list->currentIndex++;
}
list->size++;
}
U_CAPI UBool U_EXPORT2 ulist_containsString(const UList *list, const char *data, int32_t length) {
UBool result = FALSE;
const UListNode *pointer = NULL;
if (list != NULL && list->size != 0) {
pointer = list->head;
while (pointer != NULL) {
if (length == uprv_strlen(pointer->data)) {
if (uprv_memcmp(data, pointer->data, length) == 0) {
result = TRUE;
break;
}
}
pointer = pointer->next;
}
}
return result;
}
U_CAPI void *U_EXPORT2 ulist_getNext(UList *list) {
UListNode *curr = NULL;
if (list == NULL || list->curr == NULL) {
return NULL;
}
curr = list->curr;
list->curr = curr->next;
list->currentIndex++;
return curr->data;
}
U_CAPI int32_t U_EXPORT2 ulist_getListSize(const UList *list) {
if (list != NULL) {
return list->size;
}
return -1;
}
U_CAPI void U_EXPORT2 ulist_resetList(UList *list) {
if (list != NULL) {
list->curr = list->head;
list->currentIndex = 0;
}
}
U_CAPI void U_EXPORT2 ulist_deleteList(UList *list) {
UListNode *listHead = NULL;
UListNode *listPointer = NULL;
if (list != NULL) {
listHead = list->head;
listPointer = listHead;
while (listHead != NULL) {
listPointer = listHead->next;
if (listHead->forceDelete) {
uprv_free(listHead->data);
}
uprv_free(listHead);
listHead = listPointer;
}
uprv_free(list);
list = NULL;
}
}
U_CAPI void U_EXPORT2 ulist_close_keyword_values_iterator(UEnumeration *en) {
UList *list = (UList *)(en->context);
ulist_deleteList(list);
uprv_free(en);
}
U_CAPI int32_t U_EXPORT2 ulist_count_keyword_values(UEnumeration *en, UErrorCode *status) {
if (U_FAILURE(*status)) {
return -1;
}
UList *list = (UList *)(en->context);
return ulist_getListSize(list);
}
U_CAPI const char * U_EXPORT2 ulist_next_keyword_value(UEnumeration *en, int32_t *resultLength, UErrorCode *status) {
if (U_FAILURE(*status)) {
return NULL;
}
const char *result;
UList *list = (UList *)(en->context);
result = (const char *)ulist_getNext(list);
/* TODO: resultLength; */
return result;
}
U_CAPI void U_EXPORT2 ulist_reset_keyword_values_iterator(UEnumeration *en, UErrorCode *status) {
if (U_FAILURE(*status)) {
return ;
}
UList *list = (UList *)(en->context);
ulist_resetList(list);
}
U_CAPI UList * U_EXPORT2 ulist_getListFromEnum(UEnumeration *en) {
return (UList *)(en->context);
}

View File

@ -0,0 +1,46 @@
/*
******************************************************************************
* Copyright (C) 2009, International Business Machines
* Corporation and others. All Rights Reserved.
******************************************************************************
*/
#ifndef ULIST_H
#define ULIST_H
#include "unicode/utypes.h"
#include "unicode/uenum.h"
struct UList;
typedef struct UList UList;
U_CAPI UList * U_EXPORT2 ulist_createEmptyList(UErrorCode *status);
U_CAPI void U_EXPORT2 ulist_addItemEndList(UList *list, const void *data, UBool forceDelete, UErrorCode *status);
U_CAPI void U_EXPORT2 ulist_addItemBeginList(UList *list, const void *data, UBool forceDelete, UErrorCode *status);
U_CAPI UBool U_EXPORT2 ulist_containsString(const UList *list, const char *data, int32_t length);
U_CAPI void *U_EXPORT2 ulist_getNext(UList *list);
U_CAPI int32_t U_EXPORT2 ulist_getListSize(const UList *list);
U_CAPI void U_EXPORT2 ulist_resetList(UList *list);
U_CAPI void U_EXPORT2 ulist_deleteList(UList *list);
/*
* The following are for use when creating UEnumeration object backed by UList.
*/
U_CAPI void U_EXPORT2 ulist_close_keyword_values_iterator(UEnumeration *en);
U_CAPI int32_t U_EXPORT2 ulist_count_keyword_values(UEnumeration *en, UErrorCode *status);
U_CAPI const char * U_EXPORT2 ulist_next_keyword_value(UEnumeration* en, int32_t *resultLength, UErrorCode* status);
U_CAPI void U_EXPORT2 ulist_reset_keyword_values_iterator(UEnumeration* en, UErrorCode* status);
U_CAPI UList * U_EXPORT2 ulist_getListFromEnum(UEnumeration *en);
#endif

View File

@ -20,6 +20,8 @@
#include "cmemory.h"
#include "cstring.h"
#include "ustrenum.h"
#include "uenumimp.h"
#include "ulist.h"
U_NAMESPACE_USE
@ -531,10 +533,146 @@ ucal_getType(const UCalendar *cal, UErrorCode* status)
return ((Calendar*)cal)->getType();
}
static const UEnumeration defaultKeywordValues = {
NULL,
NULL,
ulist_close_keyword_values_iterator,
ulist_count_keyword_values,
uenum_unextDefault,
ulist_next_keyword_value,
ulist_reset_keyword_values_iterator
};
static const char * const CAL_TYPES[] = {
"gregorian",
"japanese",
"buddhist",
"roc",
"persian",
"islamic-civil",
"islamic",
"hebrew",
"chinese",
"indian",
"coptic",
"ethiopic",
"ethiopic-amete-alem",
NULL
};
#define CALPREF_LENGTH 39
#define CALPREF_MAX_NUM_KEYWORDS 4
static const char * const CALPREF[CALPREF_LENGTH][CALPREF_MAX_NUM_KEYWORDS+1] = {
{ "001", "gregorian", NULL, NULL, NULL },
{ "AE", "gregorian", "islamic", "islamic-civil", NULL },
{ "AF", "gregorian", "islamic", "islamic-civil", "persian" },
{ "BH", "gregorian", "islamic", "islamic-civil", NULL },
{ "CN", "gregorian", "chinese", NULL, NULL },
{ "CX", "gregorian", "chinese", NULL, NULL },
{ "DJ", "gregorian", "islamic", "islamic-civil", NULL },
{ "DZ", "gregorian", "islamic", "islamic-civil", NULL },
{ "EG", "gregorian", "islamic", "islamic-civil", "coptic" },
{ "EH", "gregorian", "islamic", "islamic-civil", NULL },
{ "ER", "gregorian", "islamic", "islamic-civil", NULL },
{ "ET", "gregorian", "ethiopic", "ethiopic-amete-alem", NULL },
{ "HK", "gregorian", "chinese", NULL, NULL },
{ "IL", "gregorian", "hebrew", NULL, NULL },
{ "IL", "gregorian", "islamic", "islamic-civil", NULL },
{ "IN", "gregorian", "indian", NULL, NULL },
{ "IQ", "gregorian", "islamic", "islamic-civil", NULL },
{ "IR", "gregorian", "islamic", "islamic-civil", "persian" },
{ "JO", "gregorian", "islamic", "islamic-civil", NULL },
{ "JP", "gregorian", "japanese", NULL, NULL },
{ "KM", "gregorian", "islamic", "islamic-civil", NULL },
{ "KW", "gregorian", "islamic", "islamic-civil", NULL },
{ "LB", "gregorian", "islamic", "islamic-civil", NULL },
{ "LY", "gregorian", "islamic", "islamic-civil", NULL },
{ "MA", "gregorian", "islamic", "islamic-civil", NULL },
{ "MO", "gregorian", "chinese", NULL, NULL },
{ "MR", "gregorian", "islamic", "islamic-civil", NULL },
{ "OM", "gregorian", "islamic", "islamic-civil", NULL },
{ "PS", "gregorian", "islamic", "islamic-civil", NULL },
{ "QA", "gregorian", "islamic", "islamic-civil", NULL },
{ "SA", "gregorian", "islamic", "islamic-civil", NULL },
{ "SD", "gregorian", "islamic", "islamic-civil", NULL },
{ "SG", "gregorian", "chinese", NULL, NULL },
{ "SY", "gregorian", "islamic", "islamic-civil", NULL },
{ "TD", "gregorian", "islamic", "islamic-civil", NULL },
{ "TH", "buddhist", "gregorian", NULL, NULL },
{ "TN", "gregorian", "islamic", "islamic-civil", NULL },
{ "TW", "gregorian", "roc", "chinese", NULL },
{ "YE", "gregorian", "islamic", "islamic-civl", NULL }
};
#define MAX_LOC_SIZE_KEYWORD_VALUES 64
#define MAX_LENGTH_KEYWORD_VALUE 64
U_CAPI UEnumeration* U_EXPORT2
ucal_getKeywordValuesForLocale(const char *key, const char* locale, UBool commonlyUsed, UErrorCode *status) {
//TODO: provide actual implementation!
return NULL;
// Resolve region
char prefRegion[MAX_LOC_SIZE_KEYWORD_VALUES];
int32_t prefRegionLength = 0;
prefRegionLength = uloc_getCountry(locale, prefRegion, MAX_LOC_SIZE_KEYWORD_VALUES, status);
if (prefRegionLength == 0) {
char loc[MAX_LOC_SIZE_KEYWORD_VALUES];
int32_t locLength = 0;
locLength = uloc_addLikelySubtags(locale, loc, MAX_LOC_SIZE_KEYWORD_VALUES, status);
prefRegionLength = uloc_getCountry(loc, prefRegion, MAX_LOC_SIZE_KEYWORD_VALUES, status);
}
// Read preferred calendar values from supplementalData calendarPreference
UList *values = ulist_createEmptyList(status);
UEnumeration *en = (UEnumeration *)uprv_malloc(sizeof(UEnumeration));
if (U_FAILURE(*status) || en == NULL) {
if (en == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
} else {
uprv_free(en);
}
ulist_deleteList(values);
return NULL;
}
memcpy(en, &defaultKeywordValues, sizeof(UEnumeration));
en->context = values;
int32_t preferences = 0;
for (int32_t i = 0; i < CALPREF_LENGTH; i++) {
if (uprv_strcmp(prefRegion, CALPREF[i][0]) == 0) {
preferences = i;
break;
}
}
for (int32_t i = 1; CALPREF[preferences][i] != NULL && i <= CALPREF_MAX_NUM_KEYWORDS; i++) {
if (!ulist_containsString(values, CALPREF[preferences][i], uprv_strlen(CALPREF[preferences][i]))) {
ulist_addItemEndList(values, CALPREF[preferences][i], FALSE, status);
if (U_FAILURE(*status)) {
break;
}
}
}
if (U_SUCCESS(*status) && !commonlyUsed) {
// If not commonlyUsed, add other available values
for (int32_t i = 0; CAL_TYPES[i] != NULL; i++) {
if (!ulist_containsString(values, CAL_TYPES[i], uprv_strlen(CAL_TYPES[i]))) {
ulist_addItemEndList(values, CAL_TYPES[i], FALSE, status);
if (U_FAILURE(*status)) {
break;
}
}
}
}
if (U_FAILURE(*status)) {
uenum_close(en);
return NULL;
}
ulist_resetList(values);
return en;
}
#endif /* #if !UCONFIG_NO_FORMATTING */

View File

@ -43,6 +43,8 @@
#include "putilimp.h"
#include "utracimp.h"
#include "cmemory.h"
#include "uenumimp.h"
#include "ulist.h"
U_NAMESPACE_USE
@ -742,11 +744,117 @@ ucol_getKeywordValues(const char *keyword, UErrorCode *status) {
return ures_getKeywordValues(U_ICUDATA_COLL, RESOURCE_NAME, status);
}
static const UEnumeration defaultKeywordValues = {
NULL,
NULL,
ulist_close_keyword_values_iterator,
ulist_count_keyword_values,
uenum_unextDefault,
ulist_next_keyword_value,
ulist_reset_keyword_values_iterator
};
#define DEFAULT_KEYWORD_VALUE_MAX_SIZE 20
#define MAX_LOCALE_SIZE 20
U_CAPI UEnumeration* U_EXPORT2
ucol_getKeywordValuesForLocale(const char* key, const char* locale,
UBool commonlyUsed, UErrorCode* status) {
//TODO: provide actual implementation!
return NULL;
/* Get the locale base name. */
char localeBuffer[MAX_LOCALE_SIZE] = "";
uloc_getBaseName(locale, localeBuffer, MAX_LOCALE_SIZE, status);
/* Create the 2 lists
* -values is the temp location for the keyword values
* -results hold the actual list used by the UEnumeration object
*/
UList *values = ulist_createEmptyList(status);
UList *results = ulist_createEmptyList(status);
UEnumeration *en = (UEnumeration *)uprv_malloc(sizeof(UEnumeration));
if (U_FAILURE(*status) || en == NULL) {
if (en == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
} else {
uprv_free(en);
}
ulist_deleteList(values);
ulist_deleteList(results);
return NULL;
}
memcpy(en, &defaultKeywordValues, sizeof(UEnumeration));
en->context = results;
/* Open the resource bundle for collation with the given locale. */
UResourceBundle bundle, collations, collres, defres;
ures_initStackObject(&bundle);
ures_initStackObject(&collations);
ures_initStackObject(&collres);
ures_initStackObject(&defres);
ures_openFillIn(&bundle, U_ICUDATA_COLL, localeBuffer, status);
while (U_SUCCESS(*status)) {
ures_getByKey(&bundle, RESOURCE_NAME, &collations, status);
ures_resetIterator(&collations);
while (U_SUCCESS(*status) && ures_hasNext(&collations)) {
ures_getNextResource(&collations, &collres, status);
const char *key = ures_getKey(&collres);
/* If the key is default, get the string and store it in results list only
* if results list is empty.
*/
if (uprv_strcmp(key, "default") == 0) {
if (ulist_getListSize(results) == 0) {
char *defcoll = (char *)uprv_malloc(sizeof(char) * DEFAULT_KEYWORD_VALUE_MAX_SIZE);
int32_t defcollLength = DEFAULT_KEYWORD_VALUE_MAX_SIZE;
ures_getNextResource(&collres, &defres, status);
ures_getUTF8String(&defres, defcoll, &defcollLength, TRUE, status);
ulist_addItemBeginList(results, defcoll, TRUE, status);
}
} else {
ulist_addItemEndList(values, key, FALSE, status);
}
}
/* If the locale is "" this is root so exit. */
if (uprv_strlen(localeBuffer) == 0) {
break;
}
/* Get the parent locale and open a new resource bundle. */
uloc_getParent(localeBuffer, localeBuffer, MAX_LOCALE_SIZE, status);
ures_openFillIn(&bundle, U_ICUDATA_COLL, localeBuffer, status);
}
ures_close(&defres);
ures_close(&collres);
ures_close(&collations);
ures_close(&bundle);
if (U_SUCCESS(*status)) {
char *value = NULL;
ulist_resetList(values);
while ((value = (char *)ulist_getNext(values)) != NULL) {
if (!ulist_containsString(results, value, uprv_strlen(value))) {
ulist_addItemEndList(results, value, FALSE, status);
if (U_FAILURE(*status)) {
break;
}
}
}
}
ulist_deleteList(values);
if (U_FAILURE(*status)){
uenum_close(en);
en = NULL;
} else {
ulist_resetList(results);
}
return en;
}
U_CAPI int32_t U_EXPORT2

View File

@ -24,6 +24,7 @@
#include "uenumimp.h"
#include "uhash.h"
#include "uresimp.h"
#include "ulist.h"
//#define UCURR_DEBUG 1
#ifdef UCURR_DEBUG
@ -1976,6 +1977,151 @@ ucurr_forLocaleAndDate(const char* locale,
return resLen;
}
static const UEnumeration defaultKeywordValues = {
NULL,
NULL,
ulist_close_keyword_values_iterator,
ulist_count_keyword_values,
uenum_unextDefault,
ulist_next_keyword_value,
ulist_reset_keyword_values_iterator
};
#define MAX_LOC_SIZE_KEYWORD_VALUES 64
#define MAX_LENGTH_KEYWORD_VALUE 64
U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, const char *locale, UBool commonlyUsed, UErrorCode* status) {
// Resolve region
char prefRegion[MAX_LOC_SIZE_KEYWORD_VALUES];
int32_t prefRegionLength = 0;
prefRegionLength = uloc_getCountry(locale, prefRegion, MAX_LOC_SIZE_KEYWORD_VALUES, status);
if (prefRegionLength == 0) {
char loc[MAX_LOC_SIZE_KEYWORD_VALUES];
int32_t locLength = 0;
locLength = uloc_addLikelySubtags(locale, loc, MAX_LOC_SIZE_KEYWORD_VALUES, status);
prefRegionLength = uloc_getCountry(loc, prefRegion, MAX_LOC_SIZE_KEYWORD_VALUES, status);
}
// Read value from supplementalData
UList *values = ulist_createEmptyList(status);
UList *otherValues = ulist_createEmptyList(status);
UEnumeration *en = (UEnumeration *)uprv_malloc(sizeof(UEnumeration));
if (U_FAILURE(*status) || en == NULL) {
if (en == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
} else {
uprv_free(en);
}
ulist_deleteList(values);
ulist_deleteList(otherValues);
return NULL;
}
memcpy(en, &defaultKeywordValues, sizeof(UEnumeration));
en->context = values;
UResourceBundle *bundle = ures_openDirect(NULL, "supplementalData", status);
ures_getByKey(bundle, "CurrencyMap", bundle, status);
UResourceBundle bundlekey, regbndl, curbndl, to;
ures_initStackObject(&bundlekey);
ures_initStackObject(&regbndl);
ures_initStackObject(&curbndl);
ures_initStackObject(&to);
while (U_SUCCESS(*status) && ures_hasNext(bundle)) {
ures_getNextResource(bundle, &bundlekey, status);
if (U_FAILURE(*status)) {
break;
}
const char *region = ures_getKey(&bundlekey);
UBool isPrefRegion = uprv_strcmp(region, prefRegion) == 0 ? TRUE : FALSE;
if (!isPrefRegion && commonlyUsed) {
// With commonlyUsed=true, we do not put
// currencies for other regionsin the
// result list.
continue;
}
ures_getByKey(bundle, region, &regbndl, status);
if (U_FAILURE(*status)) {
break;
}
while (U_SUCCESS(*status) && ures_hasNext(&regbndl)) {
ures_getNextResource(&regbndl, &curbndl, status);
if (ures_getType(&curbndl) != URES_TABLE) {
// Currently, an empty ARRAY is mixed in.
continue;
}
char *curID = (char *)uprv_malloc(sizeof(char) * MAX_LENGTH_KEYWORD_VALUE);
int32_t curIDLength = MAX_LENGTH_KEYWORD_VALUE;
if (curID == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
break;
}
ures_getUTF8StringByKey(&curbndl, "id", curID, &curIDLength, TRUE, status);
if (U_FAILURE(*status)) {
break;
}
UBool hasTo = FALSE;
ures_getByKey(&curbndl, "to", &to, status);
if (U_FAILURE(*status)) {
// Do nothing here...
*status = U_ZERO_ERROR;
} else {
hasTo = TRUE;
}
if (isPrefRegion && !hasTo && !ulist_containsString(values, curID, uprv_strlen(curID))) {
// Currently active currency for the target country
ulist_addItemEndList(values, curID, TRUE, status);
} else if (!ulist_containsString(otherValues, curID, uprv_strlen(curID)) && !commonlyUsed) {
ulist_addItemEndList(otherValues, curID, TRUE, status);
} else {
uprv_free(curID);
}
}
}
if (U_SUCCESS(*status)) {
if (commonlyUsed) {
if (ulist_getListSize(values) == 0) {
// This could happen if no valid region is supplied in the input
// locale. In this case, we use the CLDR's default.
uenum_close(en);
en = ucurr_getKeywordValuesForLocale(key, "und", TRUE, status);
}
} else {
// Consolidate the list
char *value = NULL;
ulist_resetList(otherValues);
while ((value = (char *)ulist_getNext(otherValues)) != NULL) {
if (!ulist_containsString(values, value, uprv_strlen(value))) {
char *tmpValue = (char *)uprv_malloc(sizeof(char) * MAX_LENGTH_KEYWORD_VALUE);
uprv_memcpy(tmpValue, value, uprv_strlen(value) + 1);
ulist_addItemEndList(values, tmpValue, TRUE, status);
if (U_FAILURE(*status)) {
break;
}
}
}
}
ulist_resetList((UList *)(en->context));
} else {
ulist_deleteList(values);
uprv_free(en);
values = NULL;
en = NULL;
}
ures_close(&to);
ures_close(&curbndl);
ures_close(&regbndl);
ures_close(&bundlekey);
ures_close(bundle);
ulist_deleteList(otherValues);
return en;
}
#endif /* #if !UCONFIG_NO_FORMATTING */
//eof

View File

@ -1,5 +1,5 @@
/********************************************************************
* Copyright (c) 1997-2008 International Business Machines
* Copyright (c) 1997-2009 International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************/
/*****************************************************************************
@ -29,6 +29,7 @@
#include "capitst.h"
#include "ccolltst.h"
#include "putilimp.h"
#include "cstring.h"
static void TestAttribute(void);
static void TestDefault(void);
@ -131,6 +132,7 @@ void addCollAPITest(TestNode** root)
addTest(root, &TestDefault, "tscoll/capitst/TestDefault");
addTest(root, &TestDefaultKeyword, "tscoll/capitst/TestDefaultKeyword");
addTest(root, &TestOpenVsOpenRules, "tscoll/capitst/TestOpenVsOpenRules");
addTest(root, &TestGetKeywordValuesForLocale, "tscoll/capitst/TestGetKeywordValuesForLocale");
}
void TestGetSetAttr(void) {
@ -2269,5 +2271,76 @@ static void TestDefaultKeyword(void) {
ucol_close(coll);
}
static void TestGetKeywordValuesForLocale(void) {
#define PREFERRED_SIZE 16
#define MAX_NUMBER_OF_KEYWORDS 6
const char *PREFERRED[PREFERRED_SIZE][MAX_NUMBER_OF_KEYWORDS+1] = {
{ "und", "standard", NULL, NULL, NULL, NULL, NULL },
{ "en_US", "standard", NULL, NULL, NULL, NULL, NULL },
{ "en_029", "standard", NULL, NULL, NULL, NULL, NULL },
{ "de_DE", "standard", "phonebook", NULL, NULL, NULL, NULL },
{ "de_Latn_DE", "standard", "phonebook", NULL, NULL, NULL, NULL },
{ "zh", "pinyin", "big5han", "gb2312han", "standard", "stroke", "unihan" },
{ "zh_Hans", "pinyin", "big5han", "gb2312han", "standard", "stroke", "unihan" },
{ "zh_CN", "pinyin", "big5han", "gb2312han", "standard", "stroke", "unihan" },
{ "zh_Hant", "stroke", "big5han", "gb2312han", "pinyin", "standard", "unihan" },
{ "zh_TW", "stroke", "big5han", "gb2312han", "pinyin", "standard", "unihan" },
{ "zh__PINYIN", "pinyin", "big5han", "gb2312han", "standard", "stroke", "unihan" },
{ "es_ES", "standard", "traditional", NULL, NULL, NULL, NULL },
{ "es__TRADITIONAL","traditional", "standard", NULL, NULL, NULL, NULL },
{ "und@collation=phonebook", "standard", NULL, NULL, NULL, NULL, NULL },
{ "de_DE@collation=big5han", "standard", "phonebook", NULL, NULL, NULL, NULL },
{ "zzz@collation=xxx", "standard", NULL, NULL, NULL, NULL, NULL }
};
const int32_t expectedLength[PREFERRED_SIZE] = { 1, 1, 1, 2, 2, 6, 6, 6, 6, 6, 6, 2, 2, 1, 2, 1 };
UErrorCode status = U_ZERO_ERROR;
UEnumeration *keywordValues = NULL;
int32_t i, n;
UBool errorOccurred = FALSE;
for (i = 0; i < PREFERRED_SIZE; i++) {
const char *locale = PREFERRED[i][0];
const char *value = NULL;
int32_t valueLength = 0;
int32_t size = 0;
keywordValues = ucol_getKeywordValuesForLocale("collation", locale, TRUE, &status);
if (keywordValues == NULL || U_FAILURE(status)) {
log_err("Error getting keyword values: %s\n", u_errorName(status));
break;
}
size = uenum_count(keywordValues, &status);
if (size == expectedLength[i]) {
for (n = 0; n < expectedLength[i]; n++) {
if ((value = uenum_next(keywordValues, valueLength, &status)) != NULL && U_SUCCESS(status)) {
if (uprv_strcmp(value, PREFERRED[i][n+1]) != 0) {
log_err("Keyword values differ: Got [%s] Expected [%s] for locale: %s\n", value, PREFERRED[i][n+1], locale);
errorOccurred = TRUE;
break;
}
} else {
log_err("While getting keyword value from locale: %s got this error: %s\n", locale, u_errorName(status));
errorOccurred = TRUE;
break;
}
}
if (errorOccurred) {
break;
}
} else {
log_err("Number of keywords (%d) does not match expected size (%d) for locale: %s\n", size, expectedLength[i], locale);
break;
}
uenum_close(keywordValues);
keywordValues = NULL;
}
if (keywordValues != NULL) {
uenum_close(keywordValues);
}
}
#endif /* #if !UCONFIG_NO_COLLATION */

View File

@ -1,5 +1,5 @@
/********************************************************************
* Copyright (c) 1997-2008 International Business Machines
* Copyright (c) 1997-2009 International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************/
/********************************************************************************
@ -124,6 +124,11 @@
* Test funny stuff with open binary
*/
static void TestOpenBinary(void);
/**
* Test getKeywordValuesForLocale API
*/
static void TestGetKeywordValuesForLocale(void);
#endif /* #if !UCONFIG_NO_COLLATION */
#endif

View File

@ -1,5 +1,5 @@
/********************************************************************
* Copyright (c) 1997-2008, International Business Machines
* Copyright (c) 1997-2009, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************
*
@ -28,6 +28,7 @@
#include "ccaltst.h"
#include "cformtst.h"
#include "cstring.h"
#include "ulist.h"
void TestGregorianChange(void);
@ -44,6 +45,7 @@ void addCalTest(TestNode** root)
addTest(root, &TestDOWProgression, "tsformat/ccaltst/TestDOWProgression");
addTest(root, &TestGMTvsLocal, "tsformat/ccaltst/TestGMTvsLocal");
addTest(root, &TestGregorianChange, "tsformat/ccaltst/TestGregorianChange");
addTest(root, &TestGetKeywordValuesForLocale, "tsformat/ccaltst/TestGetKeywordValuesForLocale");
}
/* "GMT" */
@ -1384,4 +1386,94 @@ void TestGregorianChange() {
ucal_close(cal);
}
static void TestGetKeywordValuesForLocale() {
#define PREFERRED_SIZE 13
#define MAX_NUMBER_OF_KEYWORDS 4
const char *PREFERRED[PREFERRED_SIZE][MAX_NUMBER_OF_KEYWORDS+1] = {
{ "root", "gregorian", NULL, NULL, NULL },
{ "und", "gregorian", NULL, NULL, NULL },
{ "en_US", "gregorian", NULL, NULL, NULL },
{ "en_029", "gregorian", NULL, NULL, NULL },
{ "th_TH", "buddhist", "gregorian", NULL, NULL },
{ "und_TH", "buddhist", "gregorian", NULL, NULL },
{ "en_TH", "buddhist", "gregorian", NULL, NULL },
{ "he_IL", "gregorian", "hebrew", NULL, NULL },
{ "ar_EG", "gregorian", "islamic", "islamic-civil", "coptic" },
{ "ja", "gregorian", "japanese", NULL, NULL },
{ "ps_Guru_IN", "gregorian", "indian", NULL, NULL },
{ "th@calendar=gregorian", "buddhist", "gregorian", NULL, NULL },
{ "en@calendar=islamic", "gregorian", NULL, NULL, NULL },
};
const int32_t EXPECTED_SIZE[PREFERRED_SIZE] = { 1, 1, 1, 1, 2, 2, 2, 2, 4, 2, 2, 2, 1 };
UErrorCode status = U_ZERO_ERROR;
int32_t i;
UEnumeration *ALL = ucal_getKeywordValuesForLocale("calendar", uloc_getDefault(), FALSE, &status);
if (U_SUCCESS(status)) {
for (i = 0; i < PREFERRED_SIZE; i++) {
UEnumeration *pref = NULL;
UEnumeration *all = NULL;
const char *loc = PREFERRED[i][0];
pref = ucal_getKeywordValuesForLocale("calendar", loc, TRUE, &status);
UBool matchPref = FALSE;
UBool matchAll = FALSE;
int32_t size, j;
const char *value = NULL;
int32_t valueLength = 0;
if (U_SUCCESS(status) && uenum_count(pref, &status) == EXPECTED_SIZE[i]) {
matchPref = TRUE;
for (j = 0; j < EXPECTED_SIZE[i]; j++) {
if ((value = uenum_next(pref, &valueLength, &status)) != NULL && U_SUCCESS(status)) {
if (uprv_strcmp(value, PREFERRED[i][j+1]) != 0) {
matchPref = FALSE;
break;
}
} else {
matchPref = FALSE;
log_err("ERROR getting keyword value for locale \"%s\"\n", loc);
break;
}
}
}
if (!matchPref) {
log_err("FAIL: Preferred values for locale \"%s\" does not match expected.\n", loc);
break;
}
uenum_close(pref);
all = ucal_getKeywordValuesForLocale("calendar", loc, FALSE, &status);
size = uenum_count(all, &status);
if (U_SUCCESS(status) && size == uenum_count(ALL, &status)) {
matchAll = TRUE;
UList *ALLList = ulist_getListFromEnum(ALL);
for (j = 0; j < size; j++) {
if ((value = uenum_next(all, &valueLength, &status)) != NULL && U_SUCCESS(status)) {
if (!ulist_containsString(ALLList, value, uprv_strlen(value))) {
log_err("Locale %s have %s not in ALL\n", loc, value);
matchAll = FALSE;
break;
}
} else {
matchAll = FALSE;
log_err("ERROR getting \"all\" keyword value for locale \"%s\"\n", loc);
break;
}
}
}
if (!matchAll) {
log_err("FAIL: All values for locale \"%s\" does not match expected.\n", loc);
}
uenum_close(all);
}
} else {
log_err("Failed to get ALL keyword values for default locale.\n");
}
uenum_close(ALL);
}
#endif /* #if !UCONFIG_NO_FORMATTING */

View File

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2001, International Business Machines Corporation and
* Copyright (c) 1997-2009, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/********************************************************************************
@ -56,6 +56,10 @@
* test subroutine used by TestGMTvsLocal()
*/
static void testZones(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
/**
* Test getKeywordValuesForLocale API
*/
static void TestGetKeywordValuesForLocale(void);
/*Internal functions used*/
/**

View File

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2008, International Business Machines Corporation
* Copyright (c) 1997-2009, International Business Machines Corporation
* and others. All Rights Reserved.
********************************************************************/
/*******************************************************************************
@ -29,6 +29,7 @@
#include "cnmdptst.h"
#include "cmemory.h"
#include "cstring.h"
#include "ulist.h"
#define CHECK(status,str) if (U_FAILURE(status)) { log_err("FAIL: %s\n", str); return; }
@ -50,6 +51,7 @@ void addNumFrDepTest(TestNode** root)
addTest(root, &TestSecondaryGrouping, "tsformat/cnmdptst/TestSecondaryGrouping");
addTest(root, &TestCurrencyKeywords, "tsformat/cnmdptst/TestCurrencyKeywords");
addTest(root, &TestRounding5350, "tsformat/cnmdptst/TestRounding5350");
addTest(root, &TestGetKeywordValuesForLocale, "tsformat/cnmdptst/TestGetKeywordValuesForLocale");
}
/*Test Various format patterns*/
@ -862,6 +864,103 @@ static void TestCurrencyKeywords(void)
}
}
static void TestGetKeywordValuesForLocale(void) {
#define PREFERRED_SIZE 13
#define MAX_NUMBER_OF_KEYWORDS 3
const char *PREFERRED[PREFERRED_SIZE][MAX_NUMBER_OF_KEYWORDS] = {
{ "root", "USD", NULL },
{ "und", "USD", NULL },
{ "und_ZZ", "USD", NULL },
{ "en_US", "USD", NULL },
{ "en_029", "USD", NULL },
{ "en_TH", "THB", NULL },
{ "de", "EUR", NULL },
{ "de_DE", "EUR", NULL },
{ "ar", "EGP", NULL },
{ "ar_PS", "JOD", "ILS" },
{ "en@currency=CAD", "USD", NULL },
{ "fr@currency=zzz", "EUR", NULL },
{ "de_DE@currency=DEM", "EUR", NULL },
};
const int32_t EXPECTED_SIZE[PREFERRED_SIZE] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1
};
UErrorCode status = U_ZERO_ERROR;
int32_t i;
UEnumeration *ALL = ucurr_getKeywordValuesForLocale("currency", uloc_getDefault(), FALSE, &status);
if (ALL == NULL) {
log_err("ERROR getting keyword value for default locale.\n");
return;
}
for (i = 0; i < PREFERRED_SIZE; i++) {
UEnumeration *pref = NULL;
UEnumeration *all = NULL;
const char *loc = PREFERRED[i][0];
pref = ucurr_getKeywordValuesForLocale("currency", loc, TRUE, &status);
UBool matchPref = FALSE;
UBool matchAll = FALSE;
int32_t size = 0, j;
const char *value = NULL, *allValue = NULL;
int32_t valueLength = 0, allValueLength = 0;
size = uenum_count(pref, &status);
if (size == EXPECTED_SIZE[i]) {
matchPref = TRUE;
for (j = 0; j < size; j++) {
if ((value = uenum_next(pref, &valueLength, &status)) != NULL && U_SUCCESS(status)) {
if (uprv_strcmp(value, PREFERRED[i][j+1]) != 0) {
matchPref = FALSE;
break;
}
} else {
matchPref = FALSE;
log_err("ERROR getting keyword value for locale \"%s\"\n", loc);
break;
}
}
}
if (!matchPref) {
log_err("FAIL: Preferred values for locale \"%s\" does not match expected.\n", loc);
break;
}
uenum_close(pref);
all = ucurr_getKeywordValuesForLocale("currency", loc, FALSE, &status);
size = uenum_count(all, &status);
if (U_SUCCESS(status) && size == uenum_count(ALL, &status)) {
matchAll = TRUE;
UList *ALLList = ulist_getListFromEnum(ALL);
for (j = 0; j < size; j++) {
if ((value = uenum_next(all, &valueLength, &status)) != NULL && U_SUCCESS(status)) {
if (!ulist_containsString(ALLList, value, uprv_strlen(value))) {
log_err("Locale %s have %s not in ALL\n", loc, value);
matchAll = FALSE;
break;
}
} else {
matchAll = FALSE;
log_err("ERROR getting \"all\" keyword value for locale \"%s\"\n", loc);
break;
}
}
}
if (!matchAll) {
log_err("FAIL: All values for locale \"%s\" does not match expected.\n", loc);
}
uenum_close(all);
}
uenum_close(ALL);
}
/**
* Test proper handling of rounding modes.
*/

View File

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2003, 2007 International Business Machines Corporation and
* Copyright (c) 1997-2003, 2007-2009 International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/********************************************************************************
@ -55,6 +55,8 @@ static void roundingTest2(UNumberFormat*, double, int32_t, const char*);
static void TestCurrencyKeywords(void);
static void TestGetKeywordValuesForLocale(void);
#endif /* #if !UCONFIG_NO_FORMATTING */
#endif