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