| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011,2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2011,2012 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 #include "core/platform/text/PlatformLocale.h" | 32 #include "platform/text/PlatformLocale.h" |
| 33 | 33 |
| 34 #include "platform/LocalizedStrings.h" | 34 #include "platform/LocalizedStrings.h" |
| 35 #include "platform/text/DateTimeFormat.h" | 35 #include "platform/text/DateTimeFormat.h" |
| 36 #include "public/platform/Platform.h" | 36 #include "public/platform/Platform.h" |
| 37 #include "wtf/MainThread.h" | 37 #include "wtf/MainThread.h" |
| 38 #include "wtf/text/StringBuilder.h" | 38 #include "wtf/text/StringBuilder.h" |
| 39 | 39 |
| 40 namespace WebCore { | 40 namespace WebCore { |
| 41 | 41 |
| 42 using WebKit::Platform; | 42 using WebKit::Platform; |
| 43 using WebKit::WebLocalizedString; | 43 using WebKit::WebLocalizedString; |
| 44 | 44 |
| 45 class DateTimeStringBuilder : private DateTimeFormat::TokenHandler { | 45 class DateTimeStringBuilder : private DateTimeFormat::TokenHandler { |
| 46 WTF_MAKE_NONCOPYABLE(DateTimeStringBuilder); | 46 WTF_MAKE_NONCOPYABLE(DateTimeStringBuilder); |
| 47 | |
| 48 public: | 47 public: |
| 49 // The argument objects must be alive until this object dies. | 48 // The argument objects must be alive until this object dies. |
| 50 DateTimeStringBuilder(Locale&, const DateComponents&); | 49 DateTimeStringBuilder(Locale&, const DateComponents&); |
| 51 | 50 |
| 52 bool build(const String&); | 51 bool build(const String&); |
| 53 String toString(); | 52 String toString(); |
| 54 | 53 |
| 55 private: | 54 private: |
| 56 // DateTimeFormat::TokenHandler functions. | 55 // DateTimeFormat::TokenHandler functions. |
| 57 virtual void visitField(DateTimeFormat::FieldType, int) OVERRIDE FINAL; | 56 virtual void visitField(DateTimeFormat::FieldType, int) OVERRIDE FINAL; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 } | 95 } |
| 97 | 96 |
| 98 void DateTimeStringBuilder::visitField(DateTimeFormat::FieldType fieldType, int
numberOfPatternCharacters) | 97 void DateTimeStringBuilder::visitField(DateTimeFormat::FieldType fieldType, int
numberOfPatternCharacters) |
| 99 { | 98 { |
| 100 switch (fieldType) { | 99 switch (fieldType) { |
| 101 case DateTimeFormat::FieldTypeYear: | 100 case DateTimeFormat::FieldTypeYear: |
| 102 // Always use padding width of 4 so it matches DateTimeEditElement. | 101 // Always use padding width of 4 so it matches DateTimeEditElement. |
| 103 appendNumber(m_date.fullYear(), 4); | 102 appendNumber(m_date.fullYear(), 4); |
| 104 return; | 103 return; |
| 105 case DateTimeFormat::FieldTypeMonth: | 104 case DateTimeFormat::FieldTypeMonth: |
| 106 if (numberOfPatternCharacters == 3) | 105 if (numberOfPatternCharacters == 3) { |
| 107 m_builder.append(m_localizer.shortMonthLabels()[m_date.month()]); | 106 m_builder.append(m_localizer.shortMonthLabels()[m_date.month()]); |
| 108 else if (numberOfPatternCharacters == 4) | 107 } else if (numberOfPatternCharacters == 4) { |
| 109 m_builder.append(m_localizer.monthLabels()[m_date.month()]); | 108 m_builder.append(m_localizer.monthLabels()[m_date.month()]); |
| 110 else { | 109 } else { |
| 111 // Always use padding width of 2 so it matches DateTimeEditElement. | 110 // Always use padding width of 2 so it matches DateTimeEditElement. |
| 112 appendNumber(m_date.month() + 1, 2); | 111 appendNumber(m_date.month() + 1, 2); |
| 113 } | 112 } |
| 114 return; | 113 return; |
| 115 case DateTimeFormat::FieldTypeMonthStandAlone: | 114 case DateTimeFormat::FieldTypeMonthStandAlone: |
| 116 if (numberOfPatternCharacters == 3) | 115 if (numberOfPatternCharacters == 3) { |
| 117 m_builder.append(m_localizer.shortStandAloneMonthLabels()[m_date.mon
th()]); | 116 m_builder.append(m_localizer.shortStandAloneMonthLabels()[m_date.mon
th()]); |
| 118 else if (numberOfPatternCharacters == 4) | 117 } else if (numberOfPatternCharacters == 4) { |
| 119 m_builder.append(m_localizer.standAloneMonthLabels()[m_date.month()]
); | 118 m_builder.append(m_localizer.standAloneMonthLabels()[m_date.month()]
); |
| 120 else { | 119 } else { |
| 121 // Always use padding width of 2 so it matches DateTimeEditElement. | 120 // Always use padding width of 2 so it matches DateTimeEditElement. |
| 122 appendNumber(m_date.month() + 1, 2); | 121 appendNumber(m_date.month() + 1, 2); |
| 123 } | 122 } |
| 124 return; | 123 return; |
| 125 case DateTimeFormat::FieldTypeDayOfMonth: | 124 case DateTimeFormat::FieldTypeDayOfMonth: |
| 126 // Always use padding width of 2 so it matches DateTimeEditElement. | 125 // Always use padding width of 2 so it matches DateTimeEditElement. |
| 127 appendNumber(m_date.monthDay(), 2); | 126 appendNumber(m_date.monthDay(), 2); |
| 128 return; | 127 return; |
| 129 case DateTimeFormat::FieldTypeWeekOfYear: | 128 case DateTimeFormat::FieldTypeWeekOfYear: |
| 130 // Always use padding width of 2 so it matches DateTimeEditElement. | 129 // Always use padding width of 2 so it matches DateTimeEditElement. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 150 int hour24 = m_date.hour(); | 149 int hour24 = m_date.hour(); |
| 151 if (!hour24) | 150 if (!hour24) |
| 152 hour24 = 24; | 151 hour24 = 24; |
| 153 appendNumber(hour24, numberOfPatternCharacters); | 152 appendNumber(hour24, numberOfPatternCharacters); |
| 154 return; | 153 return; |
| 155 } | 154 } |
| 156 case DateTimeFormat::FieldTypeMinute: | 155 case DateTimeFormat::FieldTypeMinute: |
| 157 appendNumber(m_date.minute(), numberOfPatternCharacters); | 156 appendNumber(m_date.minute(), numberOfPatternCharacters); |
| 158 return; | 157 return; |
| 159 case DateTimeFormat::FieldTypeSecond: | 158 case DateTimeFormat::FieldTypeSecond: |
| 160 if (!m_date.millisecond()) | 159 if (!m_date.millisecond()) { |
| 161 appendNumber(m_date.second(), numberOfPatternCharacters); | 160 appendNumber(m_date.second(), numberOfPatternCharacters); |
| 162 else { | 161 } else { |
| 163 double second = m_date.second() + m_date.millisecond() / 1000.0; | 162 double second = m_date.second() + m_date.millisecond() / 1000.0; |
| 164 String zeroPaddedSecondString = zeroPadString(String::format("%.03f"
, second), numberOfPatternCharacters + 4); | 163 String zeroPaddedSecondString = zeroPadString(String::format("%.03f"
, second), numberOfPatternCharacters + 4); |
| 165 m_builder.append(m_localizer.convertToLocalizedNumber(zeroPaddedSeco
ndString)); | 164 m_builder.append(m_localizer.convertToLocalizedNumber(zeroPaddedSeco
ndString)); |
| 166 } | 165 } |
| 167 return; | 166 return; |
| 168 default: | 167 default: |
| 169 return; | 168 return; |
| 170 } | 169 } |
| 171 } | 170 } |
| 172 | 171 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 | 257 |
| 259 unsigned i = 0; | 258 unsigned i = 0; |
| 260 bool isNegative = false; | 259 bool isNegative = false; |
| 261 StringBuilder builder; | 260 StringBuilder builder; |
| 262 builder.reserveCapacity(input.length()); | 261 builder.reserveCapacity(input.length()); |
| 263 | 262 |
| 264 if (input[0] == '-') { | 263 if (input[0] == '-') { |
| 265 ++i; | 264 ++i; |
| 266 isNegative = true; | 265 isNegative = true; |
| 267 builder.append(m_negativePrefix); | 266 builder.append(m_negativePrefix); |
| 268 } else | 267 } else { |
| 269 builder.append(m_positivePrefix); | 268 builder.append(m_positivePrefix); |
| 269 } |
| 270 | 270 |
| 271 for (; i < input.length(); ++i) { | 271 for (; i < input.length(); ++i) { |
| 272 switch (input[i]) { | 272 switch (input[i]) { |
| 273 case '0': | 273 case '0': |
| 274 case '1': | 274 case '1': |
| 275 case '2': | 275 case '2': |
| 276 case '3': | 276 case '3': |
| 277 case '4': | 277 case '4': |
| 278 case '5': | 278 case '5': |
| 279 case '6': | 279 case '6': |
| (...skipping 30 matching lines...) Expand all Loading... |
| 310 | 310 |
| 311 bool Locale::detectSignAndGetDigitRange(const String& input, bool& isNegative, u
nsigned& startIndex, unsigned& endIndex) | 311 bool Locale::detectSignAndGetDigitRange(const String& input, bool& isNegative, u
nsigned& startIndex, unsigned& endIndex) |
| 312 { | 312 { |
| 313 startIndex = 0; | 313 startIndex = 0; |
| 314 endIndex = input.length(); | 314 endIndex = input.length(); |
| 315 if (m_negativePrefix.isEmpty() && m_negativeSuffix.isEmpty()) { | 315 if (m_negativePrefix.isEmpty() && m_negativeSuffix.isEmpty()) { |
| 316 if (input.startsWith(m_positivePrefix) && input.endsWith(m_positiveSuffi
x)) { | 316 if (input.startsWith(m_positivePrefix) && input.endsWith(m_positiveSuffi
x)) { |
| 317 isNegative = false; | 317 isNegative = false; |
| 318 startIndex = m_positivePrefix.length(); | 318 startIndex = m_positivePrefix.length(); |
| 319 endIndex -= m_positiveSuffix.length(); | 319 endIndex -= m_positiveSuffix.length(); |
| 320 } else | 320 } else { |
| 321 isNegative = true; | 321 isNegative = true; |
| 322 } |
| 322 } else { | 323 } else { |
| 323 if (input.startsWith(m_negativePrefix) && input.endsWith(m_negativeSuffi
x)) { | 324 if (input.startsWith(m_negativePrefix) && input.endsWith(m_negativeSuffi
x)) { |
| 324 isNegative = true; | 325 isNegative = true; |
| 325 startIndex = m_negativePrefix.length(); | 326 startIndex = m_negativePrefix.length(); |
| 326 endIndex -= m_negativeSuffix.length(); | 327 endIndex -= m_negativeSuffix.length(); |
| 327 } else { | 328 } else { |
| 328 isNegative = false; | 329 isNegative = false; |
| 329 if (input.startsWith(m_positivePrefix) && input.endsWith(m_positiveS
uffix)) { | 330 if (input.startsWith(m_positivePrefix) && input.endsWith(m_positiveS
uffix)) { |
| 330 startIndex = m_positivePrefix.length(); | 331 startIndex = m_positivePrefix.length(); |
| 331 endIndex -= m_positiveSuffix.length(); | 332 endIndex -= m_positiveSuffix.length(); |
| 332 } else | 333 } else { |
| 333 return false; | 334 return false; |
| 335 } |
| 334 } | 336 } |
| 335 } | 337 } |
| 336 return true; | 338 return true; |
| 337 } | 339 } |
| 338 | 340 |
| 339 unsigned Locale::matchedDecimalSymbolIndex(const String& input, unsigned& positi
on) | 341 unsigned Locale::matchedDecimalSymbolIndex(const String& input, unsigned& positi
on) |
| 340 { | 342 { |
| 341 for (unsigned symbolIndex = 0; symbolIndex < DecimalSymbolsSize; ++symbolInd
ex) { | 343 for (unsigned symbolIndex = 0; symbolIndex < DecimalSymbolsSize; ++symbolInd
ex) { |
| 342 if (m_decimalSymbols[symbolIndex].length() && matches(input, position, m
_decimalSymbols[symbolIndex])) { | 344 if (m_decimalSymbols[symbolIndex].length() && matches(input, position, m
_decimalSymbols[symbolIndex])) { |
| 343 position += m_decimalSymbols[symbolIndex].length(); | 345 position += m_decimalSymbols[symbolIndex].length(); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 builder.build(formatType == FormatTypeShort ? dateTimeFormatWithoutSecon
ds() : dateTimeFormatWithSeconds()); | 412 builder.build(formatType == FormatTypeShort ? dateTimeFormatWithoutSecon
ds() : dateTimeFormatWithSeconds()); |
| 411 break; | 413 break; |
| 412 case DateComponents::Invalid: | 414 case DateComponents::Invalid: |
| 413 ASSERT_NOT_REACHED(); | 415 ASSERT_NOT_REACHED(); |
| 414 break; | 416 break; |
| 415 } | 417 } |
| 416 return builder.toString(); | 418 return builder.toString(); |
| 417 } | 419 } |
| 418 | 420 |
| 419 } | 421 } |
| OLD | NEW |