387 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			387 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
| // © 2016 and later: Unicode, Inc. and others.
 | |
| // License & terms of use: http://www.unicode.org/copyright.html
 | |
| /*
 | |
| ******************************************************************************
 | |
| *                                                                            *
 | |
| * Copyright (C) 2003-2016, International Business Machines                   *
 | |
| *                Corporation and others. All Rights Reserved.                *
 | |
| *                                                                            *
 | |
| ******************************************************************************
 | |
| *   file name:  ulocdata.c
 | |
| *   encoding:   UTF-8
 | |
| *   tab size:   8 (not used)
 | |
| *   indentation:4
 | |
| *
 | |
| *   created on: 2003Oct21
 | |
| *   created by: Ram Viswanadha,John Emmons
 | |
| */
 | |
| 
 | |
| #include "cmemory.h"
 | |
| #include "unicode/ustring.h"
 | |
| #include "unicode/ures.h"
 | |
| #include "unicode/uloc.h"
 | |
| #include "unicode/ulocdata.h"
 | |
| #include "uresimp.h"
 | |
| #include "ureslocs.h"
 | |
| #include "ulocimp.h"
 | |
| 
 | |
| #define MEASUREMENT_SYSTEM  "MeasurementSystem"
 | |
| #define PAPER_SIZE          "PaperSize"
 | |
| 
 | |
| /** A locale data object.
 | |
|  *  For usage in C programs.
 | |
|  *  @draft ICU 3.4
 | |
|  */
 | |
| struct ULocaleData {
 | |
|     /**
 | |
|      * Controls the "No Substitute" behavior of this locale data object
 | |
|      */
 | |
|     UBool noSubstitute;
 | |
| 
 | |
|     /**
 | |
|      * Pointer to the resource bundle associated with this locale data object
 | |
|      */
 | |
|     UResourceBundle *bundle;
 | |
| 
 | |
|     /**
 | |
|      * Pointer to the lang resource bundle associated with this locale data object
 | |
|      */
 | |
|     UResourceBundle *langBundle;
 | |
| };
 | |
| 
 | |
| U_CAPI ULocaleData* U_EXPORT2
 | |
| ulocdata_open(const char *localeID, UErrorCode *status)
 | |
| {
 | |
|    ULocaleData *uld;
 | |
| 
 | |
|    if (U_FAILURE(*status)) {
 | |
|        return NULL;
 | |
|    }
 | |
| 
 | |
|    uld = (ULocaleData *)uprv_malloc(sizeof(ULocaleData));
 | |
|    if (uld == NULL) {
 | |
|       *status = U_MEMORY_ALLOCATION_ERROR;
 | |
|       return(NULL);
 | |
|    }
 | |
| 
 | |
|    uld->langBundle = NULL;
 | |
| 
 | |
|    uld->noSubstitute = FALSE;
 | |
|    uld->bundle = ures_open(NULL, localeID, status);
 | |
|    uld->langBundle = ures_open(U_ICUDATA_LANG, localeID, status);
 | |
| 
 | |
|    if (U_FAILURE(*status)) {
 | |
|       uprv_free(uld);
 | |
|       return NULL;
 | |
|    }
 | |
| 
 | |
|    return uld;
 | |
| }
 | |
| 
 | |
| U_CAPI void U_EXPORT2
 | |
| ulocdata_close(ULocaleData *uld)
 | |
| {
 | |
|     if ( uld != NULL ) {
 | |
|        ures_close(uld->langBundle);
 | |
|        ures_close(uld->bundle);
 | |
|        uprv_free(uld);
 | |
|     }
 | |
| }
 | |
| 
 | |
| U_CAPI void U_EXPORT2
 | |
| ulocdata_setNoSubstitute(ULocaleData *uld, UBool setting)
 | |
| {
 | |
|    uld->noSubstitute = setting;
 | |
| }
 | |
| 
 | |
| U_CAPI UBool U_EXPORT2
 | |
