|
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 } |