Line data Source code
1 : // © 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: UTF-8
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 : */
35 : struct 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 :
52 : U_CAPI ULocaleData* U_EXPORT2
53 0 : ulocdata_open(const char *localeID, UErrorCode *status)
54 : {
55 : ULocaleData *uld;
56 :
57 0 : if (U_FAILURE(*status)) {
58 0 : return NULL;
59 : }
60 :
61 0 : uld = (ULocaleData *)uprv_malloc(sizeof(ULocaleData));
62 0 : if (uld == NULL) {
63 0 : *status = U_MEMORY_ALLOCATION_ERROR;
64 0 : return(NULL);
65 : }
66 :
67 0 : uld->langBundle = NULL;
68 :
69 0 : uld->noSubstitute = FALSE;
70 0 : uld->bundle = ures_open(NULL, localeID, status);
71 0 : uld->langBundle = ures_open(U_ICUDATA_LANG, localeID, status);
72 :
73 0 : if (U_FAILURE(*status)) {
74 0 : uprv_free(uld);
75 0 : return NULL;
76 : }
77 :
78 0 : return uld;
79 : }
80 :
81 : U_CAPI void U_EXPORT2
82 0 : ulocdata_close(ULocaleData *uld)
83 : {
84 0 : if ( uld != NULL ) {
85 0 : ures_close(uld->langBundle);
86 0 : ures_close(uld->bundle);
87 0 : uprv_free(uld);
88 : }
89 0 : }
90 :
91 : U_CAPI void U_EXPORT2
92 0 : ulocdata_setNoSubstitute(ULocaleData *uld, UBool setting)
93 : {
94 0 : uld->noSubstitute = setting;
95 0 : }
96 :
97 : U_CAPI UBool U_EXPORT2
98 0 : ulocdata_getNoSubstitute(ULocaleData *uld)
99 : {
100 0 : return uld->noSubstitute;
101 : }
102 :
103 : U_CAPI USet* U_EXPORT2
104 0 : ulocdata_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 0 : const UChar *exemplarChars = NULL;
112 0 : int32_t len = 0;
113 0 : UErrorCode localStatus = U_ZERO_ERROR;
114 :
115 0 : if (U_FAILURE(*status))
116 0 : return NULL;
117 :
118 0 : exemplarChars = ures_getStringByKey(uld->bundle, exemplarSetTypes[extype], &len, &localStatus);
119 0 : if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
120 0 : localStatus = U_MISSING_RESOURCE_ERROR;
121 : }
122 :
123 0 : if (localStatus != U_ZERO_ERROR) {
124 0 : *status = localStatus;
125 : }
126 :
127 0 : if (U_FAILURE(*status))
128 0 : return NULL;
129 :
130 0 : if(fillIn != NULL)
131 0 : uset_applyPattern(fillIn, exemplarChars, len,
132 0 : USET_IGNORE_SPACE | options, status);
133 : else
134 0 : fillIn = uset_openPatternOptions(exemplarChars, len,
135 0 : USET_IGNORE_SPACE | options, status);
136 :
137 0 : return fillIn;
138 :
139 : }
140 :
141 : U_CAPI int32_t U_EXPORT2
142 0 : ulocdata_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 0 : int32_t len = 0;
154 0 : const UChar *delimiter = NULL;
155 0 : UErrorCode localStatus = U_ZERO_ERROR;
156 :
157 0 : if (U_FAILURE(*status))
158 0 : return 0;
159 :
160 0 : delimiterBundle = ures_getByKey(uld->bundle, "delimiters", NULL, &localStatus);
161 :
162 0 : if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
163 0 : localStatus = U_MISSING_RESOURCE_ERROR;
164 : }
165 :
166 0 : if (localStatus != U_ZERO_ERROR) {
167 0 : *status = localStatus;
168 : }
169 :
170 0 : if (U_FAILURE(*status)){
171 0 : ures_close(delimiterBundle);
172 0 : return 0;
173 : }
174 :
175 0 : delimiter = ures_getStringByKey(delimiterBundle, delimiterKeys[type], &len, &localStatus);
176 0 : ures_close(delimiterBundle);
177 :
178 0 : if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
179 0 : localStatus = U_MISSING_RESOURCE_ERROR;
180 : }
181 :
182 0 : if (localStatus != U_ZERO_ERROR) {
183 0 : *status = localStatus;
184 : }
185 :
186 0 : if (U_FAILURE(*status)){
187 0 : return 0;
188 : }
189 :
190 0 : u_strncpy(result,delimiter, resultLength);
191 0 : return len;
192 : }
193 :
194 0 : static UResourceBundle * measurementTypeBundleForLocale(const char *localeID, const char *measurementType, UErrorCode *status){
195 : char region[ULOC_COUNTRY_CAPACITY];
196 : UResourceBundle *rb;
197 0 : UResourceBundle *measTypeBundle = NULL;
198 :
199 0 : ulocimp_getRegionForSupplementalData(localeID, TRUE, region, ULOC_COUNTRY_CAPACITY, status);
200 :
201 0 : rb = ures_openDirect(NULL, "supplementalData", status);
202 0 : ures_getByKey(rb, "measurementData", rb, status);
203 0 : if (rb != NULL) {
204 0 : UResourceBundle *measDataBundle = ures_getByKey(rb, region, NULL, status);
205 0 : if (U_SUCCESS(*status)) {
206 0 : measTypeBundle = ures_getByKey(measDataBundle, measurementType, NULL, status);
207 : }
208 0 : if (*status == U_MISSING_RESOURCE_ERROR) {
209 0 : *status = U_ZERO_ERROR;
210 0 : if (measDataBundle != NULL) {
211 0 : ures_close(measDataBundle);
212 : }
213 0 : measDataBundle = ures_getByKey(rb, "001", NULL, status);
214 0 : measTypeBundle = ures_getByKey(measDataBundle, measurementType, NULL, status);
215 : }
216 0 : ures_close(measDataBundle);
217 : }
218 0 : ures_close(rb);
219 0 : return measTypeBundle;
220 : }
221 :
222 : U_CAPI UMeasurementSystem U_EXPORT2
223 0 : ulocdata_getMeasurementSystem(const char *localeID, UErrorCode *status){
224 :
225 0 : UResourceBundle* measurement=NULL;
226 0 : UMeasurementSystem system = UMS_LIMIT;
227 :
228 0 : if(status == NULL || U_FAILURE(*status)){
229 0 : return system;
230 : }
231 :
232 0 : measurement = measurementTypeBundleForLocale(localeID, MEASUREMENT_SYSTEM, status);
233 0 : system = (UMeasurementSystem) ures_getInt(measurement, status);
234 :
235 0 : ures_close(measurement);
236 :
237 0 : return system;
238 :
239 : }
240 :
241 : U_CAPI void U_EXPORT2
242 0 : ulocdata_getPaperSize(const char* localeID, int32_t *height, int32_t *width, UErrorCode *status){
243 0 : UResourceBundle* paperSizeBundle = NULL;
244 0 : const int32_t* paperSize=NULL;
245 0 : int32_t len = 0;
246 :
247 0 : if(status == NULL || U_FAILURE(*status)){
248 0 : return;
249 : }
250 :
251 0 : paperSizeBundle = measurementTypeBundleForLocale(localeID, PAPER_SIZE, status);
252 0 : paperSize = ures_getIntVector(paperSizeBundle, &len, status);
253 :
254 0 : if(U_SUCCESS(*status)){
255 0 : if(len < 2){
256 0 : *status = U_INTERNAL_PROGRAM_ERROR;
257 : }else{
258 0 : *height = paperSize[0];
259 0 : *width = paperSize[1];
260 : }
261 : }
262 :
263 0 : ures_close(paperSizeBundle);
264 :
265 : }
266 :
267 : U_CAPI void U_EXPORT2
268 0 : ulocdata_getCLDRVersion(UVersionInfo versionArray, UErrorCode *status) {
269 0 : UResourceBundle *rb = NULL;
270 0 : rb = ures_openDirect(NULL, "supplementalData", status);
271 0 : ures_getVersionByKey(rb, "cldrVersion", versionArray, status);
272 0 : ures_close(rb);
273 0 : }
274 :
275 : U_CAPI int32_t U_EXPORT2
276 0 : ulocdata_getLocaleDisplayPattern(ULocaleData *uld,
277 : UChar *result,
278 : int32_t resultCapacity,
279 : UErrorCode *status) {
280 : UResourceBundle *patternBundle;
281 0 : int32_t len = 0;
282 0 : const UChar *pattern = NULL;
283 0 : UErrorCode localStatus = U_ZERO_ERROR;
284 :
285 0 : if (U_FAILURE(*status))
286 0 : return 0;
287 :
288 0 : patternBundle = ures_getByKey(uld->langBundle, "localeDisplayPattern", NULL, &localStatus);
289 :
290 0 : if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
291 0 : localStatus = U_MISSING_RESOURCE_ERROR;
292 : }
293 :
294 0 : if (localStatus != U_ZERO_ERROR) {
295 0 : *status = localStatus;
296 : }
297 :
298 0 : if (U_FAILURE(*status)){
299 0 : ures_close(patternBundle);
300 0 : return 0;
301 : }
302 :
303 0 : pattern = ures_getStringByKey(patternBundle, "pattern", &len, &localStatus);
304 0 : ures_close(patternBundle);
305 :
306 0 : if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
307 0 : localStatus = U_MISSING_RESOURCE_ERROR;
308 : }
309 :
310 0 : if (localStatus != U_ZERO_ERROR) {
311 0 : *status = localStatus;
312 : }
313 :
314 0 : if (U_FAILURE(*status)){
315 0 : return 0;
316 : }
317 :
318 0 : u_strncpy(result, pattern, resultCapacity);
319 0 : return len;
320 : }
321 :
322 :
323 : U_CAPI int32_t U_EXPORT2
324 0 : ulocdata_getLocaleSeparator(ULocaleData *uld,
325 : UChar *result,
326 : int32_t resultCapacity,
327 : UErrorCode *status) {
328 : UResourceBundle *separatorBundle;
329 0 : int32_t len = 0;
330 0 : const UChar *separator = NULL;
331 0 : 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 0 : if (U_FAILURE(*status))
338 0 : return 0;
339 :
340 0 : separatorBundle = ures_getByKey(uld->langBundle, "localeDisplayPattern", NULL, &localStatus);
341 :
342 0 : if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
343 0 : localStatus = U_MISSING_RESOURCE_ERROR;
344 : }
345 :
346 0 : if (localStatus != U_ZERO_ERROR) {
347 0 : *status = localStatus;
348 : }
349 :
350 0 : if (U_FAILURE(*status)){
351 0 : ures_close(separatorBundle);
352 0 : return 0;
353 : }
354 :
355 0 : separator = ures_getStringByKey(separatorBundle, "separator", &len, &localStatus);
356 0 : ures_close(separatorBundle);
357 :
358 0 : if ( (localStatus == U_USING_DEFAULT_WARNING) && uld->noSubstitute ) {
359 0 : localStatus = U_MISSING_RESOURCE_ERROR;
360 : }
361 :
362 0 : if (localStatus != U_ZERO_ERROR) {
363 0 : *status = localStatus;
364 : }
365 :
366 0 : if (U_FAILURE(*status)){
367 0 : return 0;
368 : }
369 :
370 : /* For backwards compatibility, if we have a pattern, return the portion between {0} and {1} */
371 0 : p0=u_strstr(separator, sub0);
372 0 : p1=u_strstr(separator, sub1);
373 0 : if (p0!=NULL && p1!=NULL && p0<=p1) {
374 0 : separator = (const UChar *)p0 + subLen;
375 0 : len = p1 - separator;
376 : /* Desired separator is no longer zero-terminated; handle that if necessary */
377 0 : if (len < resultCapacity) {
378 0 : u_strncpy(result, separator, len);
379 0 : result[len] = 0;
380 0 : return len;
381 : }
382 : }
383 :
384 0 : u_strncpy(result, separator, resultCapacity);
385 0 : return len;
386 : }
|