1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 ******************************************************************************
6 * Copyright (C) 2003-2016, International Business Machines *
7 * Corporation and others. All Rights Reserved. *
9 ******************************************************************************
10 * file name: ulocdata.c
12 * tab size: 8 (not used)
15 * created on: 2003Oct21
16 * created by: Ram Viswanadha,John Emmons
20 #include "unicode/ustring.h"
21 #include "unicode/ures.h"
22 #include "unicode/uloc.h"
23 #include "unicode/ulocdata.h"
28 #define MEASUREMENT_SYSTEM "MeasurementSystem"
29 #define PAPER_SIZE "PaperSize"
31 /** A locale data object.
32 * For usage in C programs.
37 * Controls the "No Substitute" behavior of this locale data object
42 * Pointer to the resource bundle associated with this locale data object
44 UResourceBundle
*bundle
;
47 * Pointer to the lang resource bundle associated with this locale data object
49 UResourceBundle
*langBundle
;
52 U_CAPI ULocaleData
* U_EXPORT2
53 ulocdata_open(const char *localeID
, UErrorCode
*status
)
57 if (U_FAILURE(*status
)) {
61 uld
= (ULocaleData
*)uprv_malloc(sizeof(ULocaleData
));
63 *status
= U_MEMORY_ALLOCATION_ERROR
;
67 uld
->langBundle
= NULL
;
69 uld
->noSubstitute
= FALSE
;
70 uld
->bundle
= ures_open(NULL
, localeID
, status
);
71 uld
->langBundle
= ures_open(U_ICUDATA_LANG
, localeID
, status
);
73 if (U_FAILURE(*status
)) {
82 ulocdata_close(ULocaleData
*uld
)
85 ures_close(uld
->langBundle
);
86 ures_close(uld
->bundle
);
92 ulocdata_setNoSubstitute(ULocaleData
*uld
, UBool setting
)
94 uld
->noSubstitute
= setting
;
97 U_CAPI UBool U_EXPORT2
98 ulocdata_getNoSubstitute(ULocaleData
*uld
)
100 return uld
->noSubstitute
;
103 U_CAPI USet
* U_EXPORT2
104 ulocdata_getExemplarSet(ULocaleData
*uld
, USet
*fillIn
,
105 uint32_t options
, ULocaleDataExemplarSetType extype
, UErrorCode
*status
){
107 static const char* const exemplarSetTypes
[] = { "ExemplarCharacters",
108 "AuxExemplarCharacters",
109 "ExemplarCharactersIndex",
110 "ExemplarCharactersPunctuation"};
111 const UChar
*exemplarChars
= NULL
;
113 UErrorCode localStatus
= U_ZERO_ERROR
;
115 if (U_FAILURE(*status
))
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
;
123 if (localStatus
!= U_ZERO_ERROR
) {
124 *status
= localStatus
;
127 if (U_FAILURE(*status
))
131 uset_applyPattern(fillIn
, exemplarChars
, len
,
132 USET_IGNORE_SPACE
| options
, status
);
134 fillIn
= uset_openPatternOptions(exemplarChars
, len
,
135 USET_IGNORE_SPACE
| options
, status
);
141 U_CAPI
int32_t U_EXPORT2
142 ulocdata_getDelimiter(ULocaleData
*uld
, ULocaleDataDelimiterType type
,
143 UChar
*result
, int32_t resultLength
, UErrorCode
*status
){
145 static const char* const delimiterKeys
[] = {
148 "alternateQuotationStart",
149 "alternateQuotationEnd"
152 UResourceBundle
*delimiterBundle
;
154 const UChar
*delimiter
= NULL
;
155 UErrorCode localStatus
= U_ZERO_ERROR
;
157 if (U_FAILURE(*status
))
160 delimiterBundle
= ures_getByKey(uld
->bundle
, "delimiters", NULL
, &localStatus
);
162 if ( (localStatus
== U_USING_DEFAULT_WARNING
) && uld
->noSubstitute
) {
163 localStatus
= U_MISSING_RESOURCE_ERROR
;
166 if (localStatus
!= U_ZERO_ERROR
) {
167 *status
= localStatus
;
170 if (U_FAILURE(*status
)){
171 ures_close(delimiterBundle
);
175 delimiter
= ures_getStringByKey(delimiterBundle
, delimiterKeys
[type
], &len
, &localStatus
);
176 ures_close(delimiterBundle
);
178 if ( (localStatus
== U_USING_DEFAULT_WARNING
) && uld
->noSubstitute
) {
179 localStatus
= U_MISSING_RESOURCE_ERROR
;
182 if (localStatus
!= U_ZERO_ERROR
) {
183 *status
= localStatus
;
186 if (U_FAILURE(*status
)){
190 u_strncpy(result
,delimiter
, resultLength
);
194 static UResourceBundle
* measurementTypeBundleForLocale(const char *localeID
, const char *measurementType
, UErrorCode
*status
){
195 char region
[ULOC_COUNTRY_CAPACITY
];
197 UResourceBundle
*measTypeBundle
= NULL
;
199 ulocimp_getRegionForSupplementalData(localeID
, TRUE
, region
, ULOC_COUNTRY_CAPACITY
, status
);
201 rb
= ures_openDirect(NULL
, "supplementalData", status
);
202 ures_getByKey(rb
, "measurementData", rb
, status
);
204 UResourceBundle
*measDataBundle
= ures_getByKey(rb
, region
, NULL
, status
);
205 if (U_SUCCESS(*status
)) {
206 measTypeBundle
= ures_getByKey(measDataBundle
, measurementType
, NULL
, status
);
208 if (*status
== U_MISSING_RESOURCE_ERROR
) {
209 *status
= U_ZERO_ERROR
;
210 if (measDataBundle
!= NULL
) {
211 ures_close(measDataBundle
);
213 measDataBundle
= ures_getByKey(rb
, "001", NULL
, status
);
214 measTypeBundle
= ures_getByKey(measDataBundle
, measurementType
, NULL
, status
);
216 ures_close(measDataBundle
);
219 return measTypeBundle
;
222 U_CAPI UMeasurementSystem U_EXPORT2
223 ulocdata_getMeasurementSystem(const char *localeID
, UErrorCode
*status
){
225 UResourceBundle
* measurement
=NULL
;
226 UMeasurementSystem system
= UMS_LIMIT
;
228 if(status
== NULL
|| U_FAILURE(*status
)){
232 measurement
= measurementTypeBundleForLocale(localeID
, MEASUREMENT_SYSTEM
, status
);
233 system
= (UMeasurementSystem
) ures_getInt(measurement
, status
);
235 ures_close(measurement
);
241 U_CAPI
void U_EXPORT2
242 ulocdata_getPaperSize(const char* localeID
, int32_t *height
, int32_t *width
, UErrorCode
*status
){
243 UResourceBundle
* paperSizeBundle
= NULL
;
244 const int32_t* paperSize
=NULL
;
247 if(status
== NULL
|| U_FAILURE(*status
)){
251 paperSizeBundle
= measurementTypeBundleForLocale(localeID
, PAPER_SIZE
, status
);
252 paperSize
= ures_getIntVector(paperSizeBundle
, &len
, status
);
254 if(U_SUCCESS(*status
)){
256 *status
= U_INTERNAL_PROGRAM_ERROR
;
258 *height
= paperSize
[0];
259 *width
= paperSize
[1];
263 ures_close(paperSizeBundle
);
267 U_CAPI
void U_EXPORT2
268 ulocdata_getCLDRVersion(UVersionInfo versionArray
, UErrorCode
*status
) {
269 UResourceBundle
*rb
= NULL
;
270 rb
= ures_openDirect(NULL
, "supplementalData", status
);
271 ures_getVersionByKey(rb
, "cldrVersion", versionArray
, status
);
275 U_CAPI
int32_t U_EXPORT2
276 ulocdata_getLocaleDisplayPattern(ULocaleData
*uld
,
278 int32_t resultCapacity
,
279 UErrorCode
*status
) {
280 UResourceBundle
*patternBundle
;
282 const UChar
*pattern
= NULL
;
283 UErrorCode localStatus
= U_ZERO_ERROR
;
285 if (U_FAILURE(*status
))
288 patternBundle
= ures_getByKey(uld
->langBundle
, "localeDisplayPattern", NULL
, &localStatus
);
290 if ( (localStatus
== U_USING_DEFAULT_WARNING
) && uld
->noSubstitute
) {
291 localStatus
= U_MISSING_RESOURCE_ERROR
;
294 if (localStatus
!= U_ZERO_ERROR
) {
295 *status
= localStatus
;
298 if (U_FAILURE(*status
)){
299 ures_close(patternBundle
);
303 pattern
= ures_getStringByKey(patternBundle
, "pattern", &len
, &localStatus
);
304 ures_close(patternBundle
);
306 if ( (localStatus
== U_USING_DEFAULT_WARNING
) && uld
->noSubstitute
) {
307 localStatus
= U_MISSING_RESOURCE_ERROR
;
310 if (localStatus
!= U_ZERO_ERROR
) {
311 *status
= localStatus
;
314 if (U_FAILURE(*status
)){
318 u_strncpy(result
, pattern
, resultCapacity
);
323 U_CAPI
int32_t U_EXPORT2
324 ulocdata_getLocaleSeparator(ULocaleData
*uld
,
326 int32_t resultCapacity
,
327 UErrorCode
*status
) {
328 UResourceBundle
*separatorBundle
;
330 const UChar
*separator
= NULL
;
331 UErrorCode localStatus
= U_ZERO_ERROR
;
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;
337 if (U_FAILURE(*status
))
340 separatorBundle
= ures_getByKey(uld
->langBundle
, "localeDisplayPattern", NULL
, &localStatus
);
342 if ( (localStatus
== U_USING_DEFAULT_WARNING
) && uld
->noSubstitute
) {
343 localStatus
= U_MISSING_RESOURCE_ERROR
;
346 if (localStatus
!= U_ZERO_ERROR
) {
347 *status
= localStatus
;
350 if (U_FAILURE(*status
)){
351 ures_close(separatorBundle
);
355 separator
= ures_getStringByKey(separatorBundle
, "separator", &len
, &localStatus
);
356 ures_close(separatorBundle
);
358 if ( (localStatus
== U_USING_DEFAULT_WARNING
) && uld
->noSubstitute
) {
359 localStatus
= U_MISSING_RESOURCE_ERROR
;
362 if (localStatus
!= U_ZERO_ERROR
) {
363 *status
= localStatus
;
366 if (U_FAILURE(*status
)){
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
);
384 u_strncpy(result
, separator
, resultCapacity
);