• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2008 the V8 project authors. 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 {
34 namespace internal {
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   template <typename Char>
50   static bool Parse(Vector<Char> str, FixedArray* output);
51 
52   enum {
53     YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, UTC_OFFSET, OUTPUT_SIZE
54   };
55 
56  private:
57   // Range testing
Between(int x,int lo,int hi)58   static inline bool Between(int x, int lo, int hi) {
59     return static_cast<unsigned>(x - lo) <= static_cast<unsigned>(hi - lo);
60   }
61   // Indicates a missing value.
62   static const int kNone = kMaxInt;
63 
64   // InputReader provides basic string parsing and character classification.
65   template <typename Char>
66   class InputReader BASE_EMBEDDED {
67    public:
InputReader(Vector<Char> s)68     explicit InputReader(Vector<Char> s)
69         : index_(0),
70           buffer_(s),
71           has_read_number_(false) {
72       Next();
73     }
74 
75     // Advance to the next character of the string.
Next()76     void Next() { ch_ = (index_ < buffer_.length()) ? buffer_[index_++] : 0; }
77 
78     // Read a string of digits as an unsigned number (cap just below kMaxInt).
ReadUnsignedNumber()79     int ReadUnsignedNumber() {
80       has_read_number_ = true;
81       int n;
82       for (n = 0; IsAsciiDigit() && n < kMaxInt / 10 - 1; Next()) {
83         n = n * 10 + ch_ - '0';
84       }
85       return n;
86     }
87 
88     // Read a word (sequence of chars. >= 'A'), fill the given buffer with a
89     // lower-case prefix, and pad any remainder of the buffer with zeroes.
90     // Return word length.
ReadWord(uint32_t * prefix,int prefix_size)91     int ReadWord(uint32_t* prefix, int prefix_size) {
92       int len;
93       for (len = 0; IsAsciiAlphaOrAbove(); Next(), len++) {
94         if (len < prefix_size) prefix[len] = GetAsciiAlphaLower();
95       }
96       for (int i = len; i < prefix_size; i++) prefix[i] = 0;
97       return len;
98     }
99 
100     // The skip methods return whether they actually skipped something.
Skip(uint32_t c)101     bool Skip(uint32_t c) { return ch_ == c ?  (Next(), true) : false; }
102 
SkipWhiteSpace()103     bool SkipWhiteSpace() {
104       return Scanner::kIsWhiteSpace.get(ch_) ? (Next(), true) : false;
105     }
106 
SkipParentheses()107     bool SkipParentheses() {
108       if (ch_ != '(') return false;
109       int balance = 0;
110       do {
111         if (ch_ == ')') --balance;
112         else if (ch_ == '(') ++balance;
113         Next();
114       } while (balance > 0 && ch_);
115       return true;
116     }
117 
118     // Character testing/classification. Non-ASCII digits are not supported.
Is(uint32_t c)119     bool Is(uint32_t c) const { return ch_ == c; }
IsEnd()120     bool IsEnd() const { return ch_ == 0; }
IsAsciiDigit()121     bool IsAsciiDigit() const { return IsDecimalDigit(ch_); }
IsAsciiAlphaOrAbove()122     bool IsAsciiAlphaOrAbove() const { return ch_ >= 'A'; }
IsAsciiSign()123     bool IsAsciiSign() const { return ch_ == '+' || ch_ == '-'; }
124 
125     // Return 1 for '+' and -1 for '-'.
GetAsciiSignValue()126     int GetAsciiSignValue() const { return 44 - static_cast<int>(ch_); }
127 
128     // Indicates whether any (possibly empty!) numbers have been read.
HasReadNumber()129     bool HasReadNumber() const { return has_read_number_; }
130 
131    private:
132     // If current character is in 'A'-'Z' or 'a'-'z', return its lower-case.
133     // Else, return something outside of 'A'-'Z' and 'a'-'z'.
GetAsciiAlphaLower()134     uint32_t GetAsciiAlphaLower() const { return ch_ | 32; }
135 
136     int index_;
137     Vector<Char> buffer_;
138     bool has_read_number_;
139     uint32_t ch_;
140   };
141 
142   enum KeywordType { INVALID, MONTH_NAME, TIME_ZONE_NAME, AM_PM };
143 
144   // KeywordTable maps names of months, time zones, am/pm to numbers.
145   class KeywordTable : public AllStatic {
146    public:
147     // Look up a word in the keyword table and return an index.
148     // 'pre' contains a prefix of the word, zero-padded to size kPrefixLength
149     // and 'len' is the word length.
150     static int Lookup(const uint32_t* pre, int len);
151     // Get the type of the keyword at index i.
GetType(int i)152     static KeywordType GetType(int i) {
153       return static_cast<KeywordType>(array[i][kTypeOffset]);
154     }
155     // Get the value of the keyword at index i.
GetValue(int i)156     static int GetValue(int i) { return array[i][kValueOffset]; }
157 
158     static const int kPrefixLength = 3;
159     static const int kTypeOffset = kPrefixLength;
160     static const int kValueOffset = kTypeOffset + 1;
161     static const int kEntrySize = kValueOffset + 1;
162     static const int8_t array[][kEntrySize];
163   };
164 
165   class TimeZoneComposer BASE_EMBEDDED {
166    public:
TimeZoneComposer()167     TimeZoneComposer() : sign_(kNone), hour_(kNone), minute_(kNone) {}
Set(int offset_in_hours)168     void Set(int offset_in_hours) {
169       sign_ = offset_in_hours < 0 ? -1 : 1;
170       hour_ = offset_in_hours * sign_;
171       minute_ = 0;
172     }
SetSign(int sign)173     void SetSign(int sign) { sign_ = sign < 0 ? -1 : 1; }
SetAbsoluteHour(int hour)174     void SetAbsoluteHour(int hour) { hour_ = hour; }
SetAbsoluteMinute(int minute)175     void SetAbsoluteMinute(int minute) { minute_ = minute; }
IsExpecting(int n)176     bool IsExpecting(int n) const {
177       return hour_ != kNone && minute_ == kNone && TimeComposer::IsMinute(n);
178     }
IsUTC()179     bool IsUTC() const { return hour_ == 0 && minute_ == 0; }
180     bool Write(FixedArray* output);
181    private:
182     int sign_;
183     int hour_;
184     int minute_;
185   };
186 
187   class TimeComposer BASE_EMBEDDED {
188    public:
TimeComposer()189     TimeComposer() : index_(0), hour_offset_(kNone) {}
IsEmpty()190     bool IsEmpty() const { return index_ == 0; }
IsExpecting(int n)191     bool IsExpecting(int n) const {
192       return (index_ == 1 && IsMinute(n)) || (index_ == 2 && IsSecond(n));
193     }
Add(int n)194     bool Add(int n) {
195       return index_ < kSize ? (comp_[index_++] = n, true) : false;
196     }
AddFinal(int n)197     bool AddFinal(int n) {
198       if (!Add(n)) return false;
199       while (index_ < kSize) comp_[index_++] = 0;
200       return true;
201     }
SetHourOffset(int n)202     void SetHourOffset(int n) { hour_offset_ = n; }
203     bool Write(FixedArray* output);
204 
IsMinute(int x)205     static bool IsMinute(int x) { return Between(x, 0, 59); }
206    private:
IsHour(int x)207     static bool IsHour(int x) { return Between(x, 0, 23); }
IsHour12(int x)208     static bool IsHour12(int x) { return Between(x, 0, 12); }
IsSecond(int x)209     static bool IsSecond(int x) { return Between(x, 0, 59); }
210 
211     static const int kSize = 3;
212     int comp_[kSize];
213     int index_;
214     int hour_offset_;
215   };
216 
217   class DayComposer BASE_EMBEDDED {
218    public:
DayComposer()219     DayComposer() : index_(0), named_month_(kNone) {}
IsEmpty()220     bool IsEmpty() const { return index_ == 0; }
Add(int n)221     bool Add(int n) {
222       return index_ < kSize ? (comp_[index_++] = n, true) : false;
223     }
SetNamedMonth(int n)224     void SetNamedMonth(int n) { named_month_ = n; }
225     bool Write(FixedArray* output);
226    private:
IsMonth(int x)227     static bool IsMonth(int x) { return Between(x, 1, 12); }
IsDay(int x)228     static bool IsDay(int x) { return Between(x, 1, 31); }
229 
230     static const int kSize = 3;
231     int comp_[kSize];
232     int index_;
233     int named_month_;
234   };
235 };
236 
237 
238 } }  // namespace v8::internal
239 
240 #endif  // V8_DATEPARSER_H_
241