1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 3fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Copyright (C) 1996-2014, International Business Machines 4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Corporation and others. All Rights Reserved. 5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* file name: ucol_res.cpp 7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* encoding: US-ASCII 8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* tab size: 8 (not used) 9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* indentation:4 10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Description: 12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* This file contains dependencies that the collation run-time doesn't normally 13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* need. This mainly contains resource bundle usage and collation meta information 14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Modification history 16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Date Name Comments 17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 1996-1999 various members of ICU team maintained C API for collation framework 18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 02/16/2001 synwee Added internal method getPrevSpecialCE 19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 03/01/2001 synwee Added maxexpansion functionality. 20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 03/16/2001 weiv Collation framework is rewritten in C and made UCA compliant 21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 12/08/2004 grhoten Split part of ucol.cpp into ucol_res.cpp 22fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* 2012-2014 markus Rewritten in C++ again. 23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h" 26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_COLLATION 28fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/coll.h" 30fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/localpointer.h" 31fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/locid.h" 32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/tblcoll.h" 33fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/ucol.h" 34fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/uloc.h" 35fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/unistr.h" 36fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/ures.h" 37fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "cmemory.h" 38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h" 39fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationdatareader.h" 40fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationroot.h" 41fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationtailoring.h" 42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "putilimp.h" 4359d709d503bab6e2b61931737e662dd293b40578ccornelius#include "uassert.h" 44fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "ucln_in.h" 45fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "ucol_imp.h" 46b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "uenumimp.h" 47b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "ulist.h" 48fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "umutex.h" 49fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "uresimp.h" 50fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "ustrenum.h" 51fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "utracimp.h" 52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 53fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) 54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 55fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_BEGIN 5627f654740f2a26ad62a5c155af9199af9e69b889claireho 57fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusnamespace { 58fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 59fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic const UChar *rootRules = NULL; 60fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic int32_t rootRulesLength = 0; 61fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic UResourceBundle *rootBundle = NULL; 62fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic UInitOnce gInitOnce = U_INITONCE_INITIALIZER; 63fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 64fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} // namespace 65c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN 67fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 68c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic UBool U_CALLCONV 69fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusucol_res_cleanup() { 70fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius rootRules = NULL; 71fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius rootRulesLength = 0; 72fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_close(rootBundle); 73fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius rootBundle = NULL; 74fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius gInitOnce.reset(); 75c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru return TRUE; 76c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru} 77c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END 79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 80fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid 81fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationLoader::loadRootRules(UErrorCode &errorCode) { 82fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return; } 83fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius rootBundle = ures_open(U_ICUDATA_COLL, kRootLocaleName, &errorCode); 84fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return; } 85fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius rootRules = ures_getStringByKey(rootBundle, "UCARules", &rootRulesLength, &errorCode); 86fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { 87fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_close(rootBundle); 88fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius rootBundle = NULL; 8959d709d503bab6e2b61931737e662dd293b40578ccornelius return; 90c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 91fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ucln_i18n_registerCleanup(UCLN_I18N_UCOL_RES, ucol_res_cleanup); 92c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru} 93c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 94fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid 95fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationLoader::appendRootRules(UnicodeString &s) { 96fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode errorCode = U_ZERO_ERROR; 97fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius umtx_initOnce(gInitOnce, CollationLoader::loadRootRules, errorCode); 98fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_SUCCESS(errorCode)) { 99fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius s.append(rootRules, rootRulesLength); 100fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 101c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru} 102c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 103fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUnicodeString * 104fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationLoader::loadRules(const char *localeID, const char *collationType, UErrorCode &errorCode) { 105fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 106fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius U_ASSERT(collationType != NULL && *collationType != 0); 107dbc22bd174be483711cea006f3189d8289835830ccornelius // Copy the type for lowercasing. 108dbc22bd174be483711cea006f3189d8289835830ccornelius char type[16]; 109dbc22bd174be483711cea006f3189d8289835830ccornelius int32_t typeLength = uprv_strlen(collationType); 110dbc22bd174be483711cea006f3189d8289835830ccornelius if(typeLength >= LENGTHOF(type)) { 111dbc22bd174be483711cea006f3189d8289835830ccornelius errorCode = U_ILLEGAL_ARGUMENT_ERROR; 112dbc22bd174be483711cea006f3189d8289835830ccornelius return NULL; 113dbc22bd174be483711cea006f3189d8289835830ccornelius } 114dbc22bd174be483711cea006f3189d8289835830ccornelius uprv_memcpy(type, collationType, typeLength + 1); 115dbc22bd174be483711cea006f3189d8289835830ccornelius T_CString_toLowerCase(type); 116fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 117fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer bundle(ures_open(U_ICUDATA_COLL, localeID, &errorCode)); 118fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer collations( 119fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getByKey(bundle.getAlias(), "collations", NULL, &errorCode)); 120fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer data( 121dbc22bd174be483711cea006f3189d8289835830ccornelius ures_getByKeyWithFallback(collations.getAlias(), type, NULL, &errorCode)); 122fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t length; 123fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UChar *s = ures_getStringByKey(data.getAlias(), "Sequence", &length, &errorCode); 124fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 125fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 126fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // No string pointer aliasing so that we need not hold onto the resource bundle. 127fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString *rules = new UnicodeString(s, length); 128fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(rules == NULL) { 129fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_MEMORY_ALLOCATION_ERROR; 130fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 131fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 132fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return rules; 133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 135fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusconst CollationTailoring * 136fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationLoader::loadTailoring(const Locale &locale, Locale &validLocale, UErrorCode &errorCode) { 137fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const CollationTailoring *root = CollationRoot::getRoot(errorCode); 138fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 139fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const char *name = locale.getName(); 140fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(*name == 0 || uprv_strcmp(name, "root") == 0) { 141fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius validLocale = Locale::getRoot(); 142fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return root; 143fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 144fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 145fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer bundle(ures_open(U_ICUDATA_COLL, name, &errorCode)); 146fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(errorCode == U_MISSING_RESOURCE_ERROR) { 147fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_USING_DEFAULT_WARNING; 148fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius validLocale = Locale::getRoot(); 149fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return root; 150fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 151fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const char *vLocale = ures_getLocaleByType(bundle.getAlias(), ULOC_ACTUAL_LOCALE, &errorCode); 152fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 153fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius validLocale = Locale(vLocale); 154fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 155fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // There are zero or more tailorings in the collations table. 156fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer collations( 157fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getByKey(bundle.getAlias(), "collations", NULL, &errorCode)); 158fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(errorCode == U_MISSING_RESOURCE_ERROR) { 159fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_USING_DEFAULT_WARNING; 160fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return root; 161fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 162fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 163fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 164fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Fetch the collation type from the locale ID and the default type from the data. 165fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius char type[16]; 166fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t typeLength = locale.getKeywordValue("collation", type, LENGTHOF(type) - 1, errorCode); 167fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { 168fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_ILLEGAL_ARGUMENT_ERROR; 169fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 170fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 171fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius type[typeLength] = 0; // in case of U_NOT_TERMINATED_WARNING 172fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius char defaultType[16]; 173fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius { 174fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode internalErrorCode = U_ZERO_ERROR; 175fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer def( 176fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getByKeyWithFallback(collations.getAlias(), "default", NULL, 177fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius &internalErrorCode)); 178fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t length; 179fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UChar *s = ures_getString(def.getAlias(), &length, &internalErrorCode); 180fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_SUCCESS(internalErrorCode) && length < LENGTHOF(defaultType)) { 181fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius u_UCharsToChars(s, defaultType, length + 1); 182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 183fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_strcpy(defaultType, "standard"); 184fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 185fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 186fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(typeLength == 0 || uprv_strcmp(type, "default") == 0) { 187fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_strcpy(type, defaultType); 188dbc22bd174be483711cea006f3189d8289835830ccornelius } else { 189dbc22bd174be483711cea006f3189d8289835830ccornelius T_CString_toLowerCase(type); 190fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 191fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 192fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Load the collations/type tailoring, with type fallback. 193fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UBool typeFallback = FALSE; 194fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer data( 195fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getByKeyWithFallback(collations.getAlias(), type, NULL, &errorCode)); 196fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(errorCode == U_MISSING_RESOURCE_ERROR && 197fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius typeLength > 6 && uprv_strncmp(type, "search", 6) == 0) { 198fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // fall back from something like "searchjl" to "search" 199fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius typeFallback = TRUE; 200fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius type[6] = 0; 201fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_ZERO_ERROR; 202fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius data.adoptInstead( 203fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getByKeyWithFallback(collations.getAlias(), type, NULL, &errorCode)); 204fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 205fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(errorCode == U_MISSING_RESOURCE_ERROR && uprv_strcmp(type, defaultType) != 0) { 206fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // fall back to the default type 207fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius typeFallback = TRUE; 208fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_strcpy(type, defaultType); 209fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_ZERO_ERROR; 210fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius data.adoptInstead( 211fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getByKeyWithFallback(collations.getAlias(), type, NULL, &errorCode)); 212fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 213fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(errorCode == U_MISSING_RESOURCE_ERROR && uprv_strcmp(type, "standard") != 0) { 214fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // fall back to the "standard" type 215fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius typeFallback = TRUE; 216fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_strcpy(type, "standard"); 217fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_ZERO_ERROR; 218fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius data.adoptInstead( 219fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getByKeyWithFallback(collations.getAlias(), type, NULL, &errorCode)); 220fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 221fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(errorCode == U_MISSING_RESOURCE_ERROR) { 222fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_USING_DEFAULT_WARNING; 223fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return root; 224fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 225fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 226fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 227fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalPointer<CollationTailoring> t(new CollationTailoring(root->settings)); 228fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(t.isNull() || t->isBogus()) { 229fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_MEMORY_ALLOCATION_ERROR; 230fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 233fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Is this the same as the root collator? If so, then use that instead. 234fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const char *actualLocale = ures_getLocaleByType(data.getAlias(), ULOC_ACTUAL_LOCALE, &errorCode); 235fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 236fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if((*actualLocale == 0 || uprv_strcmp(actualLocale, "root") == 0) && 237fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_strcmp(type, "standard") == 0) { 238fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(typeFallback) { 239fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_USING_DEFAULT_WARNING; 240fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 241fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return root; 242fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 243fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius t->actualLocale = Locale(actualLocale); 244fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 245fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // deserialize 246fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer binary( 247fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getByKey(data.getAlias(), "%%CollationBin", NULL, &errorCode)); 248fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Note: U_MISSING_RESOURCE_ERROR --> The old code built from rules if available 249fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // but that created undesirable dependencies. 250fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t length; 251fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const uint8_t *inBytes = ures_getBinary(binary.getAlias(), &length, &errorCode); 252fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 253fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius CollationDataReader::read(root, inBytes, length, *t, errorCode); 254fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Note: U_COLLATOR_VERSION_MISMATCH --> The old code built from rules if available 255fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // but that created undesirable dependencies. 256fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 257fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 258fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Try to fetch the optional rules string. 259fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius { 260fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode internalErrorCode = U_ZERO_ERROR; 261fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t length; 262fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UChar *s = ures_getStringByKey(data.getAlias(), "Sequence", &length, 263fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius &internalErrorCode); 264fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_SUCCESS(errorCode)) { 265fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius t->rules.setTo(TRUE, s, length); 266fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 267fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 268fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 269fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Set the collation types on the informational locales, 270fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // except when they match the default types (for brevity and backwards compatibility). 271fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // For the valid locale, suppress the default type. 272fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(uprv_strcmp(type, defaultType) != 0) { 273fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius validLocale.setKeywordValue("collation", type, errorCode); 274fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 275fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 276fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 277fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // For the actual locale, suppress the default type *according to the actual locale*. 278fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // For example, zh has default=pinyin and contains all of the Chinese tailorings. 279fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // zh_Hant has default=stroke but has no other data. 280fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // For the valid locale "zh_Hant" we need to suppress stroke. 281fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // For the actual locale "zh" we need to suppress pinyin instead. 282fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(uprv_strcmp(actualLocale, vLocale) != 0) { 283fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Opening a bundle for the actual locale should always succeed. 284fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer actualBundle( 285fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_open(U_ICUDATA_COLL, actualLocale, &errorCode)); 286fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 287fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode internalErrorCode = U_ZERO_ERROR; 288fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer def( 289fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getByKeyWithFallback(actualBundle.getAlias(), "collations/default", NULL, 290fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius &internalErrorCode)); 291fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t length; 292fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UChar *s = ures_getString(def.getAlias(), &length, &internalErrorCode); 293fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_SUCCESS(internalErrorCode) && length < LENGTHOF(defaultType)) { 294fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius u_UCharsToChars(s, defaultType, length + 1); 295fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 296fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_strcpy(defaultType, "standard"); 297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 299fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(uprv_strcmp(type, defaultType) != 0) { 300fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius t->actualLocale.setKeywordValue("collation", type, errorCode); 301fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return NULL; } 302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 303fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 304fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(typeFallback) { 305fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_USING_DEFAULT_WARNING; 306c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 307fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius t->bundle = bundle.orphan(); 308fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return t.orphan(); 309fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 311fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_END 312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 313fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_USE 314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UCollator* 316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_open(const char *loc, 317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *status) 318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_NAMESPACE_USE 320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UTRACE_ENTRY_OC(UTRACE_UCOL_OPEN); 322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UTRACE_DATA1(UTRACE_INFO, "locale = \"%s\"", loc); 323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UCollator *result = NULL; 324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 325fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius Collator *coll = Collator::createInstance(loc, *status); 326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_SUCCESS(*status)) { 327fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius result = coll->toUCollator(); 328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 329fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UTRACE_EXIT_PTR_STATUS(result, *status); 330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return result; 331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2 335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_getDisplayName( const char *objLoc, 336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const char *dispLoc, 337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UChar *result, 338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t resultLength, 339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode *status) 340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_NAMESPACE_USE 342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*status)) return -1; 344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString dst; 345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(!(result==NULL && resultLength==0)) { 346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // NULL destination for pure preflighting: empty dummy string 347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // otherwise, alias the destination buffer 348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dst.setTo(result, 0, resultLength); 349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Collator::getDisplayName(Locale(objLoc), Locale(dispLoc), dst); 351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return dst.extract(result, resultLength, *status); 352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI const char* U_EXPORT2 355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_getAvailable(int32_t index) 356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t count = 0; 358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const Locale *loc = Collator::getAvailableLocales(count); 359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (loc != NULL && index < count) { 360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return loc[index].getName(); 361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2 366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_countAvailable() 367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t count = 0; 369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Collator::getAvailableLocales(count); 370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return count; 371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_SERVICE 374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UEnumeration* U_EXPORT2 375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_openAvailableLocales(UErrorCode *status) { 376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_NAMESPACE_USE 377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // This is a wrapper over Collator::getAvailableLocales() 379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 382103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius StringEnumeration *s = icu::Collator::getAvailableLocales(); 383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (s == NULL) { 384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 387b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return uenum_openFromStringEnumeration(s, status); 388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Note: KEYWORDS[0] != RESOURCE_NAME - alan 392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 393c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic const char RESOURCE_NAME[] = "collations"; 394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 395c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic const char* const KEYWORDS[] = { "collation" }; 396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 397fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define KEYWORD_COUNT LENGTHOF(KEYWORDS) 398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UEnumeration* U_EXPORT2 400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_getKeywords(UErrorCode *status) { 401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UEnumeration *result = NULL; 402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_SUCCESS(*status)) { 403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return uenum_openCharStringsEnumeration(KEYWORDS, KEYWORD_COUNT, status); 404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return result; 406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UEnumeration* U_EXPORT2 409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_getKeywordValues(const char *keyword, UErrorCode *status) { 410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // hard-coded to accept exactly one collation keyword 414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // modify if additional collation keyword is added later 415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (keyword==NULL || uprv_strcmp(keyword, KEYWORDS[0])!=0) 416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_ILLEGAL_ARGUMENT_ERROR; 418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ures_getKeywordValues(U_ICUDATA_COLL, RESOURCE_NAME, status); 421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 423b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const UEnumeration defaultKeywordValues = { 424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru NULL, 425b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru NULL, 426b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ulist_close_keyword_values_iterator, 427b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ulist_count_keyword_values, 428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uenum_unextDefault, 429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ulist_next_keyword_value, 430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ulist_reset_keyword_values_iterator 431b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}; 432b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 43350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include <stdio.h> 43450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 435b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI UEnumeration* U_EXPORT2 436b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruucol_getKeywordValuesForLocale(const char* /*key*/, const char* locale, 437b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool /*commonlyUsed*/, UErrorCode* status) { 438b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* Get the locale base name. */ 439b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char localeBuffer[ULOC_FULLNAME_CAPACITY] = ""; 440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uloc_getBaseName(locale, localeBuffer, sizeof(localeBuffer), status); 441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* Create the 2 lists 443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * -values is the temp location for the keyword values 444b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * -results hold the actual list used by the UEnumeration object 445b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 446b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UList *values = ulist_createEmptyList(status); 447b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UList *results = ulist_createEmptyList(status); 448b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UEnumeration *en = (UEnumeration *)uprv_malloc(sizeof(UEnumeration)); 449b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status) || en == NULL) { 450b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (en == NULL) { 451b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 452b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 453b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(en); 454b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 455b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ulist_deleteList(values); 456b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ulist_deleteList(results); 457b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 458b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 459b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 460b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru memcpy(en, &defaultKeywordValues, sizeof(UEnumeration)); 461b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru en->context = results; 462b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 463b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* Open the resource bundle for collation with the given locale. */ 464b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UResourceBundle bundle, collations, collres, defres; 465b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_initStackObject(&bundle); 466b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_initStackObject(&collations); 467b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_initStackObject(&collres); 468b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_initStackObject(&defres); 469b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 470b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_openFillIn(&bundle, U_ICUDATA_COLL, localeBuffer, status); 471b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 472b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (U_SUCCESS(*status)) { 473b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_getByKey(&bundle, RESOURCE_NAME, &collations, status); 474b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_resetIterator(&collations); 475b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while (U_SUCCESS(*status) && ures_hasNext(&collations)) { 476b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_getNextResource(&collations, &collres, status); 477b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char *key = ures_getKey(&collres); 478b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* If the key is default, get the string and store it in results list only 479b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * if results list is empty. 480b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 481b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (uprv_strcmp(key, "default") == 0) { 482b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (ulist_getListSize(results) == 0) { 483b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *defcoll = (char *)uprv_malloc(sizeof(char) * ULOC_KEYWORDS_CAPACITY); 484b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t defcollLength = ULOC_KEYWORDS_CAPACITY; 485b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 486b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_getNextResource(&collres, &defres, status); 48750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if U_CHARSET_FAMILY==U_ASCII_FAMILY 48850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* optimize - use the utf-8 string */ 489b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_getUTF8String(&defres, defcoll, &defcollLength, TRUE, status); 49050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#else 49150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 49250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar* defString = ures_getString(&defres, &defcollLength, status); 49350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(U_SUCCESS(*status)) { 49450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(defcollLength+1 > ULOC_KEYWORDS_CAPACITY) { 49550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status = U_BUFFER_OVERFLOW_ERROR; 49650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 49750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u_UCharsToChars(defString, defcoll, defcollLength+1); 49850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 49950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 50050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 50150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif 502b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 503b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ulist_addItemBeginList(results, defcoll, TRUE, status); 504b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 505b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 506b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ulist_addItemEndList(values, key, FALSE, status); 507b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 508b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 509b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 510b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* If the locale is "" this is root so exit. */ 511b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (uprv_strlen(localeBuffer) == 0) { 512b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 513b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 514b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru /* Get the parent locale and open a new resource bundle. */ 515b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uloc_getParent(localeBuffer, localeBuffer, sizeof(localeBuffer), status); 516b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_openFillIn(&bundle, U_ICUDATA_COLL, localeBuffer, status); 517b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 518b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 519b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(&defres); 520b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(&collres); 521b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(&collations); 522b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(&bundle); 523b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 524b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(*status)) { 525b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char *value = NULL; 526b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ulist_resetList(values); 527b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while ((value = (char *)ulist_getNext(values)) != NULL) { 52850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!ulist_containsString(results, value, (int32_t)uprv_strlen(value))) { 529b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ulist_addItemEndList(results, value, FALSE, status); 530b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)) { 531b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 532b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 533b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 534b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 535b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 536b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 537b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ulist_deleteList(values); 538b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 539b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(*status)){ 540b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uenum_close(en); 541b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru en = NULL; 542b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 543b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ulist_resetList(results); 544b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 545b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 546b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return en; 547b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 548b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2 550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucol_getFunctionalEquivalent(char* result, int32_t resultCapacity, 551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const char* keyword, const char* locale, 552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool* isAvailable, UErrorCode* status) 553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // N.B.: Resource name is "collations" but keyword is "collation" 555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ures_getFunctionalEquivalent(result, resultCapacity, U_ICUDATA_COLL, 556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru "collations", keyword, locale, 557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru isAvailable, TRUE, status); 558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_COLLATION */ 561