Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* |
michael@0 | 2 | ******************************************************************************* |
michael@0 | 3 | * |
michael@0 | 4 | * Copyright (C) 1997-2013, International Business Machines |
michael@0 | 5 | * Corporation and others. All Rights Reserved. |
michael@0 | 6 | * |
michael@0 | 7 | ******************************************************************************* |
michael@0 | 8 | * file name: locdispnames.cpp |
michael@0 | 9 | * encoding: US-ASCII |
michael@0 | 10 | * tab size: 8 (not used) |
michael@0 | 11 | * indentation:4 |
michael@0 | 12 | * |
michael@0 | 13 | * created on: 2010feb25 |
michael@0 | 14 | * created by: Markus W. Scherer |
michael@0 | 15 | * |
michael@0 | 16 | * Code for locale display names, separated out from other .cpp files |
michael@0 | 17 | * that then do not depend on resource bundle code and display name data. |
michael@0 | 18 | */ |
michael@0 | 19 | |
michael@0 | 20 | #include "unicode/utypes.h" |
michael@0 | 21 | #include "unicode/brkiter.h" |
michael@0 | 22 | #include "unicode/locid.h" |
michael@0 | 23 | #include "unicode/uloc.h" |
michael@0 | 24 | #include "unicode/ures.h" |
michael@0 | 25 | #include "unicode/ustring.h" |
michael@0 | 26 | #include "cmemory.h" |
michael@0 | 27 | #include "cstring.h" |
michael@0 | 28 | #include "putilimp.h" |
michael@0 | 29 | #include "ulocimp.h" |
michael@0 | 30 | #include "uresimp.h" |
michael@0 | 31 | #include "ureslocs.h" |
michael@0 | 32 | #include "ustr_imp.h" |
michael@0 | 33 | |
michael@0 | 34 | // C++ API ----------------------------------------------------------------- *** |
michael@0 | 35 | |
michael@0 | 36 | U_NAMESPACE_BEGIN |
michael@0 | 37 | |
michael@0 | 38 | UnicodeString& |
michael@0 | 39 | Locale::getDisplayLanguage(UnicodeString& dispLang) const |
michael@0 | 40 | { |
michael@0 | 41 | return this->getDisplayLanguage(getDefault(), dispLang); |
michael@0 | 42 | } |
michael@0 | 43 | |
michael@0 | 44 | /*We cannot make any assumptions on the size of the output display strings |
michael@0 | 45 | * Yet, since we are calling through to a C API, we need to set limits on |
michael@0 | 46 | * buffer size. For all the following getDisplay functions we first attempt |
michael@0 | 47 | * to fill up a stack allocated buffer. If it is to small we heap allocated |
michael@0 | 48 | * the exact buffer we need copy it to the UnicodeString and delete it*/ |
michael@0 | 49 | |
michael@0 | 50 | UnicodeString& |
michael@0 | 51 | Locale::getDisplayLanguage(const Locale &displayLocale, |
michael@0 | 52 | UnicodeString &result) const { |
michael@0 | 53 | UChar *buffer; |
michael@0 | 54 | UErrorCode errorCode=U_ZERO_ERROR; |
michael@0 | 55 | int32_t length; |
michael@0 | 56 | |
michael@0 | 57 | buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); |
michael@0 | 58 | if(buffer==0) { |
michael@0 | 59 | result.truncate(0); |
michael@0 | 60 | return result; |
michael@0 | 61 | } |
michael@0 | 62 | |
michael@0 | 63 | length=uloc_getDisplayLanguage(fullName, displayLocale.fullName, |
michael@0 | 64 | buffer, result.getCapacity(), |
michael@0 | 65 | &errorCode); |
michael@0 | 66 | result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
michael@0 | 67 | |
michael@0 | 68 | if(errorCode==U_BUFFER_OVERFLOW_ERROR) { |
michael@0 | 69 | buffer=result.getBuffer(length); |
michael@0 | 70 | if(buffer==0) { |
michael@0 | 71 | result.truncate(0); |
michael@0 | 72 | return result; |
michael@0 | 73 | } |
michael@0 | 74 | errorCode=U_ZERO_ERROR; |
michael@0 | 75 | length=uloc_getDisplayLanguage(fullName, displayLocale.fullName, |
michael@0 | 76 | buffer, result.getCapacity(), |
michael@0 | 77 | &errorCode); |
michael@0 | 78 | result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | return result; |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | UnicodeString& |
michael@0 | 85 | Locale::getDisplayScript(UnicodeString& dispScript) const |
michael@0 | 86 | { |
michael@0 | 87 | return this->getDisplayScript(getDefault(), dispScript); |
michael@0 | 88 | } |
michael@0 | 89 | |
michael@0 | 90 | UnicodeString& |
michael@0 | 91 | Locale::getDisplayScript(const Locale &displayLocale, |
michael@0 | 92 | UnicodeString &result) const { |
michael@0 | 93 | UChar *buffer; |
michael@0 | 94 | UErrorCode errorCode=U_ZERO_ERROR; |
michael@0 | 95 | int32_t length; |
michael@0 | 96 | |
michael@0 | 97 | buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); |
michael@0 | 98 | if(buffer==0) { |
michael@0 | 99 | result.truncate(0); |
michael@0 | 100 | return result; |
michael@0 | 101 | } |
michael@0 | 102 | |
michael@0 | 103 | length=uloc_getDisplayScript(fullName, displayLocale.fullName, |
michael@0 | 104 | buffer, result.getCapacity(), |
michael@0 | 105 | &errorCode); |
michael@0 | 106 | result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
michael@0 | 107 | |
michael@0 | 108 | if(errorCode==U_BUFFER_OVERFLOW_ERROR) { |
michael@0 | 109 | buffer=result.getBuffer(length); |
michael@0 | 110 | if(buffer==0) { |
michael@0 | 111 | result.truncate(0); |
michael@0 | 112 | return result; |
michael@0 | 113 | } |
michael@0 | 114 | errorCode=U_ZERO_ERROR; |
michael@0 | 115 | length=uloc_getDisplayScript(fullName, displayLocale.fullName, |
michael@0 | 116 | buffer, result.getCapacity(), |
michael@0 | 117 | &errorCode); |
michael@0 | 118 | result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
michael@0 | 119 | } |
michael@0 | 120 | |
michael@0 | 121 | return result; |
michael@0 | 122 | } |
michael@0 | 123 | |
michael@0 | 124 | UnicodeString& |
michael@0 | 125 | Locale::getDisplayCountry(UnicodeString& dispCntry) const |
michael@0 | 126 | { |
michael@0 | 127 | return this->getDisplayCountry(getDefault(), dispCntry); |
michael@0 | 128 | } |
michael@0 | 129 | |
michael@0 | 130 | UnicodeString& |
michael@0 | 131 | Locale::getDisplayCountry(const Locale &displayLocale, |
michael@0 | 132 | UnicodeString &result) const { |
michael@0 | 133 | UChar *buffer; |
michael@0 | 134 | UErrorCode errorCode=U_ZERO_ERROR; |
michael@0 | 135 | int32_t length; |
michael@0 | 136 | |
michael@0 | 137 | buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); |
michael@0 | 138 | if(buffer==0) { |
michael@0 | 139 | result.truncate(0); |
michael@0 | 140 | return result; |
michael@0 | 141 | } |
michael@0 | 142 | |
michael@0 | 143 | length=uloc_getDisplayCountry(fullName, displayLocale.fullName, |
michael@0 | 144 | buffer, result.getCapacity(), |
michael@0 | 145 | &errorCode); |
michael@0 | 146 | result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
michael@0 | 147 | |
michael@0 | 148 | if(errorCode==U_BUFFER_OVERFLOW_ERROR) { |
michael@0 | 149 | buffer=result.getBuffer(length); |
michael@0 | 150 | if(buffer==0) { |
michael@0 | 151 | result.truncate(0); |
michael@0 | 152 | return result; |
michael@0 | 153 | } |
michael@0 | 154 | errorCode=U_ZERO_ERROR; |
michael@0 | 155 | length=uloc_getDisplayCountry(fullName, displayLocale.fullName, |
michael@0 | 156 | buffer, result.getCapacity(), |
michael@0 | 157 | &errorCode); |
michael@0 | 158 | result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | return result; |
michael@0 | 162 | } |
michael@0 | 163 | |
michael@0 | 164 | UnicodeString& |
michael@0 | 165 | Locale::getDisplayVariant(UnicodeString& dispVar) const |
michael@0 | 166 | { |
michael@0 | 167 | return this->getDisplayVariant(getDefault(), dispVar); |
michael@0 | 168 | } |
michael@0 | 169 | |
michael@0 | 170 | UnicodeString& |
michael@0 | 171 | Locale::getDisplayVariant(const Locale &displayLocale, |
michael@0 | 172 | UnicodeString &result) const { |
michael@0 | 173 | UChar *buffer; |
michael@0 | 174 | UErrorCode errorCode=U_ZERO_ERROR; |
michael@0 | 175 | int32_t length; |
michael@0 | 176 | |
michael@0 | 177 | buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); |
michael@0 | 178 | if(buffer==0) { |
michael@0 | 179 | result.truncate(0); |
michael@0 | 180 | return result; |
michael@0 | 181 | } |
michael@0 | 182 | |
michael@0 | 183 | length=uloc_getDisplayVariant(fullName, displayLocale.fullName, |
michael@0 | 184 | buffer, result.getCapacity(), |
michael@0 | 185 | &errorCode); |
michael@0 | 186 | result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
michael@0 | 187 | |
michael@0 | 188 | if(errorCode==U_BUFFER_OVERFLOW_ERROR) { |
michael@0 | 189 | buffer=result.getBuffer(length); |
michael@0 | 190 | if(buffer==0) { |
michael@0 | 191 | result.truncate(0); |
michael@0 | 192 | return result; |
michael@0 | 193 | } |
michael@0 | 194 | errorCode=U_ZERO_ERROR; |
michael@0 | 195 | length=uloc_getDisplayVariant(fullName, displayLocale.fullName, |
michael@0 | 196 | buffer, result.getCapacity(), |
michael@0 | 197 | &errorCode); |
michael@0 | 198 | result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
michael@0 | 199 | } |
michael@0 | 200 | |
michael@0 | 201 | return result; |
michael@0 | 202 | } |
michael@0 | 203 | |
michael@0 | 204 | UnicodeString& |
michael@0 | 205 | Locale::getDisplayName( UnicodeString& name ) const |
michael@0 | 206 | { |
michael@0 | 207 | return this->getDisplayName(getDefault(), name); |
michael@0 | 208 | } |
michael@0 | 209 | |
michael@0 | 210 | UnicodeString& |
michael@0 | 211 | Locale::getDisplayName(const Locale &displayLocale, |
michael@0 | 212 | UnicodeString &result) const { |
michael@0 | 213 | UChar *buffer; |
michael@0 | 214 | UErrorCode errorCode=U_ZERO_ERROR; |
michael@0 | 215 | int32_t length; |
michael@0 | 216 | |
michael@0 | 217 | buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); |
michael@0 | 218 | if(buffer==0) { |
michael@0 | 219 | result.truncate(0); |
michael@0 | 220 | return result; |
michael@0 | 221 | } |
michael@0 | 222 | |
michael@0 | 223 | length=uloc_getDisplayName(fullName, displayLocale.fullName, |
michael@0 | 224 | buffer, result.getCapacity(), |
michael@0 | 225 | &errorCode); |
michael@0 | 226 | result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
michael@0 | 227 | |
michael@0 | 228 | if(errorCode==U_BUFFER_OVERFLOW_ERROR) { |
michael@0 | 229 | buffer=result.getBuffer(length); |
michael@0 | 230 | if(buffer==0) { |
michael@0 | 231 | result.truncate(0); |
michael@0 | 232 | return result; |
michael@0 | 233 | } |
michael@0 | 234 | errorCode=U_ZERO_ERROR; |
michael@0 | 235 | length=uloc_getDisplayName(fullName, displayLocale.fullName, |
michael@0 | 236 | buffer, result.getCapacity(), |
michael@0 | 237 | &errorCode); |
michael@0 | 238 | result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
michael@0 | 239 | } |
michael@0 | 240 | |
michael@0 | 241 | return result; |
michael@0 | 242 | } |
michael@0 | 243 | |
michael@0 | 244 | #if ! UCONFIG_NO_BREAK_ITERATION |
michael@0 | 245 | |
michael@0 | 246 | // ------------------------------------- |
michael@0 | 247 | // Gets the objectLocale display name in the default locale language. |
michael@0 | 248 | UnicodeString& U_EXPORT2 |
michael@0 | 249 | BreakIterator::getDisplayName(const Locale& objectLocale, |
michael@0 | 250 | UnicodeString& name) |
michael@0 | 251 | { |
michael@0 | 252 | return objectLocale.getDisplayName(name); |
michael@0 | 253 | } |
michael@0 | 254 | |
michael@0 | 255 | // ------------------------------------- |
michael@0 | 256 | // Gets the objectLocale display name in the displayLocale language. |
michael@0 | 257 | UnicodeString& U_EXPORT2 |
michael@0 | 258 | BreakIterator::getDisplayName(const Locale& objectLocale, |
michael@0 | 259 | const Locale& displayLocale, |
michael@0 | 260 | UnicodeString& name) |
michael@0 | 261 | { |
michael@0 | 262 | return objectLocale.getDisplayName(displayLocale, name); |
michael@0 | 263 | } |
michael@0 | 264 | |
michael@0 | 265 | #endif |
michael@0 | 266 | |
michael@0 | 267 | |
michael@0 | 268 | U_NAMESPACE_END |
michael@0 | 269 | |
michael@0 | 270 | // C API ------------------------------------------------------------------- *** |
michael@0 | 271 | |
michael@0 | 272 | U_NAMESPACE_USE |
michael@0 | 273 | |
michael@0 | 274 | /* ### Constants **************************************************/ |
michael@0 | 275 | |
michael@0 | 276 | /* These strings describe the resources we attempt to load from |
michael@0 | 277 | the locale ResourceBundle data file.*/ |
michael@0 | 278 | static const char _kLanguages[] = "Languages"; |
michael@0 | 279 | static const char _kScripts[] = "Scripts"; |
michael@0 | 280 | static const char _kScriptsStandAlone[] = "Scripts%stand-alone"; |
michael@0 | 281 | static const char _kCountries[] = "Countries"; |
michael@0 | 282 | static const char _kVariants[] = "Variants"; |
michael@0 | 283 | static const char _kKeys[] = "Keys"; |
michael@0 | 284 | static const char _kTypes[] = "Types"; |
michael@0 | 285 | //static const char _kRootName[] = "root"; |
michael@0 | 286 | static const char _kCurrency[] = "currency"; |
michael@0 | 287 | static const char _kCurrencies[] = "Currencies"; |
michael@0 | 288 | static const char _kLocaleDisplayPattern[] = "localeDisplayPattern"; |
michael@0 | 289 | static const char _kPattern[] = "pattern"; |
michael@0 | 290 | static const char _kSeparator[] = "separator"; |
michael@0 | 291 | |
michael@0 | 292 | /* ### Display name **************************************************/ |
michael@0 | 293 | |
michael@0 | 294 | static int32_t |
michael@0 | 295 | _getStringOrCopyKey(const char *path, const char *locale, |
michael@0 | 296 | const char *tableKey, |
michael@0 | 297 | const char* subTableKey, |
michael@0 | 298 | const char *itemKey, |
michael@0 | 299 | const char *substitute, |
michael@0 | 300 | UChar *dest, int32_t destCapacity, |
michael@0 | 301 | UErrorCode *pErrorCode) { |
michael@0 | 302 | const UChar *s = NULL; |
michael@0 | 303 | int32_t length = 0; |
michael@0 | 304 | |
michael@0 | 305 | if(itemKey==NULL) { |
michael@0 | 306 | /* top-level item: normal resource bundle access */ |
michael@0 | 307 | UResourceBundle *rb; |
michael@0 | 308 | |
michael@0 | 309 | rb=ures_open(path, locale, pErrorCode); |
michael@0 | 310 | |
michael@0 | 311 | if(U_SUCCESS(*pErrorCode)) { |
michael@0 | 312 | s=ures_getStringByKey(rb, tableKey, &length, pErrorCode); |
michael@0 | 313 | /* see comment about closing rb near "return item;" in _res_getTableStringWithFallback() */ |
michael@0 | 314 | ures_close(rb); |
michael@0 | 315 | } |
michael@0 | 316 | } else { |
michael@0 | 317 | /* Language code should not be a number. If it is, set the error code. */ |
michael@0 | 318 | if (!uprv_strncmp(tableKey, "Languages", 9) && uprv_strtol(itemKey, NULL, 10)) { |
michael@0 | 319 | *pErrorCode = U_MISSING_RESOURCE_ERROR; |
michael@0 | 320 | } else { |
michael@0 | 321 | /* second-level item, use special fallback */ |
michael@0 | 322 | s=uloc_getTableStringWithFallback(path, locale, |
michael@0 | 323 | tableKey, |
michael@0 | 324 | subTableKey, |
michael@0 | 325 | itemKey, |
michael@0 | 326 | &length, |
michael@0 | 327 | pErrorCode); |
michael@0 | 328 | } |
michael@0 | 329 | } |
michael@0 | 330 | |
michael@0 | 331 | if(U_SUCCESS(*pErrorCode)) { |
michael@0 | 332 | int32_t copyLength=uprv_min(length, destCapacity); |
michael@0 | 333 | if(copyLength>0 && s != NULL) { |
michael@0 | 334 | u_memcpy(dest, s, copyLength); |
michael@0 | 335 | } |
michael@0 | 336 | } else { |
michael@0 | 337 | /* no string from a resource bundle: convert the substitute */ |
michael@0 | 338 | length=(int32_t)uprv_strlen(substitute); |
michael@0 | 339 | u_charsToUChars(substitute, dest, uprv_min(length, destCapacity)); |
michael@0 | 340 | *pErrorCode=U_USING_DEFAULT_WARNING; |
michael@0 | 341 | } |
michael@0 | 342 | |
michael@0 | 343 | return u_terminateUChars(dest, destCapacity, length, pErrorCode); |
michael@0 | 344 | } |
michael@0 | 345 | |
michael@0 | 346 | typedef int32_t U_CALLCONV UDisplayNameGetter(const char *, char *, int32_t, UErrorCode *); |
michael@0 | 347 | |
michael@0 | 348 | static int32_t |
michael@0 | 349 | _getDisplayNameForComponent(const char *locale, |
michael@0 | 350 | const char *displayLocale, |
michael@0 | 351 | UChar *dest, int32_t destCapacity, |
michael@0 | 352 | UDisplayNameGetter *getter, |
michael@0 | 353 | const char *tag, |
michael@0 | 354 | UErrorCode *pErrorCode) { |
michael@0 | 355 | char localeBuffer[ULOC_FULLNAME_CAPACITY*4]; |
michael@0 | 356 | int32_t length; |
michael@0 | 357 | UErrorCode localStatus; |
michael@0 | 358 | const char* root = NULL; |
michael@0 | 359 | |
michael@0 | 360 | /* argument checking */ |
michael@0 | 361 | if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { |
michael@0 | 362 | return 0; |
michael@0 | 363 | } |
michael@0 | 364 | |
michael@0 | 365 | if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { |
michael@0 | 366 | *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; |
michael@0 | 367 | return 0; |
michael@0 | 368 | } |
michael@0 | 369 | |
michael@0 | 370 | localStatus = U_ZERO_ERROR; |
michael@0 | 371 | length=(*getter)(locale, localeBuffer, sizeof(localeBuffer), &localStatus); |
michael@0 | 372 | if(U_FAILURE(localStatus) || localStatus==U_STRING_NOT_TERMINATED_WARNING) { |
michael@0 | 373 | *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; |
michael@0 | 374 | return 0; |
michael@0 | 375 | } |
michael@0 | 376 | if(length==0) { |
michael@0 | 377 | return u_terminateUChars(dest, destCapacity, 0, pErrorCode); |
michael@0 | 378 | } |
michael@0 | 379 | |
michael@0 | 380 | root = tag == _kCountries ? U_ICUDATA_REGION : U_ICUDATA_LANG; |
michael@0 | 381 | |
michael@0 | 382 | return _getStringOrCopyKey(root, displayLocale, |
michael@0 | 383 | tag, NULL, localeBuffer, |
michael@0 | 384 | localeBuffer, |
michael@0 | 385 | dest, destCapacity, |
michael@0 | 386 | pErrorCode); |
michael@0 | 387 | } |
michael@0 | 388 | |
michael@0 | 389 | U_CAPI int32_t U_EXPORT2 |
michael@0 | 390 | uloc_getDisplayLanguage(const char *locale, |
michael@0 | 391 | const char *displayLocale, |
michael@0 | 392 | UChar *dest, int32_t destCapacity, |
michael@0 | 393 | UErrorCode *pErrorCode) { |
michael@0 | 394 | return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, |
michael@0 | 395 | uloc_getLanguage, _kLanguages, pErrorCode); |
michael@0 | 396 | } |
michael@0 | 397 | |
michael@0 | 398 | U_CAPI int32_t U_EXPORT2 |
michael@0 | 399 | uloc_getDisplayScript(const char* locale, |
michael@0 | 400 | const char* displayLocale, |
michael@0 | 401 | UChar *dest, int32_t destCapacity, |
michael@0 | 402 | UErrorCode *pErrorCode) |
michael@0 | 403 | { |
michael@0 | 404 | UErrorCode err = U_ZERO_ERROR; |
michael@0 | 405 | int32_t res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, |
michael@0 | 406 | uloc_getScript, _kScriptsStandAlone, &err); |
michael@0 | 407 | |
michael@0 | 408 | if ( err == U_USING_DEFAULT_WARNING ) { |
michael@0 | 409 | return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, |
michael@0 | 410 | uloc_getScript, _kScripts, pErrorCode); |
michael@0 | 411 | } else { |
michael@0 | 412 | *pErrorCode = err; |
michael@0 | 413 | return res; |
michael@0 | 414 | } |
michael@0 | 415 | } |
michael@0 | 416 | |
michael@0 | 417 | U_INTERNAL int32_t U_EXPORT2 |
michael@0 | 418 | uloc_getDisplayScriptInContext(const char* locale, |
michael@0 | 419 | const char* displayLocale, |
michael@0 | 420 | UChar *dest, int32_t destCapacity, |
michael@0 | 421 | UErrorCode *pErrorCode) |
michael@0 | 422 | { |
michael@0 | 423 | return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, |
michael@0 | 424 | uloc_getScript, _kScripts, pErrorCode); |
michael@0 | 425 | } |
michael@0 | 426 | |
michael@0 | 427 | U_CAPI int32_t U_EXPORT2 |
michael@0 | 428 | uloc_getDisplayCountry(const char *locale, |
michael@0 | 429 | const char *displayLocale, |
michael@0 | 430 | UChar *dest, int32_t destCapacity, |
michael@0 | 431 | UErrorCode *pErrorCode) { |
michael@0 | 432 | return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, |
michael@0 | 433 | uloc_getCountry, _kCountries, pErrorCode); |
michael@0 | 434 | } |
michael@0 | 435 | |
michael@0 | 436 | /* |
michael@0 | 437 | * TODO separate variant1_variant2_variant3... |
michael@0 | 438 | * by getting each tag's display string and concatenating them with ", " |
michael@0 | 439 | * in between - similar to uloc_getDisplayName() |
michael@0 | 440 | */ |
michael@0 | 441 | U_CAPI int32_t U_EXPORT2 |
michael@0 | 442 | uloc_getDisplayVariant(const char *locale, |
michael@0 | 443 | const char *displayLocale, |
michael@0 | 444 | UChar *dest, int32_t destCapacity, |
michael@0 | 445 | UErrorCode *pErrorCode) { |
michael@0 | 446 | return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity, |
michael@0 | 447 | uloc_getVariant, _kVariants, pErrorCode); |
michael@0 | 448 | } |
michael@0 | 449 | |
michael@0 | 450 | /* Instead of having a separate pass for 'special' patterns, reintegrate the two |
michael@0 | 451 | * so we don't get bitten by preflight bugs again. We can be reasonably efficient |
michael@0 | 452 | * without two separate code paths, this code isn't that performance-critical. |
michael@0 | 453 | * |
michael@0 | 454 | * This code is general enough to deal with patterns that have a prefix or swap the |
michael@0 | 455 | * language and remainder components, since we gave developers enough rope to do such |
michael@0 | 456 | * things if they futz with the pattern data. But since we don't give them a way to |
michael@0 | 457 | * specify a pattern for arbitrary combinations of components, there's not much use in |
michael@0 | 458 | * that. I don't think our data includes such patterns, the only variable I know if is |
michael@0 | 459 | * whether there is a space before the open paren, or not. Oh, and zh uses different |
michael@0 | 460 | * chars than the standard open/close paren (which ja and ko use, btw). |
michael@0 | 461 | */ |
michael@0 | 462 | U_CAPI int32_t U_EXPORT2 |
michael@0 | 463 | uloc_getDisplayName(const char *locale, |
michael@0 | 464 | const char *displayLocale, |
michael@0 | 465 | UChar *dest, int32_t destCapacity, |
michael@0 | 466 | UErrorCode *pErrorCode) |
michael@0 | 467 | { |
michael@0 | 468 | static const UChar defaultSeparator[9] = { 0x007b, 0x0030, 0x007d, 0x002c, 0x0020, 0x007b, 0x0031, 0x007d, 0x0000 }; /* "{0}, {1}" */ |
michael@0 | 469 | static const UChar sub0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 } ; /* {0} */ |
michael@0 | 470 | static const UChar sub1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 } ; /* {1} */ |
michael@0 | 471 | static const int32_t subLen = 3; |
michael@0 | 472 | static const UChar defaultPattern[10] = { |
michael@0 | 473 | 0x007b, 0x0030, 0x007d, 0x0020, 0x0028, 0x007b, 0x0031, 0x007d, 0x0029, 0x0000 |
michael@0 | 474 | }; /* {0} ({1}) */ |
michael@0 | 475 | static const int32_t defaultPatLen = 9; |
michael@0 | 476 | static const int32_t defaultSub0Pos = 0; |
michael@0 | 477 | static const int32_t defaultSub1Pos = 5; |
michael@0 | 478 | |
michael@0 | 479 | int32_t length; /* of formatted result */ |
michael@0 | 480 | |
michael@0 | 481 | const UChar *separator; |
michael@0 | 482 | int32_t sepLen = 0; |
michael@0 | 483 | const UChar *pattern; |
michael@0 | 484 | int32_t patLen = 0; |
michael@0 | 485 | int32_t sub0Pos, sub1Pos; |
michael@0 | 486 | |
michael@0 | 487 | UChar formatOpenParen = 0x0028; // ( |
michael@0 | 488 | UChar formatReplaceOpenParen = 0x005B; // [ |
michael@0 | 489 | UChar formatCloseParen = 0x0029; // ) |
michael@0 | 490 | UChar formatReplaceCloseParen = 0x005D; // ] |
michael@0 | 491 | |
michael@0 | 492 | UBool haveLang = TRUE; /* assume true, set false if we find we don't have |
michael@0 | 493 | a lang component in the locale */ |
michael@0 | 494 | UBool haveRest = TRUE; /* assume true, set false if we find we don't have |
michael@0 | 495 | any other component in the locale */ |
michael@0 | 496 | UBool retry = FALSE; /* set true if we need to retry, see below */ |
michael@0 | 497 | |
michael@0 | 498 | int32_t langi = 0; /* index of the language substitution (0 or 1), virtually always 0 */ |
michael@0 | 499 | |
michael@0 | 500 | if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { |
michael@0 | 501 | return 0; |
michael@0 | 502 | } |
michael@0 | 503 | |
michael@0 | 504 | if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { |
michael@0 | 505 | *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; |
michael@0 | 506 | return 0; |
michael@0 | 507 | } |
michael@0 | 508 | |
michael@0 | 509 | { |
michael@0 | 510 | UErrorCode status = U_ZERO_ERROR; |
michael@0 | 511 | UResourceBundle* locbundle=ures_open(U_ICUDATA_LANG, displayLocale, &status); |
michael@0 | 512 | UResourceBundle* dspbundle=ures_getByKeyWithFallback(locbundle, _kLocaleDisplayPattern, |
michael@0 | 513 | NULL, &status); |
michael@0 | 514 | |
michael@0 | 515 | separator=ures_getStringByKeyWithFallback(dspbundle, _kSeparator, &sepLen, &status); |
michael@0 | 516 | pattern=ures_getStringByKeyWithFallback(dspbundle, _kPattern, &patLen, &status); |
michael@0 | 517 | |
michael@0 | 518 | ures_close(dspbundle); |
michael@0 | 519 | ures_close(locbundle); |
michael@0 | 520 | } |
michael@0 | 521 | |
michael@0 | 522 | /* If we couldn't find any data, then use the defaults */ |
michael@0 | 523 | if(sepLen == 0) { |
michael@0 | 524 | separator = defaultSeparator; |
michael@0 | 525 | } |
michael@0 | 526 | /* #10244: Even though separator is now a pattern, it is awkward to handle it as such |
michael@0 | 527 | * here since we are trying to build the display string in place in the dest buffer, |
michael@0 | 528 | * and to handle it as a pattern would entail having separate storage for the |
michael@0 | 529 | * substrings that need to be combined (the first of which may be the result of |
michael@0 | 530 | * previous such combinations). So for now we continue to treat the portion between |
michael@0 | 531 | * {0} and {1} as a string to be appended when joining substrings, ignoring anything |
michael@0 | 532 | * that is before {0} or after {1} (no existing separator pattern has any such thing). |
michael@0 | 533 | * This is similar to how pattern is handled below. |
michael@0 | 534 | */ |
michael@0 | 535 | { |
michael@0 | 536 | UChar *p0=u_strstr(separator, sub0); |
michael@0 | 537 | UChar *p1=u_strstr(separator, sub1); |
michael@0 | 538 | if (p0==NULL || p1==NULL || p1<p0) { |
michael@0 | 539 | *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; |
michael@0 | 540 | return 0; |
michael@0 | 541 | } |
michael@0 | 542 | separator = (const UChar *)p0 + subLen; |
michael@0 | 543 | sepLen = p1 - separator; |
michael@0 | 544 | } |
michael@0 | 545 | |
michael@0 | 546 | if(patLen==0 || (patLen==defaultPatLen && !u_strncmp(pattern, defaultPattern, patLen))) { |
michael@0 | 547 | pattern=defaultPattern; |
michael@0 | 548 | patLen=defaultPatLen; |
michael@0 | 549 | sub0Pos=defaultSub0Pos; |
michael@0 | 550 | sub1Pos=defaultSub1Pos; |
michael@0 | 551 | // use default formatOpenParen etc. set above |
michael@0 | 552 | } else { /* non-default pattern */ |
michael@0 | 553 | UChar *p0=u_strstr(pattern, sub0); |
michael@0 | 554 | UChar *p1=u_strstr(pattern, sub1); |
michael@0 | 555 | if (p0==NULL || p1==NULL) { |
michael@0 | 556 | *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; |
michael@0 | 557 | return 0; |
michael@0 | 558 | } |
michael@0 | 559 | sub0Pos=p0-pattern; |
michael@0 | 560 | sub1Pos=p1-pattern; |
michael@0 | 561 | if (sub1Pos < sub0Pos) { /* a very odd pattern */ |
michael@0 | 562 | int32_t t=sub0Pos; sub0Pos=sub1Pos; sub1Pos=t; |
michael@0 | 563 | langi=1; |
michael@0 | 564 | } |
michael@0 | 565 | if (u_strchr(pattern, 0xFF08) != NULL) { |
michael@0 | 566 | formatOpenParen = 0xFF08; // fullwidth ( |
michael@0 | 567 | formatReplaceOpenParen = 0xFF3B; // fullwidth [ |
michael@0 | 568 | formatCloseParen = 0xFF09; // fullwidth ) |
michael@0 | 569 | formatReplaceCloseParen = 0xFF3D; // fullwidth ] |
michael@0 | 570 | } |
michael@0 | 571 | } |
michael@0 | 572 | |
michael@0 | 573 | /* We loop here because there is one case in which after the first pass we could need to |
michael@0 | 574 | * reextract the data. If there's initial padding before the first element, we put in |
michael@0 | 575 | * the padding and then write that element. If it turns out there's no second element, |
michael@0 | 576 | * we didn't need the padding. If we do need the data (no preflight), and the first element |
michael@0 | 577 | * would have fit but for the padding, we need to reextract. In this case (only) we |
michael@0 | 578 | * adjust the parameters so padding is not added, and repeat. |
michael@0 | 579 | */ |
michael@0 | 580 | do { |
michael@0 | 581 | UChar* p=dest; |
michael@0 | 582 | int32_t patPos=0; /* position in the pattern, used for non-substitution portions */ |
michael@0 | 583 | int32_t langLen=0; /* length of language substitution */ |
michael@0 | 584 | int32_t langPos=0; /* position in output of language substitution */ |
michael@0 | 585 | int32_t restLen=0; /* length of 'everything else' substitution */ |
michael@0 | 586 | int32_t restPos=0; /* position in output of 'everything else' substitution */ |
michael@0 | 587 | UEnumeration* kenum = NULL; /* keyword enumeration */ |
michael@0 | 588 | |
michael@0 | 589 | /* prefix of pattern, extremely likely to be empty */ |
michael@0 | 590 | if(sub0Pos) { |
michael@0 | 591 | if(destCapacity >= sub0Pos) { |
michael@0 | 592 | while (patPos < sub0Pos) { |
michael@0 | 593 | *p++ = pattern[patPos++]; |
michael@0 | 594 | } |
michael@0 | 595 | } else { |
michael@0 | 596 | patPos=sub0Pos; |
michael@0 | 597 | } |
michael@0 | 598 | length=sub0Pos; |
michael@0 | 599 | } else { |
michael@0 | 600 | length=0; |
michael@0 | 601 | } |
michael@0 | 602 | |
michael@0 | 603 | for(int32_t subi=0,resti=0;subi<2;) { /* iterate through patterns 0 and 1*/ |
michael@0 | 604 | UBool subdone = FALSE; /* set true when ready to move to next substitution */ |
michael@0 | 605 | |
michael@0 | 606 | /* prep p and cap for calls to get display components, pin cap to 0 since |
michael@0 | 607 | they complain if cap is negative */ |
michael@0 | 608 | int32_t cap=destCapacity-length; |
michael@0 | 609 | if (cap <= 0) { |
michael@0 | 610 | cap=0; |
michael@0 | 611 | } else { |
michael@0 | 612 | p=dest+length; |
michael@0 | 613 | } |
michael@0 | 614 | |
michael@0 | 615 | if (subi == langi) { /* {0}*/ |
michael@0 | 616 | if(haveLang) { |
michael@0 | 617 | langPos=length; |
michael@0 | 618 | langLen=uloc_getDisplayLanguage(locale, displayLocale, p, cap, pErrorCode); |
michael@0 | 619 | length+=langLen; |
michael@0 | 620 | haveLang=langLen>0; |
michael@0 | 621 | } |
michael@0 | 622 | subdone=TRUE; |
michael@0 | 623 | } else { /* {1} */ |
michael@0 | 624 | if(!haveRest) { |
michael@0 | 625 | subdone=TRUE; |
michael@0 | 626 | } else { |
michael@0 | 627 | int32_t len; /* length of component (plus other stuff) we just fetched */ |
michael@0 | 628 | switch(resti++) { |
michael@0 | 629 | case 0: |
michael@0 | 630 | restPos=length; |
michael@0 | 631 | len=uloc_getDisplayScriptInContext(locale, displayLocale, p, cap, pErrorCode); |
michael@0 | 632 | break; |
michael@0 | 633 | case 1: |
michael@0 | 634 | len=uloc_getDisplayCountry(locale, displayLocale, p, cap, pErrorCode); |
michael@0 | 635 | break; |
michael@0 | 636 | case 2: |
michael@0 | 637 | len=uloc_getDisplayVariant(locale, displayLocale, p, cap, pErrorCode); |
michael@0 | 638 | break; |
michael@0 | 639 | case 3: |
michael@0 | 640 | kenum = uloc_openKeywords(locale, pErrorCode); |
michael@0 | 641 | /* fall through */ |
michael@0 | 642 | default: { |
michael@0 | 643 | const char* kw=uenum_next(kenum, &len, pErrorCode); |
michael@0 | 644 | if (kw == NULL) { |
michael@0 | 645 | uenum_close(kenum); |
michael@0 | 646 | len=0; /* mark that we didn't add a component */ |
michael@0 | 647 | subdone=TRUE; |
michael@0 | 648 | } else { |
michael@0 | 649 | /* incorporating this behavior into the loop made it even more complex, |
michael@0 | 650 | so just special case it here */ |
michael@0 | 651 | len = uloc_getDisplayKeyword(kw, displayLocale, p, cap, pErrorCode); |
michael@0 | 652 | if(len) { |
michael@0 | 653 | if(len < cap) { |
michael@0 | 654 | p[len]=0x3d; /* '=', assume we'll need it */ |
michael@0 | 655 | } |
michael@0 | 656 | len+=1; |
michael@0 | 657 | |
michael@0 | 658 | /* adjust for call to get keyword */ |
michael@0 | 659 | cap-=len; |
michael@0 | 660 | if(cap <= 0) { |
michael@0 | 661 | cap=0; |
michael@0 | 662 | } else { |
michael@0 | 663 | p+=len; |
michael@0 | 664 | } |
michael@0 | 665 | } |
michael@0 | 666 | /* reset for call below */ |
michael@0 | 667 | if(*pErrorCode == U_BUFFER_OVERFLOW_ERROR) { |
michael@0 | 668 | *pErrorCode=U_ZERO_ERROR; |
michael@0 | 669 | } |
michael@0 | 670 | int32_t vlen = uloc_getDisplayKeywordValue(locale, kw, displayLocale, |
michael@0 | 671 | p, cap, pErrorCode); |
michael@0 | 672 | if(len) { |
michael@0 | 673 | if(vlen==0) { |
michael@0 | 674 | --len; /* remove unneeded '=' */ |
michael@0 | 675 | } |
michael@0 | 676 | /* restore cap and p to what they were at start */ |
michael@0 | 677 | cap=destCapacity-length; |
michael@0 | 678 | if(cap <= 0) { |
michael@0 | 679 | cap=0; |
michael@0 | 680 | } else { |
michael@0 | 681 | p=dest+length; |
michael@0 | 682 | } |
michael@0 | 683 | } |
michael@0 | 684 | len+=vlen; /* total we added for key + '=' + value */ |
michael@0 | 685 | } |
michael@0 | 686 | } break; |
michael@0 | 687 | } /* end switch */ |
michael@0 | 688 | |
michael@0 | 689 | if (len>0) { |
michael@0 | 690 | /* we addeed a component, so add separator and write it if there's room. */ |
michael@0 | 691 | if(len+sepLen<=cap) { |
michael@0 | 692 | const UChar * plimit = p + len; |
michael@0 | 693 | for (; p < plimit; p++) { |
michael@0 | 694 | if (*p == formatOpenParen) { |
michael@0 | 695 | *p = formatReplaceOpenParen; |
michael@0 | 696 | } else if (*p == formatCloseParen) { |
michael@0 | 697 | *p = formatReplaceCloseParen; |
michael@0 | 698 | } |
michael@0 | 699 | } |
michael@0 | 700 | for(int32_t i=0;i<sepLen;++i) { |
michael@0 | 701 | *p++=separator[i]; |
michael@0 | 702 | } |
michael@0 | 703 | } |
michael@0 | 704 | length+=len+sepLen; |
michael@0 | 705 | } else if(subdone) { |
michael@0 | 706 | /* remove separator if we added it */ |
michael@0 | 707 | if (length!=restPos) { |
michael@0 | 708 | length-=sepLen; |
michael@0 | 709 | } |
michael@0 | 710 | restLen=length-restPos; |
michael@0 | 711 | haveRest=restLen>0; |
michael@0 | 712 | } |
michael@0 | 713 | } |
michael@0 | 714 | } |
michael@0 | 715 | |
michael@0 | 716 | if(*pErrorCode == U_BUFFER_OVERFLOW_ERROR) { |
michael@0 | 717 | *pErrorCode=U_ZERO_ERROR; |
michael@0 | 718 | } |
michael@0 | 719 | |
michael@0 | 720 | if(subdone) { |
michael@0 | 721 | if(haveLang && haveRest) { |
michael@0 | 722 | /* append internal portion of pattern, the first time, |
michael@0 | 723 | or last portion of pattern the second time */ |
michael@0 | 724 | int32_t padLen; |
michael@0 | 725 | patPos+=subLen; |
michael@0 | 726 | padLen=(subi==0 ? sub1Pos : patLen)-patPos; |
michael@0 | 727 | if(length+padLen < destCapacity) { |
michael@0 | 728 | p=dest+length; |
michael@0 | 729 | for(int32_t i=0;i<padLen;++i) { |
michael@0 | 730 | *p++=pattern[patPos++]; |
michael@0 | 731 | } |
michael@0 | 732 | } else { |
michael@0 | 733 | patPos+=padLen; |
michael@0 | 734 | } |
michael@0 | 735 | length+=padLen; |
michael@0 | 736 | } else if(subi==0) { |
michael@0 | 737 | /* don't have first component, reset for second component */ |
michael@0 | 738 | sub0Pos=0; |
michael@0 | 739 | length=0; |
michael@0 | 740 | } else if(length>0) { |
michael@0 | 741 | /* true length is the length of just the component we got. */ |
michael@0 | 742 | length=haveLang?langLen:restLen; |
michael@0 | 743 | if(dest && sub0Pos!=0) { |
michael@0 | 744 | if (sub0Pos+length<=destCapacity) { |
michael@0 | 745 | /* first component not at start of result, |
michael@0 | 746 | but we have full component in buffer. */ |
michael@0 | 747 | u_memmove(dest, dest+(haveLang?langPos:restPos), length); |
michael@0 | 748 | } else { |
michael@0 | 749 | /* would have fit, but didn't because of pattern prefix. */ |
michael@0 | 750 | sub0Pos=0; /* stops initial padding (and a second retry, |
michael@0 | 751 | so we won't end up here again) */ |
michael@0 | 752 | retry=TRUE; |
michael@0 | 753 | } |
michael@0 | 754 | } |
michael@0 | 755 | } |
michael@0 | 756 | |
michael@0 | 757 | ++subi; /* move on to next substitution */ |
michael@0 | 758 | } |
michael@0 | 759 | } |
michael@0 | 760 | } while(retry); |
michael@0 | 761 | |
michael@0 | 762 | return u_terminateUChars(dest, destCapacity, length, pErrorCode); |
michael@0 | 763 | } |
michael@0 | 764 | |
michael@0 | 765 | U_CAPI int32_t U_EXPORT2 |
michael@0 | 766 | uloc_getDisplayKeyword(const char* keyword, |
michael@0 | 767 | const char* displayLocale, |
michael@0 | 768 | UChar* dest, |
michael@0 | 769 | int32_t destCapacity, |
michael@0 | 770 | UErrorCode* status){ |
michael@0 | 771 | |
michael@0 | 772 | /* argument checking */ |
michael@0 | 773 | if(status==NULL || U_FAILURE(*status)) { |
michael@0 | 774 | return 0; |
michael@0 | 775 | } |
michael@0 | 776 | |
michael@0 | 777 | if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { |
michael@0 | 778 | *status=U_ILLEGAL_ARGUMENT_ERROR; |
michael@0 | 779 | return 0; |
michael@0 | 780 | } |
michael@0 | 781 | |
michael@0 | 782 | |
michael@0 | 783 | /* pass itemKey=NULL to look for a top-level item */ |
michael@0 | 784 | return _getStringOrCopyKey(U_ICUDATA_LANG, displayLocale, |
michael@0 | 785 | _kKeys, NULL, |
michael@0 | 786 | keyword, |
michael@0 | 787 | keyword, |
michael@0 | 788 | dest, destCapacity, |
michael@0 | 789 | status); |
michael@0 | 790 | |
michael@0 | 791 | } |
michael@0 | 792 | |
michael@0 | 793 | |
michael@0 | 794 | #define UCURRENCY_DISPLAY_NAME_INDEX 1 |
michael@0 | 795 | |
michael@0 | 796 | U_CAPI int32_t U_EXPORT2 |
michael@0 | 797 | uloc_getDisplayKeywordValue( const char* locale, |
michael@0 | 798 | const char* keyword, |
michael@0 | 799 | const char* displayLocale, |
michael@0 | 800 | UChar* dest, |
michael@0 | 801 | int32_t destCapacity, |
michael@0 | 802 | UErrorCode* status){ |
michael@0 | 803 | |
michael@0 | 804 | |
michael@0 | 805 | char keywordValue[ULOC_FULLNAME_CAPACITY*4]; |
michael@0 | 806 | int32_t capacity = ULOC_FULLNAME_CAPACITY*4; |
michael@0 | 807 | int32_t keywordValueLen =0; |
michael@0 | 808 | |
michael@0 | 809 | /* argument checking */ |
michael@0 | 810 | if(status==NULL || U_FAILURE(*status)) { |
michael@0 | 811 | return 0; |
michael@0 | 812 | } |
michael@0 | 813 | |
michael@0 | 814 | if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { |
michael@0 | 815 | *status=U_ILLEGAL_ARGUMENT_ERROR; |
michael@0 | 816 | return 0; |
michael@0 | 817 | } |
michael@0 | 818 | |
michael@0 | 819 | /* get the keyword value */ |
michael@0 | 820 | keywordValue[0]=0; |
michael@0 | 821 | keywordValueLen = uloc_getKeywordValue(locale, keyword, keywordValue, capacity, status); |
michael@0 | 822 | |
michael@0 | 823 | /* |
michael@0 | 824 | * if the keyword is equal to currency .. then to get the display name |
michael@0 | 825 | * we need to do the fallback ourselves |
michael@0 | 826 | */ |
michael@0 | 827 | if(uprv_stricmp(keyword, _kCurrency)==0){ |
michael@0 | 828 | |
michael@0 | 829 | int32_t dispNameLen = 0; |
michael@0 | 830 | const UChar *dispName = NULL; |
michael@0 | 831 | |
michael@0 | 832 | UResourceBundle *bundle = ures_open(U_ICUDATA_CURR, displayLocale, status); |
michael@0 | 833 | UResourceBundle *currencies = ures_getByKey(bundle, _kCurrencies, NULL, status); |
michael@0 | 834 | UResourceBundle *currency = ures_getByKeyWithFallback(currencies, keywordValue, NULL, status); |
michael@0 | 835 | |
michael@0 | 836 | dispName = ures_getStringByIndex(currency, UCURRENCY_DISPLAY_NAME_INDEX, &dispNameLen, status); |
michael@0 | 837 | |
michael@0 | 838 | /*close the bundles */ |
michael@0 | 839 | ures_close(currency); |
michael@0 | 840 | ures_close(currencies); |
michael@0 | 841 | ures_close(bundle); |
michael@0 | 842 | |
michael@0 | 843 | if(U_FAILURE(*status)){ |
michael@0 | 844 | if(*status == U_MISSING_RESOURCE_ERROR){ |
michael@0 | 845 | /* we just want to write the value over if nothing is available */ |
michael@0 | 846 | *status = U_USING_DEFAULT_WARNING; |
michael@0 | 847 | }else{ |
michael@0 | 848 | return 0; |
michael@0 | 849 | } |
michael@0 | 850 | } |
michael@0 | 851 | |
michael@0 | 852 | /* now copy the dispName over if not NULL */ |
michael@0 | 853 | if(dispName != NULL){ |
michael@0 | 854 | if(dispNameLen <= destCapacity){ |
michael@0 | 855 | uprv_memcpy(dest, dispName, dispNameLen * U_SIZEOF_UCHAR); |
michael@0 | 856 | return u_terminateUChars(dest, destCapacity, dispNameLen, status); |
michael@0 | 857 | }else{ |
michael@0 | 858 | *status = U_BUFFER_OVERFLOW_ERROR; |
michael@0 | 859 | return dispNameLen; |
michael@0 | 860 | } |
michael@0 | 861 | }else{ |
michael@0 | 862 | /* we have not found the display name for the value .. just copy over */ |
michael@0 | 863 | if(keywordValueLen <= destCapacity){ |
michael@0 | 864 | u_charsToUChars(keywordValue, dest, keywordValueLen); |
michael@0 | 865 | return u_terminateUChars(dest, destCapacity, keywordValueLen, status); |
michael@0 | 866 | }else{ |
michael@0 | 867 | *status = U_BUFFER_OVERFLOW_ERROR; |
michael@0 | 868 | return keywordValueLen; |
michael@0 | 869 | } |
michael@0 | 870 | } |
michael@0 | 871 | |
michael@0 | 872 | |
michael@0 | 873 | }else{ |
michael@0 | 874 | |
michael@0 | 875 | return _getStringOrCopyKey(U_ICUDATA_LANG, displayLocale, |
michael@0 | 876 | _kTypes, keyword, |
michael@0 | 877 | keywordValue, |
michael@0 | 878 | keywordValue, |
michael@0 | 879 | dest, destCapacity, |
michael@0 | 880 | status); |
michael@0 | 881 | } |
michael@0 | 882 | } |