platform/text/Base64.cpp
platform/text/BidiContext.cpp
+ platform/text/DateTimeFormat.cpp
platform/text/Hyphenation.cpp
platform/text/LineEnding.cpp
platform/text/LocaleToScriptMappingDefault.cpp
+2012-06-29 Yoshifumi Inoue <yosin@chromium.org>
+
+ [Platform] Implement Date Time format parser
+ https://bugs.webkit.org/show_bug.cgi?id=89963
+
+ Reviewed by Kent Tamura.
+
+ This patch introduces Unicode TR35 LDML date time format parser for
+ input type "time" if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) is true.
+
+ Test: WebKit/chromium/tests/DateTimeFormatTest.cpp
+
+ * CMakeLists.txt: Added DateTimeFormat.cpp
+ * GNUmakefile.list.am: Added DateTimeFormat.{cpp,h}
+ * Target.pri: ditto
+ * WebCore.gypi: ditto
+ * WebCore.vcproj/WebCore.vcproj: ditto
+ * WebCore.xcodeproj/product.pbxproj: ditto
+ * platform/text/DateTimeFormat.cpp: Added.
+ (WebCore::mapCharacterToFieldTypeInternal):
+ (WebCore::DateTimeFormat::DateTimeFormat):
+ (WebCore::DateTimeFormat::mapCharacterToFieldType):
+ (WebCore::DateTimeFormat::parse):
+ * platform/text/DateTimeFormat.h: Added.
+ (DateTimeFormat):
+ (TokenHandler):
+ (WebCore::DateTimeFormat::TokenHandler::~TokenHandler):
+
2012-06-29 Eric Seidel <eric@webkit.org>
Remove more BUILDING_ON_LEOPARD usage in PLATFORM(MAC) code
Source/WebCore/platform/text/BidiContext.h \
Source/WebCore/platform/text/BidiResolver.h \
Source/WebCore/platform/text/BidiRunList.h \
+ Source/WebCore/platform/text/DateTimeFormat.cpp \
+ Source/WebCore/platform/text/DateTimeFormat.h \
Source/WebCore/platform/text/DecodeEscapeSequences.h \
Source/WebCore/platform/text/Hyphenation.cpp \
Source/WebCore/platform/text/Hyphenation.h \
platform/Arena.cpp \
platform/text/Base64.cpp \
platform/text/BidiContext.cpp \
+ platform/text/DateTimeFormat.cpp \
platform/text/Hyphenation.cpp \
platform/text/LocaleToScriptMappingDefault.cpp \
platform/text/LocalizedDateNone.cpp \
platform/sql/SQLValue.h \
platform/text/Base64.h \
platform/text/BidiContext.h \
+ platform/text/DateTimeFormat.h \
platform/text/DecodeEscapeSequences.h \
platform/text/Hyphenation.h \
platform/text/QuotedPrintable.h \
'platform/text/BidiRunList.h',
'platform/text/BidiContext.h',
'platform/text/BidiResolver.h',
+ 'platform/text/DateTimeFormat.h',
'platform/text/DecodeEscapeSequences.h',
'platform/text/LineBreakIteratorPoolICU.h',
'platform/text/LineEnding.h',
'platform/text/AtomicStringKeyedMRUCache.h',
'platform/text/Base64.cpp',
'platform/text/BidiContext.cpp',
+ 'platform/text/DateTimeFormat.cpp',
'platform/text/Hyphenation.cpp',
'platform/text/Hyphenation.h',
'platform/text/LineEnding.cpp',
>
</File>
<File
+ RelativePath="..\platform\text\DateTimeFormat.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\platform\text\DateTimeFormat.h"
+ >
+ </File>
+ <File
RelativePath="..\platform\text\DecodeEscapeSequences.h"
>
</File>
45099C411370A7800058D513 /* IconURL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45099C401370A7800058D513 /* IconURL.cpp */; };
450CEBF015073BBE002BB149 /* LabelableElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 450CEBEE15073BBE002BB149 /* LabelableElement.cpp */; };
450CEBF115073BBE002BB149 /* LabelableElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 450CEBEF15073BBE002BB149 /* LabelableElement.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 453EB636159C570400001BB7 /* DateTimeFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 453EB634159C570400001BB7 /* DateTimeFormat.cpp */; };
+ 453EB637159C570400001BB7 /* DateTimeFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 453EB635159C570400001BB7 /* DateTimeFormat.h */; settings = {ATTRIBUTES = (Private, ); }; };
458FE4091589DF0B005609E6 /* RenderSearchField.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 458FE4071589DF0B005609E6 /* RenderSearchField.cpp */; };
458FE40A1589DF0B005609E6 /* RenderSearchField.h in Headers */ = {isa = PBXBuildFile; fileRef = 458FE4081589DF0B005609E6 /* RenderSearchField.h */; };
45BAC2B01360BBAB005DA258 /* IconURL.h in Headers */ = {isa = PBXBuildFile; fileRef = 45BAC2AF1360BBAB005DA258 /* IconURL.h */; settings = {ATTRIBUTES = (Private, ); }; };
45099C401370A7800058D513 /* IconURL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IconURL.cpp; sourceTree = "<group>"; };
450CEBEE15073BBE002BB149 /* LabelableElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LabelableElement.cpp; sourceTree = "<group>"; };
450CEBEF15073BBE002BB149 /* LabelableElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelableElement.h; sourceTree = "<group>"; };
+ 453EB634159C570400001BB7 /* DateTimeFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DateTimeFormat.cpp; sourceTree = "<group>"; };
+ 453EB635159C570400001BB7 /* DateTimeFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateTimeFormat.h; sourceTree = "<group>"; };
458FE4071589DF0B005609E6 /* RenderSearchField.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSearchField.cpp; sourceTree = "<group>"; };
458FE4081589DF0B005609E6 /* RenderSearchField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSearchField.h; sourceTree = "<group>"; };
45BAC2AF1360BBAB005DA258 /* IconURL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IconURL.h; sourceTree = "<group>"; };
B2C3D9F30D006C1D00EF6F26 /* BidiContext.h */,
B2C3D9F40D006C1D00EF6F26 /* BidiResolver.h */,
A8C402921348B2220063F1E5 /* BidiRunList.h */,
+ 453EB634159C570400001BB7 /* DateTimeFormat.cpp */,
+ 453EB635159C570400001BB7 /* DateTimeFormat.h */,
CECCFC3A141973D5002A0AC1 /* DecodeEscapeSequences.h */,
375CD231119D43C800A2A859 /* Hyphenation.h */,
A5ABB78613B904BC00F197E3 /* LineBreakIteratorPoolICU.h */,
81AC599A131636E60009A7E0 /* DataTransferItemList.h in Headers */,
2E97CCEB12939CB800C5C8FF /* DataView.h in Headers */,
A5732B0B136A161D005C8D7C /* DateComponents.h in Headers */,
+ 453EB637159C570400001BB7 /* DateTimeFormat.h in Headers */,
F55B3DB61251F12D003EF269 /* DateInputType.h in Headers */,
F55B3DB81251F12D003EF269 /* DateTimeInputType.h in Headers */,
F55B3DBA1251F12D003EF269 /* DateTimeLocalInputType.h in Headers */,
2E97CCEA12939CB800C5C8FF /* DataView.cpp in Sources */,
A5732B0A136A161D005C8D7C /* DateComponents.cpp in Sources */,
F55B3DB51251F12D003EF269 /* DateInputType.cpp in Sources */,
+ 453EB636159C570400001BB7 /* DateTimeFormat.cpp in Sources */,
F55B3DB71251F12D003EF269 /* DateTimeInputType.cpp in Sources */,
F55B3DB91251F12D003EF269 /* DateTimeLocalInputType.cpp in Sources */,
45FEA5CF156DDE8C00654101 /* Decimal.cpp in Sources */,
--- /dev/null
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DateTimeFormat.h"
+
+#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
+#include <wtf/ASCIICType.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+static const DateTimeFormat::FieldType lowerCaseToFieldTypeMap[26] = {
+ DateTimeFormat::FieldTypePeriod, // a
+ DateTimeFormat::FieldTypeInvalid, // b
+ DateTimeFormat::FieldTypeLocalDayOfWeekStandAlon, // c
+ DateTimeFormat::FieldTypeDayOfMonth, // d
+ DateTimeFormat::FieldTypeLocalDayOfWeek, // e
+ DateTimeFormat::FieldTypeInvalid, // f
+ DateTimeFormat::FieldTypeModifiedJulianDay, // g
+ DateTimeFormat::FieldTypeHour12, // h
+ DateTimeFormat::FieldTypeInvalid, // i
+ DateTimeFormat::FieldTypeInvalid, // j
+ DateTimeFormat::FieldTypeHour24, // k
+ DateTimeFormat::FieldTypeInvalid, // l
+ DateTimeFormat::FieldTypeMinute, // m
+ DateTimeFormat::FieldTypeInvalid, // n
+ DateTimeFormat::FieldTypeInvalid, // o
+ DateTimeFormat::FieldTypeInvalid, // p
+ DateTimeFormat::FieldTypeQuaterStandAlone, // q
+ DateTimeFormat::FieldTypeInvalid, // r
+ DateTimeFormat::FieldTypeSecond, // s
+ DateTimeFormat::FieldTypeInvalid, // t
+ DateTimeFormat::FieldTypeExtendedYear, // u
+ DateTimeFormat::FieldTypeNonLocationZone, // v
+ DateTimeFormat::FieldTypeWeekOfMonth, // w
+ DateTimeFormat::FieldTypeInvalid, // x
+ DateTimeFormat::FieldTypeYear, // y
+ DateTimeFormat::FieldTypeZone, // z
+};
+
+static const DateTimeFormat::FieldType upperCaseToFieldTypeMap[26] = {
+ DateTimeFormat::FieldTypeMillisecondsInDay, // A
+ DateTimeFormat::FieldTypeInvalid, // B
+ DateTimeFormat::FieldTypeInvalid, // C
+ DateTimeFormat::FieldTypeDayOfYear, // D
+ DateTimeFormat::FieldTypeDayOfWeek, // E
+ DateTimeFormat::FieldTypeDayOfWeekInMonth, // F
+ DateTimeFormat::FieldTypeEra, // G
+ DateTimeFormat::FieldTypeHour23, // H
+ DateTimeFormat::FieldTypeInvalid, // I
+ DateTimeFormat::FieldTypeInvalid, // J
+ DateTimeFormat::FieldTypeHour11, // K
+ DateTimeFormat::FieldTypeMonthStandAlone, // L
+ DateTimeFormat::FieldTypeMonth, // M
+ DateTimeFormat::FieldTypeInvalid, // N
+ DateTimeFormat::FieldTypeInvalid, // O
+ DateTimeFormat::FieldTypeInvalid, // P
+ DateTimeFormat::FieldTypeQuater, // Q
+ DateTimeFormat::FieldTypeInvalid, // R
+ DateTimeFormat::FieldTypeFractionalSecond, // S
+ DateTimeFormat::FieldTypeInvalid, // T
+ DateTimeFormat::FieldTypeInvalid, // U
+ DateTimeFormat::FieldTypeInvalid, // V
+ DateTimeFormat::FieldTypeWeekOfYear, // W
+ DateTimeFormat::FieldTypeInvalid, // X
+ DateTimeFormat::FieldTypeYearOfWeekOfYear, // Y
+ DateTimeFormat::FieldTypeRFC822Zone, // Z
+};
+
+static DateTimeFormat::FieldType mapCharacterToFieldType(const UChar ch)
+{
+ if (isASCIIUpper(ch))
+ return upperCaseToFieldTypeMap[ch - 'A'];
+
+ if (isASCIILower(ch))
+ return lowerCaseToFieldTypeMap[ch - 'a'];
+
+ return DateTimeFormat::FieldTypeLiteral;
+}
+
+bool DateTimeFormat::parse(const String& source, TokenHandler& tokenHandler)
+{
+ enum State {
+ StateInQuote,
+ StateInQuoteQuote,
+ StateLiteral,
+ StateQuote,
+ StateSymbol,
+ } state = StateLiteral;
+
+ FieldType fieldType = FieldTypeLiteral;
+ StringBuilder literalBuffer;
+ int fieldCounter = 0;
+
+ for (unsigned int index = 0; index < source.length(); ++index) {
+ const UChar ch = source[index];
+ switch (state) {
+ case StateInQuote:
+ if (ch == '\'') {
+ state = StateInQuoteQuote;
+ break;
+ }
+
+ literalBuffer.append(ch);
+ break;
+
+ case StateInQuoteQuote:
+ if (ch == '\'') {
+ literalBuffer.append('\'');
+ state = StateInQuote;
+ break;
+ }
+
+ fieldType = mapCharacterToFieldType(ch);
+ if (fieldType == FieldTypeInvalid)
+ return false;
+
+ if (fieldType == FieldTypeLiteral) {
+ literalBuffer.append(ch);
+ state = StateLiteral;
+ break;
+ }
+
+ if (literalBuffer.length()) {
+ tokenHandler.visitLiteral(literalBuffer.toString());
+ literalBuffer.clear();
+ }
+
+ fieldCounter = 1;
+ state = StateSymbol;
+ break;
+
+ case StateLiteral:
+ if (ch == '\'') {
+ state = StateQuote;
+ break;
+ }
+
+ fieldType = mapCharacterToFieldType(ch);
+ if (fieldType == FieldTypeInvalid)
+ return false;
+
+ if (fieldType == FieldTypeLiteral) {
+ literalBuffer.append(ch);
+ break;
+ }
+
+ if (literalBuffer.length()) {
+ tokenHandler.visitLiteral(literalBuffer.toString());
+ literalBuffer.clear();
+ }
+
+ fieldCounter = 1;
+ state = StateSymbol;
+ break;
+
+ case StateQuote:
+ literalBuffer.append(ch);
+ state = ch == '\'' ? StateLiteral : StateInQuote;
+ break;
+
+ case StateSymbol: {
+ ASSERT(fieldType != FieldTypeInvalid);
+ ASSERT(fieldType != FieldTypeLiteral);
+ ASSERT(literalBuffer.isEmpty());
+
+ FieldType fieldType2 = mapCharacterToFieldType(ch);
+ if (fieldType2 == FieldTypeInvalid)
+ return false;
+
+ if (fieldType == fieldType2) {
+ ++fieldCounter;
+ break;
+ }
+
+ tokenHandler.visitField(fieldType, fieldCounter);
+
+ if (fieldType2 == FieldTypeLiteral) {
+ if (ch == '\'')
+ state = StateQuote;
+ else {
+ literalBuffer.append(ch);
+ state = StateLiteral;
+ }
+ break;
+ }
+
+ fieldCounter = 1;
+ fieldType = fieldType2;
+ break;
+ }
+ }
+ }
+
+ ASSERT(fieldType != FieldTypeInvalid);
+
+ switch (state) {
+ case StateLiteral:
+ case StateInQuoteQuote:
+ if (literalBuffer.length())
+ tokenHandler.visitLiteral(literalBuffer.toString());
+ return true;
+
+ case StateQuote:
+ case StateInQuote:
+ if (literalBuffer.length())
+ tokenHandler.visitLiteral(literalBuffer.toString());
+ return false;
+
+ case StateSymbol:
+ ASSERT(fieldType != FieldTypeLiteral);
+ ASSERT(!literalBuffer.length());
+ tokenHandler.visitField(fieldType, fieldCounter);
+ return true;
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+} // namespace WebCore
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef DateTimeFormat_h
+#define DateTimeFormat_h
+
+#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+// DateTimeFormat parses date time format defined in Unicode Technical
+// standard 35, Locale Data Markup Language (LDML)[1].
+// [1] LDML http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns
+class DateTimeFormat {
+public:
+ enum FieldType {
+ FieldTypeInvalid,
+ FieldTypeLiteral,
+
+ // Era: AD
+ FieldTypeEra = 'G',
+
+ // Year: 1996
+ FieldTypeYear = 'y',
+ FieldTypeYearOfWeekOfYear = 'Y',
+ FieldTypeExtendedYear = 'u',
+
+ // Quater: Q2
+ FieldTypeQuater = 'Q',
+ FieldTypeQuaterStandAlone = 'q',
+
+ // Month: September
+ FieldTypeMonth = 'M',
+ FieldTypeMonthStandAlone = 'L',
+
+ // Week: 42
+ FieldTypeWeekOfYear = 'W',
+ FieldTypeWeekOfMonth = 'w',
+
+ // Day: 12
+ FieldTypeDayOfMonth = 'd',
+ FieldTypeDayOfYear = 'D',
+ FieldTypeDayOfWeekInMonth = 'F',
+ FieldTypeModifiedJulianDay = 'g',
+
+ // Week Day: Tuesday
+ FieldTypeDayOfWeek = 'E',
+ FieldTypeLocalDayOfWeek = 'e',
+ FieldTypeLocalDayOfWeekStandAlon = 'c',
+
+ // Period: AM or PM
+ FieldTypePeriod = 'a',
+
+ // Hour: 7
+ FieldTypeHour12 = 'h',
+ FieldTypeHour23 = 'H',
+ FieldTypeHour11 = 'K',
+ FieldTypeHour24 = 'k',
+
+ // Minute: 59
+ FieldTypeMinute = 'm',
+
+ // Second: 12
+ FieldTypeSecond = 's',
+ FieldTypeFractionalSecond = 'S',
+ FieldTypeMillisecondsInDay = 'A',
+
+ // Zone: PDT
+ FieldTypeZone = 'z',
+ FieldTypeRFC822Zone = 'Z',
+ FieldTypeNonLocationZone = 'v',
+ };
+
+ class TokenHandler {
+ public:
+ virtual ~TokenHandler() { }
+ virtual void visitField(FieldType, int numberOfPatternCharacters) = 0;
+ virtual void visitLiteral(const String&) = 0;
+ };
+
+ // Returns true if succeeded, false if failed.
+ static bool parse(const String&, TokenHandler&);
+};
+
+} // namespace WebCore
+
+#endif
+
+#endif // DateTimeFormat_h
+2012-06-29 Yoshifumi Inoue <yosin@chromium.org>
+
+ [Platform] Implement Date Time format parser
+ https://bugs.webkit.org/show_bug.cgi?id=89963
+
+ Reviewed by Kent Tamura.
+
+ This patch adds an unit test for date time format parser if
+ ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) is true.
+
+ * tests/DateTimeFormatTest.cpp: Added.
+ (DateTimeFormatTest):
+ (Token):
+ (DateTimeFormatTest::Token::Token):
+ (DateTimeFormatTest::Token::operator==):
+ (DateTimeFormatTest::Token::toString):
+ (Tokens):
+ (DateTimeFormatTest::Tokens::Tokens):
+ (DateTimeFormatTest::Tokens::operator==):
+ (DateTimeFormatTest::Tokens::toString):
+ (DateTimeFormatTest::parse):
+ (DateTimeFormatTest::single):
+ (TokenHandler):
+ (DateTimeFormatTest::TokenHandler::~TokenHandler):
+ (DateTimeFormatTest::TokenHandler::fieldType):
+ (DateTimeFormatTest::TokenHandler::tokens):
+ (DateTimeFormatTest::TokenHandler::visitField):
+ (DateTimeFormatTest::TokenHandler::visitLiteral):
+ (operator<<):
+ (TEST_F):
+
2012-06-28 Joshua Bell <jsbell@chromium.org>
IndexedDB: Implement IDBTransaction internal active flag
'tests/CCTimerTest.cpp',
'tests/ClipboardChromiumTest.cpp',
'tests/CompositorFakeWebGraphicsContext3D.h',
+ 'tests/DateTimeFormatTest.cpp',
'tests/DecimalTest.cpp',
'tests/DragImageTest.cpp',
'tests/EventListenerTest.cpp',
--- /dev/null
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DateTimeFormat.h"
+
+#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS)
+#include <gtest/gtest.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+
+using namespace WebCore;
+
+class DateTimeFormatTest : public ::testing::Test {
+public:
+ typedef DateTimeFormat::FieldType FieldType;
+
+ struct Token {
+ String string;
+ int count;
+ FieldType fieldType;
+
+ Token(FieldType fieldType, int count = 1)
+ : count(count)
+ , fieldType(fieldType)
+ {
+ ASSERT(fieldType != DateTimeFormat::FieldTypeLiteral);
+ }
+
+ Token(const String& string)
+ : string(string)
+ , count(0)
+ , fieldType(DateTimeFormat::FieldTypeLiteral)
+ {
+ }
+
+ bool operator==(const Token& other) const
+ {
+ return fieldType == other.fieldType && count == other.count && string == other.string;
+ }
+
+ String toString() const
+ {
+ switch (fieldType) {
+ case DateTimeFormat::FieldTypeInvalid:
+ return "*invalid*";
+ case DateTimeFormat::FieldTypeLiteral: {
+ StringBuilder builder;
+ builder.append('"');
+ builder.append(string);
+ builder.append('"');
+ return builder.toString();
+ }
+ default:
+ return String::format("Token(%d, %d)", fieldType, count);
+ }
+ }
+ };
+
+ class Tokens {
+ public:
+ Tokens() { }
+
+ explicit Tokens(const Vector<Token> tokens)
+ : m_tokens(tokens)
+ {
+ }
+
+ explicit Tokens(const String& string)
+ {
+ m_tokens.append(Token(string));
+ }
+
+ explicit Tokens(Token token1)
+ {
+ m_tokens.append(token1);
+ }
+
+ Tokens(Token token1, Token token2)
+ {
+ m_tokens.append(token1);
+ m_tokens.append(token2);
+ }
+
+ Tokens(Token token1, Token token2, Token token3)
+ {
+ m_tokens.append(token1);
+ m_tokens.append(token2);
+ m_tokens.append(token3);
+ }
+
+ Tokens(Token token1, Token token2, Token token3, Token token4)
+ {
+ m_tokens.append(token1);
+ m_tokens.append(token2);
+ m_tokens.append(token3);
+ m_tokens.append(token4);
+ }
+
+ Tokens(Token token1, Token token2, Token token3, Token token4, Token token5)
+ {
+ m_tokens.append(token1);
+ m_tokens.append(token2);
+ m_tokens.append(token3);
+ m_tokens.append(token4);
+ m_tokens.append(token5);
+ }
+
+ Tokens(Token token1, Token token2, Token token3, Token token4, Token token5, Token token6)
+ {
+ m_tokens.append(token1);
+ m_tokens.append(token2);
+ m_tokens.append(token3);
+ m_tokens.append(token4);
+ m_tokens.append(token5);
+ m_tokens.append(token6);
+ }
+
+ bool operator==(const Tokens& other) const
+ {
+ return m_tokens == other.m_tokens;
+ }
+
+ String toString() const
+ {
+ StringBuilder builder;
+ builder.append("Tokens(");
+ for (unsigned index = 0; index < m_tokens.size(); ++index) {
+ if (index)
+ builder.append(",");
+ builder.append(m_tokens[index].toString());
+ }
+ builder.append(")");
+ return builder.toString();
+ }
+
+ private:
+ Vector<Token> m_tokens;
+ };
+
+protected:
+ Tokens parse(const String& formatString)
+ {
+ TokenHandler handler;
+ if (!DateTimeFormat::parse(formatString, handler))
+ return Tokens(Token("*failed*"));
+ return handler.tokens();
+ }
+
+ FieldType single(const char ch)
+ {
+ char formatString[2];
+ formatString[0] = ch;
+ formatString[1] = 0;
+ TokenHandler handler;
+ if (!DateTimeFormat::parse(formatString, handler))
+ return DateTimeFormat::FieldTypeInvalid;
+ return handler.fieldType(0);
+ }
+
+private:
+ class TokenHandler : public DateTimeFormat::TokenHandler {
+ public:
+ virtual ~TokenHandler() { }
+
+ FieldType fieldType(int index) const
+ {
+ return index >=0 && index < static_cast<int>(m_tokens.size()) ? m_tokens[index].fieldType : DateTimeFormat::FieldTypeInvalid;
+ }
+
+ Tokens tokens() const { return Tokens(m_tokens); }
+
+ private:
+ virtual void visitField(FieldType fieldType, int count) OVERRIDE
+ {
+ m_tokens.append(Token(fieldType, count));
+ }
+
+ virtual void visitLiteral(const String& string) OVERRIDE
+ {
+ m_tokens.append(Token(string));
+ }
+
+ Vector<Token> m_tokens;
+ };
+};
+
+std::ostream& operator<<(std::ostream& os, const DateTimeFormatTest::Tokens& tokens)
+{
+ return os << tokens.toString().ascii().data();
+}
+
+TEST_F(DateTimeFormatTest, CommonPattern)
+{
+ EXPECT_EQ(Tokens(), parse(""));
+
+ EXPECT_EQ(
+ Tokens(
+ Token(DateTimeFormat::FieldTypeYear, 4), Token("-"),
+ Token(DateTimeFormat::FieldTypeMonth, 2), Token("-"),
+ Token(DateTimeFormat::FieldTypeDayOfMonth, 2)),
+ parse("yyyy-MM-dd"));
+
+ EXPECT_EQ(
+ Tokens(
+ Token(DateTimeFormat::FieldTypeHour24, 2), Token(":"),
+ Token(DateTimeFormat::FieldTypeMinute, 2), Token(":"),
+ Token(DateTimeFormat::FieldTypeSecond, 2)),
+ parse("kk:mm:ss"));
+
+ EXPECT_EQ(
+ Tokens(
+ Token(DateTimeFormat::FieldTypeHour12), Token(":"),
+ Token(DateTimeFormat::FieldTypeMinute), Token(" "),
+ Token(DateTimeFormat::FieldTypePeriod)),
+ parse("h:m a"));
+
+ EXPECT_EQ(
+ Tokens(
+ Token(DateTimeFormat::FieldTypeYear), Token("Nen "),
+ Token(DateTimeFormat::FieldTypeMonth), Token("Getsu "),
+ Token(DateTimeFormat::FieldTypeDayOfMonth), Token("Nichi")),
+ parse("y'Nen' M'Getsu' d'Nichi'"));
+}
+
+TEST_F(DateTimeFormatTest, MissingClosingQuote)
+{
+ EXPECT_EQ(Tokens("*failed*"), parse("'foo"));
+ EXPECT_EQ(Tokens("*failed*"), parse("fo'o"));
+ EXPECT_EQ(Tokens("*failed*"), parse("foo'"));
+}
+
+TEST_F(DateTimeFormatTest, Quote)
+{
+ EXPECT_EQ(Tokens("FooBar"), parse("'FooBar'"));
+ EXPECT_EQ(Tokens("'"), parse("''"));
+ EXPECT_EQ(Tokens("'-'"), parse("''-''"));
+ EXPECT_EQ(Tokens("Foo'Bar"), parse("'Foo''Bar'"));
+ EXPECT_EQ(
+ Tokens(Token(DateTimeFormat::FieldTypeEra), Token("'s")),
+ parse("G'''s'"));
+ EXPECT_EQ(
+ Tokens(Token(DateTimeFormat::FieldTypeEra), Token("'"), Token(DateTimeFormat::FieldTypeSecond)),
+ parse("G''s"));
+}
+
+TEST_F(DateTimeFormatTest, SingleLowerCaseCharacter)
+{
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('b'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeLocalDayOfWeekStandAlon, single('c'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeDayOfMonth, single('d'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeLocalDayOfWeek, single('e'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeModifiedJulianDay, single('g'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeHour12, single('h'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeHour24, single('k'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeMinute, single('m'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeQuaterStandAlone, single('q'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeSecond, single('s'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeExtendedYear, single('u'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeNonLocationZone, single('v'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeWeekOfMonth, single('w'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeYear, single('y'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeZone, single('z'));
+}
+
+TEST_F(DateTimeFormatTest, SingleLowerCaseInvalid)
+{
+ EXPECT_EQ(DateTimeFormat::FieldTypePeriod, single('a'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('f'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('i'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('j'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('l'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('n'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('o'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('p'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('r'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('t'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('x'));
+}
+
+TEST_F(DateTimeFormatTest, SingleUpperCaseCharacter)
+{
+ EXPECT_EQ(DateTimeFormat::FieldTypeMillisecondsInDay, single('A'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeDayOfYear, single('D'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeDayOfWeek, single('E'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeDayOfWeekInMonth, single('F'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeEra, single('G'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeHour23, single('H'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeHour11, single('K'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeMonthStandAlone, single('L'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeMonth, single('M'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeQuater, single('Q'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeFractionalSecond, single('S'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeWeekOfYear, single('W'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeYearOfWeekOfYear, single('Y'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeRFC822Zone, single('Z'));
+}
+
+TEST_F(DateTimeFormatTest, SingleUpperCaseInvalid)
+{
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('B'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('C'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('I'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('J'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('N'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('O'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('P'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('R'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('T'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('U'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('V'));
+ EXPECT_EQ(DateTimeFormat::FieldTypeInvalid, single('X'));
+}
+
+#endif