Chromium Code Reviews| Index: src/dateparser.h |
| diff --git a/src/dateparser.h b/src/dateparser.h |
| index bf968525f5f657e494040da7901da0aee4677c8d..f03ff681980db18f452a4a50d8b8c203691faa66 100644 |
| --- a/src/dateparser.h |
| +++ b/src/dateparser.h |
| @@ -32,7 +32,6 @@ |
| namespace v8 { namespace internal { |
| - |
| class DateParser : public AllStatic { |
| public: |
| @@ -46,25 +45,32 @@ class DateParser : public AllStatic { |
| // [5]: second |
| // [6]: UTC offset in seconds, or null value if no timezone specified |
| // If parsing fails, return false (content of output array is not defined). |
| - static bool Parse(String* str, FixedArray* output); |
| + template <typename Char> |
| + static bool Parse(Vector<Char> str, FixedArray* output); |
| enum {YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, UTC_OFFSET, OUTPUT_SIZE}; |
| private: |
| // Range testing |
| - static bool Between(int x, int lo, int hi) { return x >= lo && x <= hi; } |
| + static inline bool Between(int x, int lo, int hi) { |
| + return static_cast<unsigned>(x - lo) <= static_cast<unsigned>(hi - lo); |
| + } |
| // Indicates a missing value. |
| static const int kNone = kMaxInt; |
| // InputReader provides basic string parsing and character classification. |
| + template <typename Char> |
| class InputReader BASE_EMBEDDED { |
| public: |
| - explicit InputReader(String* s) : buffer_(s), has_read_number_(false) { |
| + explicit InputReader(Vector<Char> s) |
| + : index_(0), |
| + buffer_(s), |
| + has_read_number_(false) { |
| Next(); |
| } |
| // Advance to the next character of the string. |
| - void Next() { ch_ = buffer_.has_more() ? buffer_.GetNext() : 0; } |
| + void Next() { ch_ = (index_ < buffer_.length()) ? buffer_[index_++] : 0; } |
| // Read a string of digits as an unsigned number (cap just below kMaxInt). |
| int ReadUnsignedNumber() { |
| @@ -124,7 +130,8 @@ class DateParser : public AllStatic { |
| // Else, return something outside of 'A'-'Z' and 'a'-'z'. |
| uint32_t GetAsciiAlphaLower() const { return ch_ | 32; } |
| - StringInputBuffer buffer_; |
| + int index_; |
| + Vector<Char> buffer_; |
| bool has_read_number_; |
| uint32_t ch_; |
| }; |
| @@ -225,6 +232,83 @@ class DateParser : public AllStatic { |
| }; |
| +template <typename Char> |
|
Erik Corry
2009/03/17 13:09:01
Since the templates force us to move this to a .h
|
| +bool DateParser::Parse(Vector<Char> str, FixedArray* out) { |
| + ASSERT(out->length() == OUTPUT_SIZE); |
| + InputReader<Char> in(str); |
| + TimeZoneComposer tz; |
| + TimeComposer time; |
| + DayComposer day; |
| + |
| + while (!in.IsEnd()) { |
| + if (in.IsAsciiDigit()) { |
| + // Parse a number (possibly with 1 or 2 trailing colons). |
| + int n = in.ReadUnsignedNumber(); |
| + if (in.Skip(':')) { |
| + if (in.Skip(':')) { |
| + // n + "::" |
| + if (!time.IsEmpty()) return false; |
| + time.Add(n); |
| + time.Add(0); |
| + } else { |
| + // n + ":" |
| + if (!time.Add(n)) return false; |
| + } |
| + } else if (tz.IsExpecting(n)) { |
| + tz.SetAbsoluteMinute(n); |
| + } else if (time.IsExpecting(n)) { |
| + time.AddFinal(n); |
| + // Require end or white space immediately after finalizing time. |
| + if (!in.IsEnd() && !in.SkipWhiteSpace()) return false; |
| + } else { |
| + if (!day.Add(n)) return false; |
| + in.Skip('-'); // Ignore suffix '-' for year, month, or day. |
| + } |
| + } else if (in.IsAsciiAlphaOrAbove()) { |
| + // Parse a "word" (sequence of chars. >= 'A'). |
| + uint32_t pre[KeywordTable::kPrefixLength]; |
| + int len = in.ReadWord(pre, KeywordTable::kPrefixLength); |
| + int index = KeywordTable::Lookup(pre, len); |
| + KeywordType type = KeywordTable::GetType(index); |
| + |
| + if (type == AM_PM && !time.IsEmpty()) { |
| + time.SetHourOffset(KeywordTable::GetValue(index)); |
| + } else if (type == MONTH_NAME) { |
| + day.SetNamedMonth(KeywordTable::GetValue(index)); |
| + in.Skip('-'); // Ignore suffix '-' for month names |
| + } else if (type == TIME_ZONE_NAME && in.HasReadNumber()) { |
| + tz.Set(KeywordTable::GetValue(index)); |
| + } else { |
| + // Garbage words are illegal if a number has been read. |
| + if (in.HasReadNumber()) return false; |
| + } |
| + } else if (in.IsAsciiSign() && (tz.IsUTC() || !time.IsEmpty())) { |
| + // Parse UTC offset (only after UTC or time). |
| + tz.SetSign(in.GetAsciiSignValue()); |
| + in.Next(); |
| + int n = in.ReadUnsignedNumber(); |
| + if (in.Skip(':')) { |
| + tz.SetAbsoluteHour(n); |
| + tz.SetAbsoluteMinute(kNone); |
| + } else { |
| + tz.SetAbsoluteHour(n / 100); |
| + tz.SetAbsoluteMinute(n % 100); |
| + } |
| + } else if (in.Is('(')) { |
| + // Ignore anything from '(' to a matching ')' or end of string. |
| + in.SkipParentheses(); |
| + } else if ((in.IsAsciiSign() || in.Is(')')) && in.HasReadNumber()) { |
| + // Extra sign or ')' is illegal if a number has been read. |
| + // TODO(lrn) Is this correct? |
|
Erik Corry
2009/03/17 13:09:01
I should be possible to find the answer to this an
|
| + return false; |
| + } else { |
| + // Ignore other characters. |
| + in.Next(); |
| + } |
| + } |
| + return day.Write(out) && time.Write(out) && tz.Write(out); |
| +} |
| + |
| } } // namespace v8::internal |
| #endif // V8_DATEPARSER_H_ |