1 /* 2 ******************************************************************************* 3 * 4 * Copyright (C) 1997-2012, International Business Machines 5 * Corporation and others. All Rights Reserved. 6 * 7 ******************************************************************************* 8 * file name: loclikely.cpp 9 * encoding: US-ASCII 10 * tab size: 8 (not used) 11 * indentation:4 12 * 13 * created on: 2010feb25 14 * created by: Markus W. Scherer 15 * 16 * Code for miscellaneous locale-related resource bundle data access, 17 * separated out from other .cpp files 18 * that then do not depend on resource bundle code and this data. 19 */ 20 21 #include "unicode/utypes.h" 22 #include "unicode/putil.h" 23 #include "unicode/uloc.h" 24 #include "unicode/ures.h" 25 #include "cstring.h" 26 #include "ulocimp.h" 27 #include "uresimp.h" 28 29 /* 30 * Lookup a resource bundle table item with fallback on the table level. 31 * Regular resource bundle lookups perform fallback to parent locale bundles 32 * and eventually the root bundle, but only for top-level items. 33 * This function takes the name of a top-level table and of an item in that table 34 * and performs a lookup of both, falling back until a bundle contains a table 35 * with this item. 36 * 37 * Note: Only the opening of entire bundles falls back through the default locale 38 * before root. Once a bundle is open, item lookups do not go through the 39 * default locale because that would result in a mix of languages that is 40 * unpredictable to the programmer and most likely useless. 41 */ 42 U_CAPI const UChar * U_EXPORT2 43 uloc_getTableStringWithFallback(const char *path, const char *locale, 44 const char *tableKey, const char *subTableKey, 45 const char *itemKey, 46 int32_t *pLength, 47 UErrorCode *pErrorCode) 48 { 49 /* char localeBuffer[ULOC_FULLNAME_CAPACITY*4];*/ 50 UResourceBundle *rb=NULL, table, subTable; 51 const UChar *item=NULL; 52 UErrorCode errorCode; 53 char explicitFallbackName[ULOC_FULLNAME_CAPACITY] = {0}; 54 55 /* 56 * open the bundle for the current locale 57 * this falls back through the locale's chain to root 58 */ 59 errorCode=U_ZERO_ERROR; 60 rb=ures_open(path, locale, &errorCode); 61 62 if(U_FAILURE(errorCode)) { 63 /* total failure, not even root could be opened */ 64 *pErrorCode=errorCode; 65 return NULL; 66 } else if(errorCode==U_USING_DEFAULT_WARNING || 67 (errorCode==U_USING_FALLBACK_WARNING && *pErrorCode!=U_USING_DEFAULT_WARNING) 68 ) { 69 /* set the "strongest" error code (success->fallback->default->failure) */ 70 *pErrorCode=errorCode; 71 } 72 73 for(;;){ 74 ures_initStackObject(&table); 75 ures_initStackObject(&subTable); 76 ures_getByKeyWithFallback(rb, tableKey, &table, &errorCode); 77 78 if (subTableKey != NULL) { 79 /* 80 ures_getByKeyWithFallback(&table,subTableKey, &subTable, &errorCode); 81 item = ures_getStringByKeyWithFallback(&subTable, itemKey, pLength, &errorCode); 82 if(U_FAILURE(errorCode)){ 83 *pErrorCode = errorCode; 84 } 85 86 break;*/ 87 88 ures_getByKeyWithFallback(&table,subTableKey, &table, &errorCode); 89 } 90 if(U_SUCCESS(errorCode)){ 91 item = ures_getStringByKeyWithFallback(&table, itemKey, pLength, &errorCode); 92 if(U_FAILURE(errorCode)){ 93 const char* replacement = NULL; 94 *pErrorCode = errorCode; /*save the errorCode*/ 95 errorCode = U_ZERO_ERROR; 96 /* may be a deprecated code */ 97 if(uprv_strcmp(tableKey, "Countries")==0){ 98 replacement = uloc_getCurrentCountryID(itemKey); 99 }else if(uprv_strcmp(tableKey, "Languages")==0){ 100 replacement = uloc_getCurrentLanguageID(itemKey); 101 } 102 /*pointer comparison is ok since uloc_getCurrentCountryID & uloc_getCurrentLanguageID return the key itself is replacement is not found*/ 103 if(replacement!=NULL && itemKey != replacement){ 104 item = ures_getStringByKeyWithFallback(&table, replacement, pLength, &errorCode); 105 if(U_SUCCESS(errorCode)){ 106 *pErrorCode = errorCode; 107 break; 108 } 109 } 110 }else{ 111 break; 112 } 113 } 114 115 if(U_FAILURE(errorCode)){ 116 117 /* still can't figure out ?.. try the fallback mechanism */ 118 int32_t len = 0; 119 const UChar* fallbackLocale = NULL; 120 *pErrorCode = errorCode; 121 errorCode = U_ZERO_ERROR; 122 123 fallbackLocale = ures_getStringByKeyWithFallback(&table, "Fallback", &len, &errorCode); 124 if(U_FAILURE(errorCode)){ 125 *pErrorCode = errorCode; 126 break; 127 } 128 129 u_UCharsToChars(fallbackLocale, explicitFallbackName, len); 130 131 /* guard against recursive fallback */ 132 if(uprv_strcmp(explicitFallbackName, locale)==0){ 133 *pErrorCode = U_INTERNAL_PROGRAM_ERROR; 134 break; 135 } 136 ures_close(rb); 137 rb = ures_open(path, explicitFallbackName, &errorCode); 138 if(U_FAILURE(errorCode)){ 139 *pErrorCode = errorCode; 140 break; 141 } 142 /* succeeded in opening the fallback bundle .. continue and try to fetch the item */ 143 }else{ 144 break; 145 } 146 } 147 /* done with the locale string - ready to close table and rb */ 148 ures_close(&subTable); 149 ures_close(&table); 150 ures_close(rb); 151 return item; 152 } 153 154 static ULayoutType 155 _uloc_getOrientationHelper(const char* localeId, 156 const char* key, 157 UErrorCode *status) 158 { 159 ULayoutType result = ULOC_LAYOUT_UNKNOWN; 160 161 if (!U_FAILURE(*status)) { 162 int32_t length = 0; 163 char localeBuffer[ULOC_FULLNAME_CAPACITY]; 164 165 uloc_canonicalize(localeId, localeBuffer, sizeof(localeBuffer), status); 166 167 if (!U_FAILURE(*status)) { 168 const UChar* const value = 169 uloc_getTableStringWithFallback( 170 NULL, 171 localeBuffer, 172 "layout", 173 NULL, 174 key, 175 &length, 176 status); 177 178 if (!U_FAILURE(*status) && length != 0) { 179 switch(value[0]) 180 { 181 case 0x0062: /* 'b' */ 182 result = ULOC_LAYOUT_BTT; 183 break; 184 case 0x006C: /* 'l' */ 185 result = ULOC_LAYOUT_LTR; 186 break; 187 case 0x0072: /* 'r' */ 188 result = ULOC_LAYOUT_RTL; 189 break; 190 case 0x0074: /* 't' */ 191 result = ULOC_LAYOUT_TTB; 192 break; 193 default: 194 *status = U_INTERNAL_PROGRAM_ERROR; 195 break; 196 } 197 } 198 } 199 } 200 201 return result; 202 } 203 204 U_CAPI ULayoutType U_EXPORT2 205 uloc_getCharacterOrientation(const char* localeId, 206 UErrorCode *status) 207 { 208 return _uloc_getOrientationHelper(localeId, "characters", status); 209 } 210 211 /** 212 * Get the layout line orientation for the specified locale. 213 * 214 * @param localeID locale name 215 * @param status Error status 216 * @return an enum indicating the layout orientation for lines. 217 */ 218 U_CAPI ULayoutType U_EXPORT2 219 uloc_getLineOrientation(const char* localeId, 220 UErrorCode *status) 221 { 222 return _uloc_getOrientationHelper(localeId, "lines", status); 223 } 224