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 */ 16 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" 24 25 #define MEASUREMENT_SYSTEM "MeasurementSystem" 26 #define PAPER_SIZE "PaperSize" 27 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; 37 38 /** 39 * Pointer to the resource bundle associated with this locale data object 40 */ 41 UResourceBundle *bundle; 42 43 /** 44 * Pointer to the lang resource bundle associated with this locale data object 45 */ 46 UResourceBundle *langBundle; 47 }; 48 49 U_CAPI ULocaleData* U_EXPORT2 50 ulocdata_open(const char *localeID, UErrorCode *status) 51 { 52 ULocaleData *uld; 53 54 if (U_FAILURE(*status)) { 55 return NULL; 56 } 57 58 uld = (ULocaleData *)uprv_malloc(sizeof(ULocaleData)); 59 if (uld == NULL) { 60 *status = U_MEMORY_ALLOCATION_ERROR; 61 return(NULL); 62 } 63 64 uld->langBundle = NULL; 65 66 uld->noSubstitute = FALSE; 67 uld->bundle = ures_open(NULL, localeID, status); 68 uld->langBundle = ures_open(U_ICUDATA_LANG, localeID, status); 69 70 if (U_FAILURE(*status)) { 71 uprv_free(uld); 72 return NULL; 73 } 74 75 return uld; 76 } 77 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 } 87 88 U_CAPI void U_EXPORT2 89 ulocdata_setNoSubstitute(ULocaleData *uld, UBool setting) 90 { 91 uld->noSubstitute = setting; 92 } 93 94 U_CAPI UBool U_EXPORT2 95 ulocdata_getNoSubstitute(ULocaleData *uld) 96 { 97 return uld->noSubstitute; 98 } 99 100 U_CAPI USet* U_EXPORT2 101 ulocdata_getExemplarSet(ULocaleData *uld, USet *fillIn, 102 uint32_t options, ULocaleDataExemplarSetType extype, UErrorCode *status){ 103 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; 111 112 if (U_FAILURE(*status)) 113 return NULL; 114 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 } 119 120 if (localStatus != U_ZERO_ERROR) { 121 *status = localStatus; 122 } 123 124 if (U_FAILURE(*status)) 125 return NULL; 126 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); 133 134 return fillIn; 135 136 } 137 138 U_CAPI int32_t U_EXPORT2 139 ulocdata_getDelimiter(ULocaleData *uld, ULocaleDataDelimiterType type, 140 UChar *result, int32_t resultLength, UErrorCode *status){ 141 142 static const char* const delimiterKeys[] = { 143 "quotationStart", 144 "quotationEnd", 145 "alternateQuotationStart", 146 "alternateQuotationEnd" 147 }; 148 149 UResourceBundle *delimiterBundle; 150 int32_t len = 0; 151 const UChar *delimiter = NULL; 152 UErrorCode localStatus = U_ZERO_ERROR; 153 154 if (U_FAILURE(*status)) 155 return 0; 156 157 delimiterBundle = ures_getByKey(uld->bundle, "delimiters", NULL, &localStatus); 158 159 if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) { 160 localStatus = U_MISSING_RESOURCE_ERROR; 161 } 162 163 if (localStatus != U_ZERO_ERROR) { 164 *status = localStatus; 165 } 166 167 if (U_FAILURE(*status)){ 168 ures_close(delimiterBundle); 169 return 0; 170 } 171 172 delimiter = ures_getStringByKey(delimiterBundle, delimiterKeys[type], &len, &localStatus); 173 ures_close(delimiterBundle); 174 175 if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) { 176 localStatus = U_MISSING_RESOURCE_ERROR; 177 } 178 179 if (localStatus != U_ZERO_ERROR) { 180 *status = localStatus; 181 } 182 183 if (U_FAILURE(*status)){ 184 return 0; 185 } 186 187 u_strncpy(result,delimiter, resultLength); 188 return len; 189 } 190 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; 196 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); 202 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 } 223 224 U_CAPI UMeasurementSystem U_EXPORT2 225 ulocdata_getMeasurementSystem(const char *localeID, UErrorCode *status){ 226 227 UResourceBundle* measurement=NULL; 228 UMeasurementSystem system = UMS_LIMIT; 229 230 if(status == NULL || U_FAILURE(*status)){ 231 return system; 232 } 233 234 measurement = measurementTypeBundleForLocale(localeID, MEASUREMENT_SYSTEM, status); 235 system = (UMeasurementSystem) ures_getInt(measurement, status); 236 237 ures_close(measurement); 238 239 return system; 240 241 } 242 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; 248 249 if(status == NULL || U_FAILURE(*status)){ 250 return; 251 } 252 253 paperSizeBundle = measurementTypeBundleForLocale(localeID, PAPER_SIZE, status); 254 paperSize = ures_getIntVector(paperSizeBundle, &len, status); 255 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 } 264 265 ures_close(paperSizeBundle); 266 267 } 268 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 } 276 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; 286 287 if (U_FAILURE(*status)) 288 return 0; 289 290 patternBundle = ures_getByKey(uld->langBundle, "localeDisplayPattern", NULL, &localStatus); 291 292 if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) { 293 localStatus = U_MISSING_RESOURCE_ERROR; 294 } 295 296 if (localStatus != U_ZERO_ERROR) { 297 *status = localStatus; 298 } 299 300 if (U_FAILURE(*status)){ 301 ures_close(patternBundle); 302 return 0; 303 } 304 305 pattern = ures_getStringByKey(patternBundle, "pattern", &len, &localStatus); 306 ures_close(patternBundle); 307 308 if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) { 309 localStatus = U_MISSING_RESOURCE_ERROR; 310 } 311 312 if (localStatus != U_ZERO_ERROR) { 313 *status = localStatus; 314 } 315 316 if (U_FAILURE(*status)){ 317 return 0; 318 } 319 320 u_strncpy(result, pattern, resultCapacity); 321 return len; 322 } 323 324 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; 338 339 if (U_FAILURE(*status)) 340 return 0; 341 342 separatorBundle = ures_getByKey(uld->langBundle, "localeDisplayPattern", NULL, &localStatus); 343 344 if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) { 345 localStatus = U_MISSING_RESOURCE_ERROR; 346 } 347 348 if (localStatus != U_ZERO_ERROR) { 349 *status = localStatus; 350 } 351 352 if (U_FAILURE(*status)){ 353 ures_close(separatorBundle); 354 return 0; 355 } 356 357 separator = ures_getStringByKey(separatorBundle, "separator", &len, &localStatus); 358 ures_close(separatorBundle); 359 360 if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) { 361 localStatus = U_MISSING_RESOURCE_ERROR; 362 } 363 364 if (localStatus != U_ZERO_ERROR) { 365 *status = localStatus; 366 } 367 368 if (U_FAILURE(*status)){ 369 return 0; 370 } 371 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 } 385 386 u_strncpy(result, separator, resultCapacity); 387 return len; 388 } 389