| Index: source/i18n/ucol_res.cpp
|
| diff --git a/source/i18n/ucol_res.cpp b/source/i18n/ucol_res.cpp
|
| index 55138ae0ecf85795486f2fc42f79f21d13516202..314b766ee6db02c3c382dab666ec97808c8231a5 100644
|
| --- a/source/i18n/ucol_res.cpp
|
| +++ b/source/i18n/ucol_res.cpp
|
| @@ -1,6 +1,8 @@
|
| +// Copyright (C) 2016 and later: Unicode, Inc. and others.
|
| +// License & terms of use: http://www.unicode.org/copyright.html
|
| /*
|
| *******************************************************************************
|
| -* 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 +36,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"
|
| @@ -74,9 +78,7 @@ ucol_res_cleanup() {
|
| return TRUE;
|
| }
|
|
|
| -U_CDECL_END
|
| -
|
| -void
|
| +void U_CALLCONV
|
| CollationLoader::loadRootRules(UErrorCode &errorCode) {
|
| if(U_FAILURE(errorCode)) { return; }
|
| rootBundle = ures_open(U_ICUDATA_COLL, kRootLocaleName, &errorCode);
|
| @@ -90,6 +92,8 @@ CollationLoader::loadRootRules(UErrorCode &errorCode) {
|
| ucln_i18n_registerCleanup(UCLN_I18N_UCOL_RES, ucol_res_cleanup);
|
| }
|
|
|
| +U_CDECL_END
|
| +
|
| void
|
| CollationLoader::appendRootRules(UnicodeString &s) {
|
| UErrorCode errorCode = U_ZERO_ERROR;
|
| @@ -501,8 +505,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 +525,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 +558,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 +613,75 @@ static const UEnumeration defaultKeywordValues = {
|
| ulist_reset_keyword_values_iterator
|
| };
|
|
|
| -#include <stdio.h>
|
| -
|
| -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);
|
| -
|
| - /* 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;
|
| - }
|
| +namespace {
|
|
|
| - 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);
|
| - }
|
| - }
|
| +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;
|
| }
|
| -#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;
|
| + } 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);
|
| +}
|
|
|
| - if (U_FAILURE(*status)){
|
| - uenum_close(en);
|
| - en = NULL;
|
| - } else {
|
| - ulist_resetList(results);
|
| - }
|
| +} // namespace
|
| +
|
| +U_CAPI UEnumeration* U_EXPORT2
|
| +ucol_getKeywordValuesForLocale(const char* /*key*/, const char* locale,
|
| + UBool /*commonlyUsed*/, UErrorCode* 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; }
|
|
|
| + UEnumeration *en = (UEnumeration *)uprv_malloc(sizeof(UEnumeration));
|
| + if (en == NULL) {
|
| + *status = U_MEMORY_ALLOCATION_ERROR;
|
| + return NULL;
|
| + }
|
| + memcpy(en, &defaultKeywordValues, sizeof(UEnumeration));
|
| + en->context = sink.values;
|
| + sink.values = NULL; // Avoid deletion in the sink destructor.
|
| return en;
|
| }
|
|
|
|
|