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