Commit 40e9e5f0 authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

Make ToIntegralType() behavior configurable.

Introduce NumberParsingOptions, which is a set of parsing behavior flags, and
CharactersToFoo{,Strict}() pass options to ToIntegralType().

This CL has no behavior changes.
This CL is a preparation to merge CharactersToFoo and CharactersToFooStrict.

Bug: 746157
Change-Id: I34d001bb193928288b99afcd0d531536105ce7e0
Reviewed-on: https://chromium-review.googlesource.com/580170Reviewed-by: default avatarTakayoshi Kochi <kochi@chromium.org>
Commit-Queue: Kent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#488581}
parent 26ffad3a
...@@ -27,6 +27,7 @@ bool IsCharacterAllowedInBase<16>(UChar c) { ...@@ -27,6 +27,7 @@ bool IsCharacterAllowedInBase<16>(UChar c) {
template <typename IntegralType, typename CharType, int base> template <typename IntegralType, typename CharType, int base>
static inline IntegralType ToIntegralType(const CharType* data, static inline IntegralType ToIntegralType(const CharType* data,
size_t length, size_t length,
NumberParsingOptions options,
NumberParsingState* parsing_state) { NumberParsingState* parsing_state) {
static_assert(std::is_integral<IntegralType>::value, static_assert(std::is_integral<IntegralType>::value,
"IntegralType must be an integral type."); "IntegralType must be an integral type.");
...@@ -46,17 +47,18 @@ static inline IntegralType ToIntegralType(const CharType* data, ...@@ -46,17 +47,18 @@ static inline IntegralType ToIntegralType(const CharType* data,
if (!data) if (!data)
goto bye; goto bye;
// skip leading whitespace if (options.AcceptWhitespace()) {
while (length && IsSpaceOrNewline(*data)) { while (length && IsSpaceOrNewline(*data)) {
--length; --length;
++data; ++data;
}
} }
if (kIsSigned && length && *data == '-') { if (kIsSigned && length && *data == '-') {
--length; --length;
++data; ++data;
is_negative = true; is_negative = true;
} else if (length && *data == '+') { } else if (length && options.AcceptLeadingPlus() && *data == '+') {
--length; --length;
++data; ++data;
} }
...@@ -105,13 +107,14 @@ static inline IntegralType ToIntegralType(const CharType* data, ...@@ -105,13 +107,14 @@ static inline IntegralType ToIntegralType(const CharType* data,
++data; ++data;
} }
// skip trailing space if (options.AcceptWhitespace()) {
while (length && IsSpaceOrNewline(*data)) { while (length && IsSpaceOrNewline(*data)) {
--length; --length;
++data; ++data;
}
} }
if (length == 0) { if (length == 0 || options.AcceptTrailingGarbage()) {
if (!overflow) if (!overflow)
state = NumberParsingState::kSuccess; state = NumberParsingState::kSuccess;
} else { } else {
...@@ -126,129 +129,118 @@ bye: ...@@ -126,129 +129,118 @@ bye:
template <typename IntegralType, typename CharType, int base> template <typename IntegralType, typename CharType, int base>
static inline IntegralType ToIntegralType(const CharType* data, static inline IntegralType ToIntegralType(const CharType* data,
size_t length, size_t length,
NumberParsingOptions options,
bool* ok) { bool* ok) {
NumberParsingState state; NumberParsingState state;
IntegralType value = IntegralType value = ToIntegralType<IntegralType, CharType, base>(
ToIntegralType<IntegralType, CharType, base>(data, length, &state); data, length, options, &state);
if (ok) if (ok)
*ok = state == NumberParsingState::kSuccess; *ok = state == NumberParsingState::kSuccess;
return value; return value;
} }
template <typename CharType>
static unsigned LengthOfCharactersAsInteger(const CharType* data,
size_t length) {
size_t i = 0;
// Allow leading spaces.
for (; i != length; ++i) {
if (!IsSpaceOrNewline(data[i]))
break;
}
// Allow sign.
if (i != length && (data[i] == '+' || data[i] == '-'))
++i;
// Allow digits.
for (; i != length; ++i) {
if (!IsASCIIDigit(data[i]))
break;
}
return i;
}
unsigned CharactersToUIntStrict(const LChar* data, unsigned CharactersToUIntStrict(const LChar* data,
size_t length, size_t length,
NumberParsingState* state) { NumberParsingState* state) {
return ToIntegralType<unsigned, LChar, 10>(data, length, state); return ToIntegralType<unsigned, LChar, 10>(
data, length, NumberParsingOptions::kStrict, state);
} }
unsigned CharactersToUIntStrict(const UChar* data, unsigned CharactersToUIntStrict(const UChar* data,
size_t length, size_t length,
NumberParsingState* state) { NumberParsingState* state) {
return ToIntegralType<unsigned, UChar, 10>(data, length, state); return ToIntegralType<unsigned, UChar, 10>(
data, length, NumberParsingOptions::kStrict, state);
} }
int CharactersToIntStrict(const LChar* data, size_t length, bool* ok) { int CharactersToIntStrict(const LChar* data, size_t length, bool* ok) {
return ToIntegralType<int, LChar, 10>(data, length, ok); return ToIntegralType<int, LChar, 10>(data, length,
NumberParsingOptions::kStrict, ok);
} }
int CharactersToIntStrict(const UChar* data, size_t length, bool* ok) { int CharactersToIntStrict(const UChar* data, size_t length, bool* ok) {
return ToIntegralType<int, UChar, 10>(data, length, ok); return ToIntegralType<int, UChar, 10>(data, length,
NumberParsingOptions::kStrict, ok);
} }
unsigned CharactersToUIntStrict(const LChar* data, size_t length, bool* ok) { unsigned CharactersToUIntStrict(const LChar* data, size_t length, bool* ok) {
return ToIntegralType<unsigned, LChar, 10>(data, length, ok); return ToIntegralType<unsigned, LChar, 10>(data, length,
NumberParsingOptions::kStrict, ok);
} }
unsigned CharactersToUIntStrict(const UChar* data, size_t length, bool* ok) { unsigned CharactersToUIntStrict(const UChar* data, size_t length, bool* ok) {
return ToIntegralType<unsigned, UChar, 10>(data, length, ok); return ToIntegralType<unsigned, UChar, 10>(data, length,
NumberParsingOptions::kStrict, ok);
} }
unsigned HexCharactersToUIntStrict(const LChar* data, size_t length, bool* ok) { unsigned HexCharactersToUIntStrict(const LChar* data, size_t length, bool* ok) {
return ToIntegralType<unsigned, LChar, 16>(data, length, ok); return ToIntegralType<unsigned, LChar, 16>(data, length,
NumberParsingOptions::kStrict, ok);
} }
unsigned HexCharactersToUIntStrict(const UChar* data, size_t length, bool* ok) { unsigned HexCharactersToUIntStrict(const UChar* data, size_t length, bool* ok) {
return ToIntegralType<unsigned, UChar, 16>(data, length, ok); return ToIntegralType<unsigned, UChar, 16>(data, length,
NumberParsingOptions::kStrict, ok);
} }
int64_t CharactersToInt64Strict(const LChar* data, size_t length, bool* ok) { int64_t CharactersToInt64Strict(const LChar* data, size_t length, bool* ok) {
return ToIntegralType<int64_t, LChar, 10>(data, length, ok); return ToIntegralType<int64_t, LChar, 10>(data, length,
NumberParsingOptions::kStrict, ok);
} }
int64_t CharactersToInt64Strict(const UChar* data, size_t length, bool* ok) { int64_t CharactersToInt64Strict(const UChar* data, size_t length, bool* ok) {
return ToIntegralType<int64_t, UChar, 10>(data, length, ok); return ToIntegralType<int64_t, UChar, 10>(data, length,
NumberParsingOptions::kStrict, ok);
} }
uint64_t CharactersToUInt64Strict(const LChar* data, size_t length, bool* ok) { uint64_t CharactersToUInt64Strict(const LChar* data, size_t length, bool* ok) {
return ToIntegralType<uint64_t, LChar, 10>(data, length, ok); return ToIntegralType<uint64_t, LChar, 10>(data, length,
NumberParsingOptions::kStrict, ok);
} }
uint64_t CharactersToUInt64Strict(const UChar* data, size_t length, bool* ok) { uint64_t CharactersToUInt64Strict(const UChar* data, size_t length, bool* ok) {
return ToIntegralType<uint64_t, UChar, 10>(data, length, ok); return ToIntegralType<uint64_t, UChar, 10>(data, length,
NumberParsingOptions::kStrict, ok);
} }
int CharactersToInt(const LChar* data, size_t length, bool* ok) { int CharactersToInt(const LChar* data, size_t length, bool* ok) {
return ToIntegralType<int, LChar, 10>( return ToIntegralType<int, LChar, 10>(data, length,
data, LengthOfCharactersAsInteger<LChar>(data, length), ok); NumberParsingOptions::kLoose, ok);
} }
int CharactersToInt(const UChar* data, size_t length, bool* ok) { int CharactersToInt(const UChar* data, size_t length, bool* ok) {
return ToIntegralType<int, UChar, 10>( return ToIntegralType<int, UChar, 10>(data, length,
data, LengthOfCharactersAsInteger(data, length), ok); NumberParsingOptions::kLoose, ok);
} }
unsigned CharactersToUInt(const LChar* data, size_t length, bool* ok) { unsigned CharactersToUInt(const LChar* data, size_t length, bool* ok) {
return ToIntegralType<unsigned, LChar, 10>( return ToIntegralType<unsigned, LChar, 10>(data, length,
data, LengthOfCharactersAsInteger<LChar>(data, length), ok); NumberParsingOptions::kLoose, ok);
} }
unsigned CharactersToUInt(const UChar* data, size_t length, bool* ok) { unsigned CharactersToUInt(const UChar* data, size_t length, bool* ok) {
return ToIntegralType<unsigned, UChar, 10>( return ToIntegralType<unsigned, UChar, 10>(data, length,
data, LengthOfCharactersAsInteger<UChar>(data, length), ok); NumberParsingOptions::kLoose, ok);
} }
int64_t CharactersToInt64(const LChar* data, size_t length, bool* ok) { int64_t CharactersToInt64(const LChar* data, size_t length, bool* ok) {
return ToIntegralType<int64_t, LChar, 10>( return ToIntegralType<int64_t, LChar, 10>(data, length,
data, LengthOfCharactersAsInteger<LChar>(data, length), ok); NumberParsingOptions::kLoose, ok);
} }
int64_t CharactersToInt64(const UChar* data, size_t length, bool* ok) { int64_t CharactersToInt64(const UChar* data, size_t length, bool* ok) {
return ToIntegralType<int64_t, UChar, 10>( return ToIntegralType<int64_t, UChar, 10>(data, length,
data, LengthOfCharactersAsInteger<UChar>(data, length), ok); NumberParsingOptions::kLoose, ok);
} }
uint64_t CharactersToUInt64(const LChar* data, size_t length, bool* ok) { uint64_t CharactersToUInt64(const LChar* data, size_t length, bool* ok) {
return ToIntegralType<uint64_t, LChar, 10>( return ToIntegralType<uint64_t, LChar, 10>(data, length,
data, LengthOfCharactersAsInteger<LChar>(data, length), ok); NumberParsingOptions::kLoose, ok);
} }
uint64_t CharactersToUInt64(const UChar* data, size_t length, bool* ok) { uint64_t CharactersToUInt64(const UChar* data, size_t length, bool* ok) {
return ToIntegralType<uint64_t, UChar, 10>( return ToIntegralType<uint64_t, UChar, 10>(data, length,
data, LengthOfCharactersAsInteger<UChar>(data, length), ok); NumberParsingOptions::kLoose, ok);
} }
enum TrailingJunkPolicy { kDisallowTrailingJunk, kAllowTrailingJunk }; enum TrailingJunkPolicy { kDisallowTrailingJunk, kAllowTrailingJunk };
......
...@@ -10,6 +10,39 @@ ...@@ -10,6 +10,39 @@
namespace WTF { namespace WTF {
// Copyable and immutable object representing number parsing flags.
class NumberParsingOptions {
public:
static constexpr unsigned kNone = 0;
static constexpr unsigned kAcceptTrailingGarbage = 1;
static constexpr unsigned kAcceptLeadingPlus = 1 << 1;
static constexpr unsigned kAcceptLeadingTrailingWhitespace = 1 << 2;
// TODO(tkent): Add kAcceptMinusZeroForUnsigned
// Legacy 'Strict' behavior.
static constexpr unsigned kStrict =
kAcceptLeadingPlus | kAcceptLeadingTrailingWhitespace;
// Legacy non-'Strict' behavior.
static constexpr unsigned kLoose = kStrict | kAcceptTrailingGarbage;
// This constructor allows implicit conversion from unsigned.
NumberParsingOptions(unsigned options) : options_(options) {}
bool AcceptTrailingGarbage() const {
return options_ & kAcceptTrailingGarbage;
}
bool AcceptLeadingPlus() const { return options_ & kAcceptLeadingPlus; }
bool AcceptWhitespace() const {
return options_ & kAcceptLeadingTrailingWhitespace;
}
private:
unsigned options_;
};
// TODO(tkent): Merge CharactersToFooStrict and CharactersToFoo by adding
// NumberParsingOptions argument.
// string -> int. // string -> int.
WTF_EXPORT int CharactersToIntStrict(const LChar*, size_t, bool* ok); WTF_EXPORT int CharactersToIntStrict(const LChar*, size_t, bool* ok);
WTF_EXPORT int CharactersToIntStrict(const UChar*, size_t, bool* ok); WTF_EXPORT int CharactersToIntStrict(const UChar*, size_t, bool* ok);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment