Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Side by Side Diff: source/i18n/smpdtfmt.cpp

Issue 1621843002: ICU 56 update step 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@561
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « source/i18n/smallintformatter.cpp ('k') | source/i18n/timezone.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 ******************************************************************************* 2 *******************************************************************************
3 * Copyright (C) 1997-2014, International Business Machines Corporation and * 3 * Copyright (C) 1997-2015, International Business Machines Corporation and *
4 * others. All Rights Reserved. * 4 * others. All Rights Reserved. *
5 ******************************************************************************* 5 *******************************************************************************
6 * 6 *
7 * File SMPDTFMT.CPP 7 * File SMPDTFMT.CPP
8 * 8 *
9 * Modification History: 9 * Modification History:
10 * 10 *
11 * Date Name Description 11 * Date Name Description
12 * 02/19/97 aliu Converted from java. 12 * 02/19/97 aliu Converted from java.
13 * 03/31/97 aliu Modified extensively to work with 50 locales. 13 * 03/31/97 aliu Modified extensively to work with 50 locales.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 #include "patternprops.h" 53 #include "patternprops.h"
54 #include "fphdlimp.h" 54 #include "fphdlimp.h"
55 #include "gregoimp.h" 55 #include "gregoimp.h"
56 #include "hebrwcal.h" 56 #include "hebrwcal.h"
57 #include "cstring.h" 57 #include "cstring.h"
58 #include "uassert.h" 58 #include "uassert.h"
59 #include "cmemory.h" 59 #include "cmemory.h"
60 #include "umutex.h" 60 #include "umutex.h"
61 #include <float.h> 61 #include <float.h>
62 #include "smpdtfst.h" 62 #include "smpdtfst.h"
63 #include "sharednumberformat.h"
64 #include "ustr_imp.h"
63 65
64 #if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL) 66 #if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
65 #include <stdio.h> 67 #include <stdio.h>
66 #endif 68 #endif
67 69
68 // ***************************************************************************** 70 // *****************************************************************************
69 // class SimpleDateFormat 71 // class SimpleDateFormat
70 // ***************************************************************************** 72 // *****************************************************************************
71 73
72 U_NAMESPACE_BEGIN 74 U_NAMESPACE_BEGIN
73 75
74 static const UChar PATTERN_CHAR_BASE = 0x40;
75
76 /** 76 /**
77 * Last-resort string to use for "GMT" when constructing time zone strings. 77 * Last-resort string to use for "GMT" when constructing time zone strings.
78 */ 78 */
79 // For time zones that have no names, use strings GMT+minutes and 79 // For time zones that have no names, use strings GMT+minutes and
80 // GMT-minutes. For instance, in France the time zone is GMT+60. 80 // GMT-minutes. For instance, in France the time zone is GMT+60.
81 // Also accepted are GMT+H:MM or GMT-H:MM. 81 // Also accepted are GMT+H:MM or GMT-H:MM.
82 // Currently not being used 82 // Currently not being used
83 //static const UChar gGmt[] = {0x0047, 0x004D, 0x0054, 0x0000}; // "GMT" 83 //static const UChar gGmt[] = {0x0047, 0x004D, 0x0054, 0x0000}; // "GMT"
84 //static const UChar gGmtPlus[] = {0x0047, 0x004D, 0x0054, 0x002B, 0x0000}; // "GMT+" 84 //static const UChar gGmtPlus[] = {0x0047, 0x004D, 0x0054, 0x002B, 0x0000}; // "GMT+"
85 //static const UChar gGmtMinus[] = {0x0047, 0x004D, 0x0054, 0x002D, 0x0000}; // "GMT-" 85 //static const UChar gGmtMinus[] = {0x0047, 0x004D, 0x0054, 0x002D, 0x0000}; // "GMT-"
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 * A value of -1 means that the value is not checked. 174 * A value of -1 means that the value is not checked.
175 */ 175 */
176 static const int32_t gFieldRangeBias[] = { 176 static const int32_t gFieldRangeBias[] = {
177 -1, // 'G' - UDAT_ERA_FIELD 177 -1, // 'G' - UDAT_ERA_FIELD
178 -1, // 'y' - UDAT_YEAR_FIELD 178 -1, // 'y' - UDAT_YEAR_FIELD
179 1, // 'M' - UDAT_MONTH_FIELD 179 1, // 'M' - UDAT_MONTH_FIELD
180 0, // 'd' - UDAT_DATE_FIELD 180 0, // 'd' - UDAT_DATE_FIELD
181 -1, // 'k' - UDAT_HOUR_OF_DAY1_FIELD 181 -1, // 'k' - UDAT_HOUR_OF_DAY1_FIELD
182 -1, // 'H' - UDAT_HOUR_OF_DAY0_FIELD 182 -1, // 'H' - UDAT_HOUR_OF_DAY0_FIELD
183 0, // 'm' - UDAT_MINUTE_FIELD 183 0, // 'm' - UDAT_MINUTE_FIELD
184 0, // 's' - UDAT_SEOND_FIELD 184 0, // 's' - UDAT_SECOND_FIELD
185 -1, // 'S' - UDAT_FRACTIONAL_SECOND_FIELD (0-999?) 185 -1, // 'S' - UDAT_FRACTIONAL_SECOND_FIELD (0-999?)
186 -1, // 'E' - UDAT_DAY_OF_WEEK_FIELD (1-7?) 186 -1, // 'E' - UDAT_DAY_OF_WEEK_FIELD (1-7?)
187 -1, // 'D' - UDAT_DAY_OF_YEAR_FIELD (1 - 366?) 187 -1, // 'D' - UDAT_DAY_OF_YEAR_FIELD (1 - 366?)
188 -1, // 'F' - UDAT_DAY_OF_WEEK_IN_MONTH_FIELD (1-5?) 188 -1, // 'F' - UDAT_DAY_OF_WEEK_IN_MONTH_FIELD (1-5?)
189 -1, // 'w' - UDAT_WEEK_OF_YEAR_FIELD (1-52?) 189 -1, // 'w' - UDAT_WEEK_OF_YEAR_FIELD (1-52?)
190 -1, // 'W' - UDAT_WEEK_OF_MONTH_FIELD (1-5?) 190 -1, // 'W' - UDAT_WEEK_OF_MONTH_FIELD (1-5?)
191 -1, // 'a' - UDAT_AM_PM_FIELD 191 -1, // 'a' - UDAT_AM_PM_FIELD
192 -1, // 'h' - UDAT_HOUR1_FIELD 192 -1, // 'h' - UDAT_HOUR1_FIELD
193 -1, // 'K' - UDAT_HOUR0_FIELD 193 -1, // 'K' - UDAT_HOUR0_FIELD
194 -1, // 'z' - UDAT_TIMEZONE_FIELD 194 -1, // 'z' - UDAT_TIMEZONE_FIELD
195 -1, // 'Y' - UDAT_YEAR_WOY_FIELD 195 -1, // 'Y' - UDAT_YEAR_WOY_FIELD
196 -1, // 'e' - UDAT_DOW_LOCAL_FIELD 196 -1, // 'e' - UDAT_DOW_LOCAL_FIELD
197 -1, // 'u' - UDAT_EXTENDED_YEAR_FIELD 197 -1, // 'u' - UDAT_EXTENDED_YEAR_FIELD
198 -1, // 'g' - UDAT_JULIAN_DAY_FIELD 198 -1, // 'g' - UDAT_JULIAN_DAY_FIELD
199 -1, // 'A' - UDAT_MILLISECONDS_IN_DAY_FIELD 199 -1, // 'A' - UDAT_MILLISECONDS_IN_DAY_FIELD
200 -1, // 'Z' - UDAT_TIMEZONE_RFC_FIELD 200 -1, // 'Z' - UDAT_TIMEZONE_RFC_FIELD
201 -1, // 'v' - UDAT_TIMEZONE_GENERIC_FIELD 201 -1, // 'v' - UDAT_TIMEZONE_GENERIC_FIELD
202 0, // 'c' - UDAT_STANDALONE_DAY_FIELD 202 0, // 'c' - UDAT_STANDALONE_DAY_FIELD
203 1, // 'L' - UDAT_STANDALONE_MONTH_FIELD 203 1, // 'L' - UDAT_STANDALONE_MONTH_FIELD
204 -1, // 'Q' - UDAT_QUARTER_FIELD (1-4?) 204 -1, // 'Q' - UDAT_QUARTER_FIELD (1-4?)
205 -1, // 'q' - UDAT_STANDALONE_QUARTER_FIELD 205 -1, // 'q' - UDAT_STANDALONE_QUARTER_FIELD
206 -1, // 'V' - UDAT_TIMEZONE_SPECIAL_FIELD 206 -1, // 'V' - UDAT_TIMEZONE_SPECIAL_FIELD
207 -1, // 'U' - UDAT_YEAR_NAME_FIELD 207 -1, // 'U' - UDAT_YEAR_NAME_FIELD
208 -1, // 'O' - UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD 208 -1, // 'O' - UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD
209 -1, // 'X' - UDAT_TIMEZONE_ISO_FIELD 209 -1, // 'X' - UDAT_TIMEZONE_ISO_FIELD
210 -1, // 'x' - UDAT_TIMEZONE_ISO_LOCAL_FIELD 210 -1, // 'x' - UDAT_TIMEZONE_ISO_LOCAL_FIELD
211 -1, // 'r' - UDAT_RELATED_YEAR_FIELD 211 -1, // 'r' - UDAT_RELATED_YEAR_FIELD
212 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
213 -1, // ':' - UDAT_TIME_SEPARATOR_FIELD
214 #else
215 -1, // (no pattern character currently) - UDAT_TIME_SEPARATOR_FIELD
216 #endif
212 }; 217 };
213 218
214 // When calendar uses hebr numbering (i.e. he@calendar=hebrew), 219 // When calendar uses hebr numbering (i.e. he@calendar=hebrew),
215 // offset the years within the current millenium down to 1-999 220 // offset the years within the current millenium down to 1-999
216 static const int32_t HEBREW_CAL_CUR_MILLENIUM_START_YEAR = 5000; 221 static const int32_t HEBREW_CAL_CUR_MILLENIUM_START_YEAR = 5000;
217 static const int32_t HEBREW_CAL_CUR_MILLENIUM_END_YEAR = 6000; 222 static const int32_t HEBREW_CAL_CUR_MILLENIUM_END_YEAR = 6000;
218 223
219 static UMutex LOCK = U_MUTEX_INITIALIZER; 224 static UMutex LOCK = U_MUTEX_INITIALIZER;
220 225
221 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat) 226 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat)
222 227
228 SimpleDateFormat::NSOverride::~NSOverride() {
229 if (snf != NULL) {
230 snf->removeRef();
231 }
232 }
233
234
235 void SimpleDateFormat::NSOverride::free() {
236 NSOverride *cur = this;
237 while (cur) {
238 NSOverride *next = cur->next;
239 delete cur;
240 cur = next;
241 }
242 }
243
244 // no matter what the locale's default number format looked like, we want
245 // to modify it so that it doesn't use thousands separators, doesn't always
246 // show the decimal point, and recognizes integers only when parsing
247 static void fixNumberFormatForDates(NumberFormat &nf) {
248 nf.setGroupingUsed(FALSE);
249 DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(&nf);
250 if (decfmt != NULL) {
251 decfmt->setDecimalSeparatorAlwaysShown(FALSE);
252 }
253 nf.setParseIntegerOnly(TRUE);
254 nf.setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
255 }
256
257 static const SharedNumberFormat *createSharedNumberFormat(
258 NumberFormat *nfToAdopt) {
259 fixNumberFormatForDates(*nfToAdopt);
260 const SharedNumberFormat *result = new SharedNumberFormat(nfToAdopt);
261 if (result == NULL) {
262 delete nfToAdopt;
263 }
264 return result;
265 }
266
267 static const SharedNumberFormat *createSharedNumberFormat(
268 const Locale &loc, UErrorCode &status) {
269 NumberFormat *nf = NumberFormat::createInstance(loc, status);
270 if (U_FAILURE(status)) {
271 return NULL;
272 }
273 const SharedNumberFormat *result = createSharedNumberFormat(nf);
274 if (result == NULL) {
275 status = U_MEMORY_ALLOCATION_ERROR;
276 }
277 return result;
278 }
279
280 static const SharedNumberFormat **allocSharedNumberFormatters() {
281 const SharedNumberFormat **result = (const SharedNumberFormat**)
282 uprv_malloc(UDAT_FIELD_COUNT * sizeof(const SharedNumberFormat*));
283 if (result == NULL) {
284 return NULL;
285 }
286 for (int32_t i = 0; i < UDAT_FIELD_COUNT; ++i) {
287 result[i] = NULL;
288 }
289 return result;
290 }
291
292 static void freeSharedNumberFormatters(const SharedNumberFormat ** list) {
293 for (int32_t i = 0; i < UDAT_FIELD_COUNT; ++i) {
294 SharedObject::clearPtr(list[i]);
295 }
296 uprv_free(list);
297 }
298
299 const NumberFormat *SimpleDateFormat::getNumberFormatByIndex(
300 UDateFormatField index) const {
301 if (fSharedNumberFormatters == NULL ||
302 fSharedNumberFormatters[index] == NULL) {
303 return fNumberFormat;
304 }
305 return &(**fSharedNumberFormatters[index]);
306 }
307
308 class SimpleDateFormatMutableNFNode {
309 public:
310 const NumberFormat *key;
311 NumberFormat *value;
312 SimpleDateFormatMutableNFNode()
313 : key(NULL), value(NULL) { }
314 ~SimpleDateFormatMutableNFNode() {
315 delete value;
316 }
317 private:
318 SimpleDateFormatMutableNFNode(const SimpleDateFormatMutableNFNode &);
319 SimpleDateFormatMutableNFNode &operator=(const SimpleDateFormatMutableNFNode &);
320 };
321
322 // Single threaded cache of non const NumberFormats. Designed to be stack
323 // allocated and used for a single format call.
324 class SimpleDateFormatMutableNFs : public UMemory {
325 public:
326 SimpleDateFormatMutableNFs() {
327 }
328
329 // Returns a non-const clone of nf which can be safely modified.
330 // Subsequent calls with same nf will return the same non-const clone.
331 // This object maintains ownership of all returned non-const
332 // NumberFormat objects. On memory allocation error returns NULL.
333 // Caller must check for NULL return value.
334 NumberFormat *get(const NumberFormat *nf) {
335 if (nf == NULL) {
336 return NULL;
337 }
338 int32_t idx = 0;
339 while (nodes[idx].value) {
340 if (nf == nodes[idx].key) {
341 return nodes[idx].value;
342 }
343 ++idx;
344 }
345 U_ASSERT(idx < UDAT_FIELD_COUNT);
346 nodes[idx].key = nf;
347 nodes[idx].value = (NumberFormat *) nf->clone();
348 return nodes[idx].value;
349 }
350 private:
351 // +1 extra for sentinel. If each field had its own NumberFormat, this
352 // cache would have to allocate UDAT_FIELD_COUNT mutable versions worst
353 // case.
354 SimpleDateFormatMutableNFNode nodes[UDAT_FIELD_COUNT + 1];
355 SimpleDateFormatMutableNFs(const SimpleDateFormatMutableNFs &);
356 SimpleDateFormatMutableNFs &operator=(const SimpleDateFormatMutableNFs &);
357 };
358
223 //---------------------------------------------------------------------- 359 //----------------------------------------------------------------------
224 360
225 SimpleDateFormat::~SimpleDateFormat() 361 SimpleDateFormat::~SimpleDateFormat()
226 { 362 {
227 delete fSymbols; 363 delete fSymbols;
228 if (fNumberFormatters) { 364 if (fSharedNumberFormatters) {
229 uprv_free(fNumberFormatters); 365 freeSharedNumberFormatters(fSharedNumberFormatters);
230 } 366 }
231 if (fTimeZoneFormat) { 367 if (fTimeZoneFormat) {
232 delete fTimeZoneFormat; 368 delete fTimeZoneFormat;
233 } 369 }
234 370
235 while (fOverrideList) {
236 NSOverride *cur = fOverrideList;
237 fOverrideList = cur->next;
238 delete cur->nf;
239 uprv_free(cur);
240 }
241
242 #if !UCONFIG_NO_BREAK_ITERATION 371 #if !UCONFIG_NO_BREAK_ITERATION
243 delete fCapitalizationBrkIter; 372 delete fCapitalizationBrkIter;
244 #endif 373 #endif
245 } 374 }
246 375
247 //---------------------------------------------------------------------- 376 //----------------------------------------------------------------------
248 377
249 SimpleDateFormat::SimpleDateFormat(UErrorCode& status) 378 SimpleDateFormat::SimpleDateFormat(UErrorCode& status)
250 : fLocale(Locale::getDefault()), 379 : fLocale(Locale::getDefault()),
251 fSymbols(NULL), 380 fSymbols(NULL),
252 fTimeZoneFormat(NULL), 381 fTimeZoneFormat(NULL),
253 fNumberFormatters(NULL), 382 fSharedNumberFormatters(NULL),
254 fOverrideList(NULL),
255 fCapitalizationBrkIter(NULL) 383 fCapitalizationBrkIter(NULL)
256 { 384 {
257 initializeBooleanAttributes(); 385 initializeBooleanAttributes();
258 construct(kShort, (EStyle) (kShort + kDateOffset), fLocale, status); 386 construct(kShort, (EStyle) (kShort + kDateOffset), fLocale, status);
259 initializeDefaultCentury(); 387 initializeDefaultCentury();
260 } 388 }
261 389
262 //---------------------------------------------------------------------- 390 //----------------------------------------------------------------------
263 391
264 SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern, 392 SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
265 UErrorCode &status) 393 UErrorCode &status)
266 : fPattern(pattern), 394 : fPattern(pattern),
267 fLocale(Locale::getDefault()), 395 fLocale(Locale::getDefault()),
268 fSymbols(NULL), 396 fSymbols(NULL),
269 fTimeZoneFormat(NULL), 397 fTimeZoneFormat(NULL),
270 fNumberFormatters(NULL), 398 fSharedNumberFormatters(NULL),
271 fOverrideList(NULL),
272 fCapitalizationBrkIter(NULL) 399 fCapitalizationBrkIter(NULL)
273 { 400 {
274 fDateOverride.setToBogus(); 401 fDateOverride.setToBogus();
275 fTimeOverride.setToBogus(); 402 fTimeOverride.setToBogus();
276 initializeBooleanAttributes(); 403 initializeBooleanAttributes();
277 initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status); 404 initializeCalendar(NULL,fLocale,status);
405 fSymbols = DateFormatSymbols::createForLocale(fLocale, status);
278 initialize(fLocale, status); 406 initialize(fLocale, status);
279 initializeDefaultCentury(); 407 initializeDefaultCentury();
280 408
281 } 409 }
282 //---------------------------------------------------------------------- 410 //----------------------------------------------------------------------
283 411
284 SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern, 412 SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
285 const UnicodeString& override, 413 const UnicodeString& override,
286 UErrorCode &status) 414 UErrorCode &status)
287 : fPattern(pattern), 415 : fPattern(pattern),
288 fLocale(Locale::getDefault()), 416 fLocale(Locale::getDefault()),
289 fSymbols(NULL), 417 fSymbols(NULL),
290 fTimeZoneFormat(NULL), 418 fTimeZoneFormat(NULL),
291 fNumberFormatters(NULL), 419 fSharedNumberFormatters(NULL),
292 fOverrideList(NULL),
293 fCapitalizationBrkIter(NULL) 420 fCapitalizationBrkIter(NULL)
294 { 421 {
295 fDateOverride.setTo(override); 422 fDateOverride.setTo(override);
296 fTimeOverride.setToBogus(); 423 fTimeOverride.setToBogus();
297 initializeBooleanAttributes(); 424 initializeBooleanAttributes();
298 initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status); 425 initializeCalendar(NULL,fLocale,status);
426 fSymbols = DateFormatSymbols::createForLocale(fLocale, status);
299 initialize(fLocale, status); 427 initialize(fLocale, status);
300 initializeDefaultCentury(); 428 initializeDefaultCentury();
301 429
302 processOverrideString(fLocale,override,kOvrStrBoth,status); 430 processOverrideString(fLocale,override,kOvrStrBoth,status);
303 431
304 } 432 }
305 433
306 //---------------------------------------------------------------------- 434 //----------------------------------------------------------------------
307 435
308 SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern, 436 SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
309 const Locale& locale, 437 const Locale& locale,
310 UErrorCode& status) 438 UErrorCode& status)
311 : fPattern(pattern), 439 : fPattern(pattern),
312 fLocale(locale), 440 fLocale(locale),
313 fTimeZoneFormat(NULL), 441 fTimeZoneFormat(NULL),
314 fNumberFormatters(NULL), 442 fSharedNumberFormatters(NULL),
315 fOverrideList(NULL),
316 fCapitalizationBrkIter(NULL) 443 fCapitalizationBrkIter(NULL)
317 { 444 {
318 445
319 fDateOverride.setToBogus(); 446 fDateOverride.setToBogus();
320 fTimeOverride.setToBogus(); 447 fTimeOverride.setToBogus();
321 initializeBooleanAttributes(); 448 initializeBooleanAttributes();
322 449
323 initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status); 450 initializeCalendar(NULL,fLocale,status);
451 fSymbols = DateFormatSymbols::createForLocale(fLocale, status);
324 initialize(fLocale, status); 452 initialize(fLocale, status);
325 initializeDefaultCentury(); 453 initializeDefaultCentury();
326 } 454 }
327 455
328 //---------------------------------------------------------------------- 456 //----------------------------------------------------------------------
329 457
330 SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern, 458 SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
331 const UnicodeString& override, 459 const UnicodeString& override,
332 const Locale& locale, 460 const Locale& locale,
333 UErrorCode& status) 461 UErrorCode& status)
334 : fPattern(pattern), 462 : fPattern(pattern),
335 fLocale(locale), 463 fLocale(locale),
336 fTimeZoneFormat(NULL), 464 fTimeZoneFormat(NULL),
337 fNumberFormatters(NULL), 465 fSharedNumberFormatters(NULL),
338 fOverrideList(NULL),
339 fCapitalizationBrkIter(NULL) 466 fCapitalizationBrkIter(NULL)
340 { 467 {
341 468
342 fDateOverride.setTo(override); 469 fDateOverride.setTo(override);
343 fTimeOverride.setToBogus(); 470 fTimeOverride.setToBogus();
344 initializeBooleanAttributes(); 471 initializeBooleanAttributes();
345 472
346 initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status); 473 initializeCalendar(NULL,fLocale,status);
474 fSymbols = DateFormatSymbols::createForLocale(fLocale, status);
347 initialize(fLocale, status); 475 initialize(fLocale, status);
348 initializeDefaultCentury(); 476 initializeDefaultCentury();
349 477
350 processOverrideString(locale,override,kOvrStrBoth,status); 478 processOverrideString(locale,override,kOvrStrBoth,status);
351 479
352 } 480 }
353 481
354 //---------------------------------------------------------------------- 482 //----------------------------------------------------------------------
355 483
356 SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern, 484 SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
357 DateFormatSymbols* symbolsToAdopt, 485 DateFormatSymbols* symbolsToAdopt,
358 UErrorCode& status) 486 UErrorCode& status)
359 : fPattern(pattern), 487 : fPattern(pattern),
360 fLocale(Locale::getDefault()), 488 fLocale(Locale::getDefault()),
361 fSymbols(symbolsToAdopt), 489 fSymbols(symbolsToAdopt),
362 fTimeZoneFormat(NULL), 490 fTimeZoneFormat(NULL),
363 fNumberFormatters(NULL), 491 fSharedNumberFormatters(NULL),
364 fOverrideList(NULL),
365 fCapitalizationBrkIter(NULL) 492 fCapitalizationBrkIter(NULL)
366 { 493 {
367 494
368 fDateOverride.setToBogus(); 495 fDateOverride.setToBogus();
369 fTimeOverride.setToBogus(); 496 fTimeOverride.setToBogus();
370 initializeBooleanAttributes(); 497 initializeBooleanAttributes();
371 498
372 initializeCalendar(NULL,fLocale,status); 499 initializeCalendar(NULL,fLocale,status);
373 initialize(fLocale, status); 500 initialize(fLocale, status);
374 initializeDefaultCentury(); 501 initializeDefaultCentury();
375 } 502 }
376 503
377 //---------------------------------------------------------------------- 504 //----------------------------------------------------------------------
378 505
379 SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern, 506 SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
380 const DateFormatSymbols& symbols, 507 const DateFormatSymbols& symbols,
381 UErrorCode& status) 508 UErrorCode& status)
382 : fPattern(pattern), 509 : fPattern(pattern),
383 fLocale(Locale::getDefault()), 510 fLocale(Locale::getDefault()),
384 fSymbols(new DateFormatSymbols(symbols)), 511 fSymbols(new DateFormatSymbols(symbols)),
385 fTimeZoneFormat(NULL), 512 fTimeZoneFormat(NULL),
386 fNumberFormatters(NULL), 513 fSharedNumberFormatters(NULL),
387 fOverrideList(NULL),
388 fCapitalizationBrkIter(NULL) 514 fCapitalizationBrkIter(NULL)
389 { 515 {
390 516
391 fDateOverride.setToBogus(); 517 fDateOverride.setToBogus();
392 fTimeOverride.setToBogus(); 518 fTimeOverride.setToBogus();
393 initializeBooleanAttributes(); 519 initializeBooleanAttributes();
394 520
395 initializeCalendar(NULL, fLocale, status); 521 initializeCalendar(NULL, fLocale, status);
396 initialize(fLocale, status); 522 initialize(fLocale, status);
397 initializeDefaultCentury(); 523 initializeDefaultCentury();
398 } 524 }
399 525
400 //---------------------------------------------------------------------- 526 //----------------------------------------------------------------------
401 527
402 // Not for public consumption; used by DateFormat 528 // Not for public consumption; used by DateFormat
403 SimpleDateFormat::SimpleDateFormat(EStyle timeStyle, 529 SimpleDateFormat::SimpleDateFormat(EStyle timeStyle,
404 EStyle dateStyle, 530 EStyle dateStyle,
405 const Locale& locale, 531 const Locale& locale,
406 UErrorCode& status) 532 UErrorCode& status)
407 : fLocale(locale), 533 : fLocale(locale),
408 fSymbols(NULL), 534 fSymbols(NULL),
409 fTimeZoneFormat(NULL), 535 fTimeZoneFormat(NULL),
410 fNumberFormatters(NULL), 536 fSharedNumberFormatters(NULL),
411 fOverrideList(NULL),
412 fCapitalizationBrkIter(NULL) 537 fCapitalizationBrkIter(NULL)
413 { 538 {
414 initializeBooleanAttributes(); 539 initializeBooleanAttributes();
415 construct(timeStyle, dateStyle, fLocale, status); 540 construct(timeStyle, dateStyle, fLocale, status);
416 if(U_SUCCESS(status)) { 541 if(U_SUCCESS(status)) {
417 initializeDefaultCentury(); 542 initializeDefaultCentury();
418 } 543 }
419 } 544 }
420 545
421 //---------------------------------------------------------------------- 546 //----------------------------------------------------------------------
422 547
423 /** 548 /**
424 * Not for public consumption; used by DateFormat. This constructor 549 * Not for public consumption; used by DateFormat. This constructor
425 * never fails. If the resource data is not available, it uses the 550 * never fails. If the resource data is not available, it uses the
426 * the last resort symbols. 551 * the last resort symbols.
427 */ 552 */
428 SimpleDateFormat::SimpleDateFormat(const Locale& locale, 553 SimpleDateFormat::SimpleDateFormat(const Locale& locale,
429 UErrorCode& status) 554 UErrorCode& status)
430 : fPattern(gDefaultPattern), 555 : fPattern(gDefaultPattern),
431 fLocale(locale), 556 fLocale(locale),
432 fSymbols(NULL), 557 fSymbols(NULL),
433 fTimeZoneFormat(NULL), 558 fTimeZoneFormat(NULL),
434 fNumberFormatters(NULL), 559 fSharedNumberFormatters(NULL),
435 fOverrideList(NULL),
436 fCapitalizationBrkIter(NULL) 560 fCapitalizationBrkIter(NULL)
437 { 561 {
438 if (U_FAILURE(status)) return; 562 if (U_FAILURE(status)) return;
439 initializeBooleanAttributes(); 563 initializeBooleanAttributes();
440 initializeSymbols(fLocale, initializeCalendar(NULL, fLocale, status),status) ; 564 initializeCalendar(NULL, fLocale, status);
565 fSymbols = DateFormatSymbols::createForLocale(fLocale, status);
441 if (U_FAILURE(status)) 566 if (U_FAILURE(status))
442 { 567 {
443 status = U_ZERO_ERROR; 568 status = U_ZERO_ERROR;
444 delete fSymbols; 569 delete fSymbols;
445 // This constructor doesn't fail; it uses last resort data 570 // This constructor doesn't fail; it uses last resort data
446 fSymbols = new DateFormatSymbols(status); 571 fSymbols = new DateFormatSymbols(status);
447 /* test for NULL */ 572 /* test for NULL */
448 if (fSymbols == 0) { 573 if (fSymbols == 0) {
449 status = U_MEMORY_ALLOCATION_ERROR; 574 status = U_MEMORY_ALLOCATION_ERROR;
450 return; 575 return;
451 } 576 }
452 } 577 }
453 578
454 fDateOverride.setToBogus(); 579 fDateOverride.setToBogus();
455 fTimeOverride.setToBogus(); 580 fTimeOverride.setToBogus();
456 581
457 initialize(fLocale, status); 582 initialize(fLocale, status);
458 if(U_SUCCESS(status)) { 583 if(U_SUCCESS(status)) {
459 initializeDefaultCentury(); 584 initializeDefaultCentury();
460 } 585 }
461 } 586 }
462 587
463 //---------------------------------------------------------------------- 588 //----------------------------------------------------------------------
464 589
465 SimpleDateFormat::SimpleDateFormat(const SimpleDateFormat& other) 590 SimpleDateFormat::SimpleDateFormat(const SimpleDateFormat& other)
466 : DateFormat(other), 591 : DateFormat(other),
467 fLocale(other.fLocale), 592 fLocale(other.fLocale),
468 fSymbols(NULL), 593 fSymbols(NULL),
469 fTimeZoneFormat(NULL), 594 fTimeZoneFormat(NULL),
470 fNumberFormatters(NULL), 595 fSharedNumberFormatters(NULL),
471 fOverrideList(NULL),
472 fCapitalizationBrkIter(NULL) 596 fCapitalizationBrkIter(NULL)
473 { 597 {
474 initializeBooleanAttributes(); 598 initializeBooleanAttributes();
475 *this = other; 599 *this = other;
476 } 600 }
477 601
478 //---------------------------------------------------------------------- 602 //----------------------------------------------------------------------
479 603
480 SimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other) 604 SimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other)
481 { 605 {
482 if (this == &other) { 606 if (this == &other) {
483 return *this; 607 return *this;
484 } 608 }
485 DateFormat::operator=(other); 609 DateFormat::operator=(other);
610 fDateOverride = other.fDateOverride;
611 fTimeOverride = other.fTimeOverride;
486 612
487 delete fSymbols; 613 delete fSymbols;
488 fSymbols = NULL; 614 fSymbols = NULL;
489 615
490 if (other.fSymbols) 616 if (other.fSymbols)
491 fSymbols = new DateFormatSymbols(*other.fSymbols); 617 fSymbols = new DateFormatSymbols(*other.fSymbols);
492 618
493 fDefaultCenturyStart = other.fDefaultCenturyStart; 619 fDefaultCenturyStart = other.fDefaultCenturyStart;
494 fDefaultCenturyStartYear = other.fDefaultCenturyStartYear; 620 fDefaultCenturyStartYear = other.fDefaultCenturyStartYear;
495 fHaveDefaultCentury = other.fHaveDefaultCentury; 621 fHaveDefaultCentury = other.fHaveDefaultCentury;
496 622
497 fPattern = other.fPattern; 623 fPattern = other.fPattern;
498 624
499 // TimeZoneFormat in ICU4C only depends on a locale for now 625 // TimeZoneFormat in ICU4C only depends on a locale for now
500 if (fLocale != other.fLocale) { 626 if (fLocale != other.fLocale) {
501 delete fTimeZoneFormat; 627 delete fTimeZoneFormat;
502 fTimeZoneFormat = NULL; // forces lazy instantiation with the other loca le 628 fTimeZoneFormat = NULL; // forces lazy instantiation with the other loca le
503 fLocale = other.fLocale; 629 fLocale = other.fLocale;
504 } 630 }
505 631
506 #if !UCONFIG_NO_BREAK_ITERATION 632 #if !UCONFIG_NO_BREAK_ITERATION
507 if (other.fCapitalizationBrkIter != NULL) { 633 if (other.fCapitalizationBrkIter != NULL) {
508 fCapitalizationBrkIter = (other.fCapitalizationBrkIter)->clone(); 634 fCapitalizationBrkIter = (other.fCapitalizationBrkIter)->clone();
509 } 635 }
510 #endif 636 #endif
511 637
638 if (fSharedNumberFormatters != NULL) {
639 freeSharedNumberFormatters(fSharedNumberFormatters);
640 fSharedNumberFormatters = NULL;
641 }
642 if (other.fSharedNumberFormatters != NULL) {
643 fSharedNumberFormatters = allocSharedNumberFormatters();
644 if (fSharedNumberFormatters) {
645 for (int32_t i = 0; i < UDAT_FIELD_COUNT; ++i) {
646 SharedObject::copyPtr(
647 other.fSharedNumberFormatters[i],
648 fSharedNumberFormatters[i]);
649 }
650 }
651 }
652
512 return *this; 653 return *this;
513 } 654 }
514 655
515 //---------------------------------------------------------------------- 656 //----------------------------------------------------------------------
516 657
517 Format* 658 Format*
518 SimpleDateFormat::clone() const 659 SimpleDateFormat::clone() const
519 { 660 {
520 return new SimpleDateFormat(*this); 661 return new SimpleDateFormat(*this);
521 } 662 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 if (ures_getSize(dateTimePatterns) <= kDateTime) 704 if (ures_getSize(dateTimePatterns) <= kDateTime)
564 { 705 {
565 status = U_INVALID_FORMAT_ERROR; 706 status = U_INVALID_FORMAT_ERROR;
566 return; 707 return;
567 } 708 }
568 709
569 setLocaleIDs(ures_getLocaleByType(dateTimePatterns, ULOC_VALID_LOCALE, &stat us), 710 setLocaleIDs(ures_getLocaleByType(dateTimePatterns, ULOC_VALID_LOCALE, &stat us),
570 ures_getLocaleByType(dateTimePatterns, ULOC_ACTUAL_LOCALE, &sta tus)); 711 ures_getLocaleByType(dateTimePatterns, ULOC_ACTUAL_LOCALE, &sta tus));
571 712
572 // create a symbols object from the locale 713 // create a symbols object from the locale
573 initializeSymbols(locale,fCalendar, status); 714 fSymbols = DateFormatSymbols::createForLocale(locale, status);
574 if (U_FAILURE(status)) return; 715 if (U_FAILURE(status)) return;
575 /* test for NULL */ 716 /* test for NULL */
576 if (fSymbols == 0) { 717 if (fSymbols == 0) {
577 status = U_MEMORY_ALLOCATION_ERROR; 718 status = U_MEMORY_ALLOCATION_ERROR;
578 return; 719 return;
579 } 720 }
580 721
581 const UChar *resStr,*ovrStr; 722 const UChar *resStr,*ovrStr;
582 int32_t resStrLen,ovrStrLen = 0; 723 int32_t resStrLen,ovrStrLen = 0;
583 fDateOverride.setToBogus(); 724 fDateOverride.setToBogus();
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 } 875 }
735 876
736 //---------------------------------------------------------------------- 877 //----------------------------------------------------------------------
737 878
738 Calendar* 879 Calendar*
739 SimpleDateFormat::initializeCalendar(TimeZone* adoptZone, const Locale& locale, UErrorCode& status) 880 SimpleDateFormat::initializeCalendar(TimeZone* adoptZone, const Locale& locale, UErrorCode& status)
740 { 881 {
741 if(!U_FAILURE(status)) { 882 if(!U_FAILURE(status)) {
742 fCalendar = Calendar::createInstance(adoptZone?adoptZone:TimeZone::creat eDefault(), locale, status); 883 fCalendar = Calendar::createInstance(adoptZone?adoptZone:TimeZone::creat eDefault(), locale, status);
743 } 884 }
744 if (U_SUCCESS(status) && fCalendar == NULL) {
745 status = U_MEMORY_ALLOCATION_ERROR;
746 }
747 return fCalendar; 885 return fCalendar;
748 } 886 }
749 887
750 void 888 void
751 SimpleDateFormat::initializeSymbols(const Locale& locale, Calendar* calendar, UE rrorCode& status)
752 {
753 if(U_FAILURE(status)) {
754 fSymbols = NULL;
755 } else {
756 // pass in calendar type - use NULL (default) if no calendar set (or err).
757 fSymbols = new DateFormatSymbols(locale, calendar?calendar->getType() :NULL , status);
758 // Null pointer check
759 if (fSymbols == NULL) {
760 status = U_MEMORY_ALLOCATION_ERROR;
761 return;
762 }
763 }
764 }
765
766 void
767 SimpleDateFormat::initialize(const Locale& locale, 889 SimpleDateFormat::initialize(const Locale& locale,
768 UErrorCode& status) 890 UErrorCode& status)
769 { 891 {
770 if (U_FAILURE(status)) return; 892 if (U_FAILURE(status)) return;
771 893
772 // We don't need to check that the row count is >= 1, since all 2d arrays ha ve at 894 // We don't need to check that the row count is >= 1, since all 2d arrays ha ve at
773 // least one row 895 // least one row
774 fNumberFormat = NumberFormat::createInstance(locale, status); 896 fNumberFormat = NumberFormat::createInstance(locale, status);
775 if (fNumberFormat != NULL && U_SUCCESS(status)) 897 if (fNumberFormat != NULL && U_SUCCESS(status))
776 { 898 {
777 // no matter what the locale's default number format looked like, we wan t 899 fixNumberFormatForDates(*fNumberFormat);
778 // to modify it so that it doesn't use thousands separators, doesn't alw ays
779 // show the decimal point, and recognizes integers only when parsing
780
781 fNumberFormat->setGroupingUsed(FALSE);
782 DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(fNumberFormat);
783 if (decfmt != NULL) {
784 decfmt->setDecimalSeparatorAlwaysShown(FALSE);
785 }
786 fNumberFormat->setParseIntegerOnly(TRUE);
787 fNumberFormat->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 199 7.00"
788
789 //fNumberFormat->setLenient(TRUE); // Java uses a custom DateNumberForma t to format/parse 900 //fNumberFormat->setLenient(TRUE); // Java uses a custom DateNumberForma t to format/parse
790 901
791 initNumberFormatters(locale,status); 902 initNumberFormatters(locale,status);
792 903
793 } 904 }
794 else if (U_SUCCESS(status)) 905 else if (U_SUCCESS(status))
795 { 906 {
796 status = U_MISSING_RESOURCE_ERROR; 907 status = U_MISSING_RESOURCE_ERROR;
797 } 908 }
798 } 909 }
(...skipping 17 matching lines...) Expand all
816 927
817 /* 928 /*
818 * Initialize the boolean attributes. Separate so we can call it from all constr uctors. 929 * Initialize the boolean attributes. Separate so we can call it from all constr uctors.
819 */ 930 */
820 void SimpleDateFormat::initializeBooleanAttributes() 931 void SimpleDateFormat::initializeBooleanAttributes()
821 { 932 {
822 UErrorCode status = U_ZERO_ERROR; 933 UErrorCode status = U_ZERO_ERROR;
823 934
824 setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status); 935 setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status);
825 setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status); 936 setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
826 setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, true, status); 937 setBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, true, status);
827 setBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, true, status); 938 setBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, true, status);
828 } 939 }
829 940
830 /* Define one-century window into which to disambiguate dates using 941 /* Define one-century window into which to disambiguate dates using
831 * two-digit years. Make public in JDK 1.2. 942 * two-digit years. Make public in JDK 1.2.
832 */ 943 */
833 void SimpleDateFormat::parseAmbiguousDatesAsAfter(UDate startDate, UErrorCode& s tatus) 944 void SimpleDateFormat::parseAmbiguousDatesAsAfter(UDate startDate, UErrorCode& s tatus)
834 { 945 {
835 if(U_FAILURE(status)) { 946 if(U_FAILURE(status)) {
836 return; 947 return;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
894 return appendTo; 1005 return appendTo;
895 } 1006 }
896 } 1007 }
897 1008
898 UBool inQuote = FALSE; 1009 UBool inQuote = FALSE;
899 UChar prevCh = 0; 1010 UChar prevCh = 0;
900 int32_t count = 0; 1011 int32_t count = 0;
901 int32_t fieldNum = 0; 1012 int32_t fieldNum = 0;
902 UDisplayContext capitalizationContext = getContext(UDISPCTX_TYPE_CAPITALIZAT ION, status); 1013 UDisplayContext capitalizationContext = getContext(UDISPCTX_TYPE_CAPITALIZAT ION, status);
903 1014
1015 // Create temporary cache of mutable number format objects. This way
1016 // subFormat won't have to clone the const NumberFormat for each field.
1017 // if several fields share the same NumberFormat, which will almost
1018 // always be the case, this is a big save.
1019 SimpleDateFormatMutableNFs mutableNFs;
904 // loop through the pattern string character by character 1020 // loop through the pattern string character by character
905 for (int32_t i = 0; i < fPattern.length() && U_SUCCESS(status); ++i) { 1021 for (int32_t i = 0; i < fPattern.length() && U_SUCCESS(status); ++i) {
906 UChar ch = fPattern[i]; 1022 UChar ch = fPattern[i];
907 1023
908 // Use subFormat() to format a repeated pattern character 1024 // Use subFormat() to format a repeated pattern character
909 // when a different pattern or non-pattern character is seen 1025 // when a different pattern or non-pattern character is seen
910 if (ch != prevCh && count > 0) { 1026 if (ch != prevCh && count > 0) {
911 subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++ , handler, *workCal, status); 1027 subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++ , handler, *workCal, mutableNFs, status);
912 count = 0; 1028 count = 0;
913 } 1029 }
914 if (ch == QUOTE) { 1030 if (ch == QUOTE) {
915 // Consecutive single quotes are a single quote literal, 1031 // Consecutive single quotes are a single quote literal,
916 // either outside of quotes or between quotes 1032 // either outside of quotes or between quotes
917 if ((i+1) < fPattern.length() && fPattern[i+1] == QUOTE) { 1033 if ((i+1) < fPattern.length() && fPattern[i+1] == QUOTE) {
918 appendTo += (UChar)QUOTE; 1034 appendTo += (UChar)QUOTE;
919 ++i; 1035 ++i;
920 } else { 1036 } else {
921 inQuote = ! inQuote; 1037 inQuote = ! inQuote;
922 } 1038 }
923 } 1039 }
924 else if ( ! inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/) 1040 else if (!inQuote && isSyntaxChar(ch)) {
925 || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
926 // ch is a date-time pattern character to be interpreted 1041 // ch is a date-time pattern character to be interpreted
927 // by subFormat(); count the number of times it is repeated 1042 // by subFormat(); count the number of times it is repeated
928 prevCh = ch; 1043 prevCh = ch;
929 ++count; 1044 ++count;
930 } 1045 }
931 else { 1046 else {
932 // Append quoted characters and unquoted non-pattern characters 1047 // Append quoted characters and unquoted non-pattern characters
933 appendTo += ch; 1048 appendTo += ch;
934 } 1049 }
935 } 1050 }
936 1051
937 // Format the last item in the pattern, if any 1052 // Format the last item in the pattern, if any
938 if (count > 0) { 1053 if (count > 0) {
939 subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, ha ndler, *workCal, status); 1054 subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, ha ndler, *workCal, mutableNFs, status);
940 } 1055 }
941 1056
942 if (calClone != NULL) { 1057 if (calClone != NULL) {
943 delete calClone; 1058 delete calClone;
944 } 1059 }
945 1060
946 return appendTo; 1061 return appendTo;
947 } 1062 }
948 1063
949 //---------------------------------------------------------------------- 1064 //----------------------------------------------------------------------
(...skipping 10 matching lines...) Expand all
960 /*GyM*/ 0, 10, 20, 1075 /*GyM*/ 0, 10, 20,
961 /*wW*/ 20, 30, 1076 /*wW*/ 20, 30,
962 /*dDEF*/ 30, 20, 30, 30, 1077 /*dDEF*/ 30, 20, 30, 30,
963 /*ahHm*/ 40, 50, 50, 60, 1078 /*ahHm*/ 40, 50, 50, 60,
964 /*sS*/ 70, 80, 1079 /*sS*/ 70, 80,
965 /*z?Y*/ 0, 0, 10, 1080 /*z?Y*/ 0, 0, 10,
966 /*eug*/ 30, 10, 0, 1081 /*eug*/ 30, 10, 0,
967 /*A?.*/ 40, 0, 0 1082 /*A?.*/ 40, 0, 0
968 }; 1083 };
969 1084
1085 int32_t SimpleDateFormat::getLevelFromChar(UChar ch) {
1086 // Map date field LETTER into calendar field level.
1087 // the larger the level, the smaller the field unit.
1088 // NOTE: if new fields adds in, the table needs to update.
1089 static const int32_t mapCharToLevel[] = {
1090 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1091 //
1092 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1093 // ! " # $ % & ' ( ) * + , - . /
1094 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1095 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
1096 // 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
1097 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1,
1098 #else
1099 // 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
1100 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1101 #endif
1102 // @ A B C D E F G H I J K L M N O
1103 -1, 40, -1, -1, 20, 30, 30, 0, 50, -1, -1, 50, 20, 20, -1, 0,
1104 // P Q R S T U V W X Y Z [ \ ] ^ _
1105 -1, 20, -1, 80, -1, 10, 0, 30, 0, 10, 0, -1, -1, -1, -1, -1,
1106 // ` a b c d e f g h i j k l m n o
1107 -1, 40, -1, 30, 30, 30, -1, 0, 50, -1, -1, 50, 0, 60, -1, -1,
1108 // p q r s t u v w x y z { | } ~
1109 -1, 20, 10, 70, -1, 10, 0, 20, 0, 10, 0, -1, -1, -1, -1, -1
1110 };
970 1111
971 /* Map calendar field LETTER into calendar field level. 1112 return ch < UPRV_LENGTHOF(mapCharToLevel) ? mapCharToLevel[ch] : -1;
972 * the larger the level, the smaller the field unit. 1113 }
973 * NOTE: if new fields adds in, the table needs to update.
974 */
975 const int32_t
976 SimpleDateFormat::fgPatternCharToLevel[] = {
977 // A B C D E F G H I J K L M N O
978 -1, 40, -1, -1, 20, 30, 30, 0, 50, -1, -1, 50, 20, 20, -1, 0,
979 // P Q R S T U V W X Y Z
980 -1, 20, -1, 80, -1, 10, 0, 30, 0, 10, 0, -1, -1, -1, -1, -1,
981 // a b c d e f g h i j k l m n o
982 -1, 40, -1, 30, 30, 30, -1, 0, 50, -1, -1, 50, -1, 60, -1, -1,
983 // p q r s t u v w x y z
984 -1, 20, 10, 70, -1, 10, 0, 20, 0, 10, 0, -1, -1, -1, -1, -1
985 };
986 1114
1115 UBool SimpleDateFormat::isSyntaxChar(UChar ch) {
1116 static const UBool mapCharToIsSyntax[] = {
1117 //
1118 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
1119 //
1120 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
1121 //
1122 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
1123 //
1124 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
1125 // ! " # $ % & '
1126 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
1127 // ( ) * + , - . /
1128 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
1129 // 0 1 2 3 4 5 6 7
1130 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
1131 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
1132 // 8 9 : ; < = > ?
1133 FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
1134 #else
1135 // 8 9 : ; < = > ?
1136 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
1137 #endif
1138 // @ A B C D E F G
1139 FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
1140 // H I J K L M N O
1141 TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
1142 // P Q R S T U V W
1143 TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
1144 // X Y Z [ \ ] ^ _
1145 TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
1146 // ` a b c d e f g
1147 FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
1148 // h i j k l m n o
1149 TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
1150 // p q r s t u v w
1151 TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
1152 // x y z { | } ~
1153 TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE
1154 };
1155
1156 return ch < UPRV_LENGTHOF(mapCharToIsSyntax) ? mapCharToIsSyntax[ch] : FALSE ;
1157 }
987 1158
988 // Map index into pattern character string to Calendar field number. 1159 // Map index into pattern character string to Calendar field number.
989 const UCalendarDateFields 1160 const UCalendarDateFields
990 SimpleDateFormat::fgPatternIndexToCalendarField[] = 1161 SimpleDateFormat::fgPatternIndexToCalendarField[] =
991 { 1162 {
992 /*GyM*/ UCAL_ERA, UCAL_YEAR, UCAL_MONTH, 1163 /*GyM*/ UCAL_ERA, UCAL_YEAR, UCAL_MONTH,
993 /*dkH*/ UCAL_DATE, UCAL_HOUR_OF_DAY, UCAL_HOUR_OF_DAY, 1164 /*dkH*/ UCAL_DATE, UCAL_HOUR_OF_DAY, UCAL_HOUR_OF_DAY,
994 /*msS*/ UCAL_MINUTE, UCAL_SECOND, UCAL_MILLISECOND, 1165 /*msS*/ UCAL_MINUTE, UCAL_SECOND, UCAL_MILLISECOND,
995 /*EDF*/ UCAL_DAY_OF_WEEK, UCAL_DAY_OF_YEAR, UCAL_DAY_OF_WEEK_IN_MONTH, 1166 /*EDF*/ UCAL_DAY_OF_WEEK, UCAL_DAY_OF_YEAR, UCAL_DAY_OF_WEEK_IN_MONTH,
996 /*wWa*/ UCAL_WEEK_OF_YEAR, UCAL_WEEK_OF_MONTH, UCAL_AM_PM, 1167 /*wWa*/ UCAL_WEEK_OF_YEAR, UCAL_WEEK_OF_MONTH, UCAL_AM_PM,
997 /*hKz*/ UCAL_HOUR, UCAL_HOUR, UCAL_ZONE_OFFSET, 1168 /*hKz*/ UCAL_HOUR, UCAL_HOUR, UCAL_ZONE_OFFSET,
998 /*Yeu*/ UCAL_YEAR_WOY, UCAL_DOW_LOCAL, UCAL_EXTENDED_YEAR, 1169 /*Yeu*/ UCAL_YEAR_WOY, UCAL_DOW_LOCAL, UCAL_EXTENDED_YEAR,
999 /*gAZ*/ UCAL_JULIAN_DAY, UCAL_MILLISECONDS_IN_DAY, UCAL_ZONE_OFFSET, 1170 /*gAZ*/ UCAL_JULIAN_DAY, UCAL_MILLISECONDS_IN_DAY, UCAL_ZONE_OFFSET,
1000 /*v*/ UCAL_ZONE_OFFSET, 1171 /*v*/ UCAL_ZONE_OFFSET,
1001 /*c*/ UCAL_DOW_LOCAL, 1172 /*c*/ UCAL_DOW_LOCAL,
1002 /*L*/ UCAL_MONTH, 1173 /*L*/ UCAL_MONTH,
1003 /*Q*/ UCAL_MONTH, 1174 /*Q*/ UCAL_MONTH,
1004 /*q*/ UCAL_MONTH, 1175 /*q*/ UCAL_MONTH,
1005 /*V*/ UCAL_ZONE_OFFSET, 1176 /*V*/ UCAL_ZONE_OFFSET,
1006 /*U*/ UCAL_YEAR, 1177 /*U*/ UCAL_YEAR,
1007 /*O*/ UCAL_ZONE_OFFSET, 1178 /*O*/ UCAL_ZONE_OFFSET,
1008 /*Xx*/ UCAL_ZONE_OFFSET, UCAL_ZONE_OFFSET, 1179 /*Xx*/ UCAL_ZONE_OFFSET, UCAL_ZONE_OFFSET,
1009 /*r*/ UCAL_EXTENDED_YEAR, 1180 /*r*/ UCAL_EXTENDED_YEAR,
1181 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
1182 /*:*/ UCAL_FIELD_COUNT, /* => no useful mapping to any calendar field */
1183 #else
1184 /*no pattern char for UDAT_TIME_SEPARATOR_FIELD*/ UCAL_FIELD_COUNT, /* => no useful mapping to any calendar field */
1185 #endif
1010 }; 1186 };
1011 1187
1012 // Map index into pattern character string to DateFormat field number 1188 // Map index into pattern character string to DateFormat field number
1013 const UDateFormatField 1189 const UDateFormatField
1014 SimpleDateFormat::fgPatternIndexToDateFormatField[] = { 1190 SimpleDateFormat::fgPatternIndexToDateFormatField[] = {
1015 /*GyM*/ UDAT_ERA_FIELD, UDAT_YEAR_FIELD, UDAT_MONTH_FIELD, 1191 /*GyM*/ UDAT_ERA_FIELD, UDAT_YEAR_FIELD, UDAT_MONTH_FIELD,
1016 /*dkH*/ UDAT_DATE_FIELD, UDAT_HOUR_OF_DAY1_FIELD, UDAT_HOUR_OF_DAY0_FIELD, 1192 /*dkH*/ UDAT_DATE_FIELD, UDAT_HOUR_OF_DAY1_FIELD, UDAT_HOUR_OF_DAY0_FIELD,
1017 /*msS*/ UDAT_MINUTE_FIELD, UDAT_SECOND_FIELD, UDAT_FRACTIONAL_SECOND_FIELD, 1193 /*msS*/ UDAT_MINUTE_FIELD, UDAT_SECOND_FIELD, UDAT_FRACTIONAL_SECOND_FIELD,
1018 /*EDF*/ UDAT_DAY_OF_WEEK_FIELD, UDAT_DAY_OF_YEAR_FIELD, UDAT_DAY_OF_WEEK_IN_ MONTH_FIELD, 1194 /*EDF*/ UDAT_DAY_OF_WEEK_FIELD, UDAT_DAY_OF_YEAR_FIELD, UDAT_DAY_OF_WEEK_IN_ MONTH_FIELD,
1019 /*wWa*/ UDAT_WEEK_OF_YEAR_FIELD, UDAT_WEEK_OF_MONTH_FIELD, UDAT_AM_PM_FIELD, 1195 /*wWa*/ UDAT_WEEK_OF_YEAR_FIELD, UDAT_WEEK_OF_MONTH_FIELD, UDAT_AM_PM_FIELD,
1020 /*hKz*/ UDAT_HOUR1_FIELD, UDAT_HOUR0_FIELD, UDAT_TIMEZONE_FIELD, 1196 /*hKz*/ UDAT_HOUR1_FIELD, UDAT_HOUR0_FIELD, UDAT_TIMEZONE_FIELD,
1021 /*Yeu*/ UDAT_YEAR_WOY_FIELD, UDAT_DOW_LOCAL_FIELD, UDAT_EXTENDED_YEAR_FIELD, 1197 /*Yeu*/ UDAT_YEAR_WOY_FIELD, UDAT_DOW_LOCAL_FIELD, UDAT_EXTENDED_YEAR_FIELD,
1022 /*gAZ*/ UDAT_JULIAN_DAY_FIELD, UDAT_MILLISECONDS_IN_DAY_FIELD, UDAT_TIMEZONE _RFC_FIELD, 1198 /*gAZ*/ UDAT_JULIAN_DAY_FIELD, UDAT_MILLISECONDS_IN_DAY_FIELD, UDAT_TIMEZONE _RFC_FIELD,
1023 /*v*/ UDAT_TIMEZONE_GENERIC_FIELD, 1199 /*v*/ UDAT_TIMEZONE_GENERIC_FIELD,
1024 /*c*/ UDAT_STANDALONE_DAY_FIELD, 1200 /*c*/ UDAT_STANDALONE_DAY_FIELD,
1025 /*L*/ UDAT_STANDALONE_MONTH_FIELD, 1201 /*L*/ UDAT_STANDALONE_MONTH_FIELD,
1026 /*Q*/ UDAT_QUARTER_FIELD, 1202 /*Q*/ UDAT_QUARTER_FIELD,
1027 /*q*/ UDAT_STANDALONE_QUARTER_FIELD, 1203 /*q*/ UDAT_STANDALONE_QUARTER_FIELD,
1028 /*V*/ UDAT_TIMEZONE_SPECIAL_FIELD, 1204 /*V*/ UDAT_TIMEZONE_SPECIAL_FIELD,
1029 /*U*/ UDAT_YEAR_NAME_FIELD, 1205 /*U*/ UDAT_YEAR_NAME_FIELD,
1030 /*O*/ UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD, 1206 /*O*/ UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD,
1031 /*Xx*/ UDAT_TIMEZONE_ISO_FIELD, UDAT_TIMEZONE_ISO_LOCAL_FIELD, 1207 /*Xx*/ UDAT_TIMEZONE_ISO_FIELD, UDAT_TIMEZONE_ISO_LOCAL_FIELD,
1032 /*r*/ UDAT_RELATED_YEAR_FIELD, 1208 /*r*/ UDAT_RELATED_YEAR_FIELD,
1209 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
1210 /*:*/ UDAT_TIME_SEPARATOR_FIELD,
1211 #else
1212 /*no pattern char for UDAT_TIME_SEPARATOR_FIELD*/ UDAT_TIME_SEPARATOR_FIEL D,
1213 #endif
1033 }; 1214 };
1034 1215
1035 //---------------------------------------------------------------------- 1216 //----------------------------------------------------------------------
1036 1217
1037 /** 1218 /**
1038 * Append symbols[value] to dst. Make sure the array index is not out 1219 * Append symbols[value] to dst. Make sure the array index is not out
1039 * of bounds. 1220 * of bounds.
1040 */ 1221 */
1041 static inline void 1222 static inline void
1042 _appendSymbol(UnicodeString& dst, 1223 _appendSymbol(UnicodeString& dst,
(...skipping 23 matching lines...) Expand all
1066 //---------------------------------------------------------------------- 1247 //----------------------------------------------------------------------
1067 void 1248 void
1068 SimpleDateFormat::initNumberFormatters(const Locale &locale,UErrorCode &status) { 1249 SimpleDateFormat::initNumberFormatters(const Locale &locale,UErrorCode &status) {
1069 if (U_FAILURE(status)) { 1250 if (U_FAILURE(status)) {
1070 return; 1251 return;
1071 } 1252 }
1072 if ( fDateOverride.isBogus() && fTimeOverride.isBogus() ) { 1253 if ( fDateOverride.isBogus() && fTimeOverride.isBogus() ) {
1073 return; 1254 return;
1074 } 1255 }
1075 umtx_lock(&LOCK); 1256 umtx_lock(&LOCK);
1076 if (fNumberFormatters == NULL) { 1257 if (fSharedNumberFormatters == NULL) {
1077 fNumberFormatters = (NumberFormat**)uprv_malloc(UDAT_FIELD_COUNT * sizeo f(NumberFormat*)); 1258 fSharedNumberFormatters = allocSharedNumberFormatters();
1078 if (fNumberFormatters) { 1259 if (fSharedNumberFormatters == NULL) {
1079 for (int32_t i = 0; i < UDAT_FIELD_COUNT; i++) {
1080 fNumberFormatters[i] = fNumberFormat;
1081 }
1082 } else {
1083 status = U_MEMORY_ALLOCATION_ERROR; 1260 status = U_MEMORY_ALLOCATION_ERROR;
1084 } 1261 }
1085 } 1262 }
1086 umtx_unlock(&LOCK); 1263 umtx_unlock(&LOCK);
1087 1264
1088 if (U_FAILURE(status)) { 1265 if (U_FAILURE(status)) {
1089 return; 1266 return;
1090 } 1267 }
1091 1268
1092 processOverrideString(locale,fDateOverride,kOvrStrDate,status); 1269 processOverrideString(locale,fDateOverride,kOvrStrDate,status);
1093 processOverrideString(locale,fTimeOverride,kOvrStrTime,status); 1270 processOverrideString(locale,fTimeOverride,kOvrStrTime,status);
1094 } 1271 }
1095 1272
1096 void 1273 void
1097 SimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeStrin g &str, int8_t type, UErrorCode &status) { 1274 SimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeStrin g &str, int8_t type, UErrorCode &status) {
1098 if (str.isBogus() || U_FAILURE(status)) { 1275 if (str.isBogus() || U_FAILURE(status)) {
1099 return; 1276 return;
1100 } 1277 }
1101 1278
1102 U_ASSERT(fNumberFormatters != NULL);
1103
1104 int32_t start = 0; 1279 int32_t start = 0;
1105 int32_t len; 1280 int32_t len;
1106 UnicodeString nsName; 1281 UnicodeString nsName;
1107 UnicodeString ovrField; 1282 UnicodeString ovrField;
1108 UBool moreToProcess = TRUE; 1283 UBool moreToProcess = TRUE;
1284 NSOverride *overrideList = NULL;
1109 1285
1110 while (moreToProcess) { 1286 while (moreToProcess) {
1111 int32_t delimiterPosition = str.indexOf((UChar)ULOC_KEYWORD_ITEM_SEPARAT OR_UNICODE,start); 1287 int32_t delimiterPosition = str.indexOf((UChar)ULOC_KEYWORD_ITEM_SEPARAT OR_UNICODE,start);
1112 if (delimiterPosition == -1) { 1288 if (delimiterPosition == -1) {
1113 moreToProcess = FALSE; 1289 moreToProcess = FALSE;
1114 len = str.length() - start; 1290 len = str.length() - start;
1115 } else { 1291 } else {
1116 len = delimiterPosition - start; 1292 len = delimiterPosition - start;
1117 } 1293 }
1118 UnicodeString currentString(str,start,len); 1294 UnicodeString currentString(str,start,len);
1119 int32_t equalSignPosition = currentString.indexOf((UChar)ULOC_KEYWORD_AS SIGN_UNICODE,0); 1295 int32_t equalSignPosition = currentString.indexOf((UChar)ULOC_KEYWORD_AS SIGN_UNICODE,0);
1120 if (equalSignPosition == -1) { // Simple override string such as "hebrew " 1296 if (equalSignPosition == -1) { // Simple override string such as "hebrew "
1121 nsName.setTo(currentString); 1297 nsName.setTo(currentString);
1122 ovrField.setToBogus(); 1298 ovrField.setToBogus();
1123 } else { // Field specific override string such as "y=hebrew" 1299 } else { // Field specific override string such as "y=hebrew"
1124 nsName.setTo(currentString,equalSignPosition+1); 1300 nsName.setTo(currentString,equalSignPosition+1);
1125 ovrField.setTo(currentString,0,1); // We just need the first charact er. 1301 ovrField.setTo(currentString,0,1); // We just need the first charact er.
1126 } 1302 }
1127 1303
1128 int32_t nsNameHash = nsName.hashCode(); 1304 int32_t nsNameHash = nsName.hashCode();
1129 // See if the numbering system is in the override list, if not, then add it. 1305 // See if the numbering system is in the override list, if not, then add it.
1130 NSOverride *cur = fOverrideList; 1306 NSOverride *cur = overrideList;
1131 NumberFormat *nf = NULL; 1307 const SharedNumberFormat *snf = NULL;
1132 UBool found = FALSE; 1308 UBool found = FALSE;
1133 while ( cur && !found ) { 1309 while ( cur && !found ) {
1134 if ( cur->hash == nsNameHash ) { 1310 if ( cur->hash == nsNameHash ) {
1135 nf = cur->nf; 1311 snf = cur->snf;
1136 found = TRUE; 1312 found = TRUE;
1137 } 1313 }
1138 cur = cur->next; 1314 cur = cur->next;
1139 } 1315 }
1140 1316
1141 if (!found) { 1317 if (!found) {
1142 cur = (NSOverride *)uprv_malloc(sizeof(NSOverride)); 1318 LocalPointer<NSOverride> cur(new NSOverride);
1143 if (cur) { 1319 if (!cur.isNull()) {
1144 char kw[ULOC_KEYWORD_AND_VALUES_CAPACITY]; 1320 char kw[ULOC_KEYWORD_AND_VALUES_CAPACITY];
1145 uprv_strcpy(kw,"numbers="); 1321 uprv_strcpy(kw,"numbers=");
1146 nsName.extract(0,len,kw+8,ULOC_KEYWORD_AND_VALUES_CAPACITY-8,US_I NV); 1322 nsName.extract(0,len,kw+8,ULOC_KEYWORD_AND_VALUES_CAPACITY-8,US_I NV);
1147 1323
1148 Locale ovrLoc(locale.getLanguage(),locale.getCountry(),locale.get Variant(),kw); 1324 Locale ovrLoc(locale.getLanguage(),locale.getCountry(),locale.get Variant(),kw);
1149 nf = NumberFormat::createInstance(ovrLoc,status); 1325 cur->hash = nsNameHash;
1150 1326 cur->next = overrideList;
1151 // no matter what the locale's default number format looked like, we want 1327 SharedObject::copyPtr(
1152 // to modify it so that it doesn't use thousands separators, does n't always 1328 createSharedNumberFormat(ovrLoc, status), cur->snf);
1153 // show the decimal point, and recognizes integers only when pars ing 1329 if (U_FAILURE(status)) {
1154 1330 if (overrideList) {
1155 if (U_SUCCESS(status)) { 1331 overrideList->free();
1156 nf->setGroupingUsed(FALSE);
1157 DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(nf);
1158 if (decfmt != NULL) {
1159 decfmt->setDecimalSeparatorAlwaysShown(FALSE);
1160 } 1332 }
1161 nf->setParseIntegerOnly(TRUE); 1333 return;
1162 nf->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 199 7.00"
1163
1164 cur->nf = nf;
1165 cur->hash = nsNameHash;
1166 cur->next = fOverrideList;
1167 fOverrideList = cur;
1168 } 1334 }
1169 else { 1335 snf = cur->snf;
1170 // clean up before returning 1336 overrideList = cur.orphan();
1171 if (cur != NULL) {
1172 uprv_free(cur);
1173 }
1174 return;
1175 }
1176
1177 } else { 1337 } else {
1178 status = U_MEMORY_ALLOCATION_ERROR; 1338 status = U_MEMORY_ALLOCATION_ERROR;
1339 if (overrideList) {
1340 overrideList->free();
1341 }
1179 return; 1342 return;
1180 } 1343 }
1181 } 1344 }
1182 1345
1183 // Now that we have an appropriate number formatter, fill in the appropr iate spaces in the 1346 // Now that we have an appropriate number formatter, fill in the appropr iate spaces in the
1184 // number formatters table. 1347 // number formatters table.
1185 if (ovrField.isBogus()) { 1348 if (ovrField.isBogus()) {
1186 switch (type) { 1349 switch (type) {
1187 case kOvrStrDate: 1350 case kOvrStrDate:
1188 case kOvrStrBoth: { 1351 case kOvrStrBoth: {
1189 for ( int8_t i=0 ; i<kDateFieldsCount; i++ ) { 1352 for ( int8_t i=0 ; i<kDateFieldsCount; i++ ) {
1190 fNumberFormatters[kDateFields[i]] = nf; 1353 SharedObject::copyPtr(snf, fSharedNumberFormatters[kDate Fields[i]]);
1191 } 1354 }
1192 if (type==kOvrStrDate) { 1355 if (type==kOvrStrDate) {
1193 break; 1356 break;
1194 } 1357 }
1195 } 1358 }
1196 case kOvrStrTime : { 1359 case kOvrStrTime : {
1197 for ( int8_t i=0 ; i<kTimeFieldsCount; i++ ) { 1360 for ( int8_t i=0 ; i<kTimeFieldsCount; i++ ) {
1198 fNumberFormatters[kTimeFields[i]] = nf; 1361 SharedObject::copyPtr(snf, fSharedNumberFormatters[kTime Fields[i]]);
1199 } 1362 }
1200 break; 1363 break;
1201 } 1364 }
1202 } 1365 }
1203 } else { 1366 } else {
1204 // if the pattern character is unrecognized, signal an error and bail out 1367 // if the pattern character is unrecognized, signal an error and bail out
1205 UDateFormatField patternCharIndex = 1368 UDateFormatField patternCharIndex =
1206 DateFormatSymbols::getPatternCharIndex(ovrField.charAt(0)); 1369 DateFormatSymbols::getPatternCharIndex(ovrField.charAt(0));
1207 if (patternCharIndex == UDAT_FIELD_COUNT) { 1370 if (patternCharIndex == UDAT_FIELD_COUNT) {
1208 status = U_INVALID_FORMAT_ERROR; 1371 status = U_INVALID_FORMAT_ERROR;
1372 if (overrideList) {
1373 overrideList->free();
1374 }
1209 return; 1375 return;
1210 } 1376 }
1211 1377 SharedObject::copyPtr(snf, fSharedNumberFormatters[patternCharIndex]) ;
1212 // Set the number formatter in the table
1213 fNumberFormatters[patternCharIndex] = nf;
1214 } 1378 }
1215 1379
1216 start = delimiterPosition + 1; 1380 start = delimiterPosition + 1;
1217 } 1381 }
1382 if (overrideList) {
1383 overrideList->free();
1384 }
1218 } 1385 }
1219 1386
1220 //--------------------------------------------------------------------- 1387 //---------------------------------------------------------------------
1221 void 1388 void
1222 SimpleDateFormat::subFormat(UnicodeString &appendTo, 1389 SimpleDateFormat::subFormat(UnicodeString &appendTo,
1223 UChar ch, 1390 UChar ch,
1224 int32_t count, 1391 int32_t count,
1225 UDisplayContext capitalizationContext, 1392 UDisplayContext capitalizationContext,
1226 int32_t fieldNum, 1393 int32_t fieldNum,
1227 FieldPositionHandler& handler, 1394 FieldPositionHandler& handler,
1228 Calendar& cal, 1395 Calendar& cal,
1396 SimpleDateFormatMutableNFs &mutableNFs,
1229 UErrorCode& status) const 1397 UErrorCode& status) const
1230 { 1398 {
1231 if (U_FAILURE(status)) { 1399 if (U_FAILURE(status)) {
1232 return; 1400 return;
1233 } 1401 }
1234 1402
1235 // this function gets called by format() to produce the appropriate substitu tion 1403 // this function gets called by format() to produce the appropriate substitu tion
1236 // text for an individual pattern symbol (e.g., "HH" or "yyyy") 1404 // text for an individual pattern symbol (e.g., "HH" or "yyyy")
1237 1405
1238 UDateFormatField patternCharIndex = DateFormatSymbols::getPatternCharIndex(c h); 1406 UDateFormatField patternCharIndex = DateFormatSymbols::getPatternCharIndex(c h);
1239 const int32_t maxIntCount = 10; 1407 const int32_t maxIntCount = 10;
1240 int32_t beginOffset = appendTo.length(); 1408 int32_t beginOffset = appendTo.length();
1241 NumberFormat *currentNumberFormat; 1409 NumberFormat *currentNumberFormat;
1242 DateFormatSymbols::ECapitalizationContextUsageType capContextUsageType = Dat eFormatSymbols::kCapContextUsageOther; 1410 DateFormatSymbols::ECapitalizationContextUsageType capContextUsageType = Dat eFormatSymbols::kCapContextUsageOther;
1243 1411
1244 UBool isHebrewCalendar = (uprv_strcmp(cal.getType(),"hebrew") == 0); 1412 UBool isHebrewCalendar = (uprv_strcmp(cal.getType(),"hebrew") == 0);
1245 UBool isChineseCalendar = (uprv_strcmp(cal.getType(),"chinese") == 0 || uprv _strcmp(cal.getType(),"dangi") == 0); 1413 UBool isChineseCalendar = (uprv_strcmp(cal.getType(),"chinese") == 0 || uprv _strcmp(cal.getType(),"dangi") == 0);
1246 1414
1247 // if the pattern character is unrecognized, signal an error and dump out 1415 // if the pattern character is unrecognized, signal an error and dump out
1248 if (patternCharIndex == UDAT_FIELD_COUNT) 1416 if (patternCharIndex == UDAT_FIELD_COUNT)
1249 { 1417 {
1250 if (ch != 0x6C) { // pattern char 'l' (SMALL LETTER L) just gets ignored 1418 if (ch != 0x6C) { // pattern char 'l' (SMALL LETTER L) just gets ignored
1251 status = U_INVALID_FORMAT_ERROR; 1419 status = U_INVALID_FORMAT_ERROR;
1252 } 1420 }
1253 return; 1421 return;
1254 } 1422 }
1255 1423
1256 UCalendarDateFields field = fgPatternIndexToCalendarField[patternCharIndex]; 1424 UCalendarDateFields field = fgPatternIndexToCalendarField[patternCharIndex];
1257 int32_t value = (patternCharIndex != UDAT_RELATED_YEAR_FIELD)? cal.get(field , status): cal.getRelatedYear(status); 1425 int32_t value = 0;
1426 // Don't get value unless it is useful
1427 if (field < UCAL_FIELD_COUNT) {
1428 value = (patternCharIndex != UDAT_RELATED_YEAR_FIELD)? cal.get(field, st atus): cal.getRelatedYear(status);
1429 }
1258 if (U_FAILURE(status)) { 1430 if (U_FAILURE(status)) {
1259 return; 1431 return;
1260 } 1432 }
1261 1433
1262 currentNumberFormat = getNumberFormatByIndex(patternCharIndex); 1434 currentNumberFormat = mutableNFs.get(getNumberFormatByIndex(patternCharIndex ));
1435 if (currentNumberFormat == NULL) {
1436 status = U_MEMORY_ALLOCATION_ERROR;
1437 return;
1438 }
1263 UnicodeString hebr("hebr", 4, US_INV); 1439 UnicodeString hebr("hebr", 4, US_INV);
1264 1440
1265 switch (patternCharIndex) { 1441 switch (patternCharIndex) {
1266 1442
1267 // for any "G" symbol, write out the appropriate era string 1443 // for any "G" symbol, write out the appropriate era string
1268 // "GGGG" is wide era name, "GGGGG" is narrow era name, anything else is abb reviated name 1444 // "GGGG" is wide era name, "GGGGG" is narrow era name, anything else is abb reviated name
1269 case UDAT_ERA_FIELD: 1445 case UDAT_ERA_FIELD:
1270 if (isChineseCalendar) { 1446 if (isChineseCalendar) {
1271 zeroPaddingNumber(currentNumberFormat,appendTo, value, 1, 9); // as in ICU4J 1447 zeroPaddingNumber(currentNumberFormat,appendTo, value, 1, 9); // as in ICU4J
1272 } else { 1448 } else {
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1456 _appendSymbol(appendTo, value, fSymbols->fStandaloneShorterWeekdays, 1632 _appendSymbol(appendTo, value, fSymbols->fStandaloneShorterWeekdays,
1457 fSymbols->fStandaloneShorterWeekdaysCount); 1633 fSymbols->fStandaloneShorterWeekdaysCount);
1458 capContextUsageType = DateFormatSymbols::kCapContextUsageDayStandalo ne; 1634 capContextUsageType = DateFormatSymbols::kCapContextUsageDayStandalo ne;
1459 } else { // count == 3 1635 } else { // count == 3
1460 _appendSymbol(appendTo, value, fSymbols->fStandaloneShortWeekdays, 1636 _appendSymbol(appendTo, value, fSymbols->fStandaloneShortWeekdays,
1461 fSymbols->fStandaloneShortWeekdaysCount); 1637 fSymbols->fStandaloneShortWeekdaysCount);
1462 capContextUsageType = DateFormatSymbols::kCapContextUsageDayStandalo ne; 1638 capContextUsageType = DateFormatSymbols::kCapContextUsageDayStandalo ne;
1463 } 1639 }
1464 break; 1640 break;
1465 1641
1466 // for and "a" symbol, write out the whole AM/PM string 1642 // for "a" symbol, write out the whole AM/PM string
1467 case UDAT_AM_PM_FIELD: 1643 case UDAT_AM_PM_FIELD:
1468 _appendSymbol(appendTo, value, fSymbols->fAmPms, 1644 if (count < 5) {
1469 fSymbols->fAmPmsCount); 1645 _appendSymbol(appendTo, value, fSymbols->fAmPms,
1646 fSymbols->fAmPmsCount);
1647 } else {
1648 _appendSymbol(appendTo, value, fSymbols->fNarrowAmPms,
1649 fSymbols->fNarrowAmPmsCount);
1650 }
1651 break;
1652
1653 // if we see pattern character for UDAT_TIME_SEPARATOR_FIELD (none currently defined),
1654 // write out the time separator string. Leave support in for future definiti on.
1655 case UDAT_TIME_SEPARATOR_FIELD:
1656 {
1657 UnicodeString separator;
1658 appendTo += fSymbols->getTimeSeparatorString(separator);
1659 }
1470 break; 1660 break;
1471 1661
1472 // for "h" and "hh", write out the hour, adjusting noon and midnight to show up 1662 // for "h" and "hh", write out the hour, adjusting noon and midnight to show up
1473 // as "12" 1663 // as "12"
1474 case UDAT_HOUR1_FIELD: 1664 case UDAT_HOUR1_FIELD:
1475 if (value == 0) 1665 if (value == 0)
1476 zeroPaddingNumber(currentNumberFormat,appendTo, cal.getLeastMaximum( UCAL_HOUR) + 1, count, maxIntCount); 1666 zeroPaddingNumber(currentNumberFormat,appendTo, cal.getLeastMaximum( UCAL_HOUR) + 1, count, maxIntCount);
1477 else 1667 else
1478 zeroPaddingNumber(currentNumberFormat,appendTo, value, count, maxInt Count); 1668 zeroPaddingNumber(currentNumberFormat,appendTo, value, count, maxInt Count);
1479 break; 1669 break;
1480 1670
1481 case UDAT_TIMEZONE_FIELD: // 'z' 1671 case UDAT_TIMEZONE_FIELD: // 'z'
1482 case UDAT_TIMEZONE_RFC_FIELD: // 'Z' 1672 case UDAT_TIMEZONE_RFC_FIELD: // 'Z'
1483 case UDAT_TIMEZONE_GENERIC_FIELD: // 'v' 1673 case UDAT_TIMEZONE_GENERIC_FIELD: // 'v'
1484 case UDAT_TIMEZONE_SPECIAL_FIELD: // 'V' 1674 case UDAT_TIMEZONE_SPECIAL_FIELD: // 'V'
1485 case UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD: // 'O' 1675 case UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD: // 'O'
1486 case UDAT_TIMEZONE_ISO_FIELD: // 'X' 1676 case UDAT_TIMEZONE_ISO_FIELD: // 'X'
1487 case UDAT_TIMEZONE_ISO_LOCAL_FIELD: // 'x' 1677 case UDAT_TIMEZONE_ISO_LOCAL_FIELD: // 'x'
1488 { 1678 {
1489 UnicodeString zoneString; 1679 UChar zsbuf[64];
1680 UnicodeString zoneString(zsbuf, 0, UPRV_LENGTHOF(zsbuf));
1490 const TimeZone& tz = cal.getTimeZone(); 1681 const TimeZone& tz = cal.getTimeZone();
1491 UDate date = cal.getTime(status); 1682 UDate date = cal.getTime(status);
1492 if (U_SUCCESS(status)) { 1683 if (U_SUCCESS(status)) {
1493 if (patternCharIndex == UDAT_TIMEZONE_FIELD) { 1684 if (patternCharIndex == UDAT_TIMEZONE_FIELD) {
1494 if (count < 4) { 1685 if (count < 4) {
1495 // "z", "zz", "zzz" 1686 // "z", "zz", "zzz"
1496 tzFormat()->format(UTZFMT_STYLE_SPECIFIC_SHORT, tz, date , zoneString); 1687 tzFormat()->format(UTZFMT_STYLE_SPECIFIC_SHORT, tz, date , zoneString);
1497 capContextUsageType = DateFormatSymbols::kCapContextUsag eMetazoneShort; 1688 capContextUsageType = DateFormatSymbols::kCapContextUsag eMetazoneShort;
1498 } else { 1689 } else {
1499 // "zzzz" or longer 1690 // "zzzz" or longer
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
1647 } 1838 }
1648 } 1839 }
1649 #endif 1840 #endif
1650 1841
1651 handler.addAttribute(fgPatternIndexToDateFormatField[patternCharIndex], begi nOffset, appendTo.length()); 1842 handler.addAttribute(fgPatternIndexToDateFormatField[patternCharIndex], begi nOffset, appendTo.length());
1652 } 1843 }
1653 1844
1654 //---------------------------------------------------------------------- 1845 //----------------------------------------------------------------------
1655 1846
1656 void SimpleDateFormat::adoptNumberFormat(NumberFormat *formatToAdopt) { 1847 void SimpleDateFormat::adoptNumberFormat(NumberFormat *formatToAdopt) {
1657 formatToAdopt->setParseIntegerOnly(TRUE); 1848 fixNumberFormatForDates(*formatToAdopt);
1658 if (fNumberFormat && fNumberFormat != formatToAdopt){ 1849 delete fNumberFormat;
1659 delete fNumberFormat;
1660 }
1661 fNumberFormat = formatToAdopt; 1850 fNumberFormat = formatToAdopt;
1662
1663 if (fNumberFormatters) {
1664 for (int32_t i = 0; i < UDAT_FIELD_COUNT; i++) {
1665 if (fNumberFormatters[i] == formatToAdopt) {
1666 fNumberFormatters[i] = NULL;
1667 }
1668 }
1669 uprv_free(fNumberFormatters);
1670 fNumberFormatters = NULL;
1671 }
1672 1851
1673 while (fOverrideList) { 1852 // We successfully set the default number format. Now delete the overrides
1674 NSOverride *cur = fOverrideList; 1853 // (can't fail).
1675 fOverrideList = cur->next; 1854 if (fSharedNumberFormatters) {
1676 if (cur->nf != formatToAdopt) { // only delete those not duplicate 1855 freeSharedNumberFormatters(fSharedNumberFormatters);
1677 delete cur->nf; 1856 fSharedNumberFormatters = NULL;
1678 uprv_free(cur);
1679 } else {
1680 cur->nf = NULL;
1681 uprv_free(cur);
1682 }
1683 } 1857 }
1684 } 1858 }
1685 1859
1686 void SimpleDateFormat::adoptNumberFormat(const UnicodeString& fields, NumberForm at *formatToAdopt, UErrorCode &status){ 1860 void SimpleDateFormat::adoptNumberFormat(const UnicodeString& fields, NumberForm at *formatToAdopt, UErrorCode &status){
1687 // if it has not been initialized yet, initialize 1861 fixNumberFormatForDates(*formatToAdopt);
1688 if (fNumberFormatters == NULL) { 1862 LocalPointer<NumberFormat> fmt(formatToAdopt);
1689 fNumberFormatters = (NumberFormat**)uprv_malloc(UDAT_FIELD_COUNT * sizeo f(NumberFormat*)); 1863 if (U_FAILURE(status)) {
1690 if (fNumberFormatters) { 1864 return;
1691 for (int32_t i = 0; i < UDAT_FIELD_COUNT; i++) { 1865 }
1692 fNumberFormatters[i] = fNumberFormat; 1866
1693 } 1867 // We must ensure fSharedNumberFormatters is allocated.
1694 } else { 1868 if (fSharedNumberFormatters == NULL) {
1869 fSharedNumberFormatters = allocSharedNumberFormatters();
1870 if (fSharedNumberFormatters == NULL) {
1695 status = U_MEMORY_ALLOCATION_ERROR; 1871 status = U_MEMORY_ALLOCATION_ERROR;
1696 return; 1872 return;
1697 } 1873 }
1698 } 1874 }
1699 1875 const SharedNumberFormat *newFormat = createSharedNumberFormat(fmt.orphan()) ;
1700 // See if the numbering format is in the override list, if not, then add it. 1876 if (newFormat == NULL) {
1701 NSOverride *cur = fOverrideList; 1877 status = U_MEMORY_ALLOCATION_ERROR;
1702 UBool found = FALSE; 1878 return;
1703 while (cur && !found) {
1704 if ( cur->nf == formatToAdopt ) {
1705 found = TRUE;
1706 }
1707 cur = cur->next;
1708 } 1879 }
1709
1710 if (!found) {
1711 cur = (NSOverride *)uprv_malloc(sizeof(NSOverride));
1712 if (cur) {
1713 // no matter what the locale's default number format looked like, we want
1714 // to modify it so that it doesn't use thousands separators, doesn't always
1715 // show the decimal point, and recognizes integers only when parsing
1716 formatToAdopt->setGroupingUsed(FALSE);
1717 DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(formatToAdopt);
1718 if (decfmt != NULL) {
1719 decfmt->setDecimalSeparatorAlwaysShown(FALSE);
1720 }
1721 formatToAdopt->setParseIntegerOnly(TRUE);
1722 formatToAdopt->setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
1723
1724 cur->nf = formatToAdopt;
1725 cur->hash = -1; // set duplicate here (before we set it with NumberS ystem Hash, here we cannot get nor use it)
1726 cur->next = fOverrideList;
1727 fOverrideList = cur;
1728 } else {
1729 status = U_MEMORY_ALLOCATION_ERROR;
1730 return;
1731 }
1732 }
1733
1734 for (int i=0; i<fields.length(); i++) { 1880 for (int i=0; i<fields.length(); i++) {
1735 UChar field = fields.charAt(i); 1881 UChar field = fields.charAt(i);
1736 // if the pattern character is unrecognized, signal an error and bail ou t 1882 // if the pattern character is unrecognized, signal an error and bail ou t
1737 UDateFormatField patternCharIndex = DateFormatSymbols::getPatternCharInd ex(field); 1883 UDateFormatField patternCharIndex = DateFormatSymbols::getPatternCharInd ex(field);
1738 if (patternCharIndex == UDAT_FIELD_COUNT) { 1884 if (patternCharIndex == UDAT_FIELD_COUNT) {
1739 status = U_INVALID_FORMAT_ERROR; 1885 status = U_INVALID_FORMAT_ERROR;
1886 newFormat->deleteIfZeroRefCount();
1740 return; 1887 return;
1741 } 1888 }
1742 1889
1743 // Set the number formatter in the table 1890 // Set the number formatter in the table
1744 fNumberFormatters[patternCharIndex] = formatToAdopt; 1891 SharedObject::copyPtr(
1892 newFormat, fSharedNumberFormatters[patternCharIndex]);
1745 } 1893 }
1894 newFormat->deleteIfZeroRefCount();
1746 } 1895 }
1747 1896
1748 const NumberFormat * 1897 const NumberFormat *
1749 SimpleDateFormat::getNumberFormatForField(UChar field) const { 1898 SimpleDateFormat::getNumberFormatForField(UChar field) const {
1750 UDateFormatField index = DateFormatSymbols::getPatternCharIndex(field); 1899 UDateFormatField index = DateFormatSymbols::getPatternCharIndex(field);
1900 if (index == UDAT_FIELD_COUNT) {
1901 return NULL;
1902 }
1751 return getNumberFormatByIndex(index); 1903 return getNumberFormatByIndex(index);
1752 } 1904 }
1753 1905
1754 NumberFormat *
1755 SimpleDateFormat::getNumberFormatByIndex(UDateFormatField index) const {
1756 if (fNumberFormatters != NULL) {
1757 return fNumberFormatters[index];
1758 } else {
1759 return fNumberFormat;
1760 }
1761 }
1762
1763 //---------------------------------------------------------------------- 1906 //----------------------------------------------------------------------
1764 void 1907 void
1765 SimpleDateFormat::zeroPaddingNumber(NumberFormat *currentNumberFormat,UnicodeStr ing &appendTo, 1908 SimpleDateFormat::zeroPaddingNumber(
1766 int32_t value, int32_t minDigits, int32_t ma xDigits) const 1909 NumberFormat *currentNumberFormat,
1910 UnicodeString &appendTo,
1911 int32_t value, int32_t minDigits, int32_t maxDigits) const
1767 { 1912 {
1768 if (currentNumberFormat!=NULL) { 1913 if (currentNumberFormat!=NULL) {
1769 FieldPosition pos(0); 1914 FieldPosition pos(0);
1770 1915
1771 currentNumberFormat->setMinimumIntegerDigits(minDigits); 1916 currentNumberFormat->setMinimumIntegerDigits(minDigits);
1772 currentNumberFormat->setMaximumIntegerDigits(maxDigits); 1917 currentNumberFormat->setMaximumIntegerDigits(maxDigits);
1773 currentNumberFormat->format(value, appendTo, pos); // 3rd arg is there to speed up processing 1918 currentNumberFormat->format(value, appendTo, pos); // 3rd arg is there to speed up processing
1774 } 1919 }
1775 } 1920 }
1776 1921
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1827 parsePos.setErrorIndex(0); 1972 parsePos.setErrorIndex(0);
1828 return; 1973 return;
1829 } 1974 }
1830 int32_t start = pos; 1975 int32_t start = pos;
1831 1976
1832 1977
1833 UBool ambiguousYear[] = { FALSE }; 1978 UBool ambiguousYear[] = { FALSE };
1834 int32_t saveHebrewMonth = -1; 1979 int32_t saveHebrewMonth = -1;
1835 int32_t count = 0; 1980 int32_t count = 0;
1836 UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN; 1981 UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
1982 SimpleDateFormatMutableNFs mutableNFs;
1837 1983
1838 // For parsing abutting numeric fields. 'abutPat' is the 1984 // For parsing abutting numeric fields. 'abutPat' is the
1839 // offset into 'pattern' of the first of 2 or more abutting 1985 // offset into 'pattern' of the first of 2 or more abutting
1840 // numeric fields. 'abutStart' is the offset into 'text' 1986 // numeric fields. 'abutStart' is the offset into 'text'
1841 // where parsing the fields begins. 'abutPass' starts off as 0 1987 // where parsing the fields begins. 'abutPass' starts off as 0
1842 // and increments each time we try to parse the fields. 1988 // and increments each time we try to parse the fields.
1843 int32_t abutPat = -1; // If >=0, we are in a run of abutting numeric fields 1989 int32_t abutPat = -1; // If >=0, we are in a run of abutting numeric fields
1844 int32_t abutStart = 0; 1990 int32_t abutStart = 0;
1845 int32_t abutPass = 0; 1991 int32_t abutPass = 0;
1846 UBool inQuote = FALSE; 1992 UBool inQuote = FALSE;
(...skipping 27 matching lines...) Expand all
1874 goto ExitParse; 2020 goto ExitParse;
1875 } else if (U_FAILURE(status)) { 2021 } else if (U_FAILURE(status)) {
1876 goto ExitParse; // this will delete numericLeapMonthFormatter 2022 goto ExitParse; // this will delete numericLeapMonthFormatter
1877 } 2023 }
1878 } 2024 }
1879 2025
1880 for (int32_t i=0; i<fPattern.length(); ++i) { 2026 for (int32_t i=0; i<fPattern.length(); ++i) {
1881 UChar ch = fPattern.charAt(i); 2027 UChar ch = fPattern.charAt(i);
1882 2028
1883 // Handle alphabetic field characters. 2029 // Handle alphabetic field characters.
1884 if (!inQuote && ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A ))) { // [A-Za-z] 2030 if (!inQuote && isSyntaxChar(ch)) {
1885 int32_t fieldPat = i; 2031 int32_t fieldPat = i;
1886 2032
1887 // Count the length of this field specifier 2033 // Count the length of this field specifier
1888 count = 1; 2034 count = 1;
1889 while ((i+1)<fPattern.length() && 2035 while ((i+1)<fPattern.length() &&
1890 fPattern.charAt(i+1) == ch) { 2036 fPattern.charAt(i+1) == ch) {
1891 ++count; 2037 ++count;
1892 ++i; 2038 ++i;
1893 } 2039 }
1894 2040
(...skipping 25 matching lines...) Expand all
1920 // abutting numeric fields has failed. 2066 // abutting numeric fields has failed.
1921 if (fieldPat == abutPat) { 2067 if (fieldPat == abutPat) {
1922 count -= abutPass++; 2068 count -= abutPass++;
1923 if (count == 0) { 2069 if (count == 0) {
1924 status = U_PARSE_ERROR; 2070 status = U_PARSE_ERROR;
1925 goto ExitParse; 2071 goto ExitParse;
1926 } 2072 }
1927 } 2073 }
1928 2074
1929 pos = subParse(text, pos, ch, count, 2075 pos = subParse(text, pos, ch, count,
1930 TRUE, FALSE, ambiguousYear, saveHebrewMonth, *wor kCal, i, numericLeapMonthFormatter, &tzTimeType); 2076 TRUE, FALSE, ambiguousYear, saveHebrewMonth, *wor kCal, i, numericLeapMonthFormatter, &tzTimeType, mutableNFs);
1931 2077
1932 // If the parse fails anywhere in the run, back up to the 2078 // If the parse fails anywhere in the run, back up to the
1933 // start of the run and retry. 2079 // start of the run and retry.
1934 if (pos < 0) { 2080 if (pos < 0) {
1935 i = abutPat - 1; 2081 i = abutPat - 1;
1936 pos = abutStart; 2082 pos = abutStart;
1937 continue; 2083 continue;
1938 } 2084 }
1939 } 2085 }
1940 2086
1941 // Handle non-numeric fields and non-abutting numeric 2087 // Handle non-numeric fields and non-abutting numeric
1942 // fields. 2088 // fields.
1943 else if (ch != 0x6C) { // pattern char 'l' (SMALL LETTER L) just get s ignored 2089 else if (ch != 0x6C) { // pattern char 'l' (SMALL LETTER L) just get s ignored
1944 int32_t s = subParse(text, pos, ch, count, 2090 int32_t s = subParse(text, pos, ch, count,
1945 FALSE, TRUE, ambiguousYear, saveHebrewMonth, *wor kCal, i, numericLeapMonthFormatter, &tzTimeType); 2091 FALSE, TRUE, ambiguousYear, saveHebrewMonth, *wor kCal, i, numericLeapMonthFormatter, &tzTimeType, mutableNFs);
1946 2092
1947 if (s == -pos-1) { 2093 if (s == -pos-1) {
1948 // era not present, in special cases allow this to continue 2094 // era not present, in special cases allow this to continue
1949 // from the position where the era was expected 2095 // from the position where the era was expected
1950 s = pos; 2096 s = pos;
1951 2097
1952 if (i+1 < fPattern.length()) { 2098 if (i+1 < fPattern.length()) {
1953 // move to next pattern character 2099 // move to next pattern character
1954 UChar ch = fPattern.charAt(i+1); 2100 UChar ch = fPattern.charAt(i+1);
1955 2101
(...skipping 16 matching lines...) Expand all
1972 } 2118 }
1973 } 2119 }
1974 2120
1975 // Handle literal pattern characters. These are any 2121 // Handle literal pattern characters. These are any
1976 // quoted characters and non-alphabetic unquoted 2122 // quoted characters and non-alphabetic unquoted
1977 // characters. 2123 // characters.
1978 else { 2124 else {
1979 2125
1980 abutPat = -1; // End of any abutting fields 2126 abutPat = -1; // End of any abutting fields
1981 2127
1982 if (! matchLiterals(fPattern, i, text, pos, getBooleanAttribute(UDAT _PARSE_ALLOW_WHITESPACE, status), getBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, status), isLenient())) { 2128 if (! matchLiterals(fPattern, i, text, pos, getBooleanAttribute(UDAT _PARSE_ALLOW_WHITESPACE, status), getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL _MATCH, status), isLenient())) {
1983 status = U_PARSE_ERROR; 2129 status = U_PARSE_ERROR;
1984 goto ExitParse; 2130 goto ExitParse;
1985 } 2131 }
1986 } 2132 }
1987 } 2133 }
1988 2134
1989 // Special hack for trailing "." after non-numeric field. 2135 // Special hack for trailing "." after non-numeric field.
1990 if (text.charAt(pos) == 0x2e && getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESP ACE, status)) { 2136 if (text.charAt(pos) == 0x2e && getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESP ACE, status)) {
1991 // only do if the last field is not numeric 2137 // only do if the last field is not numeric
1992 if (isAfterNonNumericField(fPattern, fPattern.length())) { 2138 if (isAfterNonNumericField(fPattern, fPattern.length())) {
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
2173 // couldn't parse the string, when in reality this isn't quite accurate-- 2319 // couldn't parse the string, when in reality this isn't quite accurate--
2174 // we did parse it; the Calendar calls just failed. 2320 // we did parse it; the Calendar calls just failed.
2175 if (U_FAILURE(status)) { 2321 if (U_FAILURE(status)) {
2176 parsePos.setErrorIndex(pos); 2322 parsePos.setErrorIndex(pos);
2177 parsePos.setIndex(start); 2323 parsePos.setIndex(start);
2178 } 2324 }
2179 } 2325 }
2180 2326
2181 //---------------------------------------------------------------------- 2327 //----------------------------------------------------------------------
2182 2328
2183 static UBool 2329 static int32_t
2184 newBestMatchWithOptionalDot(const UnicodeString &lcaseText, 2330 matchStringWithOptionalDot(const UnicodeString &text,
2185 const UnicodeString &data, 2331 int32_t index,
2186 UnicodeString &bestMatchName, 2332 const UnicodeString &data);
2187 int32_t &bestMatchLength);
2188 2333
2189 int32_t SimpleDateFormat::matchQuarterString(const UnicodeString& text, 2334 int32_t SimpleDateFormat::matchQuarterString(const UnicodeString& text,
2190 int32_t start, 2335 int32_t start,
2191 UCalendarDateFields field, 2336 UCalendarDateFields field,
2192 const UnicodeString* data, 2337 const UnicodeString* data,
2193 int32_t dataCount, 2338 int32_t dataCount,
2194 Calendar& cal) const 2339 Calendar& cal) const
2195 { 2340 {
2196 int32_t i = 0; 2341 int32_t i = 0;
2197 int32_t count = dataCount; 2342 int32_t count = dataCount;
2198 2343
2199 // There may be multiple strings in the data[] array which begin with 2344 // There may be multiple strings in the data[] array which begin with
2200 // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech). 2345 // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech).
2201 // We keep track of the longest match, and return that. Note that this 2346 // We keep track of the longest match, and return that. Note that this
2202 // unfortunately requires us to test all array elements. 2347 // unfortunately requires us to test all array elements.
2203 int32_t bestMatchLength = 0, bestMatch = -1; 2348 int32_t bestMatchLength = 0, bestMatch = -1;
2204 UnicodeString bestMatchName; 2349 UnicodeString bestMatchName;
2205 2350
2206 // {sfb} kludge to support case-insensitive comparison 2351 for (; i < count; ++i) {
2207 // {markus 2002oct11} do not just use caseCompareBetween because we do not k now 2352 int32_t matchLength = 0;
2208 // the length of the match after case folding 2353 if ((matchLength = matchStringWithOptionalDot(text, start, data[i])) > b estMatchLength) {
2209 // {alan 20040607} don't case change the whole string, since the length 2354 bestMatchLength = matchLength;
2210 // can change
2211 // TODO we need a case-insensitive startsWith function
2212 UnicodeString lcaseText;
2213 text.extract(start, INT32_MAX, lcaseText);
2214 lcaseText.foldCase();
2215
2216 for (; i < count; ++i)
2217 {
2218 // Always compare if we have no match yet; otherwise only compare
2219 // against potentially better matches (longer strings).
2220
2221 if (newBestMatchWithOptionalDot(lcaseText, data[i], bestMatchName, bestM atchLength)) {
2222 bestMatch = i; 2355 bestMatch = i;
2223 } 2356 }
2224 } 2357 }
2225 if (bestMatch >= 0) 2358
2226 { 2359 if (bestMatch >= 0) {
2227 cal.set(field, bestMatch * 3); 2360 cal.set(field, bestMatch * 3);
2228 2361 return start + bestMatchLength;
2229 // Once we have a match, we have to determine the length of the
2230 // original source string. This will usually be == the length of
2231 // the case folded string, but it may differ (e.g. sharp s).
2232
2233 // Most of the time, the length will be the same as the length
2234 // of the string from the locale data. Sometimes it will be
2235 // different, in which case we will have to figure it out by
2236 // adding a character at a time, until we have a match. We do
2237 // this all in one loop, where we try 'len' first (at index
2238 // i==0).
2239 int32_t len = bestMatchName.length(); // 99+% of the time
2240 int32_t n = text.length() - start;
2241 for (i=0; i<=n; ++i) {
2242 int32_t j=i;
2243 if (i == 0) {
2244 j = len;
2245 } else if (i == len) {
2246 continue; // already tried this when i was 0
2247 }
2248 text.extract(start, j, lcaseText);
2249 lcaseText.foldCase();
2250 if (bestMatchName == lcaseText) {
2251 return start + j;
2252 }
2253 }
2254 } 2362 }
2255 2363
2256 return -start; 2364 return -start;
2257 } 2365 }
2258 2366
2259 //---------------------------------------------------------------------- 2367 //----------------------------------------------------------------------
2260 UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern, 2368 UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
2261 int32_t &patternOffset, 2369 int32_t &patternOffset,
2262 const UnicodeString &text, 2370 const UnicodeString &text,
2263 int32_t &textOffset, 2371 int32_t &textOffset,
2264 UBool whitespaceLenient, 2372 UBool whitespaceLenient,
2265 UBool partialMatchLenient, 2373 UBool partialMatchLenient,
2266 UBool oldLeniency) 2374 UBool oldLeniency)
2267 { 2375 {
2268 UBool inQuote = FALSE; 2376 UBool inQuote = FALSE;
2269 UnicodeString literal; 2377 UnicodeString literal;
2270 int32_t i = patternOffset; 2378 int32_t i = patternOffset;
2271 » 2379
2272 // scan pattern looking for contiguous literal characters 2380 // scan pattern looking for contiguous literal characters
2273 for ( ; i < pattern.length(); i += 1) { 2381 for ( ; i < pattern.length(); i += 1) {
2274 UChar ch = pattern.charAt(i); 2382 UChar ch = pattern.charAt(i);
2275 2383
2276 if (!inQuote && ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A ))) { // unquoted [A-Za-z] 2384 if (!inQuote && isSyntaxChar(ch)) {
2277 break; 2385 break;
2278 } 2386 }
2279 2387
2280 if (ch == QUOTE) { 2388 if (ch == QUOTE) {
2281 // Match a quote literal ('') inside OR outside of quotes 2389 // Match a quote literal ('') inside OR outside of quotes
2282 if ((i + 1) < pattern.length() && pattern.charAt(i + 1) == QUOTE) { 2390 if ((i + 1) < pattern.length() && pattern.charAt(i + 1) == QUOTE) {
2283 i += 1; 2391 i += 1;
2284 } else { 2392 } else {
2285 inQuote = !inQuote; 2393 inQuote = !inQuote;
2286 continue; 2394 continue;
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
2417 if (field == UCAL_DAY_OF_WEEK) i = 1; 2525 if (field == UCAL_DAY_OF_WEEK) i = 1;
2418 2526
2419 // There may be multiple strings in the data[] array which begin with 2527 // There may be multiple strings in the data[] array which begin with
2420 // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech). 2528 // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech).
2421 // We keep track of the longest match, and return that. Note that this 2529 // We keep track of the longest match, and return that. Note that this
2422 // unfortunately requires us to test all array elements. 2530 // unfortunately requires us to test all array elements.
2423 int32_t bestMatchLength = 0, bestMatch = -1; 2531 int32_t bestMatchLength = 0, bestMatch = -1;
2424 UnicodeString bestMatchName; 2532 UnicodeString bestMatchName;
2425 int32_t isLeapMonth = 0; 2533 int32_t isLeapMonth = 0;
2426 2534
2427 // {sfb} kludge to support case-insensitive comparison 2535 for (; i < count; ++i) {
2428 // {markus 2002oct11} do not just use caseCompareBetween because we do not k now 2536 int32_t matchLen = 0;
2429 // the length of the match after case folding 2537 if ((matchLen = matchStringWithOptionalDot(text, start, data[i])) > best MatchLength) {
2430 // {alan 20040607} don't case change the whole string, since the length
2431 // can change
2432 // TODO we need a case-insensitive startsWith function
2433 UnicodeString lcaseText;
2434 text.extract(start, INT32_MAX, lcaseText);
2435 lcaseText.foldCase();
2436
2437 for (; i < count; ++i)
2438 {
2439 // Always compare if we have no match yet; otherwise only compare
2440 // against potentially better matches (longer strings).
2441
2442 if (newBestMatchWithOptionalDot(lcaseText, data[i], bestMatchName, bestM atchLength)) {
2443 bestMatch = i; 2538 bestMatch = i;
2444 isLeapMonth = 0; 2539 bestMatchLength = matchLen;
2445 } 2540 }
2446 2541
2447 if (monthPattern != NULL) { 2542 if (monthPattern != NULL) {
2448 UErrorCode status = U_ZERO_ERROR; 2543 UErrorCode status = U_ZERO_ERROR;
2449 UnicodeString leapMonthName; 2544 UnicodeString leapMonthName;
2450 Formattable monthName((const UnicodeString&)(data[i])); 2545 Formattable monthName((const UnicodeString&)(data[i]));
2451 MessageFormat::format(*monthPattern, &monthName, 1, leapMonthName, s tatus); 2546 MessageFormat::format(*monthPattern, &monthName, 1, leapMonthName, s tatus);
2452 if (U_SUCCESS(status)) { 2547 if (U_SUCCESS(status)) {
2453 if (newBestMatchWithOptionalDot(lcaseText, leapMonthName, bestMa tchName, bestMatchLength)) { 2548 if ((matchLen = matchStringWithOptionalDot(text, start, leapMont hName)) > bestMatchLength) {
2454 bestMatch = i; 2549 bestMatch = i;
2550 bestMatchLength = matchLen;
2455 isLeapMonth = 1; 2551 isLeapMonth = 1;
2456 } 2552 }
2457 } 2553 }
2458 } 2554 }
2459 } 2555 }
2460 if (bestMatch >= 0) 2556
2461 { 2557 if (bestMatch >= 0) {
2462 // Adjustment for Hebrew Calendar month Adar II 2558 if (field < UCAL_FIELD_COUNT) {
2463 if (!strcmp(cal.getType(),"hebrew") && field==UCAL_MONTH && bestMatch==1 3) { 2559 // Adjustment for Hebrew Calendar month Adar II
2464 cal.set(field,6); 2560 if (!strcmp(cal.getType(),"hebrew") && field==UCAL_MONTH && bestMatc h==13) {
2465 } 2561 cal.set(field,6);
2466 else { 2562 } else {
2467 if (field == UCAL_YEAR) { 2563 if (field == UCAL_YEAR) {
2468 bestMatch++; // only get here for cyclic year names, which match 1-based years 1-60 2564 bestMatch++; // only get here for cyclic year names, which m atch 1-based years 1-60
2565 }
2566 cal.set(field, bestMatch);
2469 } 2567 }
2470 cal.set(field, bestMatch); 2568 if (monthPattern != NULL) {
2471 } 2569 cal.set(UCAL_IS_LEAP_MONTH, isLeapMonth);
2472 if (monthPattern != NULL) { 2570 }
2473 cal.set(UCAL_IS_LEAP_MONTH, isLeapMonth);
2474 } 2571 }
2475 2572
2476 // Once we have a match, we have to determine the length of the 2573 return start + bestMatchLength;
2477 // original source string. This will usually be == the length of
2478 // the case folded string, but it may differ (e.g. sharp s).
2479
2480 // Most of the time, the length will be the same as the length
2481 // of the string from the locale data. Sometimes it will be
2482 // different, in which case we will have to figure it out by
2483 // adding a character at a time, until we have a match. We do
2484 // this all in one loop, where we try 'len' first (at index
2485 // i==0).
2486 int32_t len = bestMatchName.length(); // 99+% of the time
2487 int32_t n = text.length() - start;
2488 for (i=0; i<=n; ++i) {
2489 int32_t j=i;
2490 if (i == 0) {
2491 j = len;
2492 } else if (i == len) {
2493 continue; // already tried this when i was 0
2494 }
2495 text.extract(start, j, lcaseText);
2496 lcaseText.foldCase();
2497 if (bestMatchName == lcaseText) {
2498 return start + j;
2499 }
2500 }
2501 } 2574 }
2502 2575
2503 return -start; 2576 return -start;
2504 } 2577 }
2505 2578
2506 static UBool 2579 static int32_t
2507 newBestMatchWithOptionalDot(const UnicodeString &lcaseText, 2580 matchStringWithOptionalDot(const UnicodeString &text,
2508 const UnicodeString &data, 2581 int32_t index,
2509 UnicodeString &bestMatchName, 2582 const UnicodeString &data) {
2510 int32_t &bestMatchLength) { 2583 UErrorCode sts = U_ZERO_ERROR;
2511 UnicodeString lcase; 2584 int32_t matchLenText = 0;
2512 lcase.fastCopyFrom(data).foldCase(); 2585 int32_t matchLenData = 0;
2513 int32_t length = lcase.length(); 2586
2514 if (length <= bestMatchLength) { 2587 u_caseInsensitivePrefixMatch(text.getBuffer() + index, text.length() - index ,
2515 // data cannot provide a better match. 2588 data.getBuffer(), data.length(),
2516 return FALSE; 2589 0 /* default case option */,
2590 &matchLenText, &matchLenData,
2591 &sts);
2592 U_ASSERT (U_SUCCESS(sts));
2593
2594 if (matchLenData == data.length() /* normal match */
2595 || (data.charAt(data.length() - 1) == 0x2e
2596 && matchLenData == data.length() - 1 /* match without trailing dot * /)) {
2597 return matchLenText;
2517 } 2598 }
2518 2599
2519 if (lcaseText.compareBetween(0, length, lcase, 0, length) == 0) { 2600 return 0;
2520 // normal match
2521 bestMatchName = lcase;
2522 bestMatchLength = length;
2523 return TRUE;
2524 }
2525 if (lcase.charAt(--length) == 0x2e) {
2526 if (lcaseText.compareBetween(0, length, lcase, 0, length) == 0) {
2527 // The input text matches the data except for data's trailing dot.
2528 bestMatchName = lcase;
2529 bestMatchName.truncate(length);
2530 bestMatchLength = length;
2531 return TRUE;
2532 }
2533 }
2534 return FALSE;
2535 } 2601 }
2536 2602
2537 //---------------------------------------------------------------------- 2603 //----------------------------------------------------------------------
2538 2604
2539 void 2605 void
2540 SimpleDateFormat::set2DigitYearStart(UDate d, UErrorCode& status) 2606 SimpleDateFormat::set2DigitYearStart(UDate d, UErrorCode& status)
2541 { 2607 {
2542 parseAmbiguousDatesAsAfter(d, status); 2608 parseAmbiguousDatesAsAfter(d, status);
2543 } 2609 }
2544 2610
2545 /** 2611 /**
2546 * Private member function that converts the parsed date strings into 2612 * Private member function that converts the parsed date strings into
2547 * timeFields. Returns -start (for ParsePosition) if failed. 2613 * timeFields. Returns -start (for ParsePosition) if failed.
2548 */ 2614 */
2549 int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC har ch, int32_t count, 2615 int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC har ch, int32_t count,
2550 UBool obeyCount, UBool allowNegative, UBool ambiguous Year[], int32_t& saveHebrewMonth, Calendar& cal, 2616 UBool obeyCount, UBool allowNegative, UBool ambiguous Year[], int32_t& saveHebrewMonth, Calendar& cal,
2551 int32_t patLoc, MessageFormat * numericLeapMonthForma tter, UTimeZoneFormatTimeType *tzTimeType) const 2617 int32_t patLoc, MessageFormat * numericLeapMonthForma tter, UTimeZoneFormatTimeType *tzTimeType, SimpleDateFormatMutableNFs &mutableNF s) const
2552 { 2618 {
2553 Formattable number; 2619 Formattable number;
2554 int32_t value = 0; 2620 int32_t value = 0;
2555 int32_t i; 2621 int32_t i;
2556 int32_t ps = 0; 2622 int32_t ps = 0;
2557 UErrorCode status = U_ZERO_ERROR; 2623 UErrorCode status = U_ZERO_ERROR;
2558 ParsePosition pos(0); 2624 ParsePosition pos(0);
2559 UDateFormatField patternCharIndex = DateFormatSymbols::getPatternCharIndex(c h); 2625 UDateFormatField patternCharIndex = DateFormatSymbols::getPatternCharIndex(c h);
2560 NumberFormat *currentNumberFormat; 2626 NumberFormat *currentNumberFormat;
2561 UnicodeString temp; 2627 UnicodeString temp;
2562 UBool gotNumber = FALSE; 2628 UBool gotNumber = FALSE;
2563 2629
2564 #if defined (U_DEBUG_CAL) 2630 #if defined (U_DEBUG_CAL)
2565 //fprintf(stderr, "%s:%d - [%c] st=%d \n", __FILE__, __LINE__, (char) ch, s tart); 2631 //fprintf(stderr, "%s:%d - [%c] st=%d \n", __FILE__, __LINE__, (char) ch, s tart);
2566 #endif 2632 #endif
2567 2633
2568 if (patternCharIndex == UDAT_FIELD_COUNT) { 2634 if (patternCharIndex == UDAT_FIELD_COUNT) {
2569 return -start; 2635 return -start;
2570 } 2636 }
2571 2637
2572 currentNumberFormat = getNumberFormatByIndex(patternCharIndex); 2638 currentNumberFormat = mutableNFs.get(getNumberFormatByIndex(patternCharIndex ));
2573 UCalendarDateFields field = fgPatternIndexToCalendarField[patternCharIndex]; 2639 if (currentNumberFormat == NULL) {
2640 return -start;
2641 }
2642 UCalendarDateFields field = fgPatternIndexToCalendarField[patternCharIndex]; // UCAL_FIELD_COUNT if irrelevant
2574 UnicodeString hebr("hebr", 4, US_INV); 2643 UnicodeString hebr("hebr", 4, US_INV);
2575 2644
2576 if (numericLeapMonthFormatter != NULL) { 2645 if (numericLeapMonthFormatter != NULL) {
2577 numericLeapMonthFormatter->setFormats((const Format **)&currentNumberFor mat, 1); 2646 numericLeapMonthFormatter->setFormats((const Format **)&currentNumberFor mat, 1);
2578 } 2647 }
2579 UBool isChineseCalendar = (uprv_strcmp(cal.getType(),"chinese") == 0 || uprv _strcmp(cal.getType(),"dangi") == 0); 2648 UBool isChineseCalendar = (uprv_strcmp(cal.getType(),"chinese") == 0 || uprv _strcmp(cal.getType(),"dangi") == 0);
2580 2649
2581 // If there are any spaces here, skip over them. If we hit the end 2650 // If there are any spaces here, skip over them. If we hit the end
2582 // of the string, then fail. 2651 // of the string, then fail.
2583 for (;;) { 2652 for (;;) {
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
2974 fSymbols->fStandaloneShorterWeekdays, fSymbols->fStandaloneShorterWeekdaysCount, NULL, cal)) > 0) 3043 fSymbols->fStandaloneShorterWeekdays, fSymbols->fStandaloneShorterWeekdaysCount, NULL, cal)) > 0)
2975 return newStart; 3044 return newStart;
2976 } 3045 }
2977 if (!getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status)) 3046 if (!getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status))
2978 return newStart; 3047 return newStart;
2979 // else we allowing parsing as number, below 3048 // else we allowing parsing as number, below
2980 } 3049 }
2981 break; 3050 break;
2982 3051
2983 case UDAT_AM_PM_FIELD: 3052 case UDAT_AM_PM_FIELD:
2984 return matchString(text, start, UCAL_AM_PM, fSymbols->fAmPms, fSymbols-> fAmPmsCount, NULL, cal); 3053 {
3054 // optionally try both wide/abbrev and narrow forms
3055 int32_t newStart = 0;
3056 // try wide/abbrev
3057 if( getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, stat us) || count < 5 ) {
3058 if ((newStart = matchString(text, start, UCAL_AM_PM, fSymbols->f AmPms, fSymbols->fAmPmsCount, NULL, cal)) > 0) {
3059 return newStart;
3060 }
3061 }
3062 // try narrow
3063 if( getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, stat us) || count >= 5 ) {
3064 if ((newStart = matchString(text, start, UCAL_AM_PM, fSymbols->f NarrowAmPms, fSymbols->fNarrowAmPmsCount, NULL, cal)) > 0) {
3065 return newStart;
3066 }
3067 }
3068 // no matches for given options
3069 return -start;
3070 }
2985 3071
2986 case UDAT_HOUR1_FIELD: 3072 case UDAT_HOUR1_FIELD:
2987 // [We computed 'value' above.] 3073 // [We computed 'value' above.]
2988 if (value == cal.getLeastMaximum(UCAL_HOUR)+1) 3074 if (value == cal.getLeastMaximum(UCAL_HOUR)+1)
2989 value = 0; 3075 value = 0;
2990 3076
2991 // fall through to set field 3077 // fall through to set field
2992 3078
2993 case UDAT_HOUR0_FIELD: 3079 case UDAT_HOUR0_FIELD:
2994 cal.set(UCAL_HOUR, value); 3080 cal.set(UCAL_HOUR, value);
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
3170 style = UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FULL; 3256 style = UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FULL;
3171 break; 3257 break;
3172 } 3258 }
3173 TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); 3259 TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType);
3174 if (tz != NULL) { 3260 if (tz != NULL) {
3175 cal.adoptTimeZone(tz); 3261 cal.adoptTimeZone(tz);
3176 return pos.getIndex(); 3262 return pos.getIndex();
3177 } 3263 }
3178 return -start; 3264 return -start;
3179 } 3265 }
3266 // currently no pattern character is defined for UDAT_TIME_SEPARATOR_FIELD
3267 // so we should not get here. Leave support in for future definition.
3268 case UDAT_TIME_SEPARATOR_FIELD: //
3269 {
3270 static const UChar def_sep = DateFormatSymbols::DEFAULT_TIME_SEPARAT OR;
3271 static const UChar alt_sep = DateFormatSymbols::ALTERNATE_TIME_SEPAR ATOR;
3272
3273 // Try matching a time separator.
3274 int32_t count = 1;
3275 UnicodeString data[3];
3276 fSymbols->getTimeSeparatorString(data[0]);
3277
3278 // Add the default, if different from the locale.
3279 if (data[0].compare(&def_sep, 1) != 0) {
3280 data[count++].setTo(def_sep);
3281 }
3282
3283 // If lenient, add also the alternate, if different from the locale.
3284 if (isLenient() && data[0].compare(&alt_sep, 1) != 0) {
3285 data[count++].setTo(alt_sep);
3286 }
3287
3288 return matchString(text, start, UCAL_FIELD_COUNT /* => nothing to se t */, data, count, NULL, cal);
3289 }
3180 3290
3181 default: 3291 default:
3182 // Handle "generic" fields 3292 // Handle "generic" fields
3183 // this is now handled below, outside the switch block 3293 // this is now handled below, outside the switch block
3184 break; 3294 break;
3185 } 3295 }
3186 // Handle "generic" fields: 3296 // Handle "generic" fields:
3187 // switch default case now handled here (outside switch block) to allow 3297 // switch default case now handled here (outside switch block) to allow
3188 // parsing of some string fields as digits for lenient case 3298 // parsing of some string fields as digits for lenient case
3189 3299
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
3309 } 3419 }
3310 3420
3311 //---------------------------------------------------------------------- 3421 //----------------------------------------------------------------------
3312 3422
3313 void SimpleDateFormat::translatePattern(const UnicodeString& originalPattern, 3423 void SimpleDateFormat::translatePattern(const UnicodeString& originalPattern,
3314 UnicodeString& translatedPattern, 3424 UnicodeString& translatedPattern,
3315 const UnicodeString& from, 3425 const UnicodeString& from,
3316 const UnicodeString& to, 3426 const UnicodeString& to,
3317 UErrorCode& status) 3427 UErrorCode& status)
3318 { 3428 {
3319 // run through the pattern and convert any pattern symbols from the version 3429 // run through the pattern and convert any pattern symbols from the version
3320 // in "from" to the corresponding character ion "to". This code takes 3430 // in "from" to the corresponding character ion "to". This code takes
3321 // quoted strings into account (it doesn't try to translate them), and it sign als 3431 // quoted strings into account (it doesn't try to translate them), and it si gnals
3322 // an error if a particular "pattern character" doesn't appear in "from". 3432 // an error if a particular "pattern character" doesn't appear in "from".
3323 // Depending on the values of "from" and "to" this can convert from generic 3433 // Depending on the values of "from" and "to" this can convert from generic
3324 // to localized patterns or localized to generic. 3434 // to localized patterns or localized to generic.
3325 if (U_FAILURE(status)) 3435 if (U_FAILURE(status)) {
3326 return; 3436 return;
3437 }
3327 3438
3328 translatedPattern.remove(); 3439 translatedPattern.remove();
3329 UBool inQuote = FALSE; 3440 UBool inQuote = FALSE;
3330 for (int32_t i = 0; i < originalPattern.length(); ++i) { 3441 for (int32_t i = 0; i < originalPattern.length(); ++i) {
3331 UChar c = originalPattern[i]; 3442 UChar c = originalPattern[i];
3443 if (inQuote) {
3444 if (c == QUOTE) {
3445 inQuote = FALSE;
3446 }
3447 } else {
3448 if (c == QUOTE) {
3449 inQuote = TRUE;
3450 } else if (isSyntaxChar(c)) {
3451 int32_t ci = from.indexOf(c);
3452 if (ci == -1) {
3453 status = U_INVALID_FORMAT_ERROR;
3454 return;
3455 }
3456 c = to[ci];
3457 }
3458 }
3459 translatedPattern += c;
3460 }
3332 if (inQuote) { 3461 if (inQuote) {
3333 if (c == QUOTE) 3462 status = U_INVALID_FORMAT_ERROR;
3334 inQuote = FALSE; 3463 return;
3335 } 3464 }
3336 else {
3337 if (c == QUOTE)
3338 inQuote = TRUE;
3339 else if ((c >= 0x0061 /*'a'*/ && c <= 0x007A) /*'z'*/
3340 || (c >= 0x0041 /*'A'*/ && c <= 0x005A /*'Z'*/)) {
3341 int32_t ci = from.indexOf(c);
3342 if (ci == -1) {
3343 status = U_INVALID_FORMAT_ERROR;
3344 return;
3345 }
3346 c = to[ci];
3347 }
3348 }
3349 translatedPattern += c;
3350 }
3351 if (inQuote) {
3352 status = U_INVALID_FORMAT_ERROR;
3353 return;
3354 }
3355 } 3465 }
3356 3466
3357 //---------------------------------------------------------------------- 3467 //----------------------------------------------------------------------
3358 3468
3359 UnicodeString& 3469 UnicodeString&
3360 SimpleDateFormat::toPattern(UnicodeString& result) const 3470 SimpleDateFormat::toPattern(UnicodeString& result) const
3361 { 3471 {
3362 result = fPattern; 3472 result = fPattern;
3363 return result; 3473 return result;
3364 } 3474 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
3440 delete fTimeZoneFormat; 3550 delete fTimeZoneFormat;
3441 fTimeZoneFormat = new TimeZoneFormat(newTimeZoneFormat); 3551 fTimeZoneFormat = new TimeZoneFormat(newTimeZoneFormat);
3442 } 3552 }
3443 3553
3444 //---------------------------------------------------------------------- 3554 //----------------------------------------------------------------------
3445 3555
3446 3556
3447 void SimpleDateFormat::adoptCalendar(Calendar* calendarToAdopt) 3557 void SimpleDateFormat::adoptCalendar(Calendar* calendarToAdopt)
3448 { 3558 {
3449 UErrorCode status = U_ZERO_ERROR; 3559 UErrorCode status = U_ZERO_ERROR;
3560 Locale calLocale(fLocale);
3561 calLocale.setKeywordValue("calendar", calendarToAdopt->getType(), status);
3562 DateFormatSymbols *newSymbols =
3563 DateFormatSymbols::createForLocale(calLocale, status);
3564 if (U_FAILURE(status)) {
3565 return;
3566 }
3450 DateFormat::adoptCalendar(calendarToAdopt); 3567 DateFormat::adoptCalendar(calendarToAdopt);
3451 delete fSymbols; 3568 delete fSymbols;
3452 fSymbols=NULL; 3569 fSymbols = newSymbols;
3453 initializeSymbols(fLocale, fCalendar, status); // we need new symbols
3454 initializeDefaultCentury(); // we need a new century (possibly) 3570 initializeDefaultCentury(); // we need a new century (possibly)
3455 } 3571 }
3456 3572
3457 3573
3458 //---------------------------------------------------------------------- 3574 //----------------------------------------------------------------------
3459 3575
3460 3576
3461 // override the DateFormat implementation in order to 3577 // override the DateFormat implementation in order to
3462 // lazily initialize fCapitalizationBrkIter 3578 // lazily initialize fCapitalizationBrkIter
3463 void 3579 void
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3495 int32_t fieldLevel = fgCalendarFieldToLevel[field]; 3611 int32_t fieldLevel = fgCalendarFieldToLevel[field];
3496 int32_t level; 3612 int32_t level;
3497 UChar ch; 3613 UChar ch;
3498 UBool inQuote = FALSE; 3614 UBool inQuote = FALSE;
3499 UChar prevCh = 0; 3615 UChar prevCh = 0;
3500 int32_t count = 0; 3616 int32_t count = 0;
3501 3617
3502 for (int32_t i = 0; i < pattern.length(); ++i) { 3618 for (int32_t i = 0; i < pattern.length(); ++i) {
3503 ch = pattern[i]; 3619 ch = pattern[i];
3504 if (ch != prevCh && count > 0) { 3620 if (ch != prevCh && count > 0) {
3505 level = fgPatternCharToLevel[prevCh - PATTERN_CHAR_BASE]; 3621 level = getLevelFromChar(prevCh);
3506 // the larger the level, the smaller the field unit. 3622 // the larger the level, the smaller the field unit.
3507 if ( fieldLevel <= level ) { 3623 if (fieldLevel <= level) {
3508 return FALSE; 3624 return FALSE;
3509 } 3625 }
3510 count = 0; 3626 count = 0;
3511 } 3627 }
3512 if (ch == QUOTE) { 3628 if (ch == QUOTE) {
3513 if ((i+1) < pattern.length() && pattern[i+1] == QUOTE) { 3629 if ((i+1) < pattern.length() && pattern[i+1] == QUOTE) {
3514 ++i; 3630 ++i;
3515 } else { 3631 } else {
3516 inQuote = ! inQuote; 3632 inQuote = ! inQuote;
3517 } 3633 }
3518 } 3634 }
3519 else if ( ! inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/) 3635 else if (!inQuote && isSyntaxChar(ch)) {
3520 || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
3521 prevCh = ch; 3636 prevCh = ch;
3522 ++count; 3637 ++count;
3523 } 3638 }
3524 } 3639 }
3525 if ( count > 0 ) { 3640 if (count > 0) {
3526 // last item 3641 // last item
3527 level = fgPatternCharToLevel[prevCh - PATTERN_CHAR_BASE]; 3642 level = getLevelFromChar(prevCh);
3528 if ( fieldLevel <= level ) { 3643 if (fieldLevel <= level) {
3529 return FALSE; 3644 return FALSE;
3530 } 3645 }
3531 } 3646 }
3532 return TRUE; 3647 return TRUE;
3533 } 3648 }
3534 3649
3535 //---------------------------------------------------------------------- 3650 //----------------------------------------------------------------------
3536 3651
3537 const Locale& 3652 const Locale&
3538 SimpleDateFormat::getSmpFmtLocale(void) const { 3653 SimpleDateFormat::getSmpFmtLocale(void) const {
3539 return fLocale; 3654 return fLocale;
3540 } 3655 }
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
3701 umtx_unlock(&LOCK); 3816 umtx_unlock(&LOCK);
3702 } 3817 }
3703 return fTimeZoneFormat; 3818 return fTimeZoneFormat;
3704 } 3819 }
3705 3820
3706 U_NAMESPACE_END 3821 U_NAMESPACE_END
3707 3822
3708 #endif /* #if !UCONFIG_NO_FORMATTING */ 3823 #endif /* #if !UCONFIG_NO_FORMATTING */
3709 3824
3710 //eof 3825 //eof
OLDNEW
« no previous file with comments | « source/i18n/smallintformatter.cpp ('k') | source/i18n/timezone.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698