OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 **)¤tNumberFor
mat, 1); | 2646 numericLeapMonthFormatter->setFormats((const Format **)¤tNumberFor
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |