mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 07:39:16 +00:00
ICU-12520 ucol_getKeywordValuesForLocale() resource data enumeration
X-SVN-Rev: 38674
This commit is contained in:
parent
fef70d16f0
commit
3947687fcc
3 changed files with 117 additions and 126 deletions
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 2009-2014, International Business Machines
|
||||
* Copyright (C) 2009-2016, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
@ -63,18 +63,45 @@ static void ulist_addFirstItem(UList *list, UListNode *newItem) {
|
|||
newItem->previous = NULL;
|
||||
list->head = newItem;
|
||||
list->tail = newItem;
|
||||
}
|
||||
|
||||
static void ulist_removeItem(UList *list, UListNode *p) {
|
||||
if (p->previous == NULL) {
|
||||
// p is the list head.
|
||||
list->head = p->next;
|
||||
} else {
|
||||
p->previous->next = p->next;
|
||||
}
|
||||
if (p->next == NULL) {
|
||||
// p is the list tail.
|
||||
list->tail = p->previous;
|
||||
} else {
|
||||
p->next->previous = p->previous;
|
||||
}
|
||||
list->curr = NULL;
|
||||
list->currentIndex = 0;
|
||||
--list->size;
|
||||
if (p->forceDelete) {
|
||||
uprv_free(p->data);
|
||||
}
|
||||
uprv_free(p);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (forceDelete) {
|
||||
uprv_free((void *)data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
newItem = (UListNode *)uprv_malloc(sizeof(UListNode));
|
||||
if (newItem == NULL) {
|
||||
if (forceDelete) {
|
||||
uprv_free((void *)data);
|
||||
}
|
||||
*status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
|
@ -97,11 +124,17 @@ U_CAPI void U_EXPORT2 ulist_addItemBeginList(UList *list, const void *data, UBoo
|
|||
UListNode *newItem = NULL;
|
||||
|
||||
if (U_FAILURE(*status) || list == NULL || data == NULL) {
|
||||
if (forceDelete) {
|
||||
uprv_free((void *)data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
newItem = (UListNode *)uprv_malloc(sizeof(UListNode));
|
||||
if (newItem == NULL) {
|
||||
if (forceDelete) {
|
||||
uprv_free((void *)data);
|
||||
}
|
||||
*status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
|
@ -122,25 +155,29 @@ U_CAPI void U_EXPORT2 ulist_addItemBeginList(UList *list, const void *data, UBoo
|
|||
}
|
||||
|
||||
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 (list != NULL) {
|
||||
for (const UListNode *pointer = list->head; pointer != NULL; pointer = pointer->next) {
|
||||
if (length == uprv_strlen(pointer->data)) {
|
||||
if (uprv_memcmp(data, pointer->data, length) == 0) {
|
||||
result = TRUE;
|
||||
break;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
pointer = pointer->next;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
U_CAPI UBool U_EXPORT2 ulist_removeString(UList *list, const char *data) {
|
||||
if (list != NULL) {
|
||||
for (UListNode *pointer = list->head; pointer != NULL; pointer = pointer->next) {
|
||||
if (uprv_strcmp(data, pointer->data) == 0) {
|
||||
ulist_removeItem(list, pointer);
|
||||
// Remove only the first occurrence, like Java LinkedList.remove(Object).
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
U_CAPI void *U_EXPORT2 ulist_getNext(UList *list) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 2009, International Business Machines
|
||||
* Copyright (C) 2009-2016, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
@ -22,6 +22,8 @@ U_CAPI void U_EXPORT2 ulist_addItemBeginList(UList *list, const void *data, UBoo
|
|||
|
||||
U_CAPI UBool U_EXPORT2 ulist_containsString(const UList *list, const char *data, int32_t length);
|
||||
|
||||
U_CAPI UBool U_EXPORT2 ulist_removeString(UList *list, const char *data);
|
||||
|
||||
U_CAPI void *U_EXPORT2 ulist_getNext(UList *list);
|
||||
|
||||
U_CAPI int32_t U_EXPORT2 ulist_getListSize(const UList *list);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1996-2014, International Business Machines
|
||||
* Copyright (C) 1996-2016, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
* file name: ucol_res.cpp
|
||||
|
@ -34,11 +34,13 @@
|
|||
#include "unicode/uloc.h"
|
||||
#include "unicode/unistr.h"
|
||||
#include "unicode/ures.h"
|
||||
#include "charstr.h"
|
||||
#include "cmemory.h"
|
||||
#include "cstring.h"
|
||||
#include "collationdatareader.h"
|
||||
#include "collationroot.h"
|
||||
#include "collationtailoring.h"
|
||||
#include "resource.h"
|
||||
#include "putilimp.h"
|
||||
#include "uassert.h"
|
||||
#include "ucln_in.h"
|
||||
|
@ -501,8 +503,6 @@ U_CAPI UCollator*
|
|||
ucol_open(const char *loc,
|
||||
UErrorCode *status)
|
||||
{
|
||||
U_NAMESPACE_USE
|
||||
|
||||
UTRACE_ENTRY_OC(UTRACE_UCOL_OPEN);
|
||||
UTRACE_DATA1(UTRACE_INFO, "locale = \"%s\"", loc);
|
||||
UCollator *result = NULL;
|
||||
|
@ -523,8 +523,6 @@ ucol_getDisplayName( const char *objLoc,
|
|||
int32_t resultLength,
|
||||
UErrorCode *status)
|
||||
{
|
||||
U_NAMESPACE_USE
|
||||
|
||||
if(U_FAILURE(*status)) return -1;
|
||||
UnicodeString dst;
|
||||
if(!(result==NULL && resultLength==0)) {
|
||||
|
@ -558,8 +556,6 @@ ucol_countAvailable()
|
|||
#if !UCONFIG_NO_SERVICE
|
||||
U_CAPI UEnumeration* U_EXPORT2
|
||||
ucol_openAvailableLocales(UErrorCode *status) {
|
||||
U_NAMESPACE_USE
|
||||
|
||||
// This is a wrapper over Collator::getAvailableLocales()
|
||||
if (U_FAILURE(*status)) {
|
||||
return NULL;
|
||||
|
@ -615,119 +611,75 @@ static const UEnumeration defaultKeywordValues = {
|
|||
ulist_reset_keyword_values_iterator
|
||||
};
|
||||
|
||||
#include <stdio.h>
|
||||
namespace {
|
||||
|
||||
struct KeywordsSink : public ResourceSink {
|
||||
public:
|
||||
KeywordsSink(UErrorCode &errorCode) :
|
||||
values(ulist_createEmptyList(&errorCode)), hasDefault(FALSE) {}
|
||||
virtual ~KeywordsSink();
|
||||
|
||||
virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/,
|
||||
UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
ResourceTable collations = value.getTable(errorCode);
|
||||
for (int32_t i = 0; collations.getKeyAndValue(i, key, value); ++i) {
|
||||
UResType type = value.getType();
|
||||
if (type == URES_STRING) {
|
||||
if (!hasDefault && uprv_strcmp(key, "default") == 0) {
|
||||
CharString defcoll;
|
||||
defcoll.appendInvariantChars(value.getUnicodeString(errorCode), errorCode);
|
||||
if (U_SUCCESS(errorCode) && !defcoll.isEmpty()) {
|
||||
char *ownedDefault = uprv_strdup(defcoll.data());
|
||||
if (ownedDefault == NULL) {
|
||||
errorCode = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
ulist_removeString(values, defcoll.data());
|
||||
ulist_addItemBeginList(values, ownedDefault, TRUE, &errorCode);
|
||||
hasDefault = TRUE;
|
||||
}
|
||||
}
|
||||
} else if (type == URES_TABLE && uprv_strncmp(key, "private-", 8) != 0) {
|
||||
if (!ulist_containsString(values, key, (int32_t)uprv_strlen(key))) {
|
||||
ulist_addItemEndList(values, key, FALSE, &errorCode);
|
||||
}
|
||||
}
|
||||
if (U_FAILURE(errorCode)) { return; }
|
||||
}
|
||||
}
|
||||
|
||||
UList *values;
|
||||
UBool hasDefault;
|
||||
};
|
||||
|
||||
KeywordsSink::~KeywordsSink() {
|
||||
ulist_deleteList(values);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
U_CAPI UEnumeration* U_EXPORT2
|
||||
ucol_getKeywordValuesForLocale(const char* /*key*/, const char* locale,
|
||||
UBool /*commonlyUsed*/, UErrorCode* status) {
|
||||
/* Get the locale base name. */
|
||||
char localeBuffer[ULOC_FULLNAME_CAPACITY] = "";
|
||||
uloc_getBaseName(locale, localeBuffer, sizeof(localeBuffer), status);
|
||||
// Note: The parameter commonlyUsed is not used.
|
||||
// The switch is in the method signature for consistency
|
||||
// with other locale services.
|
||||
|
||||
// Read available collation values from collation bundles.
|
||||
LocalUResourceBundlePointer bundle(ures_open(U_ICUDATA_COLL, locale, status));
|
||||
KeywordsSink sink(*status);
|
||||
ures_getAllItemsWithFallback(bundle.getAlias(), RESOURCE_NAME, sink, *status);
|
||||
if (U_FAILURE(*status)) { return NULL; }
|
||||
|
||||
/* 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);
|
||||
if (en == NULL) {
|
||||
*status = U_MEMORY_ALLOCATION_ERROR;
|
||||
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) * ULOC_KEYWORDS_CAPACITY);
|
||||
int32_t defcollLength = ULOC_KEYWORDS_CAPACITY;
|
||||
|
||||
ures_getNextResource(&collres, &defres, status);
|
||||
#if U_CHARSET_FAMILY==U_ASCII_FAMILY
|
||||
/* optimize - use the utf-8 string */
|
||||
ures_getUTF8String(&defres, defcoll, &defcollLength, TRUE, status);
|
||||
#else
|
||||
{
|
||||
const UChar* defString = ures_getString(&defres, &defcollLength, status);
|
||||
if(U_SUCCESS(*status)) {
|
||||
if(defcollLength+1 > ULOC_KEYWORDS_CAPACITY) {
|
||||
*status = U_BUFFER_OVERFLOW_ERROR;
|
||||
} else {
|
||||
u_UCharsToChars(defString, defcoll, defcollLength+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ulist_addItemBeginList(results, defcoll, TRUE, status);
|
||||
}
|
||||
} else if (uprv_strncmp(key, "private-", 8) != 0) {
|
||||
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, sizeof(localeBuffer), 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, (int32_t)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);
|
||||
}
|
||||
|
||||
en->context = sink.values;
|
||||
sink.values = NULL; // Avoid deletion in the sink destructor.
|
||||
return en;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue