]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ******************************************************************************* | |
374ca955 | 3 | * Copyright (C) 1997-2004, International Business Machines Corporation and * |
b75a7d8f A |
4 | * others. All Rights Reserved. * |
5 | ******************************************************************************* | |
6 | * | |
7 | * File DTFMTSYM.CPP | |
8 | * | |
9 | * Modification History: | |
10 | * | |
11 | * Date Name Description | |
12 | * 02/19/97 aliu Converted from java. | |
13 | * 07/21/98 stephen Added getZoneIndex | |
14 | * Changed weekdays/short weekdays to be one-based | |
15 | * 06/14/99 stephen Removed SimpleDateFormat::fgTimeZoneDataSuffix | |
16 | * 11/16/99 weiv Added 'Y' and 'e' to fgPatternChars | |
17 | * 03/27/00 weiv Keeping resource bundle around! | |
18 | ******************************************************************************* | |
19 | */ | |
20 | ||
21 | #include "unicode/utypes.h" | |
22 | ||
23 | #if !UCONFIG_NO_FORMATTING | |
24 | ||
25 | #include "unicode/dtfmtsym.h" | |
b75a7d8f A |
26 | #include "unicode/smpdtfmt.h" |
27 | #include "ucln_in.h" | |
28 | #include "mutex.h" | |
29 | #include "cmemory.h" | |
30 | #include "cstring.h" | |
374ca955 A |
31 | #include "locbased.h" |
32 | #include "gregoimp.h" | |
b75a7d8f A |
33 | |
34 | // ***************************************************************************** | |
35 | // class DateFormatSymbols | |
36 | // ***************************************************************************** | |
37 | /** | |
38 | * These are static arrays we use only in the case where we have no | |
39 | * resource data. | |
40 | */ | |
41 | ||
374ca955 | 42 | #define PATTERN_CHARS_LEN 24 |
b75a7d8f A |
43 | |
44 | /** | |
45 | * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All | |
46 | * locales use the same these unlocalized pattern characters. | |
47 | */ | |
374ca955 A |
48 | static const UChar gPatternChars[] = { |
49 | // GyMdkHmsSEDFwWahKzYeugAZ | |
b75a7d8f | 50 | 0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45, |
374ca955 A |
51 | 0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65, |
52 | 0x75, 0x67, 0x41, 0x5A, 0 | |
b75a7d8f A |
53 | }; |
54 | ||
55 | //------------------------------------------------------ | |
56 | // Strings of last resort. These are only used if we have no resource | |
57 | // files. They aren't designed for actual use, just for backup. | |
58 | ||
59 | // These are the month names and abbreviations of last resort. | |
60 | static const UChar gLastResortMonthNames[13][3] = | |
61 | { | |
62 | {0x0030, 0x0031, 0x0000}, /* "01" */ | |
63 | {0x0030, 0x0032, 0x0000}, /* "02" */ | |
64 | {0x0030, 0x0033, 0x0000}, /* "03" */ | |
65 | {0x0030, 0x0034, 0x0000}, /* "04" */ | |
66 | {0x0030, 0x0035, 0x0000}, /* "05" */ | |
67 | {0x0030, 0x0036, 0x0000}, /* "06" */ | |
68 | {0x0030, 0x0037, 0x0000}, /* "07" */ | |
69 | {0x0030, 0x0038, 0x0000}, /* "08" */ | |
70 | {0x0030, 0x0039, 0x0000}, /* "09" */ | |
71 | {0x0031, 0x0030, 0x0000}, /* "10" */ | |
72 | {0x0031, 0x0031, 0x0000}, /* "11" */ | |
73 | {0x0031, 0x0032, 0x0000}, /* "12" */ | |
74 | {0x0031, 0x0033, 0x0000} /* "13" */ | |
75 | }; | |
76 | ||
77 | // These are the weekday names and abbreviations of last resort. | |
78 | static const UChar gLastResortDayNames[8][2] = | |
79 | { | |
80 | {0x0000, 0x0000}, /* "" */ | |
81 | {0x0031, 0x0000}, /* "1" */ | |
82 | {0x0032, 0x0000}, /* "2" */ | |
83 | {0x0033, 0x0000}, /* "3" */ | |
84 | {0x0034, 0x0000}, /* "4" */ | |
85 | {0x0035, 0x0000}, /* "5" */ | |
86 | {0x0036, 0x0000}, /* "6" */ | |
87 | {0x0037, 0x0000} /* "7" */ | |
88 | }; | |
89 | ||
90 | // These are the am/pm and BC/AD markers of last resort. | |
91 | static const UChar gLastResortAmPmMarkers[2][3] = | |
92 | { | |
93 | {0x0041, 0x004D, 0x0000}, /* "AM" */ | |
94 | {0x0050, 0x004D, 0x0000} /* "PM" */ | |
95 | }; | |
96 | ||
97 | static const UChar gLastResortEras[2][3] = | |
98 | { | |
99 | {0x0042, 0x0043, 0x0000}, /* "BC" */ | |
100 | {0x0041, 0x0044, 0x0000} /* "AD" */ | |
101 | }; | |
102 | ||
103 | ||
104 | // These are the zone strings of last resort. | |
105 | static const UChar gLastResortZoneStrings[5][4] = | |
106 | { | |
107 | {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ | |
108 | {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ | |
109 | {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ | |
110 | {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ | |
111 | {0x0047, 0x004D, 0x0054, 0x0000} /* "GMT" */ | |
112 | }; | |
113 | ||
114 | U_NAMESPACE_BEGIN | |
115 | ||
374ca955 | 116 | UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols) |
b75a7d8f A |
117 | |
118 | /** | |
119 | * These are the tags we expect to see in normal resource bundle files associated | |
374ca955 | 120 | * with a locale and calendar |
b75a7d8f | 121 | */ |
374ca955 A |
122 | const char gErasTag[]="eras"; |
123 | const char gAbbreviatedTag[] = "abbreviated"; | |
124 | const char gMonthNamesTag[]="monthNames"; | |
125 | const char gDayNamesTag[]="dayNames"; | |
126 | const char gNamesWideTag[]="wide"; | |
127 | const char gNamesAbbrTag[]="abbreviated"; | |
128 | const char gAmPmMarkersTag[]="AmPmMarkers"; | |
b75a7d8f A |
129 | |
130 | /** | |
131 | * These are the tags we expect to see in time zone data resource bundle files | |
132 | * associated with a locale. | |
133 | */ | |
374ca955 A |
134 | const char gZoneStringsTag[]="zoneStrings"; |
135 | const char gLocalPatternCharsTag[]="localPatternChars"; | |
b75a7d8f A |
136 | |
137 | /** | |
138 | * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly. | |
139 | * Work around this. | |
140 | */ | |
141 | static inline UnicodeString* newUnicodeStringArray(size_t count) { | |
142 | return new UnicodeString[count ? count : 1]; | |
143 | } | |
144 | ||
145 | //------------------------------------------------------ | |
146 | ||
147 | DateFormatSymbols::DateFormatSymbols(const Locale& locale, | |
148 | UErrorCode& status) | |
149 | : UObject() | |
150 | { | |
151 | initializeData(locale, NULL, status); | |
152 | } | |
153 | ||
154 | DateFormatSymbols::DateFormatSymbols(UErrorCode& status) | |
155 | : UObject() | |
156 | { | |
157 | initializeData(Locale::getDefault(), NULL, status, TRUE); | |
158 | } | |
159 | ||
160 | ||
161 | DateFormatSymbols::DateFormatSymbols(const Locale& locale, | |
162 | const char *type, | |
163 | UErrorCode& status) | |
164 | : UObject() | |
165 | { | |
166 | initializeData(locale, type, status); | |
167 | } | |
168 | ||
169 | DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status) | |
170 | : UObject() | |
171 | { | |
172 | initializeData(Locale::getDefault(), type, status, TRUE); | |
173 | } | |
174 | ||
175 | DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other) | |
176 | : UObject(other) | |
177 | { | |
178 | copyData(other); | |
179 | } | |
180 | ||
181 | void | |
182 | DateFormatSymbols::assignArray(UnicodeString*& dstArray, | |
183 | int32_t& dstCount, | |
184 | const UnicodeString* srcArray, | |
185 | int32_t srcCount) | |
186 | { | |
187 | // assignArray() is only called by copyData(), which in turn implements the | |
188 | // copy constructor and the assignment operator. | |
189 | // All strings in a DateFormatSymbols object are created in one of the following | |
190 | // three ways that all allow to safely use UnicodeString::fastCopyFrom(): | |
191 | // - readonly-aliases from resource bundles | |
192 | // - readonly-aliases or allocated strings from constants | |
193 | // - safely cloned strings (with owned buffers) from setXYZ() functions | |
194 | // | |
195 | // Note that this is true for as long as DateFormatSymbols can be constructed | |
196 | // only from a locale bundle or set via the cloning API, | |
197 | // *and* for as long as all the strings are in *private* fields, preventing | |
198 | // a subclass from creating these strings in an "unsafe" way (with respect to fastCopyFrom()). | |
199 | dstCount = srcCount; | |
200 | dstArray = newUnicodeStringArray(srcCount); | |
201 | if(dstArray != NULL) { | |
202 | int32_t i; | |
203 | for(i=0; i<srcCount; ++i) { | |
204 | dstArray[i].fastCopyFrom(srcArray[i]); | |
205 | } | |
206 | } | |
207 | } | |
208 | ||
209 | /** | |
210 | * Create a copy, in fZoneStrings, of the given zone strings array. The | |
211 | * member variables fZoneStringsRowCount and fZoneStringsColCount should | |
212 | * be set already by the caller. | |
213 | */ | |
214 | void | |
215 | DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings) | |
216 | { | |
217 | int32_t row, col; | |
218 | ||
219 | fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *)); | |
220 | for (row=0; row<fZoneStringsRowCount; ++row) | |
221 | { | |
222 | fZoneStrings[row] = newUnicodeStringArray(fZoneStringsColCount); | |
223 | for (col=0; col<fZoneStringsColCount; ++col) { | |
224 | // fastCopyFrom() - see assignArray comments | |
225 | fZoneStrings[row][col].fastCopyFrom(otherStrings[row][col]); | |
226 | } | |
227 | } | |
228 | } | |
229 | ||
230 | /** | |
231 | * Copy all of the other's data to this. | |
232 | */ | |
233 | void | |
234 | DateFormatSymbols::copyData(const DateFormatSymbols& other) { | |
235 | assignArray(fEras, fErasCount, other.fEras, other.fErasCount); | |
236 | assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount); | |
237 | assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount); | |
238 | assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount); | |
239 | assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount); | |
240 | assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount); | |
241 | ||
242 | fZoneStringsRowCount = other.fZoneStringsRowCount; | |
243 | fZoneStringsColCount = other.fZoneStringsColCount; | |
244 | createZoneStrings((const UnicodeString**)other.fZoneStrings); | |
245 | ||
246 | // fastCopyFrom() - see assignArray comments | |
247 | fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars); | |
248 | } | |
249 | ||
250 | /** | |
251 | * Assignment operator. | |
252 | */ | |
253 | DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other) | |
254 | { | |
255 | dispose(); | |
256 | copyData(other); | |
257 | ||
258 | return *this; | |
259 | } | |
260 | ||
261 | DateFormatSymbols::~DateFormatSymbols() | |
262 | { | |
263 | dispose(); | |
264 | } | |
265 | ||
266 | void DateFormatSymbols::dispose() | |
267 | { | |
268 | if (fEras) delete[] fEras; | |
269 | if (fMonths) delete[] fMonths; | |
270 | if (fShortMonths) delete[] fShortMonths; | |
271 | if (fWeekdays) delete[] fWeekdays; | |
272 | if (fShortWeekdays) delete[] fShortWeekdays; | |
273 | if (fAmPms) delete[] fAmPms; | |
274 | ||
275 | disposeZoneStrings(); | |
276 | } | |
277 | ||
278 | void DateFormatSymbols::disposeZoneStrings() | |
279 | { | |
280 | if (fZoneStrings) { | |
281 | for (int32_t row=0; row<fZoneStringsRowCount; ++row) | |
282 | delete[] fZoneStrings[row]; | |
283 | uprv_free(fZoneStrings); | |
284 | } | |
285 | } | |
286 | ||
287 | UBool | |
288 | DateFormatSymbols::arrayCompare(const UnicodeString* array1, | |
289 | const UnicodeString* array2, | |
290 | int32_t count) | |
291 | { | |
292 | if (array1 == array2) return TRUE; | |
293 | while (count>0) | |
294 | { | |
295 | --count; | |
296 | if (array1[count] != array2[count]) return FALSE; | |
297 | } | |
298 | return TRUE; | |
299 | } | |
300 | ||
301 | UBool | |
302 | DateFormatSymbols::operator==(const DateFormatSymbols& other) const | |
303 | { | |
304 | // First do cheap comparisons | |
305 | if (this == &other) { | |
306 | return TRUE; | |
307 | } | |
308 | if (fErasCount == other.fErasCount && | |
309 | fMonthsCount == other.fMonthsCount && | |
310 | fShortMonthsCount == other.fShortMonthsCount && | |
311 | fWeekdaysCount == other.fWeekdaysCount && | |
312 | fShortWeekdaysCount == other.fShortWeekdaysCount && | |
313 | fAmPmsCount == other.fAmPmsCount && | |
314 | fZoneStringsRowCount == other.fZoneStringsRowCount && | |
315 | fZoneStringsColCount == other.fZoneStringsColCount) | |
316 | { | |
317 | // Now compare the arrays themselves | |
318 | if (arrayCompare(fEras, other.fEras, fErasCount) && | |
319 | arrayCompare(fMonths, other.fMonths, fMonthsCount) && | |
320 | arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) && | |
321 | arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) && | |
322 | arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) && | |
323 | arrayCompare(fAmPms, other.fAmPms, fAmPmsCount)) | |
324 | { | |
325 | if (fZoneStrings == other.fZoneStrings) return TRUE; | |
326 | ||
327 | for (int32_t row=0; row<fZoneStringsRowCount; ++row) | |
328 | { | |
329 | if (!arrayCompare(fZoneStrings[row], other.fZoneStrings[row], fZoneStringsColCount)) | |
330 | return FALSE; | |
331 | } | |
332 | return TRUE; | |
333 | } | |
334 | } | |
335 | return FALSE; | |
336 | } | |
337 | ||
338 | //------------------------------------------------------ | |
339 | ||
340 | const UnicodeString* | |
341 | DateFormatSymbols::getEras(int32_t &count) const | |
342 | { | |
343 | count = fErasCount; | |
344 | return fEras; | |
345 | } | |
346 | ||
347 | const UnicodeString* | |
348 | DateFormatSymbols::getMonths(int32_t &count) const | |
349 | { | |
350 | count = fMonthsCount; | |
351 | return fMonths; | |
352 | } | |
353 | ||
354 | const UnicodeString* | |
355 | DateFormatSymbols::getShortMonths(int32_t &count) const | |
356 | { | |
357 | count = fShortMonthsCount; | |
358 | return fShortMonths; | |
359 | } | |
360 | ||
361 | const UnicodeString* | |
362 | DateFormatSymbols::getWeekdays(int32_t &count) const | |
363 | { | |
364 | count = fWeekdaysCount; | |
365 | return fWeekdays; | |
366 | } | |
367 | ||
368 | const UnicodeString* | |
369 | DateFormatSymbols::getShortWeekdays(int32_t &count) const | |
370 | { | |
371 | count = fShortWeekdaysCount; | |
372 | return fShortWeekdays; | |
373 | } | |
374 | ||
375 | const UnicodeString* | |
376 | DateFormatSymbols::getAmPmStrings(int32_t &count) const | |
377 | { | |
378 | count = fAmPmsCount; | |
379 | return fAmPms; | |
380 | } | |
381 | ||
382 | //------------------------------------------------------ | |
383 | ||
384 | void | |
385 | DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count) | |
386 | { | |
387 | // delete the old list if we own it | |
388 | if (fEras) delete[] fEras; | |
389 | ||
390 | // we always own the new list, which we create here (we duplicate rather | |
391 | // than adopting the list passed in) | |
392 | fEras = newUnicodeStringArray(count); | |
393 | uprv_arrayCopy(erasArray,fEras, count); | |
394 | fErasCount = count; | |
395 | } | |
396 | ||
397 | void | |
398 | DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count) | |
399 | { | |
400 | // delete the old list if we own it | |
401 | if (fMonths) delete[] fMonths; | |
402 | ||
403 | // we always own the new list, which we create here (we duplicate rather | |
404 | // than adopting the list passed in) | |
405 | fMonths = newUnicodeStringArray(count); | |
406 | uprv_arrayCopy( monthsArray,fMonths,count); | |
407 | fMonthsCount = count; | |
408 | } | |
409 | ||
410 | void | |
411 | DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count) | |
412 | { | |
413 | // delete the old list if we own it | |
414 | if (fShortMonths) delete[] fShortMonths; | |
415 | ||
416 | // we always own the new list, which we create here (we duplicate rather | |
417 | // than adopting the list passed in) | |
418 | fShortMonths = newUnicodeStringArray(count); | |
419 | uprv_arrayCopy(shortMonthsArray,fShortMonths, count); | |
420 | fShortMonthsCount = count; | |
421 | } | |
422 | ||
423 | void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count) | |
424 | { | |
425 | // delete the old list if we own it | |
426 | if (fWeekdays) delete[] fWeekdays; | |
427 | ||
428 | // we always own the new list, which we create here (we duplicate rather | |
429 | // than adopting the list passed in) | |
430 | fWeekdays = newUnicodeStringArray(count); | |
431 | uprv_arrayCopy(weekdaysArray,fWeekdays,count); | |
432 | fWeekdaysCount = count; | |
433 | } | |
434 | ||
435 | void | |
436 | DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count) | |
437 | { | |
438 | // delete the old list if we own it | |
439 | if (fShortWeekdays) delete[] fShortWeekdays; | |
440 | ||
441 | // we always own the new list, which we create here (we duplicate rather | |
442 | // than adopting the list passed in) | |
443 | fShortWeekdays = newUnicodeStringArray(count); | |
444 | uprv_arrayCopy( shortWeekdaysArray,fShortWeekdays,count); | |
445 | fShortWeekdaysCount = count; | |
446 | } | |
447 | ||
448 | void | |
449 | DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count) | |
450 | { | |
451 | // delete the old list if we own it | |
452 | if (fAmPms) delete[] fAmPms; | |
453 | ||
454 | // we always own the new list, which we create here (we duplicate rather | |
455 | // than adopting the list passed in) | |
456 | fAmPms = newUnicodeStringArray(count); | |
457 | uprv_arrayCopy(amPmsArray,fAmPms,count); | |
458 | fAmPmsCount = count; | |
459 | } | |
460 | ||
461 | //------------------------------------------------------ | |
462 | ||
463 | const UnicodeString** | |
464 | DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const | |
465 | { | |
466 | rowCount = fZoneStringsRowCount; | |
467 | columnCount = fZoneStringsColCount; | |
468 | return (const UnicodeString**)fZoneStrings; // Compiler requires cast | |
469 | } | |
470 | ||
471 | void | |
472 | DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t rowCount, int32_t columnCount) | |
473 | { | |
474 | // since deleting a 2-d array is a pain in the butt, we offload that task to | |
475 | // a separate function | |
476 | disposeZoneStrings(); | |
477 | ||
478 | // we always own the new list, which we create here (we duplicate rather | |
479 | // than adopting the list passed in) | |
480 | fZoneStringsRowCount = rowCount; | |
481 | fZoneStringsColCount = columnCount; | |
482 | createZoneStrings((const UnicodeString**)strings); | |
483 | } | |
484 | ||
485 | //------------------------------------------------------ | |
486 | ||
374ca955 | 487 | const UChar * U_EXPORT2 |
b75a7d8f A |
488 | DateFormatSymbols::getPatternUChars(void) |
489 | { | |
490 | return gPatternChars; | |
491 | } | |
492 | ||
493 | //------------------------------------------------------ | |
494 | ||
495 | UnicodeString& | |
496 | DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const | |
497 | { | |
498 | // fastCopyFrom() - see assignArray comments | |
499 | return result.fastCopyFrom(fLocalPatternChars); | |
500 | } | |
501 | ||
502 | //------------------------------------------------------ | |
503 | ||
504 | void | |
505 | DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars) | |
506 | { | |
507 | fLocalPatternChars = newLocalPatternChars; | |
508 | } | |
509 | ||
510 | //------------------------------------------------------ | |
511 | ||
512 | void | |
374ca955 | 513 | DateFormatSymbols::initField(UnicodeString **field, int32_t& length, const UResourceBundle *data, UErrorCode &status) { |
b75a7d8f | 514 | if (U_SUCCESS(status)) { |
374ca955 A |
515 | int32_t strLen = 0; |
516 | length = ures_getSize(data); | |
b75a7d8f A |
517 | *field = newUnicodeStringArray(length); |
518 | if (*field) { | |
519 | for(int32_t i = 0; i<length; i++) { | |
374ca955 A |
520 | const UChar *resStr = ures_getStringByIndex(data, i, &strLen, &status); |
521 | // setTo() - see assignArray comments | |
522 | (*(field)+i)->setTo(TRUE, resStr, strLen); | |
b75a7d8f A |
523 | } |
524 | } | |
525 | else { | |
526 | length = 0; | |
527 | status = U_MEMORY_ALLOCATION_ERROR; | |
528 | } | |
529 | } | |
530 | } | |
531 | ||
532 | void | |
533 | DateFormatSymbols::initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) { | |
534 | if (U_SUCCESS(status)) { | |
535 | length = numStr; | |
536 | *field = newUnicodeStringArray((size_t)numStr); | |
537 | if (*field) { | |
538 | for(int32_t i = 0; i<length; i++) { | |
539 | // readonly aliases - all "data" strings are constant | |
540 | // -1 as length for variable-length strings (gLastResortDayNames[0] is empty) | |
541 | (*(field)+i)->setTo(TRUE, data+(i*((int32_t)strLen)), -1); | |
542 | } | |
543 | } | |
544 | else { | |
545 | length = 0; | |
546 | status = U_MEMORY_ALLOCATION_ERROR; | |
547 | } | |
548 | } | |
549 | } | |
550 | ||
b75a7d8f A |
551 | void |
552 | DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData) | |
553 | { | |
554 | int32_t i; | |
374ca955 A |
555 | int32_t len = 0; |
556 | const UChar *resStr; | |
b75a7d8f A |
557 | |
558 | /* In case something goes wrong, initialize all of the data to NULL. */ | |
559 | fEras = NULL; | |
560 | fErasCount = 0; | |
561 | fMonths = NULL; | |
562 | fMonthsCount=0; | |
563 | fShortMonths = NULL; | |
564 | fShortMonthsCount=0; | |
565 | fWeekdays = NULL; | |
566 | fWeekdaysCount=0; | |
567 | fShortWeekdays = NULL; | |
568 | fShortWeekdaysCount=0; | |
569 | fAmPms = NULL; | |
570 | fAmPmsCount=0; | |
571 | fZoneStringsRowCount = 0; | |
572 | fZoneStringsColCount = 0; | |
573 | fZoneStrings = NULL; | |
574 | ||
575 | ||
576 | if (U_FAILURE(status)) return; | |
577 | ||
578 | /** | |
579 | * Retrieve the string arrays we need from the resource bundle file. | |
580 | * We cast away const here, but that's okay; we won't delete any of | |
581 | * these. | |
582 | */ | |
374ca955 A |
583 | CalendarData calData(locale, type, status); |
584 | UResourceBundle *nonCalendarData = ures_open((char*)0, locale.getName(), &status); | |
585 | ||
586 | // load the first data item | |
587 | UResourceBundle *erasMain = calData.getByKey(gErasTag, status); | |
588 | UResourceBundle *eras = ures_getByKeyWithFallback(erasMain, gAbbreviatedTag, NULL, &status); | |
589 | UResourceBundle *lsweekdaysData = NULL; // Data closed by calData | |
590 | UResourceBundle *weekdaysData = NULL; // Data closed by calData | |
591 | UResourceBundle *zoneArray = ures_getByKey(nonCalendarData, gZoneStringsTag, NULL, &status); | |
592 | UResourceBundle *zoneRow = ures_getByIndex(zoneArray, (int32_t)0, NULL, &status); | |
593 | U_LOCALE_BASED(locBased, *this); | |
b75a7d8f A |
594 | if (U_FAILURE(status)) |
595 | { | |
596 | if (useLastResortData) | |
597 | { | |
598 | // Handle the case in which there is no resource data present. | |
599 | // We don't have to generate usable patterns in this situation; | |
600 | // we just need to produce something that will be semi-intelligible | |
601 | // in most locales. | |
602 | ||
603 | status = U_USING_FALLBACK_WARNING; | |
604 | ||
605 | initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status); | |
606 | initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status); | |
607 | initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status); | |
608 | initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status); | |
609 | initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status); | |
610 | initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status); | |
611 | ||
612 | fZoneStrings = (UnicodeString **)uprv_malloc(sizeof(UnicodeString *)); | |
613 | /* test for NULL */ | |
614 | if (fZoneStrings == 0) { | |
615 | status = U_MEMORY_ALLOCATION_ERROR; | |
b75a7d8f A |
616 | } |
617 | fZoneStringsRowCount = 1; | |
618 | initField(fZoneStrings, fZoneStringsColCount, (const UChar *)gLastResortZoneStrings, kZoneNum, kZoneLen, status); | |
619 | fLocalPatternChars = gPatternChars; | |
620 | } | |
374ca955 | 621 | goto cleanup; |
b75a7d8f A |
622 | } |
623 | ||
624 | // if we make it to here, the resource data is cool, and we can get everything out | |
625 | // of it that we need except for the time-zone and localized-pattern data, which | |
374ca955 A |
626 | // are stored in a separate file |
627 | locBased.setLocaleIDs(ures_getLocaleByType(eras, ULOC_VALID_LOCALE, &status), | |
628 | ures_getLocaleByType(eras, ULOC_ACTUAL_LOCALE, &status)); | |
629 | initField(&fEras, fErasCount, eras, status); | |
630 | initField(&fMonths, fMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status); | |
631 | initField(&fShortMonths, fShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status); | |
632 | initField(&fAmPms, fAmPmsCount, calData.getByKey(gAmPmMarkersTag, status), status); | |
633 | ||
634 | // fastCopyFrom()/setTo() - see assignArray comments | |
635 | resStr = ures_getStringByKey(nonCalendarData, gLocalPatternCharsTag, &len, &status); | |
636 | fLocalPatternChars.setTo(TRUE, resStr, len); | |
637 | // If the locale data does not include new pattern chars, use the defaults | |
638 | // TODO: Consider making this an error, since this may add conflicting characters. | |
639 | if (len < PATTERN_CHARS_LEN) { | |
640 | fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len)); | |
641 | } | |
b75a7d8f | 642 | |
b75a7d8f | 643 | /* TODO: Fix the case where the zoneStrings is not a perfect square array of information. */ |
374ca955 A |
644 | fZoneStringsRowCount = ures_getSize(zoneArray); |
645 | fZoneStringsColCount = ures_getSize(zoneRow); | |
b75a7d8f A |
646 | fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *)); |
647 | /* test for NULL */ | |
648 | if (fZoneStrings == 0) { | |
649 | status = U_MEMORY_ALLOCATION_ERROR; | |
374ca955 | 650 | goto cleanup; |
b75a7d8f A |
651 | } |
652 | for(i = 0; i<fZoneStringsRowCount; i++) { | |
653 | *(fZoneStrings+i) = newUnicodeStringArray(fZoneStringsColCount); | |
654 | /* test for NULL */ | |
655 | if ((*(fZoneStrings+i)) == 0) { | |
656 | status = U_MEMORY_ALLOCATION_ERROR; | |
374ca955 | 657 | goto cleanup; |
b75a7d8f | 658 | } |
374ca955 | 659 | zoneRow = ures_getByIndex(zoneArray, i, zoneRow, &status); |
b75a7d8f | 660 | for(int32_t j = 0; j<fZoneStringsColCount; j++) { |
374ca955 A |
661 | resStr = ures_getStringByIndex(zoneRow, j, &len, &status); |
662 | // setTo() - see assignArray comments | |
663 | fZoneStrings[i][j].setTo(TRUE, resStr, len); | |
b75a7d8f A |
664 | } |
665 | } | |
666 | ||
667 | // {sfb} fixed to handle 1-based weekdays | |
374ca955 A |
668 | weekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status); |
669 | fWeekdaysCount = ures_getSize(weekdaysData); | |
b75a7d8f A |
670 | fWeekdays = new UnicodeString[fWeekdaysCount+1]; |
671 | /* test for NULL */ | |
672 | if (fWeekdays == 0) { | |
673 | status = U_MEMORY_ALLOCATION_ERROR; | |
374ca955 | 674 | goto cleanup; |
b75a7d8f A |
675 | } |
676 | // leave fWeekdays[0] empty | |
677 | for(i = 0; i<fWeekdaysCount; i++) { | |
374ca955 A |
678 | resStr = ures_getStringByIndex(weekdaysData, i, &len, &status); |
679 | // setTo() - see assignArray comments | |
680 | fWeekdays[i+1].setTo(TRUE, resStr, len); | |
b75a7d8f | 681 | } |
374ca955 | 682 | fWeekdaysCount++; |
b75a7d8f | 683 | |
374ca955 A |
684 | lsweekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status); |
685 | fShortWeekdaysCount = ures_getSize(lsweekdaysData); | |
b75a7d8f A |
686 | fShortWeekdays = new UnicodeString[fShortWeekdaysCount+1]; |
687 | /* test for NULL */ | |
688 | if (fShortWeekdays == 0) { | |
689 | status = U_MEMORY_ALLOCATION_ERROR; | |
374ca955 | 690 | goto cleanup; |
b75a7d8f A |
691 | } |
692 | // leave fShortWeekdays[0] empty | |
693 | for(i = 0; i<fShortWeekdaysCount; i++) { | |
374ca955 A |
694 | resStr = ures_getStringByIndex(lsweekdaysData, i, &len, &status); |
695 | // setTo() - see assignArray comments | |
696 | fShortWeekdays[i+1].setTo(TRUE, resStr, len); | |
b75a7d8f | 697 | } |
374ca955 A |
698 | fShortWeekdaysCount++; |
699 | cleanup: | |
700 | ures_close(eras); | |
701 | ures_close(zoneRow); | |
702 | ures_close(zoneArray); | |
703 | ures_close(nonCalendarData); | |
b75a7d8f A |
704 | } |
705 | ||
706 | /** | |
707 | * Package private: used by SimpleDateFormat | |
708 | * Gets the index for the given time zone ID to obtain the timezone | |
709 | * strings for formatting. The time zone ID is just for programmatic | |
710 | * lookup. NOT LOCALIZED!!! | |
711 | * @param ID the given time zone ID. | |
712 | * @return the index of the given time zone ID. Returns -1 if | |
713 | * the given time zone ID can't be located in the DateFormatSymbols object. | |
714 | * @see java.util.SimpleTimeZone | |
715 | */ | |
716 | int32_t DateFormatSymbols::getZoneIndex(const UnicodeString& ID) const | |
717 | { | |
718 | int32_t result = _getZoneIndex(ID); | |
719 | if (result >= 0) { | |
720 | return result; | |
721 | } | |
722 | ||
723 | // Do a search through the equivalency group for the given ID | |
724 | int32_t n = TimeZone::countEquivalentIDs(ID); | |
725 | if (n > 1) { | |
726 | int32_t i; | |
727 | for (i=0; i<n; ++i) { | |
728 | UnicodeString equivID = TimeZone::getEquivalentID(ID, i); | |
729 | if (equivID != ID) { | |
730 | int32_t equivResult = _getZoneIndex(equivID); | |
731 | if (equivResult >= 0) { | |
732 | return equivResult; | |
733 | } | |
734 | } | |
735 | } | |
736 | } | |
737 | ||
738 | return -1; | |
739 | } | |
740 | ||
741 | /** | |
742 | * Lookup the given ID. Do NOT do an equivalency search. | |
743 | */ | |
744 | int32_t DateFormatSymbols::_getZoneIndex(const UnicodeString& ID) const | |
745 | { | |
746 | for(int32_t index = 0; index < fZoneStringsRowCount; index++) { | |
747 | if (0 == ID.caseCompare(fZoneStrings[index][0], 0)) { | |
748 | return index; | |
749 | } | |
750 | } | |
751 | ||
752 | return -1; | |
753 | } | |
754 | ||
374ca955 A |
755 | Locale |
756 | DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const { | |
757 | U_LOCALE_BASED(locBased, *this); | |
758 | return locBased.getLocale(type, status); | |
759 | } | |
760 | ||
b75a7d8f A |
761 | U_NAMESPACE_END |
762 | ||
763 | #endif /* #if !UCONFIG_NO_FORMATTING */ | |
764 | ||
765 | //eof |