intl/icu/source/i18n/ulocdata.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2 ******************************************************************************
     3 *                                                                            *
     4 * Copyright (C) 2003-2013, International Business Machines                   *
     5 *                Corporation and others. All Rights Reserved.                *
     6 *                                                                            *
     7 ******************************************************************************
     8 *   file name:  ulocdata.c
     9 *   encoding:   US-ASCII
    10 *   tab size:   8 (not used)
    11 *   indentation:4
    12 *
    13 *   created on: 2003Oct21
    14 *   created by: Ram Viswanadha,John Emmons
    15 */
    17 #include "cmemory.h"
    18 #include "unicode/ustring.h"
    19 #include "unicode/ures.h"
    20 #include "unicode/uloc.h"
    21 #include "unicode/ulocdata.h"
    22 #include "uresimp.h"
    23 #include "ureslocs.h"
    25 #define MEASUREMENT_SYSTEM  "MeasurementSystem"
    26 #define PAPER_SIZE          "PaperSize"
    28 /** A locale data object.
    29  *  For usage in C programs.
    30  *  @draft ICU 3.4
    31  */
    32 struct ULocaleData {
    33     /**
    34      * Controls the "No Substitute" behavior of this locale data object
    35      */
    36     UBool noSubstitute;
    38     /**
    39      * Pointer to the resource bundle associated with this locale data object
    40      */
    41     UResourceBundle *bundle;
    43     /**
    44      * Pointer to the lang resource bundle associated with this locale data object
    45      */
    46     UResourceBundle *langBundle;
    47 };
    49 U_CAPI ULocaleData* U_EXPORT2
    50 ulocdata_open(const char *localeID, UErrorCode *status)
    51 {
    52    ULocaleData *uld;
    54    if (U_FAILURE(*status)) {
    55        return NULL;
    56    }
    58    uld = (ULocaleData *)uprv_malloc(sizeof(ULocaleData));
    59    if (uld == NULL) {
    60       *status = U_MEMORY_ALLOCATION_ERROR;
    61       return(NULL);
    62    }
    64    uld->langBundle = NULL;
    66    uld->noSubstitute = FALSE;
    67    uld->bundle = ures_open(NULL, localeID, status);
    68    uld->langBundle = ures_open(U_ICUDATA_LANG, localeID, status);
    70    if (U_FAILURE(*status)) {
    71       uprv_free(uld);
    72       return NULL;
    73    }
    75    return uld;
    76 }
    78 U_CAPI void U_EXPORT2
    79 ulocdata_close(ULocaleData *uld)
    80 {
    81     if ( uld != NULL ) {
    82        ures_close(uld->langBundle);
    83        ures_close(uld->bundle);
    84        uprv_free(uld);
    85     }
    86 }
    88 U_CAPI void U_EXPORT2
    89 ulocdata_setNoSubstitute(ULocaleData *uld, UBool setting)
    90 {
    91    uld->noSubstitute = setting;
    92 }
    94 U_CAPI UBool U_EXPORT2
    95 ulocdata_getNoSubstitute(ULocaleData *uld)
    96 {
    97    return uld->noSubstitute;
    98 }
   100 U_CAPI USet* U_EXPORT2
   101 ulocdata_getExemplarSet(ULocaleData *uld, USet *fillIn,
   102                         uint32_t options, ULocaleDataExemplarSetType extype, UErrorCode *status){
   104     static const char* const exemplarSetTypes[] = { "ExemplarCharacters", 
   105                                                     "AuxExemplarCharacters", 
   106                                                     "ExemplarCharactersIndex",
   107                                                     "ExemplarCharactersPunctuation"};
   108     const UChar *exemplarChars = NULL;
   109     int32_t len = 0;
   110     UErrorCode localStatus = U_ZERO_ERROR;
   112     if (U_FAILURE(*status))
   113         return NULL;
   115     exemplarChars = ures_getStringByKey(uld->bundle, exemplarSetTypes[extype], &len, &localStatus);
   116     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
   117         localStatus = U_MISSING_RESOURCE_ERROR;
   118     }
   120     if (localStatus != U_ZERO_ERROR) {
   121         *status = localStatus;
   122     }
   124     if (U_FAILURE(*status))
   125         return NULL;
   127     if(fillIn != NULL)
   128         uset_applyPattern(fillIn, exemplarChars, len,
   129                           USET_IGNORE_SPACE | options, status);
   130     else
   131         fillIn = uset_openPatternOptions(exemplarChars, len,
   132                                          USET_IGNORE_SPACE | options, status);
   134     return fillIn;
   136 }
   138 U_CAPI int32_t U_EXPORT2
   139 ulocdata_getDelimiter(ULocaleData *uld, ULocaleDataDelimiterType type,
   140                       UChar *result, int32_t resultLength, UErrorCode *status){
   142     static const char* const delimiterKeys[] =  {
   143         "quotationStart",
   144         "quotationEnd",
   145         "alternateQuotationStart",
   146         "alternateQuotationEnd"
   147     };
   149     UResourceBundle *delimiterBundle;
   150     int32_t len = 0;
   151     const UChar *delimiter = NULL;
   152     UErrorCode localStatus = U_ZERO_ERROR;
   154     if (U_FAILURE(*status))
   155         return 0;
   157     delimiterBundle = ures_getByKey(uld->bundle, "delimiters", NULL, &localStatus);
   159     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
   160         localStatus = U_MISSING_RESOURCE_ERROR;
   161     }
   163     if (localStatus != U_ZERO_ERROR) {
   164         *status = localStatus;
   165     }
   167     if (U_FAILURE(*status)){
   168         ures_close(delimiterBundle);
   169         return 0;
   170     }
   172     delimiter = ures_getStringByKey(delimiterBundle, delimiterKeys[type], &len, &localStatus);
   173     ures_close(delimiterBundle);
   175     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
   176         localStatus = U_MISSING_RESOURCE_ERROR;
   177     }
   179     if (localStatus != U_ZERO_ERROR) {
   180         *status = localStatus;
   181     }
   183     if (U_FAILURE(*status)){
   184         return 0;
   185     }
   187     u_strncpy(result,delimiter, resultLength);
   188     return len;
   189 }
   191 static UResourceBundle * measurementTypeBundleForLocale(const char *localeID, const char *measurementType, UErrorCode *status){
   192     char fullLoc[ULOC_FULLNAME_CAPACITY];
   193     char region[ULOC_COUNTRY_CAPACITY];
   194     UResourceBundle *rb;
   195     UResourceBundle *measTypeBundle = NULL;
   197     /* The following code is basically copied from Calendar::setWeekData and
   198      * Calendar::getCalendarTypeForLocale with adjustments for resource name
   199      */
   200     uloc_addLikelySubtags(localeID, fullLoc, ULOC_FULLNAME_CAPACITY, status);
   201     uloc_getCountry(fullLoc, region, ULOC_COUNTRY_CAPACITY, status);
   203     rb = ures_openDirect(NULL, "supplementalData", status);
   204     ures_getByKey(rb, "measurementData", rb, status);
   205     if (rb != NULL) {
   206         UResourceBundle *measDataBundle = ures_getByKey(rb, region, NULL, status);
   207         if (U_SUCCESS(*status)) {
   208         	measTypeBundle = ures_getByKey(measDataBundle, measurementType, NULL, status);
   209         }
   210         if (*status == U_MISSING_RESOURCE_ERROR) {
   211             *status = U_ZERO_ERROR;
   212             if (measDataBundle != NULL) {
   213                 ures_close(measDataBundle);
   214             }
   215             measDataBundle = ures_getByKey(rb, "001", NULL, status);
   216             measTypeBundle = ures_getByKey(measDataBundle, measurementType, NULL, status);
   217         }
   218         ures_close(measDataBundle);
   219     }
   220     ures_close(rb);
   221     return measTypeBundle;
   222 }
   224 U_CAPI UMeasurementSystem U_EXPORT2
   225 ulocdata_getMeasurementSystem(const char *localeID, UErrorCode *status){
   227     UResourceBundle* measurement=NULL;
   228     UMeasurementSystem system = UMS_LIMIT;
   230     if(status == NULL || U_FAILURE(*status)){
   231         return system;
   232     }
   234     measurement = measurementTypeBundleForLocale(localeID, MEASUREMENT_SYSTEM, status);
   235     system = (UMeasurementSystem) ures_getInt(measurement, status);
   237     ures_close(measurement);
   239     return system;
   241 }
   243 U_CAPI void U_EXPORT2
   244 ulocdata_getPaperSize(const char* localeID, int32_t *height, int32_t *width, UErrorCode *status){
   245     UResourceBundle* paperSizeBundle = NULL;
   246     const int32_t* paperSize=NULL;
   247     int32_t len = 0;
   249     if(status == NULL || U_FAILURE(*status)){
   250         return;
   251     }
   253     paperSizeBundle = measurementTypeBundleForLocale(localeID, PAPER_SIZE, status);
   254     paperSize = ures_getIntVector(paperSizeBundle, &len,  status);
   256     if(U_SUCCESS(*status)){
   257         if(len < 2){
   258             *status = U_INTERNAL_PROGRAM_ERROR;
   259         }else{
   260             *height = paperSize[0];
   261             *width  = paperSize[1];
   262         }
   263     }
   265     ures_close(paperSizeBundle);
   267 }
   269 U_CAPI void U_EXPORT2
   270 ulocdata_getCLDRVersion(UVersionInfo versionArray, UErrorCode *status) {
   271     UResourceBundle *rb = NULL;
   272     rb = ures_openDirect(NULL, "supplementalData", status);
   273     ures_getVersionByKey(rb, "cldrVersion", versionArray, status);
   274     ures_close(rb);
   275 }
   277 U_CAPI int32_t U_EXPORT2
   278 ulocdata_getLocaleDisplayPattern(ULocaleData *uld,
   279                                  UChar *result,
   280                                  int32_t resultCapacity,
   281                                  UErrorCode *status) {
   282     UResourceBundle *patternBundle;
   283     int32_t len = 0;
   284     const UChar *pattern = NULL;
   285     UErrorCode localStatus = U_ZERO_ERROR;
   287     if (U_FAILURE(*status))
   288         return 0;
   290     patternBundle = ures_getByKey(uld->langBundle, "localeDisplayPattern", NULL, &localStatus);
   292     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
   293         localStatus = U_MISSING_RESOURCE_ERROR;
   294     }
   296     if (localStatus != U_ZERO_ERROR) {
   297         *status = localStatus;
   298     }
   300     if (U_FAILURE(*status)){
   301         ures_close(patternBundle);
   302         return 0;
   303     }
   305     pattern = ures_getStringByKey(patternBundle, "pattern", &len, &localStatus);
   306     ures_close(patternBundle);
   308     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
   309         localStatus = U_MISSING_RESOURCE_ERROR;
   310     }
   312     if (localStatus != U_ZERO_ERROR) {
   313         *status = localStatus;
   314     }
   316     if (U_FAILURE(*status)){
   317         return 0;
   318     }
   320     u_strncpy(result, pattern, resultCapacity);
   321     return len;
   322 }
   325 U_CAPI int32_t U_EXPORT2
   326 ulocdata_getLocaleSeparator(ULocaleData *uld,
   327                             UChar *result,
   328                             int32_t resultCapacity,
   329                             UErrorCode *status)  {
   330     UResourceBundle *separatorBundle;
   331     int32_t len = 0;
   332     const UChar *separator = NULL;
   333     UErrorCode localStatus = U_ZERO_ERROR;
   334     UChar *p0, *p1;
   335     static const UChar sub0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 }; /* {0} */
   336     static const UChar sub1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 }; /* {1} */
   337     static const int32_t subLen = 3;
   339     if (U_FAILURE(*status))
   340         return 0;
   342     separatorBundle = ures_getByKey(uld->langBundle, "localeDisplayPattern", NULL, &localStatus);
   344     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
   345         localStatus = U_MISSING_RESOURCE_ERROR;
   346     }
   348     if (localStatus != U_ZERO_ERROR) {
   349         *status = localStatus;
   350     }
   352     if (U_FAILURE(*status)){
   353         ures_close(separatorBundle);
   354         return 0;
   355     }
   357     separator = ures_getStringByKey(separatorBundle, "separator", &len, &localStatus);
   358     ures_close(separatorBundle);
   360     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
   361         localStatus = U_MISSING_RESOURCE_ERROR;
   362     }
   364     if (localStatus != U_ZERO_ERROR) {
   365         *status = localStatus;
   366     }
   368     if (U_FAILURE(*status)){
   369         return 0;
   370     }
   372     /* For backwards compatibility, if we have a pattern, return the portion between {0} and {1} */
   373     p0=u_strstr(separator, sub0);
   374     p1=u_strstr(separator, sub1);
   375     if (p0!=NULL && p1!=NULL && p0<=p1) {
   376         separator = (const UChar *)p0 + subLen;
   377         len = p1 - separator;
   378         /* Desired separator is no longer zero-terminated; handle that if necessary */
   379         if (len < resultCapacity) {
   380             u_strncpy(result, separator, len);
   381             result[len] = 0;
   382             return len;
   383         }
   384     }
   386     u_strncpy(result, separator, resultCapacity);
   387     return len;
   388 }

mercurial