| ulocdata_getNoSubstitute(ULocaleData *uld)
 | |
| {
 | |
|    return uld->noSubstitute;
 | |
| }
 | |
| 
 | |
| U_CAPI USet* U_EXPORT2
 | |
| ulocdata_getExemplarSet(ULocaleData *uld, USet *fillIn,
 | |
|                         uint32_t options, ULocaleDataExemplarSetType extype, UErrorCode *status){
 | |
| 
 | |
|     static const char* const exemplarSetTypes[] = { "ExemplarCharacters", 
 | |
|                                                     "AuxExemplarCharacters", 
 | |
|                                                     "ExemplarCharactersIndex",
 | |
|                                                     "ExemplarCharactersPunctuation"};
 | |
|     const UChar *exemplarChars = NULL;
 | |
|     int32_t len = 0;
 | |
|     UErrorCode localStatus = U_ZERO_ERROR;
 | |
| 
 | |
|     if (U_FAILURE(*status))
 | |
|         return NULL;
 | |
| 
 | |
|     exemplarChars = ures_getStringByKey(uld->bundle, exemplarSetTypes[extype], &len, &localStatus);
 | |
|     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
 | |
|         localStatus = U_MISSING_RESOURCE_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (localStatus != U_ZERO_ERROR) {
 | |
|         *status = localStatus;
 | |
|     }
 | |
| 
 | |
|     if (U_FAILURE(*status))
 | |
|         return NULL;
 | |
| 
 | |
|     if(fillIn != NULL)
 | |
|         uset_applyPattern(fillIn, exemplarChars, len,
 | |
|                           USET_IGNORE_SPACE | options, status);
 | |
|     else
 | |
|         fillIn = uset_openPatternOptions(exemplarChars, len,
 | |
|                                          USET_IGNORE_SPACE | options, status);
 | |
| 
 | |
|     return fillIn;
 | |
| 
 | |
| }
 | |
| 
 | |
| U_CAPI int32_t U_EXPORT2
 | |
