Author: [email protected]
Date: Tue Mar 17 06:27:21 2009
New Revision: 1525

Added:
    branches/bleeding_edge/src/dateparser-inl.h
Modified:
    branches/bleeding_edge/src/char-predicates-inl.h
    branches/bleeding_edge/src/dateparser.cc
    branches/bleeding_edge/src/dateparser.h
    branches/bleeding_edge/src/runtime.cc
    branches/bleeding_edge/test/mjsunit/date-parse.js

Log:
Flatten strings before parsing them as Date strings, and work on Vector of  
chars instead.


Modified: branches/bleeding_edge/src/char-predicates-inl.h
==============================================================================
--- branches/bleeding_edge/src/char-predicates-inl.h    (original)
+++ branches/bleeding_edge/src/char-predicates-inl.h    Tue Mar 17 06:27:21  
2009
@@ -43,26 +43,28 @@
  }


+static inline bool IsInRange(int value, int lower_limit, int higher_limit)  
{
+  ASSERT(lower_limit <= higher_limit);
+  return static_cast<unsigned int>(value - lower_limit) <=
+      static_cast<unsigned int>(higher_limit - lower_limit);
+}
+
+
  inline bool IsDecimalDigit(uc32 c) {
    // ECMA-262, 3rd, 7.8.3 (p 16)
-  return
-    '0' <= c && c <= '9';
+  return IsInRange(c, '0', '9');
  }


  inline bool IsHexDigit(uc32 c) {
    // ECMA-262, 3rd, 7.6 (p 15)
-  return
-    ('0' <= c && c <= '9') ||
-    ('A' <= c && c <= 'F') ||
-    ('a' <= c && c <= 'f');
+  return IsDecimalDigit(c) || IsInRange(c | 0x20, 'a', 'f');
  }


  inline bool IsRegExpWord(uc16 c) {
-  return ('a' <= c && c <= 'z')
-      || ('A' <= c && c <= 'Z')
-      || ('0' <= c && c <= '9')
+  return IsInRange(c | 0x20, 'a', 'z')
+      || IsDecimalDigit(c)
        || (c == '_');
  }


Added: branches/bleeding_edge/src/dateparser-inl.h
==============================================================================
--- (empty file)
+++ branches/bleeding_edge/src/dateparser-inl.h Tue Mar 17 06:27:21 2009
@@ -0,0 +1,106 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace v8 { namespace internal {
+
+template <typename Char>
+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.
+      return false;
+    } else {
+      // Ignore other characters.
+      in.Next();
+    }
+  }
+  return day.Write(out) && time.Write(out) && tz.Write(out);
+}
+
+} }  // namespace v8::internal

Modified: branches/bleeding_edge/src/dateparser.cc
==============================================================================
--- branches/bleeding_edge/src/dateparser.cc    (original)
+++ branches/bleeding_edge/src/dateparser.cc    Tue Mar 17 06:27:21 2009
@@ -31,84 +31,6 @@

  namespace v8 { namespace internal {

-
-bool DateParser::Parse(String* str, FixedArray* out) {
-  ASSERT(out->length() == OUTPUT_SIZE);
-
-  InputReader 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 no number read yet.
-        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 no number read yet.
-      return false;
-    } else {
-      // Ignore other characters.
-      in.Next();
-    }
-  }
-  return day.Write(out) && time.Write(out) && tz.Write(out);
-}
-
-
  bool DateParser::DayComposer::Write(FixedArray* output) {
    int year = 0;  // Default year is 0 (=> 2000) for KJS compatibility.
    int month = kNone;
@@ -192,7 +114,6 @@
    return true;
  }

-
  bool DateParser::TimeZoneComposer::Write(FixedArray* output) {
    if (sign_ != kNone) {
      if (hour_ == kNone) hour_ = 0;
@@ -210,9 +131,8 @@
    return true;
  }

-
-const int8_t
-DateParser::KeywordTable::array[][DateParser::KeywordTable::kEntrySize] = {
+const int8_t DateParser::KeywordTable::
+    array[][DateParser::KeywordTable::kEntrySize] = {
    {'j', 'a', 'n', DateParser::MONTH_NAME, 1},
    {'f', 'e', 'b', DateParser::MONTH_NAME, 2},
    {'m', 'a', 'r', DateParser::MONTH_NAME, 3},

Modified: branches/bleeding_edge/src/dateparser.h
==============================================================================
--- branches/bleeding_edge/src/dateparser.h     (original)
+++ branches/bleeding_edge/src/dateparser.h     Tue Mar 17 06:27:21 2009
@@ -32,7 +32,6 @@

  namespace v8 { namespace internal {

-
  class DateParser : public AllStatic {
   public:

@@ -46,25 +45,32 @@
    // [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 @@
      // 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_;
    };

Modified: branches/bleeding_edge/src/runtime.cc
==============================================================================
--- branches/bleeding_edge/src/runtime.cc       (original)
+++ branches/bleeding_edge/src/runtime.cc       Tue Mar 17 06:27:21 2009
@@ -35,6 +35,7 @@
  #include "compiler.h"
  #include "cpu.h"
  #include "dateparser.h"
+#include "dateparser-inl.h"
  #include "debug.h"
  #include "execution.h"
  #include "jsregexp.h"
@@ -4484,8 +4485,19 @@
    CONVERT_CHECKED(String, string_object, args[0]);

    Handle<String> str(string_object);
+  FlattenString(str);
    Handle<FixedArray> output =  
Factory::NewFixedArray(DateParser::OUTPUT_SIZE);
-  if (DateParser::Parse(*str, *output)) {
+  bool result;
+  {
+    AssertNoAllocation no_allocation;
+    if (StringShape(*str).IsAsciiRepresentation()) {
+      result = DateParser::Parse(str->ToAsciiVector(), *output);
+    } else {
+      ASSERT(StringShape(*str).IsTwoByteRepresentation());
+      result = DateParser::Parse(str->ToUC16Vector(), *output);
+    }
+  }
+  if (result) {
      return *Factory::NewJSArrayWithElements(output);
    } else {
      return *Factory::null_value();

Modified: branches/bleeding_edge/test/mjsunit/date-parse.js
==============================================================================
--- branches/bleeding_edge/test/mjsunit/date-parse.js   (original)
+++ branches/bleeding_edge/test/mjsunit/date-parse.js   Tue Mar 17 06:27:21  
2009
@@ -41,12 +41,13 @@
  // number of milliseconds to make it timezone independent.
  function testDateParseLocalTime(string) {
    var d = Date.parse(string);
-  assertTrue(d > 0 && !isNaN(d));
+  assertTrue(!isNaN(d), string + " is NaN.");
+  assertTrue(d > 0, string + " <= 0.");
  };


  function testDateParseMisc(array) {
-  assertTrue(array.length == 2);
+  assertEquals(2, array.length, "array [" + array + "] length != 2.");
    var string = array[0];
    var expected = array[1];
    var d = Date.parse(string);
@@ -262,4 +263,6 @@
      'May 25 2008 1:30( )AM (PM)',
      'May 25 2008 AAA (GMT)'];

-testCasesNegative.forEach(function (s) { assertTrue(isNaN(Date.parse(s)));  
});
+testCasesNegative.forEach(function (s) {
+    assertTrue(isNaN(Date.parse(s)), s + " is not NaN.");
+});

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to