Support separator characters.
Fixes #49
diff --git a/double-conversion/double-conversion.cc b/double-conversion/double-conversion.cc
index ba83bef..ecd1a5e 100644
--- a/double-conversion/double-conversion.cc
+++ b/double-conversion/double-conversion.cc
@@ -551,6 +551,26 @@
return radix > 10 && c >= a_character && c < a_character + radix - 10;
}
+// Returns true, when the iterator is equal to end.
+template<class Iterator>
+static bool Advance (Iterator* it, char separator, int base, Iterator& end) {
+ if (separator == StringToDoubleConverter::kNoSeparator) {
+ ++(*it);
+ return *it == end;
+ }
+ if (!isDigit(**it, base)) {
+ ++(*it);
+ return *it == end;
+ }
+ ++(*it);
+ if (*it == end) return true;
+ if (*it + 1 == end) return false;
+ if (**it == separator && isDigit(*(*it + 1), base)) {
+ ++(*it);
+ }
+ return *it == end;
+}
+
// 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.
//
@@ -561,27 +581,35 @@
template<class Iterator>
static bool IsHexFloatString(Iterator start,
Iterator end,
+ char separator,
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.
+ bool saw_digit = false;
+ while (isDigit(*current, 16)) {
+ saw_digit = true;
+ if (Advance(¤t, separator, 16, end)) return false;
}
- if (current == end) return false;
+ if (*current == '.') {
+ if (Advance(¤t, separator, 16, end)) return false;
+ while (isDigit(*current, 16)) {
+ saw_digit = true;
+ if (Advance(¤t, separator, 16, end)) return false;
+ }
+ if (!saw_digit) return false; // Only the '.', but no digits.
+ }
if (*current != 'p' && *current != 'P') return false;
- ++current;
- if (current == end) return false;
- if (*current == '+' || *current == '-') ++current;
- if (current == end) return false;
+ if (Advance(¤t, separator, 16, end)) return false;
+ if (*current == '+' || *current == '-') {
+ if (Advance(¤t, separator, 16, end)) return false;
+ }
if (!isDigit(*current, 10)) return false;
- ++current;
- while (current != end && isDigit(*current, 10)) ++current;
+ if (Advance(¤t, separator, 16, end)) return true;
+ while (isDigit(*current, 10)) {
+ if (Advance(¤t, separator, 16, end)) return true;
+ }
return allow_trailing_junk || !AdvanceToNonspace(¤t, end);
}
@@ -594,6 +622,7 @@
static double RadixStringToIeee(Iterator* current,
Iterator end,
bool sign,
+ char separator,
bool parse_as_hex_float,
bool allow_trailing_junk,
double junk_string_value,
@@ -601,7 +630,7 @@
bool* result_is_junk) {
ASSERT(*current != end);
ASSERT(!parse_as_hex_float ||
- IsHexFloatString(*current, end, allow_trailing_junk));
+ IsHexFloatString(*current, end, separator, allow_trailing_junk));
const int kDoubleSize = Double::kSignificandSize;
const int kSingleSize = Single::kSignificandSize;
@@ -609,15 +638,6 @@
*result_is_junk = true;
- // Skip leading 0s.
- while (**current == '0') {
- ++(*current);
- if (*current == end) {
- *result_is_junk = false;
- return SignedZero(sign);
- }
- }
-
int64_t number = 0;
int exponent = 0;
const int radix = (1 << radix_log_2);
@@ -625,7 +645,15 @@
// Only relevant if parse_as_hex_float is true.
bool post_decimal = false;
- do {
+ // Skip leading 0s.
+ while (**current == '0') {
+ if (Advance(current, separator, radix, end)) {
+ *result_is_junk = false;
+ return SignedZero(sign);
+ }
+ }
+
+ while (true) {
int digit;
if (IsDecimalDigitForRadix(**current, radix)) {
digit = static_cast<char>(**current) - '0';
@@ -638,7 +666,8 @@
if (post_decimal) exponent -= radix_log_2;
} else if (parse_as_hex_float && **current == '.') {
post_decimal = true;
- ++(*current);
+ Advance(current, separator, radix, end);
+ ASSERT(*current != end);
continue;
} else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) {
break;
@@ -668,14 +697,15 @@
bool zero_tail = true;
for (;;) {
- ++(*current);
+ if (Advance(current, separator, radix, end)) break;
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);
+ Advance(current, separator, radix, end);
+ ASSERT(*current != end);
post_decimal = true;
}
- if (*current == end || !isDigit(**current, radix)) break;
+ if (!isDigit(**current, radix)) break;
zero_tail = zero_tail && **current == '0';
if (!post_decimal) exponent += radix_log_2;
}
@@ -704,8 +734,8 @@
}
break;
}
- ++(*current);
- } while (*current != end);
+ if (Advance(current, separator, radix, end)) break;
+ }
ASSERT(number < ((int64_t)1 << kSignificandSize));
ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
@@ -714,18 +744,21 @@
if (parse_as_hex_float) {
ASSERT(**current == 'p' || **current == 'P');
- ++(*current);
+ Advance(current, separator, radix, end);
+ ASSERT(*current != end);
bool is_negative = false;
if (**current == '+') {
- ++(*current);
+ Advance(current, separator, radix, end);
+ ASSERT(*current != end);
} else if (**current == '-') {
is_negative = true;
- ++(*current);
+ Advance(current, separator, radix, end);
+ ASSERT(*current != end);
}
int written_exponent = 0;
- while (*current != end && IsDecimalDigitForRadix(**current, 10)) {
+ while (IsDecimalDigitForRadix(**current, 10)) {
written_exponent = 10 * written_exponent + **current - '0';
- ++(*current);
+ if (Advance(current, separator, radix, end)) break;
}
if (is_negative) written_exponent = -written_exponent;
exponent += written_exponent;
@@ -761,7 +794,6 @@
const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
const bool allow_case_insensibility = (flags_ & ALLOW_CASE_INSENSIBILITY) != 0;
-
// To make sure that iterator dereferencing is valid the following
// convention is used:
// 1. Each '++current' statement is followed by check for equality to 'end'.
@@ -849,8 +881,7 @@
bool leading_zero = false;
if (*current == '0') {
- ++current;
- if (current == end) {
+ if (Advance(¤t, separator_, 10, end)) {
*processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
@@ -863,7 +894,7 @@
++current;
bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) &&
- IsHexFloatString(current, end, allow_trailing_junk);
+ IsHexFloatString(current, end, separator_, allow_trailing_junk);
if (current == end) return junk_string_value_; // "0x"
if (!parse_as_hex_float && !isDigit(*current, 16)) {
@@ -874,6 +905,7 @@
double result = RadixStringToIeee<4>(¤t,
end,
sign,
+ separator_,
parse_as_hex_float,
allow_trailing_junk,
junk_string_value_,
@@ -888,8 +920,7 @@
// Ignore leading zeros in the integer part.
while (*current == '0') {
- ++current;
- if (current == end) {
+ if (Advance(¤t, separator_, 10, end)) {
*processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
@@ -910,8 +941,7 @@
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
}
octal = octal && *current < '8';
- ++current;
- if (current == end) goto parsing_done;
+ if (Advance(¤t, separator_, 10, end)) goto parsing_done;
}
if (significant_digits == 0) {
@@ -922,8 +952,7 @@
if (octal && !allow_trailing_junk) return junk_string_value_;
if (octal) goto parsing_done;
- ++current;
- if (current == end) {
+ if (Advance(¤t, separator_, 10, end)) {
if (significant_digits == 0 && !leading_zero) {
return junk_string_value_;
} else {
@@ -936,8 +965,7 @@
// Integer part consists of 0 or is absent. Significant digits start after
// leading zeros (if any).
while (*current == '0') {
- ++current;
- if (current == end) {
+ if (Advance(¤t, separator_, 10, end)) {
*processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
@@ -957,8 +985,7 @@
// Ignore insignificant digits in the fractional part.
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
}
- ++current;
- if (current == end) goto parsing_done;
+ if (Advance(¤t, separator_, 10, end)) goto parsing_done;
}
}
@@ -1045,6 +1072,7 @@
result = RadixStringToIeee<3>(&start,
buffer + buffer_pos,
sign,
+ separator_,
false, // Don't parse as hex_float.
allow_trailing_junk,
junk_string_value_,
diff --git a/double-conversion/double-conversion.h b/double-conversion/double-conversion.h
index 86cf25e..7495d17 100644
--- a/double-conversion/double-conversion.h
+++ b/double-conversion/double-conversion.h
@@ -399,6 +399,8 @@
ALLOW_HEX_FLOATS = 128,
};
+ static const uc16 kNoSeparator = '\0';
+
// Flags should be a bit-or combination of the possible Flags-enum.
// - NO_FLAGS: no special flags.
// - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers.
@@ -459,6 +461,12 @@
// - they must not have the same first character.
// - they must not start with digits.
//
+ // If the separator character is not kNoSeparator, then that specific
+ // character is ignored when in between two valid digits of the significant.
+ // It is not allowed to appear in the exponent.
+ // It is not allowed to lead or trail the number.
+ // It is not allowed to appear twice next to each other.
+ //
// Examples:
// flags = ALLOW_HEX | ALLOW_TRAILING_JUNK,
// empty_string_value = 0.0,
@@ -498,16 +506,26 @@
// StringToDouble("01239E45") -> 1239e45.
// StringToDouble("-infinity") -> NaN // junk_string_value.
// StringToDouble("NaN") -> NaN // junk_string_value.
+ //
+ // flags = NO_FLAGS,
+ // separator = ' ':
+ // StringToDouble("1 2 3 4") -> 1234.0
+ // StringToDouble("1 2") -> NaN // junk_string_value
+ // StringToDouble("1 000 000.0") -> 1000000.0
+ // StringToDouble("1.000 000") -> 1.0
+ // StringToDouble("1.0e1 000") -> NaN // junk_string_value
StringToDoubleConverter(int flags,
double empty_string_value,
double junk_string_value,
const char* infinity_symbol,
- const char* nan_symbol)
+ const char* nan_symbol,
+ uc16 separator = kNoSeparator)
: flags_(flags),
empty_string_value_(empty_string_value),
junk_string_value_(junk_string_value),
infinity_symbol_(infinity_symbol),
- nan_symbol_(nan_symbol) {
+ nan_symbol_(nan_symbol),
+ separator_(separator) {
}
// Performs the conversion.
@@ -542,6 +560,7 @@
const double junk_string_value_;
const char* const infinity_symbol_;
const char* const nan_symbol_;
+ const uc16 separator_;
template <class Iterator>
double StringToIeee(Iterator start_pointer,
diff --git a/test/cctest/test-conversions.cc b/test/cctest/test-conversions.cc
index cf556e6..1173416 100644
--- a/test/cctest/test-conversions.cc
+++ b/test/cctest/test-conversions.cc
@@ -1720,9 +1720,10 @@
static double StrToD16(const uc16* str16, int length, int flags,
double empty_string_value,
- int* processed_characters_count, bool* processed_all) {
+ int* processed_characters_count, bool* processed_all,
+ uc16 separator = StringToDoubleConverter::kNoSeparator) {
StringToDoubleConverter converter(flags, empty_string_value, Double::NaN(),
- NULL, NULL);
+ NULL, NULL, separator);
double result =
converter.StringToDouble(str16, length, processed_characters_count);
*processed_all = (length == *processed_characters_count);
@@ -1731,9 +1732,10 @@
static double StrToD(const char* str, int flags, double empty_string_value,
- int* processed_characters_count, bool* processed_all) {
+ int* processed_characters_count, bool* processed_all,
+ uc16 separator = StringToDoubleConverter::kNoSeparator) {
StringToDoubleConverter converter(flags, empty_string_value, Double::NaN(),
- NULL, NULL);
+ NULL, NULL, separator);
double result = converter.StringToDouble(str, strlen(str),
processed_characters_count);
*processed_all =
@@ -1748,7 +1750,8 @@
int processed_characters_count16;
bool processed_all16;
double result16 = StrToD16(buffer16, len, flags, empty_string_value,
- &processed_characters_count16, &processed_all16);
+ &processed_characters_count16, &processed_all16,
+ separator);
CHECK_EQ(result, result16);
CHECK_EQ(*processed_characters_count, processed_characters_count16);
return result;
@@ -3196,6 +3199,323 @@
}
+TEST(StringToDoubleSeparator) {
+ int flags;
+ int processed;
+ bool all_used;
+ char separator;
+
+ separator = '\'';
+ flags = StringToDoubleConverter::NO_FLAGS;
+
+ CHECK_EQ(1.0, StrToD("000'001.0'0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(1.0, StrToD("0'0'0'0'0'1.0'0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(Double::NaN(), StrToD("'1.0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1'.0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.'0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("0''1.0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e1'0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e1'", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e'1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0'e1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("+'1.0e1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("-'1.0e1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e+'1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e-'1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e'+1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e'-1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ separator = ' ';
+ flags = StringToDoubleConverter::NO_FLAGS;
+
+ CHECK_EQ(1.0, StrToD("000 001.0 0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(1.0, StrToD("0 0 0 0 0 1.0 0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(Double::NaN(), StrToD(" 1.0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1 .0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1. 0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("0 1.0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e1 0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e1 ", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e 1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0 e1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("+ 1.0e1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("- 1.0e1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e+ 1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e- 1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e +1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e -1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ separator = ' ';
+ flags = StringToDoubleConverter::ALLOW_LEADING_SPACES |
+ StringToDoubleConverter::ALLOW_TRAILING_SPACES;
+
+ CHECK_EQ(1.0, StrToD("000 001.0 0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(1.0, StrToD("0 0 0 0 0 1.0 0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(1.0, StrToD(" 000 001.0 0 ", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(1.0, StrToD(" 0 0 0 0 0 1.0 0 ", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(1.0, StrToD(" 1.0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(Double::NaN(), StrToD("1 .0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1. 0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("0 1.0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e1 0", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(10.0, StrToD("1.0e1 ", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e 1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0 e1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("+ 1.0e1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("- 1.0e1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e+ 1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e- 1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e +1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("1.0e -1", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ separator = ' ';
+ flags = StringToDoubleConverter::ALLOW_HEX |
+ StringToDoubleConverter::ALLOW_HEX_FLOATS |
+ StringToDoubleConverter::ALLOW_LEADING_SPACES |
+ StringToDoubleConverter::ALLOW_TRAILING_SPACES;
+
+ CHECK_EQ(18.0, StrToD("0x1 2", flags, 0.0, &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(0.0, StrToD("0x0 0", flags, 1.0, &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(static_cast<double>(0x123456789),
+ StrToD("0x1 2 3 4 5 6 7 8 9", flags, Double::NaN(),
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(18.0, StrToD(" 0x1 2 ", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(0.0, StrToD(" 0x0 ", flags, 1.0,
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(static_cast<double>(0x123456789),
+ StrToD(" 0x1 2 3 4 5 6 7 8 9 ", flags, Double::NaN(),
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(static_cast<double>(0xabcdef),
+ StrToD("0xa b c d e f", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(Double::NaN(), StrToD("0x 1 2", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD("0 x0", flags, 1.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(),
+ StrToD("0x1 2 3 4 5 6 7 8 9", flags, Double::NaN(),
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(), StrToD(" 0 x1 2 ", flags, 0.0,
+ &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(3.0,
+ StrToD("0x0 3p0", flags, 0.0, &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(0.0,
+ StrToD("0x.0 0p0", flags, 0.0, &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(3.0,
+ StrToD("0x3.0 0p0", flags, 0.0, &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(3.0,
+ StrToD("0x0 3.p0", flags, 0.0, &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(Double::NaN(),
+ StrToD("0x 3p0", flags, 0.0, &processed, &all_used));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(),
+ StrToD("0x.0 p0", flags, 0.0, &processed, &all_used));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(),
+ StrToD("0x3.0p0 0", flags, 0.0, &processed, &all_used));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(),
+ StrToD("0x0 3.p 0", flags, 0.0, &processed, &all_used));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(),
+ StrToD("0x3p+ 0", flags, 0.0, &processed, &all_used));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(),
+ StrToD("0x.0p- 0", flags, 0.0, &processed, &all_used));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(),
+ StrToD("0x3.0p +0", flags, 0.0, &processed, &all_used));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(Double::NaN(),
+ StrToD("0x0 3.p -0", flags, 0.0, &processed, &all_used));
+ CHECK_EQ(0, processed);
+}
+
TEST(StringToDoubleSpecialValues) {
int processed;
int flags = StringToDoubleConverter::NO_FLAGS;
@@ -3369,6 +3689,28 @@
CHECK_EQ(Double::NaN(), StrToD("NaN", flags, 0.0, &processed, &all_used));
CHECK_EQ(0, processed);
+
+ flags = StringToDoubleConverter::NO_FLAGS;
+ char separator = ' ';
+ CHECK_EQ(1234.0,
+ StrToD("1 2 3 4", flags, 0.0, &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(Double::NaN(),
+ StrToD("1 2", flags, 0.0, &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
+
+ CHECK_EQ(1000000.0,
+ StrToD("1 000 000.0", flags, 0.0, &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(1.0,
+ StrToD("1.000 000", flags, 0.0, &processed, &all_used, separator));
+ CHECK(all_used);
+
+ CHECK_EQ(Double::NaN(),
+ StrToD("1.0e1 000", flags, 0.0, &processed, &all_used, separator));
+ CHECK_EQ(0, processed);
}