00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "v8.h"
00029
00030 #include "dateparser.h"
00031
00032 namespace v8 { namespace internal {
00033
00034
00035 bool DateParser::Parse(String* str, FixedArray* out) {
00036 ASSERT(out->length() == OUTPUT_SIZE);
00037
00038 InputReader in(str);
00039 TimeZoneComposer tz;
00040 TimeComposer time;
00041 DayComposer day;
00042
00043 while (!in.IsEnd()) {
00044 if (in.IsAsciiDigit()) {
00045
00046 int n = in.ReadUnsignedNumber();
00047 if (in.Skip(':')) {
00048 if (in.Skip(':')) {
00049
00050 if (!time.IsEmpty()) return false;
00051 time.Add(n);
00052 time.Add(0);
00053 } else {
00054
00055 if (!time.Add(n)) return false;
00056 }
00057 } else if (tz.IsExpecting(n)) {
00058 tz.SetAbsoluteMinute(n);
00059 } else if (time.IsExpecting(n)) {
00060 time.AddFinal(n);
00061
00062 if (!in.IsEnd() && !in.SkipWhiteSpace()) return false;
00063 } else {
00064 if (!day.Add(n)) return false;
00065 in.Skip('-');
00066 }
00067 } else if (in.IsAsciiAlphaOrAbove()) {
00068
00069 uint32_t pre[KeywordTable::kPrefixLength];
00070 int len = in.ReadWord(pre, KeywordTable::kPrefixLength);
00071 int index = KeywordTable::Lookup(pre, len);
00072 KeywordType type = KeywordTable::GetType(index);
00073
00074 if (type == AM_PM && !time.IsEmpty()) {
00075 time.SetHourOffset(KeywordTable::GetValue(index));
00076 } else if (type == MONTH_NAME) {
00077 day.SetNamedMonth(KeywordTable::GetValue(index));
00078 in.Skip('-');
00079 } else if (type == TIME_ZONE_NAME && in.HasReadNumber()) {
00080 tz.Set(KeywordTable::GetValue(index));
00081 } else {
00082
00083 if (in.HasReadNumber()) return false;
00084 }
00085 } else if (in.IsAsciiSign() && (tz.IsUTC() || !time.IsEmpty())) {
00086
00087 tz.SetSign(in.GetAsciiSignValue());
00088 in.Next();
00089 int n = in.ReadUnsignedNumber();
00090 if (in.Skip(':')) {
00091 tz.SetAbsoluteHour(n);
00092 tz.SetAbsoluteMinute(kNone);
00093 } else {
00094 tz.SetAbsoluteHour(n / 100);
00095 tz.SetAbsoluteMinute(n % 100);
00096 }
00097 } else if (in.Is('(')) {
00098
00099 in.SkipParentheses();
00100 } else if ((in.IsAsciiSign() || in.Is(')')) && in.HasReadNumber()) {
00101
00102 return false;
00103 } else {
00104
00105 in.Next();
00106 }
00107 }
00108 return day.Write(out) && time.Write(out) && tz.Write(out);
00109 }
00110
00111
00112 bool DateParser::DayComposer::Write(FixedArray* output) {
00113 int year = 0;
00114 int month = kNone;
00115 int day = kNone;
00116
00117 if (named_month_ == kNone) {
00118 if (index_ < 2) return false;
00119 if (index_ == 3 && !IsDay(comp_[0])) {
00120
00121 year = comp_[0];
00122 month = comp_[1];
00123 day = comp_[2];
00124 } else {
00125
00126 month = comp_[0];
00127 day = comp_[1];
00128 if (index_ == 3) year = comp_[2];
00129 }
00130 } else {
00131 month = named_month_;
00132 if (index_ < 1) return false;
00133 if (index_ == 1) {
00134
00135 day = comp_[0];
00136 } else if (!IsDay(comp_[0])) {
00137
00138 year = comp_[0];
00139 day = comp_[1];
00140 } else {
00141
00142 day = comp_[0];
00143 year = comp_[1];
00144 }
00145 }
00146
00147 if (Between(year, 0, 49)) year += 2000;
00148 else if (Between(year, 50, 99)) year += 1900;
00149
00150 if (!Smi::IsValid(year) || !IsMonth(month) || !IsDay(day)) return false;
00151
00152 output->set(YEAR,
00153 Smi::FromInt(year),
00154 SKIP_WRITE_BARRIER);
00155 output->set(MONTH,
00156 Smi::FromInt(month - 1),
00157 SKIP_WRITE_BARRIER);
00158 output->set(DAY,
00159 Smi::FromInt(day),
00160 SKIP_WRITE_BARRIER);
00161 return true;
00162 }
00163
00164
00165 bool DateParser::TimeComposer::Write(FixedArray* output) {
00166
00167 while (index_ < kSize) {
00168 comp_[index_++] = 0;
00169 }
00170
00171 int& hour = comp_[0];
00172 int& minute = comp_[1];
00173 int& second = comp_[2];
00174
00175 if (hour_offset_ != kNone) {
00176 if (!IsHour12(hour)) return false;
00177 hour %= 12;
00178 hour += hour_offset_;
00179 }
00180
00181 if (!IsHour(hour) || !IsMinute(minute) || !IsSecond(second)) return false;
00182
00183 output->set(HOUR,
00184 Smi::FromInt(hour),
00185 SKIP_WRITE_BARRIER);
00186 output->set(MINUTE,
00187 Smi::FromInt(minute),
00188 SKIP_WRITE_BARRIER);
00189 output->set(SECOND,
00190 Smi::FromInt(second),
00191 SKIP_WRITE_BARRIER);
00192 return true;
00193 }
00194
00195
00196 bool DateParser::TimeZoneComposer::Write(FixedArray* output) {
00197 if (sign_ != kNone) {
00198 if (hour_ == kNone) hour_ = 0;
00199 if (minute_ == kNone) minute_ = 0;
00200 int total_seconds = sign_ * (hour_ * 3600 + minute_ * 60);
00201 if (!Smi::IsValid(total_seconds)) return false;
00202 output->set(UTC_OFFSET,
00203 Smi::FromInt(total_seconds),
00204 SKIP_WRITE_BARRIER);
00205 } else {
00206 output->set(UTC_OFFSET,
00207 Heap::null_value(),
00208 SKIP_WRITE_BARRIER);
00209 }
00210 return true;
00211 }
00212
00213
00214 const int8_t
00215 DateParser::KeywordTable::array[][DateParser::KeywordTable::kEntrySize] = {
00216 {'j', 'a', 'n', DateParser::MONTH_NAME, 1},
00217 {'f', 'e', 'b', DateParser::MONTH_NAME, 2},
00218 {'m', 'a', 'r', DateParser::MONTH_NAME, 3},
00219 {'a', 'p', 'r', DateParser::MONTH_NAME, 4},
00220 {'m', 'a', 'y', DateParser::MONTH_NAME, 5},
00221 {'j', 'u', 'n', DateParser::MONTH_NAME, 6},
00222 {'j', 'u', 'l', DateParser::MONTH_NAME, 7},
00223 {'a', 'u', 'g', DateParser::MONTH_NAME, 8},
00224 {'s', 'e', 'p', DateParser::MONTH_NAME, 9},
00225 {'o', 'c', 't', DateParser::MONTH_NAME, 10},
00226 {'n', 'o', 'v', DateParser::MONTH_NAME, 11},
00227 {'d', 'e', 'c', DateParser::MONTH_NAME, 12},
00228 {'a', 'm', '\0', DateParser::AM_PM, 0},
00229 {'p', 'm', '\0', DateParser::AM_PM, 12},
00230 {'u', 't', '\0', DateParser::TIME_ZONE_NAME, 0},
00231 {'u', 't', 'c', DateParser::TIME_ZONE_NAME, 0},
00232 {'g', 'm', 't', DateParser::TIME_ZONE_NAME, 0},
00233 {'c', 'd', 't', DateParser::TIME_ZONE_NAME, -5},
00234 {'c', 's', 't', DateParser::TIME_ZONE_NAME, -6},
00235 {'e', 'd', 't', DateParser::TIME_ZONE_NAME, -4},
00236 {'e', 's', 't', DateParser::TIME_ZONE_NAME, -5},
00237 {'m', 'd', 't', DateParser::TIME_ZONE_NAME, -6},
00238 {'m', 's', 't', DateParser::TIME_ZONE_NAME, -7},
00239 {'p', 'd', 't', DateParser::TIME_ZONE_NAME, -7},
00240 {'p', 's', 't', DateParser::TIME_ZONE_NAME, -8},
00241 {'\0', '\0', '\0', DateParser::INVALID, 0},
00242 };
00243
00244
00245
00246 int DateParser::KeywordTable::Lookup(const uint32_t* pre, int len) {
00247 int i;
00248 for (i = 0; array[i][kTypeOffset] != INVALID; i++) {
00249 int j = 0;
00250 while (j < kPrefixLength &&
00251 pre[j] == static_cast<uint32_t>(array[i][j])) {
00252 j++;
00253 }
00254
00255
00256 if (j == kPrefixLength &&
00257 (len <= kPrefixLength || array[i][kTypeOffset] == MONTH_NAME)) {
00258 return i;
00259 }
00260 }
00261 return i;
00262 }
00263
00264
00265 } }