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