150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/*
250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*******************************************************************************
350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*
454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*   Copyright (C) 1997-2012, International Business Machines
550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*   Corporation and others.  All Rights Reserved.
650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*
750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*******************************************************************************
850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*   file name:  loclikely.cpp
950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*   encoding:   US-ASCII
1050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*   tab size:   8 (not used)
1150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*   indentation:4
1250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*
1350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*   created on: 2010feb25
1450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*   created by: Markus W. Scherer
1550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*
1650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*   Code for miscellaneous locale-related resource bundle data access,
1750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*   separated out from other .cpp files
1850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*   that then do not depend on resource bundle code and this data.
1950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho*/
2050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/utypes.h"
2250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/putil.h"
2350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/uloc.h"
2450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/ures.h"
2550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "cstring.h"
2650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "ulocimp.h"
2750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "uresimp.h"
2850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/*
3050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Lookup a resource bundle table item with fallback on the table level.
3150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Regular resource bundle lookups perform fallback to parent locale bundles
3250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * and eventually the root bundle, but only for top-level items.
3350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * This function takes the name of a top-level table and of an item in that table
3450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * and performs a lookup of both, falling back until a bundle contains a table
3550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * with this item.
3650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *
3750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Note: Only the opening of entire bundles falls back through the default locale
3850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * before root. Once a bundle is open, item lookups do not go through the
3950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * default locale because that would result in a mix of languages that is
4050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * unpredictable to the programmer and most likely useless.
4150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */
4250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI const UChar * U_EXPORT2
4350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehouloc_getTableStringWithFallback(const char *path, const char *locale,
4450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                              const char *tableKey, const char *subTableKey,
4550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                              const char *itemKey,
4650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                              int32_t *pLength,
4750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                              UErrorCode *pErrorCode)
4850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{
4950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/*    char localeBuffer[ULOC_FULLNAME_CAPACITY*4];*/
5050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle *rb=NULL, table, subTable;
5150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const UChar *item=NULL;
5250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UErrorCode errorCode;
5350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    char explicitFallbackName[ULOC_FULLNAME_CAPACITY] = {0};
5450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
5550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /*
5650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * open the bundle for the current locale
5750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * this falls back through the locale's chain to root
5850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
5950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    errorCode=U_ZERO_ERROR;
6050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    rb=ures_open(path, locale, &errorCode);
6150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
6250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(U_FAILURE(errorCode)) {
6350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /* total failure, not even root could be opened */
6450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        *pErrorCode=errorCode;
6550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return NULL;
6650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else if(errorCode==U_USING_DEFAULT_WARNING ||
6750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                (errorCode==U_USING_FALLBACK_WARNING && *pErrorCode!=U_USING_DEFAULT_WARNING)
6850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ) {
6950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /* set the "strongest" error code (success->fallback->default->failure) */
7050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        *pErrorCode=errorCode;
7150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
7250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
7350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    for(;;){
7450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_initStackObject(&table);
7550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_initStackObject(&subTable);
7650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_getByKeyWithFallback(rb, tableKey, &table, &errorCode);
7750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
7850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (subTableKey != NULL) {
7950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            /*
8050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            ures_getByKeyWithFallback(&table,subTableKey, &subTable, &errorCode);
8150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            item = ures_getStringByKeyWithFallback(&subTable, itemKey, pLength, &errorCode);
8250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(U_FAILURE(errorCode)){
8350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                *pErrorCode = errorCode;
8450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
8550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
8650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            break;*/
8750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
8850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            ures_getByKeyWithFallback(&table,subTableKey, &table, &errorCode);
8950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
9050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(U_SUCCESS(errorCode)){
9150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            item = ures_getStringByKeyWithFallback(&table, itemKey, pLength, &errorCode);
9250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(U_FAILURE(errorCode)){
9350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                const char* replacement = NULL;
9450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                *pErrorCode = errorCode; /*save the errorCode*/
9550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                errorCode = U_ZERO_ERROR;
9650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                /* may be a deprecated code */
9750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if(uprv_strcmp(tableKey, "Countries")==0){
9850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    replacement =  uloc_getCurrentCountryID(itemKey);
9950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }else if(uprv_strcmp(tableKey, "Languages")==0){
10050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    replacement =  uloc_getCurrentLanguageID(itemKey);
10150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
10250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                /*pointer comparison is ok since uloc_getCurrentCountryID & uloc_getCurrentLanguageID return the key itself is replacement is not found*/
10350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if(replacement!=NULL && itemKey != replacement){
10450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    item = ures_getStringByKeyWithFallback(&table, replacement, pLength, &errorCode);
10550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    if(U_SUCCESS(errorCode)){
10650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        *pErrorCode = errorCode;
10750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        break;
10850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    }
10950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
11050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }else{
11150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                break;
11250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
11350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
11450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
11550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(U_FAILURE(errorCode)){
11650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
11750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            /* still can't figure out ?.. try the fallback mechanism */
11850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            int32_t len = 0;
11950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            const UChar* fallbackLocale =  NULL;
12050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            *pErrorCode = errorCode;
12150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            errorCode = U_ZERO_ERROR;
12250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
12350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            fallbackLocale = ures_getStringByKeyWithFallback(&table, "Fallback", &len, &errorCode);
12450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(U_FAILURE(errorCode)){
12550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho               *pErrorCode = errorCode;
12650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                break;
12750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
12850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
12950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            u_UCharsToChars(fallbackLocale, explicitFallbackName, len);
13050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
13150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            /* guard against recursive fallback */
13250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(uprv_strcmp(explicitFallbackName, locale)==0){
13350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                *pErrorCode = U_INTERNAL_PROGRAM_ERROR;
13450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                break;
13550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
13650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            ures_close(rb);
13750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            rb = ures_open(path, explicitFallbackName, &errorCode);
13850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(U_FAILURE(errorCode)){
13950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                *pErrorCode = errorCode;
14050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                break;
14150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
14250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            /* succeeded in opening the fallback bundle .. continue and try to fetch the item */
14350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }else{
14450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            break;
14550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
14650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
14750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* done with the locale string - ready to close table and rb */
14850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_close(&subTable);
14950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_close(&table);
15050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_close(rb);
15150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return item;
15250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
15350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
15450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic ULayoutType
15550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho_uloc_getOrientationHelper(const char* localeId,
15650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                           const char* key,
15750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                           UErrorCode *status)
15850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{
15950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ULayoutType result = ULOC_LAYOUT_UNKNOWN;
16050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
16150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if (!U_FAILURE(*status)) {
16250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        int32_t length = 0;
16350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        char localeBuffer[ULOC_FULLNAME_CAPACITY];
16450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
16550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        uloc_canonicalize(localeId, localeBuffer, sizeof(localeBuffer), status);
16650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
16750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (!U_FAILURE(*status)) {
16850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            const UChar* const value =
16950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                uloc_getTableStringWithFallback(
17050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    NULL,
17150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    localeBuffer,
17250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    "layout",
17350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    NULL,
17450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    key,
17550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    &length,
17650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    status);
17750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
17850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if (!U_FAILURE(*status) && length != 0) {
17950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                switch(value[0])
18050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                {
18150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                case 0x0062: /* 'b' */
18250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    result = ULOC_LAYOUT_BTT;
18350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    break;
18450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                case 0x006C: /* 'l' */
18550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    result = ULOC_LAYOUT_LTR;
18650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    break;
18750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                case 0x0072: /* 'r' */
18850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    result = ULOC_LAYOUT_RTL;
18950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    break;
19050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                case 0x0074: /* 't' */
19150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    result = ULOC_LAYOUT_TTB;
19250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    break;
19350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                default:
19450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    *status = U_INTERNAL_PROGRAM_ERROR;
19550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    break;
19650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
19750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
19850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
19950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
20050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
20150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return result;
20250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
20350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
20454dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI ULayoutType U_EXPORT2
20550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehouloc_getCharacterOrientation(const char* localeId,
20650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                             UErrorCode *status)
20750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{
20850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return _uloc_getOrientationHelper(localeId, "characters", status);
20950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
21050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
21150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/**
21250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Get the layout line orientation for the specified locale.
21350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *
21450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * @param localeID locale name
21550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * @param status Error status
21650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * @return an enum indicating the layout orientation for lines.
21750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */
21854dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI ULayoutType U_EXPORT2
21950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehouloc_getLineOrientation(const char* localeId,
22050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        UErrorCode *status)
22150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{
22250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return _uloc_getOrientationHelper(localeId, "lines", status);
22350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
224