// © 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_getStringByKey(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; }