Skip to content
Newer
Older
100644 231 lines (198 sloc) 8 KB
44260df Initial export.
christian.plesner.hansen authored
1 // Copyright 2008 Google Inc. All Rights Reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
27
28 #ifndef V8_DATEPARSER_H_
29 #define V8_DATEPARSER_H_
30
31 #include "scanner.h"
32
33 namespace v8 { namespace internal {
34
35
36 class DateParser : public AllStatic {
37 public:
38
39 // Parse the string as a date. If parsing succeeds, return true after
40 // filling out the output array as follows (all integers are Smis):
41 // [0]: year
42 // [1]: month (0 = Jan, 1 = Feb, ...)
43 // [2]: day
44 // [3]: hour
45 // [4]: minute
46 // [5]: second
47 // [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).
49 static bool Parse(String* str, FixedArray* output);
50
51 enum {YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, UTC_OFFSET, OUTPUT_SIZE};
52
53 private:
54 // Range testing
55 static bool Between(int x, int lo, int hi) { return x >= lo && x <= hi; }
56 // Indicates a missing value.
57 static const int kNone = kMaxInt;
58
59 // InputReader provides basic string parsing and character classification.
60 class InputReader BASE_EMBEDDED {
61 public:
62 explicit InputReader(String* s) : buffer_(s), has_read_number_(false) {
63 Next();
64 }
65
66 // Advance to the next character of the string.
67 void Next() { ch_ = buffer_.has_more() ? buffer_.GetNext() : 0; }
68
69 // Read a string of digits as an unsigned number (cap just below kMaxInt).
70 int ReadUnsignedNumber() {
71 has_read_number_ = true;
72 int n;
73 for (n = 0; IsAsciiDigit() && n < kMaxInt / 10 - 1; Next()) {
74 n = n * 10 + ch_ - '0';
75 }
76 return n;
77 }
78
79 // Read a word (sequence of chars. >= 'A'), fill the given buffer with a
80 // lower-case prefix, and pad any remainder of the buffer with zeroes.
81 // Return word length.
82 int ReadWord(uint32_t* prefix, int prefix_size) {
83 int len;
84 for (len = 0; IsAsciiAlphaOrAbove(); Next(), len++) {
85 if (len < prefix_size) prefix[len] = GetAsciiAlphaLower();
86 }
87 for (int i = len; i < prefix_size; i++) prefix[i] = 0;
88 return len;
89 }
90
91 // The skip methods return whether they actually skipped something.
92 bool Skip(uint32_t c) { return ch_ == c ? (Next(), true) : false; }
93
94 bool SkipWhiteSpace() {
95 return Scanner::kIsWhiteSpace.get(ch_) ? (Next(), true) : false;
96 }
97
98 bool SkipParentheses() {
99 if (ch_ != '(') return false;
100 int balance = 0;
101 do {
102 if (ch_ == ')') --balance;
103 else if (ch_ == '(') ++balance;
104 Next();
105 } while (balance > 0 && ch_);
106 return true;
107 }
108
109 // Character testing/classification. Non-ASCII digits are not supported.
110 bool Is(uint32_t c) const { return ch_ == c; }
111 bool IsEnd() const { return ch_ == 0; }
112 bool IsAsciiDigit() const { return IsDecimalDigit(ch_); }
113 bool IsAsciiAlphaOrAbove() const { return ch_ >= 'A'; }
114 bool IsAsciiSign() const { return ch_ == '+' || ch_ == '-'; }
115
116 // Return 1 for '+' and -1 for '-'.
117 int GetAsciiSignValue() const { return 44 - static_cast<int>(ch_); }
118
119 // Indicates whether any (possibly empty!) numbers have been read.
120 bool HasReadNumber() const { return has_read_number_; }
121
122 private:
123 // 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'.
125 uint32_t GetAsciiAlphaLower() const { return ch_ | 32; }
126
127 StringInputBuffer buffer_;
128 bool has_read_number_;
129 uint32_t ch_;
130 };
131
132 enum KeywordType { INVALID, MONTH_NAME, TIME_ZONE_NAME, AM_PM };
133
134 // KeywordTable maps names of months, time zones, am/pm to numbers.
135 class KeywordTable : public AllStatic {
136 public:
137 // Look up a word in the keyword table and return an index.
138 // 'pre' contains a prefix of the word, zero-padded to size kPrefixLength
139 // and 'len' is the word length.
140 static int Lookup(const uint32_t* pre, int len);
141 // Get the type of the keyword at index i.
142 static KeywordType GetType(int i) {
143 return static_cast<KeywordType>(array[i][kTypeOffset]);
144 }
145 // Get the value of the keyword at index i.
146 static int GetValue(int i) { return array[i][kValueOffset]; }
147
148 static const int kPrefixLength = 3;
149 static const int kTypeOffset = kPrefixLength;
150 static const int kValueOffset = kTypeOffset + 1;
151 static const int kEntrySize = kValueOffset + 1;
152 static const int8_t array[][kEntrySize];
153 };
154
155 class TimeZoneComposer BASE_EMBEDDED {
156 public:
157 TimeZoneComposer() : sign_(kNone), hour_(kNone), minute_(kNone) {}
158 void Set(int offset_in_hours) {
159 sign_ = offset_in_hours < 0 ? -1 : 1;
160 hour_ = offset_in_hours * sign_;
161 minute_ = 0;
162 }
163 void SetSign(int sign) { sign_ = sign < 0 ? -1 : 1; }
164 void SetAbsoluteHour(int hour) { hour_ = hour; }
165 void SetAbsoluteMinute(int minute) { minute_ = minute; }
166 bool IsExpecting(int n) const {
167 return hour_ != kNone && minute_ == kNone && TimeComposer::IsMinute(n);
168 }
169 bool IsUTC() const { return hour_ == 0 && minute_ == 0; }
170 bool Write(FixedArray* output);
171 private:
172 int sign_;
173 int hour_;
174 int minute_;
175 };
176
177 class TimeComposer BASE_EMBEDDED {
178 public:
179 TimeComposer() : index_(0), hour_offset_(kNone) {}
180 bool IsEmpty() const { return index_ == 0; }
181 bool IsExpecting(int n) const {
182 return (index_ == 1 && IsMinute(n)) || (index_ == 2 && IsSecond(n));
183 }
184 bool Add(int n) {
185 return index_ < kSize ? (comp_[index_++] = n, true) : false;
186 }
187 bool AddFinal(int n) {
188 if (!Add(n)) return false;
189 while (index_ < kSize) comp_[index_++] = 0;
190 return true;
191 }
192 void SetHourOffset(int n) { hour_offset_ = n; }
193 bool Write(FixedArray* output);
194
195 static bool IsMinute(int x) { return Between(x, 0, 59); }
196 private:
197 static bool IsHour(int x) { return Between(x, 0, 23); }
198 static bool IsHour12(int x) { return Between(x, 0, 12); }
199 static bool IsSecond(int x) { return Between(x, 0, 59); }
200
201 static const int kSize = 3;
202 int comp_[kSize];
203 int index_;
204 int hour_offset_;
205 };
206
207 class DayComposer BASE_EMBEDDED {
208 public:
209 DayComposer() : index_(0), named_month_(kNone) {}
210 bool IsEmpty() const { return index_ == 0; }
211 bool Add(int n) {
212 return index_ < kSize ? (comp_[index_++] = n, true) : false;
213 }
214 void SetNamedMonth(int n) { named_month_ = n; }
215 bool Write(FixedArray* output);
216 private:
217 static bool IsMonth(int x) { return Between(x, 1, 12); }
218 static bool IsDay(int x) { return Between(x, 1, 31); }
219
220 static const int kSize = 3;
221 int comp_[kSize];
222 int index_;
223 int named_month_;
224 };
225 };
226
227
228 } } // namespace v8::internal
229
230 #endif // V8_DATEPARSER_H_
Something went wrong with that request. Please try again.