Home | History | Annotate | Download | only in common
      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