Add support for hexadecimal float literals.

Fixes #48.
diff --git a/double-conversion/double-conversion.cc b/double-conversion/double-conversion.cc
index 7c8e9c6..ba83bef 100644
--- a/double-conversion/double-conversion.cc
+++ b/double-conversion/double-conversion.cc
@@ -537,7 +537,7 @@
 #pragma optimize("",on)
 #else
 static bool inline IsDecimalDigitForRadix(int c, int radix) {
-	return '0' <= c && c <= '9' && (c - '0') < radix;
+  return '0' <= c && c <= '9' && (c - '0') < radix;
 }
 #endif
 // Returns true if 'c' is a character digit that is valid for the given radix.
@@ -551,17 +551,57 @@
   return radix > 10 && c >= a_character && c < a_character + radix - 10;
 }
 
+// Checks whether the string in the range start-end is a hex-float string.
+// This function assumes that the leading '0x'/'0X' is already consumed.
+//
+// Hex float strings are of one of the following forms:
+//   - hex_digits+ 'p' ('+'|'-')? exponent_digits+
+//   - hex_digits* '.' hex_digits+ 'p' ('+'|'-')? exponent_digits+
+//   - hex_digits+ '.' 'p' ('+'|'-')? exponent_digits+
+template<class Iterator>
+static bool IsHexFloatString(Iterator start,
+                             Iterator end,
+                             bool allow_trailing_junk) {
+  ASSERT(start != end);
+
+  Iterator current = start;
+
+  while (current != end && isDigit(*current, 16)) ++current;
+  if (current == end) return false;
+  if (*current == '.') {
+    ++current;
+    while (current != end && isDigit(*current, 16)) ++current;
+    if (current - start == 1) return false;  // Only the '.', but no digits.
+  }
+  if (current == end) return false;
+  if (*current != 'p' && *current != 'P') return false;
+  ++current;
+  if (current == end) return false;
+  if (*current == '+' || *current == '-') ++current;
+  if (current == end) return false;
+  if (!isDigit(*current, 10)) return false;
+  ++current;
+  while (current != end && isDigit(*current, 10)) ++current;
+  return allow_trailing_junk || !AdvanceToNonspace(&current, end);
+}
+
 
 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
