1 /*
2 *******************************************************************************
3 * Copyright (C) 1997-2015, International Business Machines Corporation and *
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 * 06/30/05 emmons Added eraNames, narrow month/day, standalone context
19 * 10/12/05 emmons Added setters for eraNames, month/day by width/context
20 *******************************************************************************
21 */
22 #include "unicode/utypes.h"
23
24 #if !UCONFIG_NO_FORMATTING
25 #include "unicode/ustring.h"
26 #include "unicode/localpointer.h"
27 #include "unicode/dtfmtsym.h"
28 #include "unicode/smpdtfmt.h"
29 #include "unicode/msgfmt.h"
30 #include "unicode/numsys.h"
31 #include "unicode/tznames.h"
32 #include "cpputils.h"
33 #include "umutex.h"
34 #include "cmemory.h"
35 #include "cstring.h"
36 #include "locbased.h"
37 #include "gregoimp.h"
38 #include "hash.h"
39 #include "uresimp.h"
40 #include "ureslocs.h"
41 #include "shareddateformatsymbols.h"
42 #include "unicode/calendar.h"
43 #include "unifiedcache.h"
44
45 // *****************************************************************************
46 // class DateFormatSymbols
47 // *****************************************************************************
48
49 /**
50 * These are static arrays we use only in the case where we have no
51 * resource data.
52 */
53
54 #define PATTERN_CHARS_LEN 36
55
56 /**
57 * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All
58 * locales use the same these unlocalized pattern characters.
59 */
60 static const UChar gPatternChars[] = {
61 // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxr:
62 0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45,
63 0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65,
64 0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0x51, 0x71, 0x56,
65 0x55, 0x4F, 0x58, 0x78, 0x72, 0x3a, 0
66 };
67
68 /* length of an array */
69 #define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0]))
70
71 //------------------------------------------------------
72 // Strings of last resort. These are only used if we have no resource
73 // files. They aren't designed for actual use, just for backup.
74
75 // These are the month names and abbreviations of last resort.
76 static const UChar gLastResortMonthNames[13][3] =
77 {
78 {0x0030, 0x0031, 0x0000}, /* "01" */
79 {0x0030, 0x0032, 0x0000}, /* "02" */
80 {0x0030, 0x0033, 0x0000}, /* "03" */
81 {0x0030, 0x0034, 0x0000}, /* "04" */
82 {0x0030, 0x0035, 0x0000}, /* "05" */
83 {0x0030, 0x0036, 0x0000}, /* "06" */
84 {0x0030, 0x0037, 0x0000}, /* "07" */
85 {0x0030, 0x0038, 0x0000}, /* "08" */
86 {0x0030, 0x0039, 0x0000}, /* "09" */
87 {0x0031, 0x0030, 0x0000}, /* "10" */
88 {0x0031, 0x0031, 0x0000}, /* "11" */
89 {0x0031, 0x0032, 0x0000}, /* "12" */
90 {0x0031, 0x0033, 0x0000} /* "13" */
91 };
92
93 // These are the weekday names and abbreviations of last resort.
94 static const UChar gLastResortDayNames[8][2] =
95 {
96 {0x0030, 0x0000}, /* "0" */
97 {0x0031, 0x0000}, /* "1" */
98 {0x0032, 0x0000}, /* "2" */
99 {0x0033, 0x0000}, /* "3" */
100 {0x0034, 0x0000}, /* "4" */
101 {0x0035, 0x0000}, /* "5" */
102 {0x0036, 0x0000}, /* "6" */
103 {0x0037, 0x0000} /* "7" */
104 };
105
106 // These are the quarter names and abbreviations of last resort.
107 static const UChar gLastResortQuarters[4][2] =
108 {
109 {0x0031, 0x0000}, /* "1" */
110 {0x0032, 0x0000}, /* "2" */
111 {0x0033, 0x0000}, /* "3" */
112 {0x0034, 0x0000}, /* "4" */
113 };
114
115 // These are the am/pm and BC/AD markers of last resort.
116 static const UChar gLastResortAmPmMarkers[2][3] =
117 {
118 {0x0041, 0x004D, 0x0000}, /* "AM" */
119 {0x0050, 0x004D, 0x0000} /* "PM" */
120 };
121
122 static const UChar gLastResortEras[2][3] =
123 {
124 {0x0042, 0x0043, 0x0000}, /* "BC" */
125 {0x0041, 0x0044, 0x0000} /* "AD" */
126 };
127
128 /* Sizes for the last resort string arrays */
129 typedef enum LastResortSize {
130 kMonthNum = 13,
131 kMonthLen = 3,
132
133 kDayNum = 8,
134 kDayLen = 2,
135
136 kAmPmNum = 2,
137 kAmPmLen = 3,
138
139 kQuarterNum = 4,
140 kQuarterLen = 2,
141
142 kEraNum = 2,
143 kEraLen = 3,
144
145 kZoneNum = 5,
146 kZoneLen = 4,
147
148 kGmtHourNum = 4,
149 kGmtHourLen = 10
150 } LastResortSize;
151
152 U_NAMESPACE_BEGIN
153
~SharedDateFormatSymbols()154 SharedDateFormatSymbols::~SharedDateFormatSymbols() {
155 }
156
157 template<> U_I18N_API
158 const SharedDateFormatSymbols *
createObject(const void *,UErrorCode & status) const159 LocaleCacheKey<SharedDateFormatSymbols>::createObject(
160 const void */*unusedContext*/, UErrorCode &status) const {
161 char type[256];
162 Calendar::getCalendarTypeFromLocale(fLoc, type, UPRV_LENGTHOF(type), status);
163 if (U_FAILURE(status)) {
164 return NULL;
165 }
166 SharedDateFormatSymbols *shared
167 = new SharedDateFormatSymbols(fLoc, type, status);
168 if (shared == NULL) {
169 status = U_MEMORY_ALLOCATION_ERROR;
170 return NULL;
171 }
172 if (U_FAILURE(status)) {
173 delete shared;
174 return NULL;
175 }
176 shared->addRef();
177 return shared;
178 }
179
180 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols)
181
182 #define kSUPPLEMENTAL "supplementalData"
183
184 /**
185 * These are the tags we expect to see in normal resource bundle files associated
186 * with a locale and calendar
187 */
188 static const char gErasTag[]="eras";
189 static const char gCyclicNameSetsTag[]="cyclicNameSets";
190 static const char gNameSetYearsTag[]="years";
191 static const char gNameSetZodiacsTag[]="zodiacs";
192 static const char gMonthNamesTag[]="monthNames";
193 static const char gMonthPatternsTag[]="monthPatterns";
194 static const char gDayNamesTag[]="dayNames";
195 static const char gNamesWideTag[]="wide";
196 static const char gNamesAbbrTag[]="abbreviated";
197 static const char gNamesShortTag[]="short";
198 static const char gNamesNarrowTag[]="narrow";
199 static const char gNamesAllTag[]="all";
200 static const char gNamesLeapTag[]="leap";
201 static const char gNamesFormatTag[]="format";
202 static const char gNamesStandaloneTag[]="stand-alone";
203 static const char gNamesNumericTag[]="numeric";
204 static const char gAmPmMarkersTag[]="AmPmMarkers";
205 static const char gAmPmMarkersNarrowTag[]="AmPmMarkersNarrow";
206 static const char gQuartersTag[]="quarters";
207 static const char gNumberElementsTag[]="NumberElements";
208 static const char gSymbolsTag[]="symbols";
209 static const char gTimeSeparatorTag[]="timeSeparator";
210
211 // static const char gZoneStringsTag[]="zoneStrings";
212
213 // static const char gLocalPatternCharsTag[]="localPatternChars";
214
215 static const char gContextTransformsTag[]="contextTransforms";
216
217 static UMutex LOCK = U_MUTEX_INITIALIZER;
218
219 /**
220 * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly.
221 * Work around this.
222 */
newUnicodeStringArray(size_t count)223 static inline UnicodeString* newUnicodeStringArray(size_t count) {
224 return new UnicodeString[count ? count : 1];
225 }
226
227 //------------------------------------------------------
228
229 DateFormatSymbols * U_EXPORT2
createForLocale(const Locale & locale,UErrorCode & status)230 DateFormatSymbols::createForLocale(
231 const Locale& locale, UErrorCode &status) {
232 const SharedDateFormatSymbols *shared = NULL;
233 UnifiedCache::getByLocale(locale, shared, status);
234 if (U_FAILURE(status)) {
235 return NULL;
236 }
237 DateFormatSymbols *result = new DateFormatSymbols(shared->get());
238 shared->removeRef();
239 if (result == NULL) {
240 status = U_MEMORY_ALLOCATION_ERROR;
241 return NULL;
242 }
243 return result;
244 }
245
DateFormatSymbols(const Locale & locale,UErrorCode & status)246 DateFormatSymbols::DateFormatSymbols(const Locale& locale,
247 UErrorCode& status)
248 : UObject()
249 {
250 initializeData(locale, NULL, status);
251 }
252
DateFormatSymbols(UErrorCode & status)253 DateFormatSymbols::DateFormatSymbols(UErrorCode& status)
254 : UObject()
255 {
256 initializeData(Locale::getDefault(), NULL, status, TRUE);
257 }
258
259
DateFormatSymbols(const Locale & locale,const char * type,UErrorCode & status)260 DateFormatSymbols::DateFormatSymbols(const Locale& locale,
261 const char *type,
262 UErrorCode& status)
263 : UObject()
264 {
265 initializeData(locale, type, status);
266 }
267
DateFormatSymbols(const char * type,UErrorCode & status)268 DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status)
269 : UObject()
270 {
271 initializeData(Locale::getDefault(), type, status, TRUE);
272 }
273
DateFormatSymbols(const DateFormatSymbols & other)274 DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other)
275 : UObject(other)
276 {
277 copyData(other);
278 }
279
280 void
assignArray(UnicodeString * & dstArray,int32_t & dstCount,const UnicodeString * srcArray,int32_t srcCount)281 DateFormatSymbols::assignArray(UnicodeString*& dstArray,
282 int32_t& dstCount,
283 const UnicodeString* srcArray,
284 int32_t srcCount)
285 {
286 // assignArray() is only called by copyData(), which in turn implements the
287 // copy constructor and the assignment operator.
288 // All strings in a DateFormatSymbols object are created in one of the following
289 // three ways that all allow to safely use UnicodeString::fastCopyFrom():
290 // - readonly-aliases from resource bundles
291 // - readonly-aliases or allocated strings from constants
292 // - safely cloned strings (with owned buffers) from setXYZ() functions
293 //
294 // Note that this is true for as long as DateFormatSymbols can be constructed
295 // only from a locale bundle or set via the cloning API,
296 // *and* for as long as all the strings are in *private* fields, preventing
297 // a subclass from creating these strings in an "unsafe" way (with respect to fastCopyFrom()).
298 dstCount = srcCount;
299 dstArray = newUnicodeStringArray(srcCount);
300 if(dstArray != NULL) {
301 int32_t i;
302 for(i=0; i<srcCount; ++i) {
303 dstArray[i].fastCopyFrom(srcArray[i]);
304 }
305 }
306 }
307
308 /**
309 * Create a copy, in fZoneStrings, of the given zone strings array. The
310 * member variables fZoneStringsRowCount and fZoneStringsColCount should
311 * be set already by the caller.
312 */
313 void
createZoneStrings(const UnicodeString * const * otherStrings)314 DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings)
315 {
316 int32_t row, col;
317 UBool failed = FALSE;
318
319 fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *));
320 if (fZoneStrings != NULL) {
321 for (row=0; row<fZoneStringsRowCount; ++row)
322 {
323 fZoneStrings[row] = newUnicodeStringArray(fZoneStringsColCount);
324 if (fZoneStrings[row] == NULL) {
325 failed = TRUE;
326 break;
327 }
328 for (col=0; col<fZoneStringsColCount; ++col) {
329 // fastCopyFrom() - see assignArray comments
330 fZoneStrings[row][col].fastCopyFrom(otherStrings[row][col]);
331 }
332 }
333 }
334 // If memory allocation failed, roll back and delete fZoneStrings
335 if (failed) {
336 for (int i = row; i >= 0; i--) {
337 delete[] fZoneStrings[i];
338 }
339 uprv_free(fZoneStrings);
340 fZoneStrings = NULL;
341 }
342 }
343
344 /**
345 * Copy all of the other's data to this.
346 */
347 void
copyData(const DateFormatSymbols & other)348 DateFormatSymbols::copyData(const DateFormatSymbols& other) {
349 UErrorCode status = U_ZERO_ERROR;
350 U_LOCALE_BASED(locBased, *this);
351 locBased.setLocaleIDs(
352 other.getLocale(ULOC_VALID_LOCALE, status),
353 other.getLocale(ULOC_ACTUAL_LOCALE, status));
354 assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
355 assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
356 assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount);
357 assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount);
358 assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount);
359 assignArray(fNarrowMonths, fNarrowMonthsCount, other.fNarrowMonths, other.fNarrowMonthsCount);
360 assignArray(fStandaloneMonths, fStandaloneMonthsCount, other.fStandaloneMonths, other.fStandaloneMonthsCount);
361 assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, other.fStandaloneShortMonths, other.fStandaloneShortMonthsCount);
362 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, other.fStandaloneNarrowMonths, other.fStandaloneNarrowMonthsCount);
363 assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount);
364 assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount);
365 assignArray(fShorterWeekdays, fShorterWeekdaysCount, other.fShorterWeekdays, other.fShorterWeekdaysCount);
366 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, other.fNarrowWeekdays, other.fNarrowWeekdaysCount);
367 assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, other.fStandaloneWeekdays, other.fStandaloneWeekdaysCount);
368 assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, other.fStandaloneShortWeekdays, other.fStandaloneShortWeekdaysCount);
369 assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, other.fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdaysCount);
370 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount);
371 assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount);
372 assignArray(fNarrowAmPms, fNarrowAmPmsCount, other.fNarrowAmPms, other.fNarrowAmPmsCount );
373 fTimeSeparator.fastCopyFrom(other.fTimeSeparator); // fastCopyFrom() - see assignArray comments
374 assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount);
375 assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount);
376 assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount);
377 assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount);
378 if (other.fLeapMonthPatterns != NULL) {
379 assignArray(fLeapMonthPatterns, fLeapMonthPatternsCount, other.fLeapMonthPatterns, other.fLeapMonthPatternsCount);
380 } else {
381 fLeapMonthPatterns = NULL;
382 fLeapMonthPatternsCount = 0;
383 }
384 if (other.fShortYearNames != NULL) {
385 assignArray(fShortYearNames, fShortYearNamesCount, other.fShortYearNames, other.fShortYearNamesCount);
386 } else {
387 fShortYearNames = NULL;
388 fShortYearNamesCount = 0;
389 }
390 if (other.fShortZodiacNames != NULL) {
391 assignArray(fShortZodiacNames, fShortZodiacNamesCount, other.fShortZodiacNames, other.fShortZodiacNamesCount);
392 } else {
393 fShortZodiacNames = NULL;
394 fShortZodiacNamesCount = 0;
395 }
396
397 if (other.fZoneStrings != NULL) {
398 fZoneStringsColCount = other.fZoneStringsColCount;
399 fZoneStringsRowCount = other.fZoneStringsRowCount;
400 createZoneStrings((const UnicodeString**)other.fZoneStrings);
401
402 } else {
403 fZoneStrings = NULL;
404 fZoneStringsColCount = 0;
405 fZoneStringsRowCount = 0;
406 }
407 fZSFLocale = other.fZSFLocale;
408 // Other zone strings data is created on demand
409 fLocaleZoneStrings = NULL;
410
411 // fastCopyFrom() - see assignArray comments
412 fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
413
414 uprv_memcpy(fCapitalization, other.fCapitalization, sizeof(fCapitalization));
415 }
416
417 /**
418 * Assignment operator.
419 */
operator =(const DateFormatSymbols & other)420 DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
421 {
422 dispose();
423 copyData(other);
424
425 return *this;
426 }
427
~DateFormatSymbols()428 DateFormatSymbols::~DateFormatSymbols()
429 {
430 dispose();
431 }
432
dispose()433 void DateFormatSymbols::dispose()
434 {
435 if (fEras) delete[] fEras;
436 if (fEraNames) delete[] fEraNames;
437 if (fNarrowEras) delete[] fNarrowEras;
438 if (fMonths) delete[] fMonths;
439 if (fShortMonths) delete[] fShortMonths;
440 if (fNarrowMonths) delete[] fNarrowMonths;
441 if (fStandaloneMonths) delete[] fStandaloneMonths;
442 if (fStandaloneShortMonths) delete[] fStandaloneShortMonths;
443 if (fStandaloneNarrowMonths) delete[] fStandaloneNarrowMonths;
444 if (fWeekdays) delete[] fWeekdays;
445 if (fShortWeekdays) delete[] fShortWeekdays;
446 if (fShorterWeekdays) delete[] fShorterWeekdays;
447 if (fNarrowWeekdays) delete[] fNarrowWeekdays;
448 if (fStandaloneWeekdays) delete[] fStandaloneWeekdays;
449 if (fStandaloneShortWeekdays) delete[] fStandaloneShortWeekdays;
450 if (fStandaloneShorterWeekdays) delete[] fStandaloneShorterWeekdays;
451 if (fStandaloneNarrowWeekdays) delete[] fStandaloneNarrowWeekdays;
452 if (fAmPms) delete[] fAmPms;
453 if (fNarrowAmPms) delete[] fNarrowAmPms;
454 if (fQuarters) delete[] fQuarters;
455 if (fShortQuarters) delete[] fShortQuarters;
456 if (fStandaloneQuarters) delete[] fStandaloneQuarters;
457 if (fStandaloneShortQuarters) delete[] fStandaloneShortQuarters;
458 if (fLeapMonthPatterns) delete[] fLeapMonthPatterns;
459 if (fShortYearNames) delete[] fShortYearNames;
460 if (fShortZodiacNames) delete[] fShortZodiacNames;
461
462 disposeZoneStrings();
463 }
464
disposeZoneStrings()465 void DateFormatSymbols::disposeZoneStrings()
466 {
467 if (fZoneStrings) {
468 for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
469 delete[] fZoneStrings[row];
470 }
471 uprv_free(fZoneStrings);
472 }
473 if (fLocaleZoneStrings) {
474 for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
475 delete[] fLocaleZoneStrings[row];
476 }
477 uprv_free(fLocaleZoneStrings);
478 }
479
480 fZoneStrings = NULL;
481 fLocaleZoneStrings = NULL;
482 fZoneStringsRowCount = 0;
483 fZoneStringsColCount = 0;
484 }
485
486 UBool
arrayCompare(const UnicodeString * array1,const UnicodeString * array2,int32_t count)487 DateFormatSymbols::arrayCompare(const UnicodeString* array1,
488 const UnicodeString* array2,
489 int32_t count)
490 {
491 if (array1 == array2) return TRUE;
492 while (count>0)
493 {
494 --count;
495 if (array1[count] != array2[count]) return FALSE;
496 }
497 return TRUE;
498 }
499
500 UBool
operator ==(const DateFormatSymbols & other) const501 DateFormatSymbols::operator==(const DateFormatSymbols& other) const
502 {
503 // First do cheap comparisons
504 if (this == &other) {
505 return TRUE;
506 }
507 if (fErasCount == other.fErasCount &&
508 fEraNamesCount == other.fEraNamesCount &&
509 fNarrowErasCount == other.fNarrowErasCount &&
510 fMonthsCount == other.fMonthsCount &&
511 fShortMonthsCount == other.fShortMonthsCount &&
512 fNarrowMonthsCount == other.fNarrowMonthsCount &&
513 fStandaloneMonthsCount == other.fStandaloneMonthsCount &&
514 fStandaloneShortMonthsCount == other.fStandaloneShortMonthsCount &&
515 fStandaloneNarrowMonthsCount == other.fStandaloneNarrowMonthsCount &&
516 fWeekdaysCount == other.fWeekdaysCount &&
517 fShortWeekdaysCount == other.fShortWeekdaysCount &&
518 fShorterWeekdaysCount == other.fShorterWeekdaysCount &&
519 fNarrowWeekdaysCount == other.fNarrowWeekdaysCount &&
520 fStandaloneWeekdaysCount == other.fStandaloneWeekdaysCount &&
521 fStandaloneShortWeekdaysCount == other.fStandaloneShortWeekdaysCount &&
522 fStandaloneShorterWeekdaysCount == other.fStandaloneShorterWeekdaysCount &&
523 fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount &&
524 fAmPmsCount == other.fAmPmsCount &&
525 fNarrowAmPmsCount == other.fNarrowAmPmsCount &&
526 fQuartersCount == other.fQuartersCount &&
527 fShortQuartersCount == other.fShortQuartersCount &&
528 fStandaloneQuartersCount == other.fStandaloneQuartersCount &&
529 fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount &&
530 fLeapMonthPatternsCount == other.fLeapMonthPatternsCount &&
531 fShortYearNamesCount == other.fShortYearNamesCount &&
532 fShortZodiacNamesCount == other.fShortZodiacNamesCount &&
533 (uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization))==0))
534 {
535 // Now compare the arrays themselves
536 if (arrayCompare(fEras, other.fEras, fErasCount) &&
537 arrayCompare(fEraNames, other.fEraNames, fEraNamesCount) &&
538 arrayCompare(fNarrowEras, other.fNarrowEras, fNarrowErasCount) &&
539 arrayCompare(fMonths, other.fMonths, fMonthsCount) &&
540 arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) &&
541 arrayCompare(fNarrowMonths, other.fNarrowMonths, fNarrowMonthsCount) &&
542 arrayCompare(fStandaloneMonths, other.fStandaloneMonths, fStandaloneMonthsCount) &&
543 arrayCompare(fStandaloneShortMonths, other.fStandaloneShortMonths, fStandaloneShortMonthsCount) &&
544 arrayCompare(fStandaloneNarrowMonths, other.fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount) &&
545 arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) &&
546 arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) &&
547 arrayCompare(fShorterWeekdays, other.fShorterWeekdays, fShorterWeekdaysCount) &&
548 arrayCompare(fNarrowWeekdays, other.fNarrowWeekdays, fNarrowWeekdaysCount) &&
549 arrayCompare(fStandaloneWeekdays, other.fStandaloneWeekdays, fStandaloneWeekdaysCount) &&
550 arrayCompare(fStandaloneShortWeekdays, other.fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount) &&
551 arrayCompare(fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount) &&
552 arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) &&
553 arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) &&
554 arrayCompare(fNarrowAmPms, other.fNarrowAmPms, fNarrowAmPmsCount) &&
555 fTimeSeparator == other.fTimeSeparator &&
556 arrayCompare(fQuarters, other.fQuarters, fQuartersCount) &&
557 arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) &&
558 arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) &&
559 arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) &&
560 arrayCompare(fLeapMonthPatterns, other.fLeapMonthPatterns, fLeapMonthPatternsCount) &&
561 arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount) &&
562 arrayCompare(fShortZodiacNames, other.fShortZodiacNames, fShortZodiacNamesCount))
563 {
564 // Compare the contents of fZoneStrings
565 if (fZoneStrings == NULL && other.fZoneStrings == NULL) {
566 if (fZSFLocale == other.fZSFLocale) {
567 return TRUE;
568 }
569 } else if (fZoneStrings != NULL && other.fZoneStrings != NULL) {
570 if (fZoneStringsRowCount == other.fZoneStringsRowCount
571 && fZoneStringsColCount == other.fZoneStringsColCount) {
572 UBool cmpres = TRUE;
573 for (int32_t i = 0; (i < fZoneStringsRowCount) && cmpres; i++) {
574 cmpres = arrayCompare(fZoneStrings[i], other.fZoneStrings[i], fZoneStringsColCount);
575 }
576 return cmpres;
577 }
578 }
579 return FALSE;
580 }
581 }
582 return FALSE;
583 }
584
585 //------------------------------------------------------
586
587 const UnicodeString*
getEras(int32_t & count) const588 DateFormatSymbols::getEras(int32_t &count) const
589 {
590 count = fErasCount;
591 return fEras;
592 }
593
594 const UnicodeString*
getEraNames(int32_t & count) const595 DateFormatSymbols::getEraNames(int32_t &count) const
596 {
597 count = fEraNamesCount;
598 return fEraNames;
599 }
600
601 const UnicodeString*
getNarrowEras(int32_t & count) const602 DateFormatSymbols::getNarrowEras(int32_t &count) const
603 {
604 count = fNarrowErasCount;
605 return fNarrowEras;
606 }
607
608 const UnicodeString*
getMonths(int32_t & count) const609 DateFormatSymbols::getMonths(int32_t &count) const
610 {
611 count = fMonthsCount;
612 return fMonths;
613 }
614
615 const UnicodeString*
getShortMonths(int32_t & count) const616 DateFormatSymbols::getShortMonths(int32_t &count) const
617 {
618 count = fShortMonthsCount;
619 return fShortMonths;
620 }
621
622 const UnicodeString*
getMonths(int32_t & count,DtContextType context,DtWidthType width) const623 DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType width ) const
624 {
625 UnicodeString *returnValue = NULL;
626
627 switch (context) {
628 case FORMAT :
629 switch(width) {
630 case WIDE :
631 count = fMonthsCount;
632 returnValue = fMonths;
633 break;
634 case ABBREVIATED :
635 case SHORT : // no month data for this, defaults to ABBREVIATED
636 count = fShortMonthsCount;
637 returnValue = fShortMonths;
638 break;
639 case NARROW :
640 count = fNarrowMonthsCount;
641 returnValue = fNarrowMonths;
642 break;
643 case DT_WIDTH_COUNT :
644 break;
645 }
646 break;
647 case STANDALONE :
648 switch(width) {
649 case WIDE :
650 count = fStandaloneMonthsCount;
651 returnValue = fStandaloneMonths;
652 break;
653 case ABBREVIATED :
654 case SHORT : // no month data for this, defaults to ABBREVIATED
655 count = fStandaloneShortMonthsCount;
656 returnValue = fStandaloneShortMonths;
657 break;
658 case NARROW :
659 count = fStandaloneNarrowMonthsCount;
660 returnValue = fStandaloneNarrowMonths;
661 break;
662 case DT_WIDTH_COUNT :
663 break;
664 }
665 break;
666 case DT_CONTEXT_COUNT :
667 break;
668 }
669 return returnValue;
670 }
671
672 const UnicodeString*
getWeekdays(int32_t & count) const673 DateFormatSymbols::getWeekdays(int32_t &count) const
674 {
675 count = fWeekdaysCount;
676 return fWeekdays;
677 }
678
679 const UnicodeString*
getShortWeekdays(int32_t & count) const680 DateFormatSymbols::getShortWeekdays(int32_t &count) const
681 {
682 count = fShortWeekdaysCount;
683 return fShortWeekdays;
684 }
685
686 const UnicodeString*
getWeekdays(int32_t & count,DtContextType context,DtWidthType width) const687 DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthType width) const
688 {
689 UnicodeString *returnValue = NULL;
690 switch (context) {
691 case FORMAT :
692 switch(width) {
693 case WIDE :
694 count = fWeekdaysCount;
695 returnValue = fWeekdays;
696 break;
697 case ABBREVIATED :
698 count = fShortWeekdaysCount;
699 returnValue = fShortWeekdays;
700 break;
701 case SHORT :
702 count = fShorterWeekdaysCount;
703 returnValue = fShorterWeekdays;
704 break;
705 case NARROW :
706 count = fNarrowWeekdaysCount;
707 returnValue = fNarrowWeekdays;
708 break;
709 case DT_WIDTH_COUNT :
710 break;
711 }
712 break;
713 case STANDALONE :
714 switch(width) {
715 case WIDE :
716 count = fStandaloneWeekdaysCount;
717 returnValue = fStandaloneWeekdays;
718 break;
719 case ABBREVIATED :
720 count = fStandaloneShortWeekdaysCount;
721 returnValue = fStandaloneShortWeekdays;
722 break;
723 case SHORT :
724 count = fStandaloneShorterWeekdaysCount;
725 returnValue = fStandaloneShorterWeekdays;
726 break;
727 case NARROW :
728 count = fStandaloneNarrowWeekdaysCount;
729 returnValue = fStandaloneNarrowWeekdays;
730 break;
731 case DT_WIDTH_COUNT :
732 break;
733 }
734 break;
735 case DT_CONTEXT_COUNT :
736 break;
737 }
738 return returnValue;
739 }
740
741 const UnicodeString*
getQuarters(int32_t & count,DtContextType context,DtWidthType width) const742 DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const
743 {
744 UnicodeString *returnValue = NULL;
745
746 switch (context) {
747 case FORMAT :
748 switch(width) {
749 case WIDE :
750 count = fQuartersCount;
751 returnValue = fQuarters;
752 break;
753 case ABBREVIATED :
754 case SHORT : // no quarter data for this, defaults to ABBREVIATED
755 count = fShortQuartersCount;
756 returnValue = fShortQuarters;
757 break;
758 case NARROW :
759 count = 0;
760 returnValue = NULL;
761 break;
762 case DT_WIDTH_COUNT :
763 break;
764 }
765 break;
766 case STANDALONE :
767 switch(width) {
768 case WIDE :
769 count = fStandaloneQuartersCount;
770 returnValue = fStandaloneQuarters;
771 break;
772 case ABBREVIATED :
773 case SHORT : // no quarter data for this, defaults to ABBREVIATED
774 count = fStandaloneShortQuartersCount;
775 returnValue = fStandaloneShortQuarters;
776 break;
777 case NARROW :
778 count = 0;
779 returnValue = NULL;
780 break;
781 case DT_WIDTH_COUNT :
782 break;
783 }
784 break;
785 case DT_CONTEXT_COUNT :
786 break;
787 }
788 return returnValue;
789 }
790
791 UnicodeString&
getTimeSeparatorString(UnicodeString & result) const792 DateFormatSymbols::getTimeSeparatorString(UnicodeString& result) const
793 {
794 // fastCopyFrom() - see assignArray comments
795 return result.fastCopyFrom(fTimeSeparator);
796 }
797
798 const UnicodeString*
getAmPmStrings(int32_t & count) const799 DateFormatSymbols::getAmPmStrings(int32_t &count) const
800 {
801 count = fAmPmsCount;
802 return fAmPms;
803 }
804
805 const UnicodeString*
getLeapMonthPatterns(int32_t & count) const806 DateFormatSymbols::getLeapMonthPatterns(int32_t &count) const
807 {
808 count = fLeapMonthPatternsCount;
809 return fLeapMonthPatterns;
810 }
811
812 const UnicodeString*
getYearNames(int32_t & count,DtContextType,DtWidthType) const813 DateFormatSymbols::getYearNames(int32_t& count,
814 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
815 {
816 count = fShortYearNamesCount;
817 return fShortYearNames;
818 }
819
820 void
setYearNames(const UnicodeString * yearNames,int32_t count,DtContextType context,DtWidthType width)821 DateFormatSymbols::setYearNames(const UnicodeString* yearNames, int32_t count,
822 DtContextType context, DtWidthType width)
823 {
824 if (context == FORMAT && width == ABBREVIATED) {
825 if (fShortYearNames) {
826 delete[] fShortYearNames;
827 }
828 fShortYearNames = newUnicodeStringArray(count);
829 uprv_arrayCopy(yearNames, fShortYearNames, count);
830 fShortYearNamesCount = count;
831 }
832 }
833
834 const UnicodeString*
getZodiacNames(int32_t & count,DtContextType,DtWidthType) const835 DateFormatSymbols::getZodiacNames(int32_t& count,
836 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
837 {
838 count = fShortZodiacNamesCount;
839 return fShortZodiacNames;
840 }
841
842 void
setZodiacNames(const UnicodeString * zodiacNames,int32_t count,DtContextType context,DtWidthType width)843 DateFormatSymbols::setZodiacNames(const UnicodeString* zodiacNames, int32_t count,
844 DtContextType context, DtWidthType width)
845 {
846 if (context == FORMAT && width == ABBREVIATED) {
847 if (fShortZodiacNames) {
848 delete[] fShortZodiacNames;
849 }
850 fShortZodiacNames = newUnicodeStringArray(count);
851 uprv_arrayCopy(zodiacNames, fShortZodiacNames, count);
852 fShortZodiacNamesCount = count;
853 }
854 }
855
856 //------------------------------------------------------
857
858 void
setEras(const UnicodeString * erasArray,int32_t count)859 DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count)
860 {
861 // delete the old list if we own it
862 if (fEras)
863 delete[] fEras;
864
865 // we always own the new list, which we create here (we duplicate rather
866 // than adopting the list passed in)
867 fEras = newUnicodeStringArray(count);
868 uprv_arrayCopy(erasArray,fEras, count);
869 fErasCount = count;
870 }
871
872 void
setEraNames(const UnicodeString * eraNamesArray,int32_t count)873 DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count)
874 {
875 // delete the old list if we own it
876 if (fEraNames)
877 delete[] fEraNames;
878
879 // we always own the new list, which we create here (we duplicate rather
880 // than adopting the list passed in)
881 fEraNames = newUnicodeStringArray(count);
882 uprv_arrayCopy(eraNamesArray,fEraNames, count);
883 fEraNamesCount = count;
884 }
885
886 void
setNarrowEras(const UnicodeString * narrowErasArray,int32_t count)887 DateFormatSymbols::setNarrowEras(const UnicodeString* narrowErasArray, int32_t count)
888 {
889 // delete the old list if we own it
890 if (fNarrowEras)
891 delete[] fNarrowEras;
892
893 // we always own the new list, which we create here (we duplicate rather
894 // than adopting the list passed in)
895 fNarrowEras = newUnicodeStringArray(count);
896 uprv_arrayCopy(narrowErasArray,fNarrowEras, count);
897 fNarrowErasCount = count;
898 }
899
900 void
setMonths(const UnicodeString * monthsArray,int32_t count)901 DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count)
902 {
903 // delete the old list if we own it
904 if (fMonths)
905 delete[] fMonths;
906
907 // we always own the new list, which we create here (we duplicate rather
908 // than adopting the list passed in)
909 fMonths = newUnicodeStringArray(count);
910 uprv_arrayCopy( monthsArray,fMonths,count);
911 fMonthsCount = count;
912 }
913
914 void
setShortMonths(const UnicodeString * shortMonthsArray,int32_t count)915 DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count)
916 {
917 // delete the old list if we own it
918 if (fShortMonths)
919 delete[] fShortMonths;
920
921 // we always own the new list, which we create here (we duplicate rather
922 // than adopting the list passed in)
923 fShortMonths = newUnicodeStringArray(count);
924 uprv_arrayCopy(shortMonthsArray,fShortMonths, count);
925 fShortMonthsCount = count;
926 }
927
928 void
setMonths(const UnicodeString * monthsArray,int32_t count,DtContextType context,DtWidthType width)929 DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, DtContextType context, DtWidthType width)
930 {
931 // delete the old list if we own it
932 // we always own the new list, which we create here (we duplicate rather
933 // than adopting the list passed in)
934
935 switch (context) {
936 case FORMAT :
937 switch (width) {
938 case WIDE :
939 if (fMonths)
940 delete[] fMonths;
941 fMonths = newUnicodeStringArray(count);
942 uprv_arrayCopy( monthsArray,fMonths,count);
943 fMonthsCount = count;
944 break;
945 case ABBREVIATED :
946 if (fShortMonths)
947 delete[] fShortMonths;
948 fShortMonths = newUnicodeStringArray(count);
949 uprv_arrayCopy( monthsArray,fShortMonths,count);
950 fShortMonthsCount = count;
951 break;
952 case NARROW :
953 if (fNarrowMonths)
954 delete[] fNarrowMonths;
955 fNarrowMonths = newUnicodeStringArray(count);
956 uprv_arrayCopy( monthsArray,fNarrowMonths,count);
957 fNarrowMonthsCount = count;
958 break;
959 default :
960 break;
961 }
962 break;
963 case STANDALONE :
964 switch (width) {
965 case WIDE :
966 if (fStandaloneMonths)
967 delete[] fStandaloneMonths;
968 fStandaloneMonths = newUnicodeStringArray(count);
969 uprv_arrayCopy( monthsArray,fStandaloneMonths,count);
970 fStandaloneMonthsCount = count;
971 break;
972 case ABBREVIATED :
973 if (fStandaloneShortMonths)
974 delete[] fStandaloneShortMonths;
975 fStandaloneShortMonths = newUnicodeStringArray(count);
976 uprv_arrayCopy( monthsArray,fStandaloneShortMonths,count);
977 fStandaloneShortMonthsCount = count;
978 break;
979 case NARROW :
980 if (fStandaloneNarrowMonths)
981 delete[] fStandaloneNarrowMonths;
982 fStandaloneNarrowMonths = newUnicodeStringArray(count);
983 uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count);
984 fStandaloneNarrowMonthsCount = count;
985 break;
986 default :
987 break;
988 }
989 break;
990 case DT_CONTEXT_COUNT :
991 break;
992 }
993 }
994
setWeekdays(const UnicodeString * weekdaysArray,int32_t count)995 void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count)
996 {
997 // delete the old list if we own it
998 if (fWeekdays)
999 delete[] fWeekdays;
1000
1001 // we always own the new list, which we create here (we duplicate rather
1002 // than adopting the list passed in)
1003 fWeekdays = newUnicodeStringArray(count);
1004 uprv_arrayCopy(weekdaysArray,fWeekdays,count);
1005 fWeekdaysCount = count;
1006 }
1007
1008 void
setShortWeekdays(const UnicodeString * shortWeekdaysArray,int32_t count)1009 DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count)
1010 {
1011 // delete the old list if we own it
1012 if (fShortWeekdays)
1013 delete[] fShortWeekdays;
1014
1015 // we always own the new list, which we create here (we duplicate rather
1016 // than adopting the list passed in)
1017 fShortWeekdays = newUnicodeStringArray(count);
1018 uprv_arrayCopy(shortWeekdaysArray, fShortWeekdays, count);
1019 fShortWeekdaysCount = count;
1020 }
1021
1022 void
setWeekdays(const UnicodeString * weekdaysArray,int32_t count,DtContextType context,DtWidthType width)1023 DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count, DtContextType context, DtWidthType width)
1024 {
1025 // delete the old list if we own it
1026 // we always own the new list, which we create here (we duplicate rather
1027 // than adopting the list passed in)
1028
1029 switch (context) {
1030 case FORMAT :
1031 switch (width) {
1032 case WIDE :
1033 if (fWeekdays)
1034 delete[] fWeekdays;
1035 fWeekdays = newUnicodeStringArray(count);
1036 uprv_arrayCopy(weekdaysArray, fWeekdays, count);
1037 fWeekdaysCount = count;
1038 break;
1039 case ABBREVIATED :
1040 if (fShortWeekdays)
1041 delete[] fShortWeekdays;
1042 fShortWeekdays = newUnicodeStringArray(count);
1043 uprv_arrayCopy(weekdaysArray, fShortWeekdays, count);
1044 fShortWeekdaysCount = count;
1045 break;
1046 case SHORT :
1047 if (fShorterWeekdays)
1048 delete[] fShorterWeekdays;
1049 fShorterWeekdays = newUnicodeStringArray(count);
1050 uprv_arrayCopy(weekdaysArray, fShorterWeekdays, count);
1051 fShorterWeekdaysCount = count;
1052 break;
1053 case NARROW :
1054 if (fNarrowWeekdays)
1055 delete[] fNarrowWeekdays;
1056 fNarrowWeekdays = newUnicodeStringArray(count);
1057 uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count);
1058 fNarrowWeekdaysCount = count;
1059 break;
1060 case DT_WIDTH_COUNT :
1061 break;
1062 }
1063 break;
1064 case STANDALONE :
1065 switch (width) {
1066 case WIDE :
1067 if (fStandaloneWeekdays)
1068 delete[] fStandaloneWeekdays;
1069 fStandaloneWeekdays = newUnicodeStringArray(count);
1070 uprv_arrayCopy(weekdaysArray, fStandaloneWeekdays, count);
1071 fStandaloneWeekdaysCount = count;
1072 break;
1073 case ABBREVIATED :
1074 if (fStandaloneShortWeekdays)
1075 delete[] fStandaloneShortWeekdays;
1076 fStandaloneShortWeekdays = newUnicodeStringArray(count);
1077 uprv_arrayCopy(weekdaysArray, fStandaloneShortWeekdays, count);
1078 fStandaloneShortWeekdaysCount = count;
1079 break;
1080 case SHORT :
1081 if (fStandaloneShorterWeekdays)
1082 delete[] fStandaloneShorterWeekdays;
1083 fStandaloneShorterWeekdays = newUnicodeStringArray(count);
1084 uprv_arrayCopy(weekdaysArray, fStandaloneShorterWeekdays, count);
1085 fStandaloneShorterWeekdaysCount = count;
1086 break;
1087 case NARROW :
1088 if (fStandaloneNarrowWeekdays)
1089 delete[] fStandaloneNarrowWeekdays;
1090 fStandaloneNarrowWeekdays = newUnicodeStringArray(count);
1091 uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count);
1092 fStandaloneNarrowWeekdaysCount = count;
1093 break;
1094 case DT_WIDTH_COUNT :
1095 break;
1096 }
1097 break;
1098 case DT_CONTEXT_COUNT :
1099 break;
1100 }
1101 }
1102
1103 void
setQuarters(const UnicodeString * quartersArray,int32_t count,DtContextType context,DtWidthType width)1104 DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count, DtContextType context, DtWidthType width)
1105 {
1106 // delete the old list if we own it
1107 // we always own the new list, which we create here (we duplicate rather
1108 // than adopting the list passed in)
1109
1110 switch (context) {
1111 case FORMAT :
1112 switch (width) {
1113 case WIDE :
1114 if (fQuarters)
1115 delete[] fQuarters;
1116 fQuarters = newUnicodeStringArray(count);
1117 uprv_arrayCopy( quartersArray,fQuarters,count);
1118 fQuartersCount = count;
1119 break;
1120 case ABBREVIATED :
1121 if (fShortQuarters)
1122 delete[] fShortQuarters;
1123 fShortQuarters = newUnicodeStringArray(count);
1124 uprv_arrayCopy( quartersArray,fShortQuarters,count);
1125 fShortQuartersCount = count;
1126 break;
1127 case NARROW :
1128 /*
1129 if (fNarrowQuarters)
1130 delete[] fNarrowQuarters;
1131 fNarrowQuarters = newUnicodeStringArray(count);
1132 uprv_arrayCopy( quartersArray,fNarrowQuarters,count);
1133 fNarrowQuartersCount = count;
1134 */
1135 break;
1136 default :
1137 break;
1138 }
1139 break;
1140 case STANDALONE :
1141 switch (width) {
1142 case WIDE :
1143 if (fStandaloneQuarters)
1144 delete[] fStandaloneQuarters;
1145 fStandaloneQuarters = newUnicodeStringArray(count);
1146 uprv_arrayCopy( quartersArray,fStandaloneQuarters,count);
1147 fStandaloneQuartersCount = count;
1148 break;
1149 case ABBREVIATED :
1150 if (fStandaloneShortQuarters)
1151 delete[] fStandaloneShortQuarters;
1152 fStandaloneShortQuarters = newUnicodeStringArray(count);
1153 uprv_arrayCopy( quartersArray,fStandaloneShortQuarters,count);
1154 fStandaloneShortQuartersCount = count;
1155 break;
1156 case NARROW :
1157 /*
1158 if (fStandaloneNarrowQuarters)
1159 delete[] fStandaloneNarrowQuarters;
1160 fStandaloneNarrowQuarters = newUnicodeStringArray(count);
1161 uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count);
1162 fStandaloneNarrowQuartersCount = count;
1163 */
1164 break;
1165 default :
1166 break;
1167 }
1168 break;
1169 case DT_CONTEXT_COUNT :
1170 break;
1171 }
1172 }
1173
1174 void
setAmPmStrings(const UnicodeString * amPmsArray,int32_t count)1175 DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count)
1176 {
1177 // delete the old list if we own it
1178 if (fAmPms) delete[] fAmPms;
1179
1180 // we always own the new list, which we create here (we duplicate rather
1181 // than adopting the list passed in)
1182 fAmPms = newUnicodeStringArray(count);
1183 uprv_arrayCopy(amPmsArray,fAmPms,count);
1184 fAmPmsCount = count;
1185 }
1186
1187 void
setTimeSeparatorString(const UnicodeString & newTimeSeparator)1188 DateFormatSymbols::setTimeSeparatorString(const UnicodeString& newTimeSeparator)
1189 {
1190 fTimeSeparator = newTimeSeparator;
1191 }
1192
1193 const UnicodeString**
getZoneStrings(int32_t & rowCount,int32_t & columnCount) const1194 DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
1195 {
1196 const UnicodeString **result = NULL;
1197
1198 umtx_lock(&LOCK);
1199 if (fZoneStrings == NULL) {
1200 if (fLocaleZoneStrings == NULL) {
1201 ((DateFormatSymbols*)this)->initZoneStringsArray();
1202 }
1203 result = (const UnicodeString**)fLocaleZoneStrings;
1204 } else {
1205 result = (const UnicodeString**)fZoneStrings;
1206 }
1207 rowCount = fZoneStringsRowCount;
1208 columnCount = fZoneStringsColCount;
1209 umtx_unlock(&LOCK);
1210
1211 return result;
1212 }
1213
1214 // For now, we include all zones
1215 #define ZONE_SET UCAL_ZONE_TYPE_ANY
1216
1217 // This code must be called within a synchronized block
1218 void
initZoneStringsArray(void)1219 DateFormatSymbols::initZoneStringsArray(void) {
1220 if (fZoneStrings != NULL || fLocaleZoneStrings != NULL) {
1221 return;
1222 }
1223
1224 UErrorCode status = U_ZERO_ERROR;
1225
1226 StringEnumeration *tzids = NULL;
1227 UnicodeString ** zarray = NULL;
1228 TimeZoneNames *tzNames = NULL;
1229 int32_t rows = 0;
1230
1231 do { // dummy do-while
1232
1233 tzids = TimeZone::createTimeZoneIDEnumeration(ZONE_SET, NULL, NULL, status);
1234 rows = tzids->count(status);
1235 if (U_FAILURE(status)) {
1236 break;
1237 }
1238
1239 // Allocate array
1240 int32_t size = rows * sizeof(UnicodeString*);
1241 zarray = (UnicodeString**)uprv_malloc(size);
1242 if (zarray == NULL) {
1243 status = U_MEMORY_ALLOCATION_ERROR;
1244 break;
1245 }
1246 uprv_memset(zarray, 0, size);
1247
1248 tzNames = TimeZoneNames::createInstance(fZSFLocale, status);
1249
1250 const UnicodeString *tzid;
1251 int32_t i = 0;
1252 UDate now = Calendar::getNow();
1253 UnicodeString tzDispName;
1254
1255 while ((tzid = tzids->snext(status))) {
1256 if (U_FAILURE(status)) {
1257 break;
1258 }
1259
1260 zarray[i] = new UnicodeString[5];
1261 if (zarray[i] == NULL) {
1262 status = U_MEMORY_ALLOCATION_ERROR;
1263 break;
1264 }
1265
1266 zarray[i][0].setTo(*tzid);
1267 zarray[i][1].setTo(tzNames->getDisplayName(*tzid, UTZNM_LONG_STANDARD, now, tzDispName));
1268 zarray[i][2].setTo(tzNames->getDisplayName(*tzid, UTZNM_SHORT_STANDARD, now, tzDispName));
1269 zarray[i][3].setTo(tzNames->getDisplayName(*tzid, UTZNM_LONG_DAYLIGHT, now, tzDispName));
1270 zarray[i][4].setTo(tzNames->getDisplayName(*tzid, UTZNM_SHORT_DAYLIGHT, now, tzDispName));
1271 i++;
1272 }
1273
1274 } while (FALSE);
1275
1276 if (U_FAILURE(status)) {
1277 if (zarray) {
1278 for (int32_t i = 0; i < rows; i++) {
1279 if (zarray[i]) {
1280 delete[] zarray[i];
1281 }
1282 }
1283 uprv_free(zarray);
1284 }
1285 }
1286
1287 if (tzNames) {
1288 delete tzNames;
1289 }
1290 if (tzids) {
1291 delete tzids;
1292 }
1293
1294 fLocaleZoneStrings = zarray;
1295 fZoneStringsRowCount = rows;
1296 fZoneStringsColCount = 5;
1297 }
1298
1299 void
setZoneStrings(const UnicodeString * const * strings,int32_t rowCount,int32_t columnCount)1300 DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t rowCount, int32_t columnCount)
1301 {
1302 // since deleting a 2-d array is a pain in the butt, we offload that task to
1303 // a separate function
1304 disposeZoneStrings();
1305 // we always own the new list, which we create here (we duplicate rather
1306 // than adopting the list passed in)
1307 fZoneStringsRowCount = rowCount;
1308 fZoneStringsColCount = columnCount;
1309 createZoneStrings((const UnicodeString**)strings);
1310 }
1311
1312 //------------------------------------------------------
1313
1314 const UChar * U_EXPORT2
getPatternUChars(void)1315 DateFormatSymbols::getPatternUChars(void)
1316 {
1317 return gPatternChars;
1318 }
1319
1320 UDateFormatField U_EXPORT2
getPatternCharIndex(UChar c)1321 DateFormatSymbols::getPatternCharIndex(UChar c) {
1322 const UChar *p = u_strchr(gPatternChars, c);
1323 if (p == NULL) {
1324 return UDAT_FIELD_COUNT;
1325 } else {
1326 return static_cast<UDateFormatField>(p - gPatternChars);
1327 }
1328 }
1329
1330 static const uint64_t kNumericFieldsAlways =
1331 ((uint64_t)1 << UDAT_YEAR_FIELD) | // y
1332 ((uint64_t)1 << UDAT_DATE_FIELD) | // d
1333 ((uint64_t)1 << UDAT_HOUR_OF_DAY1_FIELD) | // k
1334 ((uint64_t)1 << UDAT_HOUR_OF_DAY0_FIELD) | // H
1335 ((uint64_t)1 << UDAT_MINUTE_FIELD) | // m
1336 ((uint64_t)1 << UDAT_SECOND_FIELD) | // s
1337 ((uint64_t)1 << UDAT_FRACTIONAL_SECOND_FIELD) | // S
1338 ((uint64_t)1 << UDAT_DAY_OF_YEAR_FIELD) | // D
1339 ((uint64_t)1 << UDAT_DAY_OF_WEEK_IN_MONTH_FIELD) | // F
1340 ((uint64_t)1 << UDAT_WEEK_OF_YEAR_FIELD) | // w
1341 ((uint64_t)1 << UDAT_WEEK_OF_MONTH_FIELD) | // W
1342 ((uint64_t)1 << UDAT_HOUR1_FIELD) | // h
1343 ((uint64_t)1 << UDAT_HOUR0_FIELD) | // K
1344 ((uint64_t)1 << UDAT_YEAR_WOY_FIELD) | // Y
1345 ((uint64_t)1 << UDAT_EXTENDED_YEAR_FIELD) | // u
1346 ((uint64_t)1 << UDAT_JULIAN_DAY_FIELD) | // g
1347 ((uint64_t)1 << UDAT_MILLISECONDS_IN_DAY_FIELD) | // A
1348 ((uint64_t)1 << UDAT_RELATED_YEAR_FIELD); // r
1349
1350 static const uint64_t kNumericFieldsForCount12 =
1351 ((uint64_t)1 << UDAT_MONTH_FIELD) | // M or MM
1352 ((uint64_t)1 << UDAT_DOW_LOCAL_FIELD) | // e or ee
1353 ((uint64_t)1 << UDAT_STANDALONE_DAY_FIELD) | // c or cc
1354 ((uint64_t)1 << UDAT_STANDALONE_MONTH_FIELD) | // L or LL
1355 ((uint64_t)1 << UDAT_QUARTER_FIELD) | // Q or QQ
1356 ((uint64_t)1 << UDAT_STANDALONE_QUARTER_FIELD); // q or qq
1357
1358 UBool U_EXPORT2
isNumericField(UDateFormatField f,int32_t count)1359 DateFormatSymbols::isNumericField(UDateFormatField f, int32_t count) {
1360 if (f == UDAT_FIELD_COUNT) {
1361 return FALSE;
1362 }
1363 uint64_t flag = ((uint64_t)1 << f);
1364 return ((kNumericFieldsAlways & flag) != 0 || ((kNumericFieldsForCount12 & flag) != 0 && count < 3));
1365 }
1366
1367 UBool U_EXPORT2
isNumericPatternChar(UChar c,int32_t count)1368 DateFormatSymbols::isNumericPatternChar(UChar c, int32_t count) {
1369 return isNumericField(getPatternCharIndex(c), count);
1370 }
1371
1372 //------------------------------------------------------
1373
1374 UnicodeString&
getLocalPatternChars(UnicodeString & result) const1375 DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
1376 {
1377 // fastCopyFrom() - see assignArray comments
1378 return result.fastCopyFrom(fLocalPatternChars);
1379 }
1380
1381 //------------------------------------------------------
1382
1383 void
setLocalPatternChars(const UnicodeString & newLocalPatternChars)1384 DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
1385 {
1386 fLocalPatternChars = newLocalPatternChars;
1387 }
1388
1389 //------------------------------------------------------
1390
1391 static void
initField(UnicodeString ** field,int32_t & length,const UResourceBundle * data,UErrorCode & status)1392 initField(UnicodeString **field, int32_t& length, const UResourceBundle *data, UErrorCode &status) {
1393 if (U_SUCCESS(status)) {
1394 int32_t strLen = 0;
1395 length = ures_getSize(data);
1396 *field = newUnicodeStringArray(length);
1397 if (*field) {
1398 for(int32_t i = 0; i<length; i++) {
1399 const UChar *resStr = ures_getStringByIndex(data, i, &strLen, &status);
1400 // setTo() - see assignArray comments
1401 (*(field)+i)->setTo(TRUE, resStr, strLen);
1402 }
1403 }
1404 else {
1405 length = 0;
1406 status = U_MEMORY_ALLOCATION_ERROR;
1407 }
1408 }
1409 }
1410
1411 static void
initField(UnicodeString ** field,int32_t & length,const UChar * data,LastResortSize numStr,LastResortSize strLen,UErrorCode & status)1412 initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
1413 if (U_SUCCESS(status)) {
1414 length = numStr;
1415 *field = newUnicodeStringArray((size_t)numStr);
1416 if (*field) {
1417 for(int32_t i = 0; i<length; i++) {
1418 // readonly aliases - all "data" strings are constant
1419 // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
1420 (*(field)+i)->setTo(TRUE, data+(i*((int32_t)strLen)), -1);
1421 }
1422 }
1423 else {
1424 length = 0;
1425 status = U_MEMORY_ALLOCATION_ERROR;
1426 }
1427 }
1428 }
1429
1430 static void
initLeapMonthPattern(UnicodeString * field,int32_t index,const UResourceBundle * data,UErrorCode & status)1431 initLeapMonthPattern(UnicodeString *field, int32_t index, const UResourceBundle *data, UErrorCode &status) {
1432 field[index].remove();
1433 if (U_SUCCESS(status)) {
1434 int32_t strLen = 0;
1435 const UChar *resStr = ures_getStringByKey(data, gNamesLeapTag, &strLen, &status);
1436 if (U_SUCCESS(status)) {
1437 field[index].setTo(TRUE, resStr, strLen);
1438 }
1439 }
1440 status = U_ZERO_ERROR;
1441 }
1442
1443 typedef struct {
1444 const char * usageTypeName;
1445 DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
1446 } ContextUsageTypeNameToEnumValue;
1447
1448 static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
1449 // Entries must be sorted by usageTypeName; entry with NULL name terminates list.
1450 { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
1451 { "day-narrow", DateFormatSymbols::kCapContextUsageDayNarrow },
1452 { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
1453 { "era-abbr", DateFormatSymbols::kCapContextUsageEraAbbrev },
1454 { "era-name", DateFormatSymbols::kCapContextUsageEraWide },
1455 { "era-narrow", DateFormatSymbols::kCapContextUsageEraNarrow },
1456 { "metazone-long", DateFormatSymbols::kCapContextUsageMetazoneLong },
1457 { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
1458 { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
1459 { "month-narrow", DateFormatSymbols::kCapContextUsageMonthNarrow },
1460 { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
1461 { "zone-long", DateFormatSymbols::kCapContextUsageZoneLong },
1462 { "zone-short", DateFormatSymbols::kCapContextUsageZoneShort },
1463 { NULL, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
1464 };
1465
1466 void
initializeData(const Locale & locale,const char * type,UErrorCode & status,UBool useLastResortData)1467 DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
1468 {
1469 int32_t i;
1470 int32_t len = 0;
1471 const UChar *resStr;
1472 /* In case something goes wrong, initialize all of the data to NULL. */
1473 fEras = NULL;
1474 fErasCount = 0;
1475 fEraNames = NULL;
1476 fEraNamesCount = 0;
1477 fNarrowEras = NULL;
1478 fNarrowErasCount = 0;
1479 fMonths = NULL;
1480 fMonthsCount=0;
1481 fShortMonths = NULL;
1482 fShortMonthsCount=0;
1483 fNarrowMonths = NULL;
1484 fNarrowMonthsCount=0;
1485 fStandaloneMonths = NULL;
1486 fStandaloneMonthsCount=0;
1487 fStandaloneShortMonths = NULL;
1488 fStandaloneShortMonthsCount=0;
1489 fStandaloneNarrowMonths = NULL;
1490 fStandaloneNarrowMonthsCount=0;
1491 fWeekdays = NULL;
1492 fWeekdaysCount=0;
1493 fShortWeekdays = NULL;
1494 fShortWeekdaysCount=0;
1495 fShorterWeekdays = NULL;
1496 fShorterWeekdaysCount=0;
1497 fNarrowWeekdays = NULL;
1498 fNarrowWeekdaysCount=0;
1499 fStandaloneWeekdays = NULL;
1500 fStandaloneWeekdaysCount=0;
1501 fStandaloneShortWeekdays = NULL;
1502 fStandaloneShortWeekdaysCount=0;
1503 fStandaloneShorterWeekdays = NULL;
1504 fStandaloneShorterWeekdaysCount=0;
1505 fStandaloneNarrowWeekdays = NULL;
1506 fStandaloneNarrowWeekdaysCount=0;
1507 fAmPms = NULL;
1508 fAmPmsCount=0;
1509 fNarrowAmPms = NULL;
1510 fNarrowAmPmsCount=0;
1511 fTimeSeparator.setToBogus();
1512 fQuarters = NULL;
1513 fQuartersCount = 0;
1514 fShortQuarters = NULL;
1515 fShortQuartersCount = 0;
1516 fStandaloneQuarters = NULL;
1517 fStandaloneQuartersCount = 0;
1518 fStandaloneShortQuarters = NULL;
1519 fStandaloneShortQuartersCount = 0;
1520 fLeapMonthPatterns = NULL;
1521 fLeapMonthPatternsCount = 0;
1522 fShortYearNames = NULL;
1523 fShortYearNamesCount = 0;
1524 fShortZodiacNames = NULL;
1525 fShortZodiacNamesCount = 0;
1526 fZoneStringsRowCount = 0;
1527 fZoneStringsColCount = 0;
1528 fZoneStrings = NULL;
1529 fLocaleZoneStrings = NULL;
1530 uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
1531
1532 // We need to preserve the requested locale for
1533 // lazy ZoneStringFormat instantiation. ZoneStringFormat
1534 // is region sensitive, thus, bundle locale bundle's locale
1535 // is not sufficient.
1536 fZSFLocale = locale;
1537
1538 if (U_FAILURE(status)) return;
1539
1540 /**
1541 * Retrieve the string arrays we need from the resource bundle file.
1542 * We cast away const here, but that's okay; we won't delete any of
1543 * these.
1544 */
1545 CalendarData calData(locale, type, status);
1546
1547 // load the first data item
1548 UResourceBundle *erasMain = calData.getByKey(gErasTag, status);
1549 UResourceBundle *eras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
1550 UErrorCode oldStatus = status;
1551 UResourceBundle *eraNames = ures_getByKeyWithFallback(erasMain, gNamesWideTag, NULL, &status);
1552 if ( status == U_MISSING_RESOURCE_ERROR ) { // Workaround because eras/wide was omitted from CLDR 1.3
1553 status = oldStatus;
1554 eraNames = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
1555 }
1556 // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
1557 oldStatus = status;
1558 UResourceBundle *narrowEras = ures_getByKeyWithFallback(erasMain, gNamesNarrowTag, NULL, &status);
1559 if ( status == U_MISSING_RESOURCE_ERROR ) {
1560 status = oldStatus;
1561 narrowEras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
1562 }
1563
1564 UErrorCode tempStatus = U_ZERO_ERROR;
1565 UResourceBundle *monthPatterns = calData.getByKey(gMonthPatternsTag, tempStatus);
1566 if (U_SUCCESS(tempStatus) && monthPatterns != NULL) {
1567 fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
1568 if (fLeapMonthPatterns) {
1569 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calData.getByKey2(gMonthPatternsTag, gNamesWideTag, tempStatus), tempStatus);
1570 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calData.getByKey2(gMonthPatternsTag, gNamesAbbrTag, tempStatus), tempStatus);
1571 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calData.getByKey2(gMonthPatternsTag, gNamesNarrowTag, tempStatus), tempStatus);
1572 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
1573 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
1574 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
1575 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calData.getByKey3(gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
1576 if (U_SUCCESS(tempStatus)) {
1577 // Hack to fix bad C inheritance for dangi monthPatterns (OK in J); this should be handled by aliases in root, but isn't.
1578 // The ordering of the following statements is important.
1579 if (fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].isEmpty()) {
1580 fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
1581 };
1582 if (fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].isEmpty()) {
1583 fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].setTo(fLeapMonthPatterns[kLeapMonthPatternStandaloneNarrow]);
1584 };
1585 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].isEmpty()) {
1586 fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
1587 };
1588 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].isEmpty()) {
1589 fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev]);
1590 };
1591 // end of hack
1592 fLeapMonthPatternsCount = kMonthPatternsCount;
1593 } else {
1594 delete[] fLeapMonthPatterns;
1595 fLeapMonthPatterns = NULL;
1596 }
1597 }
1598 }
1599
1600 tempStatus = U_ZERO_ERROR;
1601 UResourceBundle *cyclicNameSets= calData.getByKey(gCyclicNameSetsTag, tempStatus);
1602 if (U_SUCCESS(tempStatus) && cyclicNameSets != NULL) {
1603 UResourceBundle *nameSetYears = ures_getByKeyWithFallback(cyclicNameSets, gNameSetYearsTag, NULL, &tempStatus);
1604 if (U_SUCCESS(tempStatus)) {
1605 UResourceBundle *nameSetYearsFmt = ures_getByKeyWithFallback(nameSetYears, gNamesFormatTag, NULL, &tempStatus);
1606 if (U_SUCCESS(tempStatus)) {
1607 UResourceBundle *nameSetYearsFmtAbbrev = ures_getByKeyWithFallback(nameSetYearsFmt, gNamesAbbrTag, NULL, &tempStatus);
1608 if (U_SUCCESS(tempStatus)) {
1609 initField(&fShortYearNames, fShortYearNamesCount, nameSetYearsFmtAbbrev, tempStatus);
1610 ures_close(nameSetYearsFmtAbbrev);
1611 }
1612 ures_close(nameSetYearsFmt);
1613 }
1614 ures_close(nameSetYears);
1615 }
1616 UResourceBundle *nameSetZodiacs = ures_getByKeyWithFallback(cyclicNameSets, gNameSetZodiacsTag, NULL, &tempStatus);
1617 if (U_SUCCESS(tempStatus)) {
1618 UResourceBundle *nameSetZodiacsFmt = ures_getByKeyWithFallback(nameSetZodiacs, gNamesFormatTag, NULL, &tempStatus);
1619 if (U_SUCCESS(tempStatus)) {
1620 UResourceBundle *nameSetZodiacsFmtAbbrev = ures_getByKeyWithFallback(nameSetZodiacsFmt, gNamesAbbrTag, NULL, &tempStatus);
1621 if (U_SUCCESS(tempStatus)) {
1622 initField(&fShortZodiacNames, fShortZodiacNamesCount, nameSetZodiacsFmtAbbrev, tempStatus);
1623 ures_close(nameSetZodiacsFmtAbbrev);
1624 }
1625 ures_close(nameSetZodiacsFmt);
1626 }
1627 ures_close(nameSetZodiacs);
1628 }
1629 }
1630
1631 tempStatus = U_ZERO_ERROR;
1632 UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &tempStatus);
1633 if (U_SUCCESS(tempStatus)) {
1634 UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, gContextTransformsTag, NULL, &tempStatus);
1635 if (U_SUCCESS(tempStatus)) {
1636 UResourceBundle *contextTransformUsage;
1637 while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &tempStatus)) != NULL ) {
1638 const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
1639 if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
1640 const char* usageType = ures_getKey(contextTransformUsage);
1641 if (usageType != NULL) {
1642 const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
1643 int32_t compResult = 0;
1644 // linear search; list is short and we cannot be sure that bsearch is available
1645 while ( typeMapPtr->usageTypeName != NULL && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
1646 ++typeMapPtr;
1647 }
1648 if (typeMapPtr->usageTypeName != NULL && compResult == 0) {
1649 fCapitalization[typeMapPtr->usageTypeEnumValue][0] = intVector[0];
1650 fCapitalization[typeMapPtr->usageTypeEnumValue][1] = intVector[1];
1651 }
1652 }
1653 }
1654 tempStatus = U_ZERO_ERROR;
1655 ures_close(contextTransformUsage);
1656 }
1657 ures_close(contextTransforms);
1658 }
1659
1660 tempStatus = U_ZERO_ERROR;
1661 const LocalPointer<NumberingSystem> numberingSystem(
1662 NumberingSystem::createInstance(locale, tempStatus), tempStatus);
1663 if (U_SUCCESS(tempStatus)) {
1664 // These functions all fail gracefully if passed NULL pointers and
1665 // do nothing unless U_SUCCESS(tempStatus), so it's only necessary
1666 // to check for errors once after all calls are made.
1667 const LocalUResourceBundlePointer numberElementsData(ures_getByKeyWithFallback(
1668 localeBundle, gNumberElementsTag, NULL, &tempStatus));
1669 const LocalUResourceBundlePointer nsNameData(ures_getByKeyWithFallback(
1670 numberElementsData.getAlias(), numberingSystem->getName(), NULL, &tempStatus));
1671 const LocalUResourceBundlePointer symbolsData(ures_getByKeyWithFallback(
1672 nsNameData.getAlias(), gSymbolsTag, NULL, &tempStatus));
1673 fTimeSeparator = ures_getUnicodeStringByKey(
1674 symbolsData.getAlias(), gTimeSeparatorTag, &tempStatus);
1675 if (U_FAILURE(tempStatus)) {
1676 fTimeSeparator.setToBogus();
1677 }
1678 }
1679
1680 ures_close(localeBundle);
1681 }
1682
1683 if (fTimeSeparator.isBogus()) {
1684 fTimeSeparator.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR);
1685 }
1686
1687 UResourceBundle *weekdaysData = NULL; // Data closed by calData
1688 UResourceBundle *abbrWeekdaysData = NULL; // Data closed by calData
1689 UResourceBundle *shorterWeekdaysData = NULL; // Data closed by calData
1690 UResourceBundle *narrowWeekdaysData = NULL; // Data closed by calData
1691 UResourceBundle *standaloneWeekdaysData = NULL; // Data closed by calData
1692 UResourceBundle *standaloneAbbrWeekdaysData = NULL; // Data closed by calData
1693 UResourceBundle *standaloneShorterWeekdaysData = NULL; // Data closed by calData
1694 UResourceBundle *standaloneNarrowWeekdaysData = NULL; // Data closed by calData
1695
1696 U_LOCALE_BASED(locBased, *this);
1697 if (U_FAILURE(status))
1698 {
1699 if (useLastResortData)
1700 {
1701 // Handle the case in which there is no resource data present.
1702 // We don't have to generate usable patterns in this situation;
1703 // we just need to produce something that will be semi-intelligible
1704 // in most locales.
1705
1706 status = U_USING_FALLBACK_WARNING;
1707
1708 initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
1709 initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
1710 initField(&fNarrowEras, fNarrowErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
1711 initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1712 initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1713 initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1714 initField(&fStandaloneMonths, fStandaloneMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1715 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1716 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1717 initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1718 initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1719 initField(&fShorterWeekdays, fShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1720 initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1721 initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1722 initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1723 initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1724 initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1725 initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
1726 initField(&fNarrowAmPms, fNarrowAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
1727 initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1728 initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1729 initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1730 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1731 fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
1732 }
1733 goto cleanup;
1734 }
1735
1736 // if we make it to here, the resource data is cool, and we can get everything out
1737 // of it that we need except for the time-zone and localized-pattern data, which
1738 // are stored in a separate file
1739 locBased.setLocaleIDs(ures_getLocaleByType(eras, ULOC_VALID_LOCALE, &status),
1740 ures_getLocaleByType(eras, ULOC_ACTUAL_LOCALE, &status));
1741
1742 initField(&fEras, fErasCount, eras, status);
1743 initField(&fEraNames, fEraNamesCount, eraNames, status);
1744 initField(&fNarrowEras, fNarrowErasCount, narrowEras, status);
1745
1746 initField(&fMonths, fMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status);
1747 initField(&fShortMonths, fShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1748
1749 initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesNarrowTag, status), status);
1750 if(status == U_MISSING_RESOURCE_ERROR) {
1751 status = U_ZERO_ERROR;
1752 initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
1753 }
1754 if ( status == U_MISSING_RESOURCE_ERROR ) { /* If format/narrow not available, use format/abbreviated */
1755 status = U_ZERO_ERROR;
1756 initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1757 }
1758
1759 initField(&fStandaloneMonths, fStandaloneMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
1760 if ( status == U_MISSING_RESOURCE_ERROR ) { /* If standalone/wide not available, use format/wide */
1761 status = U_ZERO_ERROR;
1762 initField(&fStandaloneMonths, fStandaloneMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status);
1763 }
1764 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
1765 if ( status == U_MISSING_RESOURCE_ERROR ) { /* If standalone/abbreviated not available, use format/abbreviated */
1766 status = U_ZERO_ERROR;
1767 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1768 }
1769 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
1770 if ( status == U_MISSING_RESOURCE_ERROR ) { /* if standalone/narrow not availabe, try format/narrow */
1771 status = U_ZERO_ERROR;
1772 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesNarrowTag, status), status);
1773 if ( status == U_MISSING_RESOURCE_ERROR ) { /* if still not there, use format/abbreviated */
1774 status = U_ZERO_ERROR;
1775 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1776 }
1777 }
1778 initField(&fAmPms, fAmPmsCount, calData.getByKey(gAmPmMarkersTag, status), status);
1779 initField(&fNarrowAmPms, fNarrowAmPmsCount, calData.getByKey(gAmPmMarkersNarrowTag, status), status);
1780
1781 initField(&fQuarters, fQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status);
1782 initField(&fShortQuarters, fShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status);
1783
1784 initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
1785 if(status == U_MISSING_RESOURCE_ERROR) {
1786 status = U_ZERO_ERROR;
1787 initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status);
1788 }
1789
1790 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
1791 if(status == U_MISSING_RESOURCE_ERROR) {
1792 status = U_ZERO_ERROR;
1793 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status);
1794 }
1795
1796 // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
1797 /*
1798 // fastCopyFrom()/setTo() - see assignArray comments
1799 resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
1800 fLocalPatternChars.setTo(TRUE, resStr, len);
1801 // If the locale data does not include new pattern chars, use the defaults
1802 // TODO: Consider making this an error, since this may add conflicting characters.
1803 if (len < PATTERN_CHARS_LEN) {
1804 fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len));
1805 }
1806 */
1807 fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
1808
1809 // Format wide weekdays -> fWeekdays
1810 // {sfb} fixed to handle 1-based weekdays
1811 weekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status);
1812 fWeekdaysCount = ures_getSize(weekdaysData);
1813 fWeekdays = new UnicodeString[fWeekdaysCount+1];
1814 /* pin the blame on system. If we cannot get a chunk of memory .. the system is dying!*/
1815 if (fWeekdays == NULL) {
1816 status = U_MEMORY_ALLOCATION_ERROR;
1817 goto cleanup;
1818 }
1819 // leave fWeekdays[0] empty
1820 for(i = 0; i<fWeekdaysCount; i++) {
1821 resStr = ures_getStringByIndex(weekdaysData, i, &len, &status);
1822 // setTo() - see assignArray comments
1823 fWeekdays[i+1].setTo(TRUE, resStr, len);
1824 }
1825 fWeekdaysCount++;
1826
1827 // Format abbreviated weekdays -> fShortWeekdays
1828 abbrWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1829 fShortWeekdaysCount = ures_getSize(abbrWeekdaysData);
1830 fShortWeekdays = new UnicodeString[fShortWeekdaysCount+1];
1831 /* test for NULL */
1832 if (fShortWeekdays == 0) {
1833 status = U_MEMORY_ALLOCATION_ERROR;
1834 goto cleanup;
1835 }
1836 // leave fShortWeekdays[0] empty
1837 for(i = 0; i<fShortWeekdaysCount; i++) {
1838 resStr = ures_getStringByIndex(abbrWeekdaysData, i, &len, &status);
1839 // setTo() - see assignArray comments
1840 fShortWeekdays[i+1].setTo(TRUE, resStr, len);
1841 }
1842 fShortWeekdaysCount++;
1843
1844 // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
1845 shorterWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesShortTag, status);
1846 if ( status == U_MISSING_RESOURCE_ERROR ) {
1847 status = U_ZERO_ERROR;
1848 shorterWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1849 }
1850 fShorterWeekdaysCount = ures_getSize(shorterWeekdaysData);
1851 fShorterWeekdays = new UnicodeString[fShorterWeekdaysCount+1];
1852 /* test for NULL */
1853 if (fShorterWeekdays == 0) {
1854 status = U_MEMORY_ALLOCATION_ERROR;
1855 goto cleanup;
1856 }
1857 // leave fShorterWeekdays[0] empty
1858 for(i = 0; i<fShorterWeekdaysCount; i++) {
1859 resStr = ures_getStringByIndex(shorterWeekdaysData, i, &len, &status);
1860 // setTo() - see assignArray comments
1861 fShorterWeekdays[i+1].setTo(TRUE, resStr, len);
1862 }
1863 fShorterWeekdaysCount++;
1864
1865 // Format narrow weekdays -> fNarrowWeekdays
1866 narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesNarrowTag, status);
1867 if(status == U_MISSING_RESOURCE_ERROR) {
1868 status = U_ZERO_ERROR;
1869 narrowWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status);
1870 }
1871 if ( status == U_MISSING_RESOURCE_ERROR ) {
1872 status = U_ZERO_ERROR;
1873 narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1874 }
1875 fNarrowWeekdaysCount = ures_getSize(narrowWeekdaysData);
1876 fNarrowWeekdays = new UnicodeString[fNarrowWeekdaysCount+1];
1877 /* test for NULL */
1878 if (fNarrowWeekdays == 0) {
1879 status = U_MEMORY_ALLOCATION_ERROR;
1880 goto cleanup;
1881 }
1882 // leave fNarrowWeekdays[0] empty
1883 for(i = 0; i<fNarrowWeekdaysCount; i++) {
1884 resStr = ures_getStringByIndex(narrowWeekdaysData, i, &len, &status);
1885 // setTo() - see assignArray comments
1886 fNarrowWeekdays[i+1].setTo(TRUE, resStr, len);
1887 }
1888 fNarrowWeekdaysCount++;
1889
1890 // Stand-alone wide weekdays -> fStandaloneWeekdays
1891 standaloneWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status);
1892 if ( status == U_MISSING_RESOURCE_ERROR ) {
1893 status = U_ZERO_ERROR;
1894 standaloneWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status);
1895 }
1896 fStandaloneWeekdaysCount = ures_getSize(standaloneWeekdaysData);
1897 fStandaloneWeekdays = new UnicodeString[fStandaloneWeekdaysCount+1];
1898 /* test for NULL */
1899 if (fStandaloneWeekdays == 0) {
1900 status = U_MEMORY_ALLOCATION_ERROR;
1901 goto cleanup;
1902 }
1903 // leave fStandaloneWeekdays[0] empty
1904 for(i = 0; i<fStandaloneWeekdaysCount; i++) {
1905 resStr = ures_getStringByIndex(standaloneWeekdaysData, i, &len, &status);
1906 // setTo() - see assignArray comments
1907 fStandaloneWeekdays[i+1].setTo(TRUE, resStr, len);
1908 }
1909 fStandaloneWeekdaysCount++;
1910
1911 // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
1912 standaloneAbbrWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status);
1913 if ( status == U_MISSING_RESOURCE_ERROR ) {
1914 status = U_ZERO_ERROR;
1915 standaloneAbbrWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1916 }
1917 fStandaloneShortWeekdaysCount = ures_getSize(standaloneAbbrWeekdaysData);
1918 fStandaloneShortWeekdays = new UnicodeString[fStandaloneShortWeekdaysCount+1];
1919 /* test for NULL */
1920 if (fStandaloneShortWeekdays == 0) {
1921 status = U_MEMORY_ALLOCATION_ERROR;
1922 goto cleanup;
1923 }
1924 // leave fStandaloneShortWeekdays[0] empty
1925 for(i = 0; i<fStandaloneShortWeekdaysCount; i++) {
1926 resStr = ures_getStringByIndex(standaloneAbbrWeekdaysData, i, &len, &status);
1927 // setTo() - see assignArray comments
1928 fStandaloneShortWeekdays[i+1].setTo(TRUE, resStr, len);
1929 }
1930 fStandaloneShortWeekdaysCount++;
1931
1932 // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
1933 standaloneShorterWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status);
1934 if ( status == U_MISSING_RESOURCE_ERROR ) {
1935 status = U_ZERO_ERROR;
1936 standaloneShorterWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1937 }
1938 fStandaloneShorterWeekdaysCount = ures_getSize(standaloneShorterWeekdaysData);
1939 fStandaloneShorterWeekdays = new UnicodeString[fStandaloneShorterWeekdaysCount+1];
1940 /* test for NULL */
1941 if (fStandaloneShorterWeekdays == 0) {
1942 status = U_MEMORY_ALLOCATION_ERROR;
1943 goto cleanup;
1944 }
1945 // leave fStandaloneShorterWeekdays[0] empty
1946 for(i = 0; i<fStandaloneShorterWeekdaysCount; i++) {
1947 resStr = ures_getStringByIndex(standaloneShorterWeekdaysData, i, &len, &status);
1948 // setTo() - see assignArray comments
1949 fStandaloneShorterWeekdays[i+1].setTo(TRUE, resStr, len);
1950 }
1951 fStandaloneShorterWeekdaysCount++;
1952
1953 // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
1954 standaloneNarrowWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status);
1955 if ( status == U_MISSING_RESOURCE_ERROR ) {
1956 status = U_ZERO_ERROR;
1957 standaloneNarrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesNarrowTag, status);
1958 if ( status == U_MISSING_RESOURCE_ERROR ) {
1959 status = U_ZERO_ERROR;
1960 standaloneNarrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1961 }
1962 }
1963 fStandaloneNarrowWeekdaysCount = ures_getSize(standaloneNarrowWeekdaysData);
1964 fStandaloneNarrowWeekdays = new UnicodeString[fStandaloneNarrowWeekdaysCount+1];
1965 /* test for NULL */
1966 if (fStandaloneNarrowWeekdays == 0) {
1967 status = U_MEMORY_ALLOCATION_ERROR;
1968 goto cleanup;
1969 }
1970 // leave fStandaloneNarrowWeekdays[0] empty
1971 for(i = 0; i<fStandaloneNarrowWeekdaysCount; i++) {
1972 resStr = ures_getStringByIndex(standaloneNarrowWeekdaysData, i, &len, &status);
1973 // setTo() - see assignArray comments
1974 fStandaloneNarrowWeekdays[i+1].setTo(TRUE, resStr, len);
1975 }
1976 fStandaloneNarrowWeekdaysCount++;
1977
1978 cleanup:
1979 ures_close(eras);
1980 ures_close(eraNames);
1981 ures_close(narrowEras);
1982 }
1983
1984 Locale
getLocale(ULocDataLocaleType type,UErrorCode & status) const1985 DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
1986 U_LOCALE_BASED(locBased, *this);
1987 return locBased.getLocale(type, status);
1988 }
1989
1990 U_NAMESPACE_END
1991
1992 #endif /* #if !UCONFIG_NO_FORMATTING */
1993
1994 //eof
1995