tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ulocdata.cpp (11787B)


      1 // © 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 ******************************************************************************
      5 *                                                                            *
      6 * Copyright (C) 2003-2016, International Business Machines                   *
      7 *                Corporation and others. All Rights Reserved.                *
      8 *                                                                            *
      9 ******************************************************************************
     10 *   file name:  ulocdata.c
     11 *   encoding:   UTF-8
     12 *   tab size:   8 (not used)
     13 *   indentation:4
     14 *
     15 *   created on: 2003Oct21
     16 *   created by: Ram Viswanadha,John Emmons
     17 */
     18 
     19 #include "charstr.h"
     20 #include "cmemory.h"
     21 #include "unicode/ustring.h"
     22 #include "unicode/ures.h"
     23 #include "unicode/uloc.h"
     24 #include "unicode/ulocdata.h"
     25 #include "uresimp.h"
     26 #include "ureslocs.h"
     27 #include "ulocimp.h"
     28 
     29 #define MEASUREMENT_SYSTEM  "MeasurementSystem"
     30 #define PAPER_SIZE          "PaperSize"
     31 
     32 /** A locale data object.
     33 *  For usage in C programs.
     34 *  @draft ICU 3.4
     35 */
     36 struct ULocaleData {
     37    /**
     38     * Controls the "No Substitute" behavior of this locale data object
     39     */
     40    UBool noSubstitute;
     41 
     42    /**
     43     * Pointer to the resource bundle associated with this locale data object
     44     */
     45    UResourceBundle *bundle;
     46 
     47    /**
     48     * Pointer to the lang resource bundle associated with this locale data object
     49     */
     50    UResourceBundle *langBundle;
     51 };
     52 
     53 U_CAPI ULocaleData* U_EXPORT2
     54 ulocdata_open(const char *localeID, UErrorCode *status)
     55 {
     56   ULocaleData *uld;
     57 
     58   if (U_FAILURE(*status)) {
     59       return nullptr;
     60   }
     61 
     62   uld = (ULocaleData *)uprv_malloc(sizeof(ULocaleData));
     63   if (uld == nullptr) {
     64      *status = U_MEMORY_ALLOCATION_ERROR;
     65      return(nullptr);
     66   }
     67 
     68   uld->langBundle = nullptr;
     69 
     70   uld->noSubstitute = false;
     71   uld->bundle = ures_open(nullptr, localeID, status);
     72 
     73   if (U_FAILURE(*status)) {
     74      uprv_free(uld);
     75      return nullptr;
     76   }
     77 
     78   // ICU-22149: not all functions require lang data, so fail gracefully if it is not present
     79   UErrorCode oldStatus = *status;
     80   uld->langBundle = ures_open(U_ICUDATA_LANG, localeID, status);
     81   if (*status == U_MISSING_RESOURCE_ERROR) {
     82      *status = oldStatus;
     83   }
     84 
     85   return uld;
     86 }
     87 
     88 U_CAPI void U_EXPORT2
     89 ulocdata_close(ULocaleData *uld)
     90 {
     91    if ( uld != nullptr ) {
     92       ures_close(uld->langBundle);
     93       ures_close(uld->bundle);
     94       uprv_free(uld);
     95    }
     96 }
     97 
     98 U_CAPI void U_EXPORT2
     99 ulocdata_setNoSubstitute(ULocaleData *uld, UBool setting)
    100 {
    101   uld->noSubstitute = setting;
    102 }
    103 
    104 U_CAPI UBool U_EXPORT2
    105 ulocdata_getNoSubstitute(ULocaleData *uld)
    106 {
    107   return uld->noSubstitute;
    108 }
    109 
    110 U_CAPI USet* U_EXPORT2
    111 ulocdata_getExemplarSet(ULocaleData *uld, USet *fillIn,
    112                        uint32_t options, ULocaleDataExemplarSetType extype, UErrorCode *status){
    113 
    114    static const char* const exemplarSetTypes[] = { "ExemplarCharacters", 
    115                                                    "AuxExemplarCharacters", 
    116                                                    "ExemplarCharactersIndex",
    117                                                    "ExemplarCharactersPunctuation"};
    118    const char16_t *exemplarChars = nullptr;
    119    int32_t len = 0;
    120    UErrorCode localStatus = U_ZERO_ERROR;
    121 
    122    if (U_FAILURE(*status))
    123        return nullptr;
    124 
    125    exemplarChars = ures_getStringByKey(uld->bundle, exemplarSetTypes[extype], &len, &localStatus);
    126    if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
    127        localStatus = U_MISSING_RESOURCE_ERROR;
    128    }
    129 
    130    if (localStatus != U_ZERO_ERROR) {
    131        *status = localStatus;
    132    }
    133 
    134    if (U_FAILURE(*status))
    135        return nullptr;
    136 
    137    if(fillIn != nullptr)
    138        uset_applyPattern(fillIn, exemplarChars, len,
    139                          USET_IGNORE_SPACE | options, status);
    140    else
    141        fillIn = uset_openPatternOptions(exemplarChars, len,
    142                                         USET_IGNORE_SPACE | options, status);
    143 
    144    return fillIn;
    145 
    146 }
    147 
    148 U_CAPI int32_t U_EXPORT2
    149 ulocdata_getDelimiter(ULocaleData *uld, ULocaleDataDelimiterType type,
    150                      char16_t *result, int32_t resultLength, UErrorCode *status){
    151 
    152    static const char* const delimiterKeys[] =  {
    153        "quotationStart",
    154        "quotationEnd",
    155        "alternateQuotationStart",
    156        "alternateQuotationEnd"
    157    };
    158 
    159    UResourceBundle *delimiterBundle;
    160    int32_t len = 0;
    161    const char16_t *delimiter = nullptr;
    162    UErrorCode localStatus = U_ZERO_ERROR;
    163 
    164    if (U_FAILURE(*status))
    165        return 0;
    166 
    167    delimiterBundle = ures_getByKey(uld->bundle, "delimiters", nullptr, &localStatus);
    168 
    169    if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
    170        localStatus = U_MISSING_RESOURCE_ERROR;
    171    }
    172 
    173    if (localStatus != U_ZERO_ERROR) {
    174        *status = localStatus;
    175    }
    176 
    177    if (U_FAILURE(*status)){
    178        ures_close(delimiterBundle);
    179        return 0;
    180    }
    181 
    182    delimiter = ures_getStringByKeyWithFallback(delimiterBundle, delimiterKeys[type], &len, &localStatus);
    183    ures_close(delimiterBundle);
    184 
    185    if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
    186        localStatus = U_MISSING_RESOURCE_ERROR;
    187    }
    188 
    189    if (localStatus != U_ZERO_ERROR) {
    190        *status = localStatus;
    191    }
    192 
    193    if (U_FAILURE(*status)){
    194        return 0;
    195    }
    196 
    197    u_strncpy(result,delimiter, resultLength);
    198    return len;
    199 }
    200 
    201 namespace {
    202 
    203 UResourceBundle * measurementTypeBundleForLocale(const char *localeID, const char *measurementType, UErrorCode *status){
    204    if (U_FAILURE(*status)) { return nullptr; }
    205 
    206    UResourceBundle *rb;
    207    UResourceBundle *measTypeBundle = nullptr;
    208 
    209    icu::CharString region = ulocimp_getRegionForSupplementalData(localeID, true, *status);
    210 
    211    rb = ures_openDirect(nullptr, "supplementalData", status);
    212    ures_getByKey(rb, "measurementData", rb, status);
    213    if (rb != nullptr) {
    214        UResourceBundle *measDataBundle = ures_getByKey(rb, region.data(), nullptr, status);
    215        if (U_SUCCESS(*status)) {
    216        	measTypeBundle = ures_getByKey(measDataBundle, measurementType, nullptr, status);
    217        }
    218        if (*status == U_MISSING_RESOURCE_ERROR) {
    219            *status = U_ZERO_ERROR;
    220            if (measDataBundle != nullptr) {
    221                ures_close(measDataBundle);
    222            }
    223            measDataBundle = ures_getByKey(rb, "001", nullptr, status);
    224            measTypeBundle = ures_getByKey(measDataBundle, measurementType, nullptr, status);
    225        }
    226        ures_close(measDataBundle);
    227    }
    228    ures_close(rb);
    229    return measTypeBundle;
    230 }
    231 
    232 }  // namespace
    233 
    234 U_CAPI UMeasurementSystem U_EXPORT2
    235 ulocdata_getMeasurementSystem(const char *localeID, UErrorCode *status){
    236 
    237    UResourceBundle* measurement=nullptr;
    238    UMeasurementSystem system = UMS_LIMIT;
    239 
    240    if(status == nullptr || U_FAILURE(*status)){
    241        return system;
    242    }
    243 
    244    measurement = measurementTypeBundleForLocale(localeID, MEASUREMENT_SYSTEM, status);
    245    int32_t result = ures_getInt(measurement, status);
    246    if (U_SUCCESS(*status)) {
    247         system = static_cast<UMeasurementSystem>(result);
    248    }
    249 
    250    ures_close(measurement);
    251 
    252    return system;
    253 
    254 }
    255 
    256 U_CAPI void U_EXPORT2
    257 ulocdata_getPaperSize(const char* localeID, int32_t *height, int32_t *width, UErrorCode *status){
    258    UResourceBundle* paperSizeBundle = nullptr;
    259    const int32_t* paperSize=nullptr;
    260    int32_t len = 0;
    261 
    262    if(status == nullptr || U_FAILURE(*status)){
    263        return;
    264    }
    265 
    266    paperSizeBundle = measurementTypeBundleForLocale(localeID, PAPER_SIZE, status);
    267    paperSize = ures_getIntVector(paperSizeBundle, &len,  status);
    268 
    269    if(U_SUCCESS(*status)){
    270        if(len < 2){
    271            *status = U_INTERNAL_PROGRAM_ERROR;
    272        }else{
    273            *height = paperSize[0];
    274            *width  = paperSize[1];
    275        }
    276    }
    277 
    278    ures_close(paperSizeBundle);
    279 
    280 }
    281 
    282 U_CAPI void U_EXPORT2
    283 ulocdata_getCLDRVersion(UVersionInfo versionArray, UErrorCode *status) {
    284    if (U_FAILURE(*status)) { return; }
    285    UResourceBundle *rb = nullptr;
    286    rb = ures_openDirect(nullptr, "supplementalData", status);
    287    ures_getVersionByKey(rb, "cldrVersion", versionArray, status);
    288    ures_close(rb);
    289 }
    290 
    291 U_CAPI int32_t U_EXPORT2
    292 ulocdata_getLocaleDisplayPattern(ULocaleData *uld,
    293                                 char16_t *result,
    294                                 int32_t resultCapacity,
    295                                 UErrorCode *status) {
    296    UResourceBundle *patternBundle;
    297    int32_t len = 0;
    298    const char16_t *pattern = nullptr;
    299    UErrorCode localStatus = U_ZERO_ERROR;
    300 
    301    if (U_FAILURE(*status))
    302        return 0;
    303 
    304    if (uld->langBundle == nullptr) {
    305        *status = U_MISSING_RESOURCE_ERROR;
    306        return 0;
    307    }
    308 
    309    patternBundle = ures_getByKey(uld->langBundle, "localeDisplayPattern", nullptr, &localStatus);
    310 
    311    if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
    312        localStatus = U_MISSING_RESOURCE_ERROR;
    313    }
    314 
    315    if (localStatus != U_ZERO_ERROR) {
    316        *status = localStatus;
    317    }
    318 
    319    if (U_FAILURE(*status)){
    320        ures_close(patternBundle);
    321        return 0;
    322    }
    323 
    324    pattern = ures_getStringByKey(patternBundle, "pattern", &len, &localStatus);
    325    ures_close(patternBundle);
    326 
    327    if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
    328        localStatus = U_MISSING_RESOURCE_ERROR;
    329    }
    330 
    331    if (localStatus != U_ZERO_ERROR) {
    332        *status = localStatus;
    333    }
    334 
    335    if (U_FAILURE(*status)){
    336        return 0;
    337    }
    338 
    339    u_strncpy(result, pattern, resultCapacity);
    340    return len;
    341 }
    342 
    343 
    344 U_CAPI int32_t U_EXPORT2
    345 ulocdata_getLocaleSeparator(ULocaleData *uld,
    346                            char16_t *result,
    347                            int32_t resultCapacity,
    348                            UErrorCode *status)  {
    349    UResourceBundle *separatorBundle;
    350    int32_t len = 0;
    351    const char16_t *separator = nullptr;
    352    UErrorCode localStatus = U_ZERO_ERROR;
    353    char16_t *p0, *p1;
    354    static const char16_t sub0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 }; /* {0} */
    355    static const char16_t sub1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 }; /* {1} */
    356    static const int32_t subLen = 3;
    357 
    358    if (U_FAILURE(*status))
    359        return 0;
    360 
    361    if (uld->langBundle == nullptr) {
    362        *status = U_MISSING_RESOURCE_ERROR;
    363        return 0;
    364    }
    365 
    366    separatorBundle = ures_getByKey(uld->langBundle, "localeDisplayPattern", nullptr, &localStatus);
    367 
    368    if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
    369        localStatus = U_MISSING_RESOURCE_ERROR;
    370    }
    371 
    372    if (localStatus != U_ZERO_ERROR) {
    373        *status = localStatus;
    374    }
    375 
    376    if (U_FAILURE(*status)){
    377        ures_close(separatorBundle);
    378        return 0;
    379    }
    380 
    381    separator = ures_getStringByKey(separatorBundle, "separator", &len, &localStatus);
    382    ures_close(separatorBundle);
    383 
    384    if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
    385        localStatus = U_MISSING_RESOURCE_ERROR;
    386    }
    387 
    388    if (localStatus != U_ZERO_ERROR) {
    389        *status = localStatus;
    390    }
    391 
    392    if (U_FAILURE(*status)){
    393        return 0;
    394    }
    395 
    396    /* For backwards compatibility, if we have a pattern, return the portion between {0} and {1} */
    397    p0=u_strstr(separator, sub0);
    398    p1=u_strstr(separator, sub1);
    399    if (p0!=nullptr && p1!=nullptr && p0<=p1) {
    400        separator = (const char16_t *)p0 + subLen;
    401        len = static_cast<int32_t>(p1 - separator);
    402        /* Desired separator is no longer zero-terminated; handle that if necessary */
    403        if (len < resultCapacity) {
    404            u_strncpy(result, separator, len);
    405            result[len] = 0;
    406            return len;
    407        }
    408    }
    409 
    410    u_strncpy(result, separator, resultCapacity);
    411    return len;
    412 }