Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_DATEPARSER_H_ | 28 #ifndef V8_DATEPARSER_H_ |
| 29 #define V8_DATEPARSER_H_ | 29 #define V8_DATEPARSER_H_ |
| 30 | 30 |
| 31 #include "scanner.h" | 31 #include "scanner.h" |
| 32 | 32 |
| 33 namespace v8 { namespace internal { | 33 namespace v8 { namespace internal { |
| 34 | 34 |
| 35 | |
| 36 class DateParser : public AllStatic { | 35 class DateParser : public AllStatic { |
| 37 public: | 36 public: |
| 38 | 37 |
| 39 // Parse the string as a date. If parsing succeeds, return true after | 38 // Parse the string as a date. If parsing succeeds, return true after |
| 40 // filling out the output array as follows (all integers are Smis): | 39 // filling out the output array as follows (all integers are Smis): |
| 41 // [0]: year | 40 // [0]: year |
| 42 // [1]: month (0 = Jan, 1 = Feb, ...) | 41 // [1]: month (0 = Jan, 1 = Feb, ...) |
| 43 // [2]: day | 42 // [2]: day |
| 44 // [3]: hour | 43 // [3]: hour |
| 45 // [4]: minute | 44 // [4]: minute |
| 46 // [5]: second | 45 // [5]: second |
| 47 // [6]: UTC offset in seconds, or null value if no timezone specified | 46 // [6]: UTC offset in seconds, or null value if no timezone specified |
| 48 // If parsing fails, return false (content of output array is not defined). | 47 // If parsing fails, return false (content of output array is not defined). |
| 49 static bool Parse(String* str, FixedArray* output); | 48 template <typename Char> |
| 49 static bool Parse(Vector<Char> str, FixedArray* output); | |
| 50 | 50 |
| 51 enum {YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, UTC_OFFSET, OUTPUT_SIZE}; | 51 enum {YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, UTC_OFFSET, OUTPUT_SIZE}; |
| 52 | 52 |
| 53 private: | 53 private: |
| 54 // Range testing | 54 // Range testing |
| 55 static bool Between(int x, int lo, int hi) { return x >= lo && x <= hi; } | 55 static inline bool Between(int x, int lo, int hi) { |
| 56 return static_cast<unsigned>(x - lo) <= static_cast<unsigned>(hi - lo); | |
| 57 } | |
| 56 // Indicates a missing value. | 58 // Indicates a missing value. |
| 57 static const int kNone = kMaxInt; | 59 static const int kNone = kMaxInt; |
| 58 | 60 |
| 59 // InputReader provides basic string parsing and character classification. | 61 // InputReader provides basic string parsing and character classification. |
| 62 template <typename Char> | |
| 60 class InputReader BASE_EMBEDDED { | 63 class InputReader BASE_EMBEDDED { |
| 61 public: | 64 public: |
| 62 explicit InputReader(String* s) : buffer_(s), has_read_number_(false) { | 65 explicit InputReader(Vector<Char> s) |
| 66 : index_(0), | |
| 67 buffer_(s), | |
| 68 has_read_number_(false) { | |
| 63 Next(); | 69 Next(); |
| 64 } | 70 } |
| 65 | 71 |
| 66 // Advance to the next character of the string. | 72 // Advance to the next character of the string. |
| 67 void Next() { ch_ = buffer_.has_more() ? buffer_.GetNext() : 0; } | 73 void Next() { ch_ = (index_ < buffer_.length()) ? buffer_[index_++] : 0; } |
| 68 | 74 |
| 69 // Read a string of digits as an unsigned number (cap just below kMaxInt). | 75 // Read a string of digits as an unsigned number (cap just below kMaxInt). |
| 70 int ReadUnsignedNumber() { | 76 int ReadUnsignedNumber() { |
| 71 has_read_number_ = true; | 77 has_read_number_ = true; |
| 72 int n; | 78 int n; |
| 73 for (n = 0; IsAsciiDigit() && n < kMaxInt / 10 - 1; Next()) { | 79 for (n = 0; IsAsciiDigit() && n < kMaxInt / 10 - 1; Next()) { |
| 74 n = n * 10 + ch_ - '0'; | 80 n = n * 10 + ch_ - '0'; |
| 75 } | 81 } |
| 76 return n; | 82 return n; |
| 77 } | 83 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 117 int GetAsciiSignValue() const { return 44 - static_cast<int>(ch_); } | 123 int GetAsciiSignValue() const { return 44 - static_cast<int>(ch_); } |
| 118 | 124 |
| 119 // Indicates whether any (possibly empty!) numbers have been read. | 125 // Indicates whether any (possibly empty!) numbers have been read. |
| 120 bool HasReadNumber() const { return has_read_number_; } | 126 bool HasReadNumber() const { return has_read_number_; } |
| 121 | 127 |
| 122 private: | 128 private: |
| 123 // If current character is in 'A'-'Z' or 'a'-'z', return its lower-case. | 129 // If current character is in 'A'-'Z' or 'a'-'z', return its lower-case. |
| 124 // Else, return something outside of 'A'-'Z' and 'a'-'z'. | 130 // Else, return something outside of 'A'-'Z' and 'a'-'z'. |
| 125 uint32_t GetAsciiAlphaLower() const { return ch_ | 32; } | 131 uint32_t GetAsciiAlphaLower() const { return ch_ | 32; } |
| 126 | 132 |
| 127 StringInputBuffer buffer_; | 133 int index_; |
| 134 Vector<Char> buffer_; | |
| 128 bool has_read_number_; | 135 bool has_read_number_; |
| 129 uint32_t ch_; | 136 uint32_t ch_; |
| 130 }; | 137 }; |
| 131 | 138 |
| 132 enum KeywordType { INVALID, MONTH_NAME, TIME_ZONE_NAME, AM_PM }; | 139 enum KeywordType { INVALID, MONTH_NAME, TIME_ZONE_NAME, AM_PM }; |
| 133 | 140 |
| 134 // KeywordTable maps names of months, time zones, am/pm to numbers. | 141 // KeywordTable maps names of months, time zones, am/pm to numbers. |
| 135 class KeywordTable : public AllStatic { | 142 class KeywordTable : public AllStatic { |
| 136 public: | 143 public: |
| 137 // Look up a word in the keyword table and return an index. | 144 // Look up a word in the keyword table and return an index. |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 218 static bool IsDay(int x) { return Between(x, 1, 31); } | 225 static bool IsDay(int x) { return Between(x, 1, 31); } |
| 219 | 226 |
| 220 static const int kSize = 3; | 227 static const int kSize = 3; |
| 221 int comp_[kSize]; | 228 int comp_[kSize]; |
| 222 int index_; | 229 int index_; |
| 223 int named_month_; | 230 int named_month_; |
| 224 }; | 231 }; |
| 225 }; | 232 }; |
| 226 | 233 |
| 227 | 234 |
| 235 template <typename Char> | |
|
Erik Corry
2009/03/17 13:09:01
Since the templates force us to move this to a .h
| |
| 236 bool DateParser::Parse(Vector<Char> str, FixedArray* out) { | |
| 237 ASSERT(out->length() == OUTPUT_SIZE); | |
| 238 InputReader<Char> in(str); | |
| 239 TimeZoneComposer tz; | |
| 240 TimeComposer time; | |
| 241 DayComposer day; | |
| 242 | |
| 243 while (!in.IsEnd()) { | |
| 244 if (in.IsAsciiDigit()) { | |
| 245 // Parse a number (possibly with 1 or 2 trailing colons). | |
| 246 int n = in.ReadUnsignedNumber(); | |
| 247 if (in.Skip(':')) { | |
| 248 if (in.Skip(':')) { | |
| 249 // n + "::" | |
| 250 if (!time.IsEmpty()) return false; | |
| 251 time.Add(n); | |
| 252 time.Add(0); | |
| 253 } else { | |
| 254 // n + ":" | |
| 255 if (!time.Add(n)) return false; | |
| 256 } | |
| 257 } else if (tz.IsExpecting(n)) { | |
| 258 tz.SetAbsoluteMinute(n); | |
| 259 } else if (time.IsExpecting(n)) { | |
| 260 time.AddFinal(n); | |
| 261 // Require end or white space immediately after finalizing time. | |
| 262 if (!in.IsEnd() && !in.SkipWhiteSpace()) return false; | |
| 263 } else { | |
| 264 if (!day.Add(n)) return false; | |
| 265 in.Skip('-'); // Ignore suffix '-' for year, month, or day. | |
| 266 } | |
| 267 } else if (in.IsAsciiAlphaOrAbove()) { | |
| 268 // Parse a "word" (sequence of chars. >= 'A'). | |
| 269 uint32_t pre[KeywordTable::kPrefixLength]; | |
| 270 int len = in.ReadWord(pre, KeywordTable::kPrefixLength); | |
| 271 int index = KeywordTable::Lookup(pre, len); | |
| 272 KeywordType type = KeywordTable::GetType(index); | |
| 273 | |
| 274 if (type == AM_PM && !time.IsEmpty()) { | |
| 275 time.SetHourOffset(KeywordTable::GetValue(index)); | |
| 276 } else if (type == MONTH_NAME) { | |
| 277 day.SetNamedMonth(KeywordTable::GetValue(index)); | |
| 278 in.Skip('-'); // Ignore suffix '-' for month names | |
| 279 } else if (type == TIME_ZONE_NAME && in.HasReadNumber()) { | |
| 280 tz.Set(KeywordTable::GetValue(index)); | |
| 281 } else { | |
| 282 // Garbage words are illegal if a number has been read. | |
| 283 if (in.HasReadNumber()) return false; | |
| 284 } | |
| 285 } else if (in.IsAsciiSign() && (tz.IsUTC() || !time.IsEmpty())) { | |
| 286 // Parse UTC offset (only after UTC or time). | |
| 287 tz.SetSign(in.GetAsciiSignValue()); | |
| 288 in.Next(); | |
| 289 int n = in.ReadUnsignedNumber(); | |
| 290 if (in.Skip(':')) { | |
| 291 tz.SetAbsoluteHour(n); | |
| 292 tz.SetAbsoluteMinute(kNone); | |
| 293 } else { | |
| 294 tz.SetAbsoluteHour(n / 100); | |
| 295 tz.SetAbsoluteMinute(n % 100); | |
| 296 } | |
| 297 } else if (in.Is('(')) { | |
| 298 // Ignore anything from '(' to a matching ')' or end of string. | |
| 299 in.SkipParentheses(); | |
| 300 } else if ((in.IsAsciiSign() || in.Is(')')) && in.HasReadNumber()) { | |
| 301 // Extra sign or ')' is illegal if a number has been read. | |
| 302 // TODO(lrn) Is this correct? | |
|
Erik Corry
2009/03/17 13:09:01
I should be possible to find the answer to this an
| |
| 303 return false; | |
| 304 } else { | |
| 305 // Ignore other characters. | |
| 306 in.Next(); | |
| 307 } | |
| 308 } | |
| 309 return day.Write(out) && time.Write(out) && tz.Write(out); | |
| 310 } | |
| 311 | |
| 228 } } // namespace v8::internal | 312 } } // namespace v8::internal |
| 229 | 313 |
| 230 #endif // V8_DATEPARSER_H_ | 314 #endif // V8_DATEPARSER_H_ |
| OLD | NEW |