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