| ulocdata_getDelimiter(ULocaleData *uld, ULocaleDataDelimiterType type,
 | |
|                       UChar *result, int32_t resultLength, UErrorCode *status){
 | |
| 
 | |
|     static const char* const delimiterKeys[] =  {
 | |
|         "quotationStart",
 | |
|         "quotationEnd",
 | |
|         "alternateQuotationStart",
 | |
|         "alternateQuotationEnd"
 | |
|     };
 | |
| 
 | |
|     UResourceBundle *delimiterBundle;
 | |
|     int32_t len = 0;
 | |
|     const UChar *delimiter = NULL;
 | |
|     UErrorCode localStatus = U_ZERO_ERROR;
 | |
| 
 | |
|     if (U_FAILURE(*status))
 | |
|         return 0;
 | |
| 
 | |
|     delimiterBundle = ures_getByKey(uld->bundle, "delimiters", NULL, &localStatus);
 | |
| 
 | |
|     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
 | |
|         localStatus = U_MISSING_RESOURCE_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (localStatus != U_ZERO_ERROR) {
 | |
|         *status = localStatus;
 | |
|     }
 | |
| 
 | |
|     if (U_FAILURE(*status)){
 | |
|         ures_close(delimiterBundle);
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     delimiter = ures_getStringByKeyWithFallback(delimiterBundle, delimiterKeys[type], &len, &localStatus);
 | |
|     ures_close(delimiterBundle);
 | |
| 
 | |
|     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
 | |
|         localStatus = U_MISSING_RESOURCE_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (localStatus != U_ZERO_ERROR) {
 | |
|         *status = localStatus;
 | |
|     }
 | |
| 
 | |
|     if (U_FAILURE(*status)){
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     u_strncpy(result,delimiter, resultLength);
 | |
|     return len;
 | |
| }
 | |
| 
 | |
| static UResourceBundle * measurementTypeBundleForLocale(const char *localeID, const char *measurementType, UErrorCode *status){
 | |
|     char region[ULOC_COUNTRY_CAPACITY];
 | |
|     UResourceBundle *rb;
 | |
|     UResourceBundle *measTypeBundle = NULL;
 | |
|     
 | |
|     ulocimp_getRegionForSupplementalData(localeID, TRUE, region, ULOC_COUNTRY_CAPACITY, status);
 | |
|     
 | |
|     rb = ures_openDirect(NULL, "supplementalData", status);
 | |
|     ures_getByKey(rb, "measurementData", rb, status);
 | |
|     if (rb != NULL) {
 | |
|         UResourceBundle *measDataBundle = ures_getByKey(rb, region, NULL, status);
 | |
|         if (U_SUCCESS(*status)) {
 | |
|         	measTypeBundle = ures_getByKey(measDataBundle, measurementType, NULL, status);
 | |
|         }
 | |
|         if (*status == U_MISSING_RESOURCE_ERROR) {
 | |
|             *status = U_ZERO_ERROR;
 | |
|             if (measDataBundle != NULL) {
 | |
|                 ures_close(measDataBundle);
 | |
|             }
 | |
|             measDataBundle = ures_getByKey(rb, "001", NULL, status);
 | |
|             measTypeBundle = ures_getByKey(measDataBundle, measurementType, NULL, status);
 | |
|         }
 | |
|         ures_close(measDataBundle);
 | |
|     }
 | |
|     ures_close(rb);
 | |
|     return measTypeBundle;
 | |
| }
 | |
| 
 | |
| U_CAPI UMeasurementSystem U_EXPORT2
 | |
| ulocdata_getMeasurementSystem(const char *localeID, UErrorCode *status){
 | |
| 
 | |
|     UResourceBundle* measurement=NULL;
 | |
|     UMeasurementSystem system = UMS_LIMIT;
 | |
| 
 | |
|     if(status == NULL || U_FAILURE(*status)){
 | |
|         return system;
 | |
|     }
 | |
| 
 | |
|     measurement = measurementTypeBundleForLocale(localeID, MEASUREMENT_SYSTEM, status);
 | |
|     system = (UMeasurementSystem) ures_getInt(measurement, status);
 | |
| 
 | |
|     ures_close(measurement);
 | |
| 
 | |
|     return system;
 | |
| 
 | |
| }
 | |
| 
 | |
| U_CAPI void U_EXPORT2
 | |
| ulocdata_getPaperSize(const char* localeID, int32_t *height, int32_t *width, UErrorCode *status){
 | |
|     UResourceBundle* paperSizeBundle = NULL;
 | |
|     const int32_t* paperSize=NULL;
 | |
|     int32_t len = 0;
 | |
| 
 | |
|     if(status == NULL || U_FAILURE(*status)){
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     paperSizeBundle = measurementTypeBundleForLocale(localeID, PAPER_SIZE, status);
 | |
|     paperSize = ures_getIntVector(paperSizeBundle, &len,  status);
 | |
| 
 | |
|     if(U_SUCCESS(*status)){
 | |
|         if(len < 2){
 | |
|             *status = U_INTERNAL_PROGRAM_ERROR;
 | |
|         }else{
 | |
|             *height = paperSize[0];
 | |
|             *width  = paperSize[1];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     ures_close(paperSizeBundle);
 | |
| 
 | |
| }
 | |
| 
 | |
| U_CAPI void U_EXPORT2
 | |
| ulocdata_getCLDRVersion(UVersionInfo versionArray, UErrorCode *status) {
 | |
|     UResourceBundle *rb = NULL;
 | |
|     rb = ures_openDirect(NULL, "supplementalData", status);
 | |
|     ures_getVersionByKey(rb, "cldrVersion", versionArray, status);
 | |
|     ures_close(rb);
 | |
| }
 | |
| 
 | |
| U_CAPI int32_t U_EXPORT2
 | |
| ulocdata_getLocaleDisplayPattern(ULocaleData *uld,
 | |
|                                  UChar *result,
 | |
|                                  int32_t resultCapacity,
 | |
|                                  UErrorCode *status) {
 | |
|     UResourceBundle *patternBundle;
 | |
|     int32_t len = 0;
 | |
|     const UChar *pattern = NULL;
 | |
|     UErrorCode localStatus = U_ZERO_ERROR;
 | |
| 
 | |
|     if (U_FAILURE(*status))
 | |
|         return 0;
 | |
| 
 | |
|     patternBundle = ures_getByKey(uld->langBundle, "localeDisplayPattern", NULL, &localStatus);
 | |
| 
 | |
|     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
 | |
|         localStatus = U_MISSING_RESOURCE_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (localStatus != U_ZERO_ERROR) {
 | |
|         *status = localStatus;
 | |
|     }
 | |
| 
 | |
|     if (U_FAILURE(*status)){
 | |
|         ures_close(patternBundle);
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     pattern = ures_getStringByKey(patternBundle, "pattern", &len, &localStatus);
 | |
|     ures_close(patternBundle);
 | |
| 
 | |
|     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
 | |
|         localStatus = U_MISSING_RESOURCE_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (localStatus != U_ZERO_ERROR) {
 | |
|         *status = localStatus;
 | |
|     }
 | |
| 
 | |
|     if (U_FAILURE(*status)){
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     u_strncpy(result, pattern, resultCapacity);
 | |
|     return len;
 | |
| }
 | |
| 
 | |
| 
 | |
| U_CAPI int32_t U_EXPORT2
 | |
| ulocdata_getLocaleSeparator(ULocaleData *uld,
 | |
|                             UChar *result,
 | |
|                             int32_t resultCapacity,
 | |
|                             UErrorCode *status)  {
 | |
|     UResourceBundle *separatorBundle;
 | |
|     int32_t len = 0;
 | |
|     const UChar *separator = NULL;
 | |
|     UErrorCode localStatus = U_ZERO_ERROR;
 | |
|     UChar *p0, *p1;
 | |
|     static const UChar sub0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 }; /* {0} */
 | |
|     static const UChar sub1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 }; /* {1} */
 | |
|     static const int32_t subLen = 3;
 | |
| 
 | |
|     if (U_FAILURE(*status))
 | |
|         return 0;
 | |
| 
 | |
|     separatorBundle = ures_getByKey(uld->langBundle, "localeDisplayPattern", NULL, &localStatus);
 | |
| 
 | |
|     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
 | |
|         localStatus = U_MISSING_RESOURCE_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (localStatus != U_ZERO_ERROR) {
 | |
|         *status = localStatus;
 | |
|     }
 | |
| 
 | |
|     if (U_FAILURE(*status)){
 | |
|         ures_close(separatorBundle);
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     separator = ures_getStringByKey(separatorBundle, "separator", &len, &localStatus);
 | |
|     ures_close(separatorBundle);
 | |
| 
 | |
|     if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
 | |
|         localStatus = U_MISSING_RESOURCE_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (localStatus != U_ZERO_ERROR) {
 | |
|         *status = localStatus;
 | |
|     }
 | |
| 
 | |
|     if (U_FAILURE(*status)){
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     /* For backwards compatibility, if we have a pattern, return the portion between {0} and {1} */
 | |
|     p0=u_strstr(separator, sub0);
 | |
|     p1=u_strstr(separator, sub1);
 | |
|     if (p0!=NULL && p1!=NULL && p0<=p1) {
 | |
|         separator = (const UChar *)p0 + subLen;
 | |
|         len = static_cast<int32_t>(p1 - separator);
 | |
|         /* Desired separator is no longer zero-terminated; handle that if necessary */
 | |
|         if (len < resultCapacity) {
 | |
|             u_strncpy(result, separator, len);
 | |
|             result[len] = 0;
 | |
|             return len;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     u_strncpy(result, separator, resultCapacity);
 | |
|     return len;
 | |
| }
 |