+//
+// If parse_as_hex_float is true, then the string must be a valid
+// hex-float.
 template <int radix_log_2, class Iterator>
 static double RadixStringToIeee(Iterator* current,
                                 Iterator end,
                                 bool sign,
+                                bool parse_as_hex_float,
                                 bool allow_trailing_junk,
                                 double junk_string_value,
                                 bool read_as_double,
                                 bool* result_is_junk) {
   ASSERT(*current != end);
+  ASSERT(!parse_as_hex_float ||
+      IsHexFloatString(*current, end, allow_trailing_junk));
 
   const int kDoubleSize = Double::kSignificandSize;
   const int kSingleSize = Single::kSignificandSize;
@@ -581,15 +621,27 @@
   int64_t number = 0;
   int exponent = 0;
   const int radix = (1 << radix_log_2);
+  // Whether we have encountered a '.' and are parsing the decimal digits.
+  // Only relevant if parse_as_hex_float is true.
+  bool post_decimal = false;
 
   do {
     int digit;
     if (IsDecimalDigitForRadix(**current, radix)) {
       digit = static_cast<char>(**current) - '0';
+      if (post_decimal) exponent -= radix_log_2;
     } else if (IsCharacterDigitForRadix(**current, radix, 'a')) {
       digit = static_cast<char>(**current) - 'a' + 10;
+      if (post_decimal) exponent -= radix_log_2;
     } else if (IsCharacterDigitForRadix(**current, radix, 'A')) {
       digit = static_cast<char>(**current) - 'A' + 10;
+      if (post_decimal) exponent -= radix_log_2;
+    } else if (parse_as_hex_float && **current == '.') {
+      post_decimal = true;
+      ++(*current);
+      continue;
+    } else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) {
+      break;
     } else {
       if (allow_trailing_junk || !AdvanceToNonspace(current, end)) {
         break;
@@ -612,17 +664,25 @@
       int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
       int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
       number >>= overflow_bits_count;
-      exponent = overflow_bits_count;
+      exponent += overflow_bits_count;
 
       bool zero_tail = true;
       for (;;) {
         ++(*current);
+        if (parse_as_hex_float && **current == '.') {
+          // Just run over the '.'. We are just trying to see whether there is
+          // a non-zero digit somewhere.
+          ++(*current);
+          post_decimal = true;
+        }
         if (*current == end || !isDigit(**current, radix)) break;
         zero_tail = zero_tail && **current == '0';
-        exponent += radix_log_2;
+        if (!post_decimal) exponent += radix_log_2;
       }
 
-      if (!allow_trailing_junk && AdvanceToNonspace(current, end)) {
+      if (!parse_as_hex_float &&
+          !allow_trailing_junk &&
+          AdvanceToNonspace(current, end)) {
         return junk_string_value;
       }
 
@@ -652,7 +712,26 @@
 
   *result_is_junk = false;
 
-  if (exponent == 0) {
+  if (parse_as_hex_float) {
+    ASSERT(**current == 'p' || **current == 'P');
+    ++(*current);
+    bool is_negative = false;
+    if (**current == '+') {
+      ++(*current);
+    } else if (**current == '-') {
+      is_negative = true;
+      ++(*current);
+    }
+    int written_exponent = 0;
+    while (*current != end && IsDecimalDigitForRadix(**current, 10)) {
+      written_exponent = 10 * written_exponent + **current - '0';
+      ++(*current);
+    }
+    if (is_negative) written_exponent = -written_exponent;
+    exponent += written_exponent;
+  }
+
+  if (exponent == 0 || number == 0) {
     if (sign) {
       if (number == 0) return -0.0;
       number = -number;
@@ -779,16 +858,23 @@
     leading_zero = true;
 
     // It could be hexadecimal value.
-    if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
+    if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) &&
+        (*current == 'x' || *current == 'X')) {
       ++current;
-      if (current == end || !isDigit(*current, 16)) {
-        return junk_string_value_;  // "0x".
+
+      bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) &&
+                          IsHexFloatString(current, end, allow_trailing_junk);
+
+      if (current == end) return junk_string_value_;  // "0x"
+      if (!parse_as_hex_float && !isDigit(*current, 16)) {
+        return junk_string_value_;
       }
 
       bool result_is_junk;
       double result = RadixStringToIeee<4>(&current,
                                            end,
                                            sign,
+                                           parse_as_hex_float,
                                            allow_trailing_junk,
                                            junk_string_value_,
                                            read_as_double,
@@ -959,6 +1045,7 @@
     result = RadixStringToIeee<3>(&start,
                                   buffer + buffer_pos,
                                   sign,
+                                  false, // Don't parse as hex_float.
                                   allow_trailing_junk,
                                   junk_string_value_,
                                   read_as_double,
diff --git a/double-conversion/double-conversion.h b/double-conversion/double-conversion.h
index 1ccd7fc..86cf25e 100644
--- a/double-conversion/double-conversion.h
+++ b/double-conversion/double-conversion.h
@@ -396,6 +396,7 @@
     ALLOW_TRAILING_SPACES = 16,
     ALLOW_SPACES_AFTER_SIGN = 32,
     ALLOW_CASE_INSENSIBILITY = 64,
+    ALLOW_HEX_FLOATS = 128,
   };
 
   // Flags should be a bit-or combination of the possible Flags-enum.
@@ -429,6 +430,11 @@
   //           StringToDouble("+   123.2") -> 123.2
   //  - ALLOW_CASE_INSENSIBILITY: ignore case of characters for special values:
   //      infinity and nan.
+  //  - ALLOW_HEX_FLOATS: allows hexadecimal float literals.
+  //      This *must* start with "0x" and separate the exponent with "p".
+  //      Examples: 0x1.2p3 == 9.0
+  //                0x10.1p0 == 16.0625
+  //      ALLOW_HEX and ALLOW_HEX_FLOATS are indendent.
   //
   // empty_string_value is returned when an empty string is given as input.
   // If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
diff --git a/test/cctest/test-conversions.cc b/test/cctest/test-conversions.cc
index d70624d..cf556e6 100644
--- a/test/cctest/test-conversions.cc
+++ b/test/cctest/test-conversions.cc
@@ -2563,6 +2563,91 @@
   CHECK_EQ(295147905179352960000.0, StrToD("0x100000000000018000", flags, 0.0,
                                            &processed, &all_used));
   CHECK(all_used);
+
+  flags = StringToDoubleConverter::ALLOW_HEX_FLOATS;
+
+  CHECK_EQ(3.0, StrToD("0x3p0", flags, 0.0, &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(0.0, StrToD("0x.0p0", flags, 0.0, &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(3.0, StrToD("0x3.0p0", flags, 0.0, &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(3.0, StrToD("0x3.p0", flags, 0.0, &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(-5.634002666912405e+27, StrToD("-0x123456789012345678901234p0",
+                                          flags, 0.0,
+                                          &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(72057594037927940.0, StrToD("0x100000000000001p0", flags, 0.0,
+                                       &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(72057594037927940.0, StrToD("0x100000000000000p0", flags, 0.0,
+                                       &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(295147905179352830000.0, StrToD("0x100000000000000001p0", flags, 0.0,
+                                       &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(295147905179352830000.0, StrToD("0x100000000000000000p0", flags, 0.0,
+                                       &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(295147905179352900000.0, StrToD("0x100000000000008001p0", flags, 0.0,
+                                           &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(295147905179352830000.0, StrToD("0x100000000000008000p0", flags, 0.0,
+                                           &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(295147905179352960000.0, StrToD("0x100000000000018001p0", flags, 0.0,
+                                           &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(295147905179352960000.0, StrToD("0x100000000000018000p0", flags, 0.0,
+                                           &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(4.722366482869645e+21, StrToD("0x100000000000000001p4", flags, 0.0,
+                                       &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(4.722366482869645e+21, StrToD("0x100000000000000000p+4", flags, 0.0,
+                                       &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(4.722366482869646e+21, StrToD("0x100000000000008001p04", flags, 0.0,
+                                           &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(18446744073709552000.0, StrToD("0x100000000000008000p-4", flags, 0.0,
+                                           &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(18446744073709560000.0, StrToD("0x100000000000018001p-04", flags, 0.0,
+                                           &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(4.722366482869647e+21, StrToD("0x100000000000018000p4", flags, 0.0,
+                                           &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(Double::Infinity(), StrToD("0x1p2000", flags, 0.0,
+                                      &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(0.0, StrToD("0x1p-2000", flags, 0.0, &processed, &all_used));
+  CHECK(all_used);
+
+  CHECK_EQ(-0.0, StrToD("-0x1p-2000", flags, 0.0, &processed, &all_used));
+  CHECK(all_used);
 }
 
 
@@ -3789,13 +3874,30 @@
   CHECK_EQ(5.0f, StrToF(" + 0x5 ", flags, 0.0f, &processed, &all_used));
   CHECK(all_used);
 
-  CHECK_EQ(Single::NaN(), StrToF("- -0x5", flags, 0.0f,  &processed, &all_used));
+  CHECK_EQ(Single::NaN(), StrToF("- -0x5", flags, 0.0f, 
+                                 &processed, &all_used));
   CHECK_EQ(0, processed);
 
-  CHECK_EQ(Single::NaN(), StrToF("- +0x5", flags, 0.0f,  &processed, &all_used));
+  CHECK_EQ(Single::NaN(), StrToF("- +0x5", flags, 0.0f,
+                                 &processed, &all_used));
   CHECK_EQ(0, processed);
 
-  CHECK_EQ(Single::NaN(), StrToF("+ +0x5", flags, 0.0f,  &processed, &all_used));
+  CHECK_EQ(Single::NaN(), StrToF("+ +0x5", flags, 0.0f,
+                                 &processed, &all_used));
+  CHECK_EQ(0, processed);
+
+  CHECK_EQ(Single::NaN(), StrToF("0x3p0", flags, 0.0f, &processed, &all_used));
+  CHECK_EQ(0, processed);
+
+  CHECK_EQ(Single::NaN(), StrToF("0x.0p0", flags, 0.0f, &processed, &all_used));
+  CHECK_EQ(0, processed);
+
+  CHECK_EQ(Single::NaN(), StrToF("0x3.0p0", flags, 0.0f,
+                                 &processed, &all_used));
+  CHECK_EQ(0, processed);
+
+  CHECK_EQ(Single::NaN(), StrToF("0x3.p0", flags, 0.0f,
+                                 &processed, &all_used));
   CHECK_EQ(0, processed);
 
   flags = StringToDoubleConverter::ALLOW_HEX;
@@ -3892,6 +3994,20 @@
   CHECK_EQ(Single::NaN(), StrToF("+ +0x5", flags, 0.0f,  &processed, &all_used));
   CHECK_EQ(0, processed);
 
+  CHECK_EQ(Single::NaN(), StrToF("0x3p0", flags, 0.0f, &processed, &all_used));
+  CHECK_EQ(0, processed);
+
+  CHECK_EQ(Single::NaN(), StrToF("0x.0p0", flags, 0.0f, &processed, &all_used));
+  CHECK_EQ(0, processed);
+
+  CHECK_EQ(Single::NaN(), StrToF("0x3.0p0", flags, 0.0f,
+                                 &processed, &all_used));
+  CHECK_EQ(0, processed);
+
+  CHECK_EQ(Single::NaN(), StrToF("0x3.p0", flags, 0.0f,
+                                 &processed, &all_used));
+  CHECK_EQ(0, processed);
+
   flags = StringToDoubleConverter::ALLOW_TRAILING_JUNK |
       StringToDoubleConverter::ALLOW_HEX;
 
@@ -4014,6 +4130,19 @@
   CHECK_EQ(Single::NaN(), StrToF("+ +0x5", flags, 0.0f,  &processed, &all_used));
   CHECK_EQ(0, processed);
 
+  CHECK_EQ(3.0f, StrToF("0x3p0", flags, 0.0f, &processed, &all_used));
+  CHECK_EQ(3, processed);
+
+  CHECK_EQ(Single::NaN(), StrToF("0x.0p0", flags, 0.0f, &processed, &all_used));
+  CHECK_EQ(0, processed);
+
+  CHECK_EQ(3.0f, StrToF("0x3.0p0", flags, 0.0f, &processed, &all_used));
+  CHECK_EQ(3, processed);
+
+  CHECK_EQ(3.0f, StrToF("0x3.p0", flags, 0.0f, &processed, &all_used));
+  CHECK_EQ(3, processed);
+
+
   flags = StringToDoubleConverter::ALLOW_TRAILING_JUNK |
       StringToDoubleConverter::ALLOW_LEADING_SPACES |
       StringToDoubleConverter::ALLOW_TRAILING_SPACES |