more optimizations
diff --git a/src/json.hpp b/src/json.hpp
index 2910245..26d8007 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -8800,44 +8800,41 @@
the value is in the responsability of the caller.
@param[out] result the result of the conversion
- @param skip_first whether the first character should be skipped
+ @param[in] digit_pointer the first digit to parse (is m_start for
+ unsigned integers and m_start+1 for signed
+ integers to skip the leading `-`)
@tparam T an unsigned integer type
@return true iff overflow occurred; false if conversion succeeded
- @pre The re2c lexer has successfully parsed an integer number. Only
- two cases are valid: (1) all characters between m_start and m_cursor
- are digits (unsigned integer) and @a skip_first is set to false, or
- (2) the character at m_start is a '-' which will be ignored (@a
- skip_first is set to true) and all other characters until m_cursor
- are digits (signed integer).
+ @pre The re2c lexer has successfully parsed an integer number. In this
+ case, all characters between @a digit_pointer and m_cursor are digits.
+ For unsigned integers, digits_pointer == m_start. For signed integers,
+ digits_pointer == m_start+1, because the `-` needs to be skipped.
- @post Either the string between m_start and m_cursor is processed
- completely, @a result contains the parsed number, and the function
- returns false; or parsing was interrupted prematurely, because an
- overflow was detected. Then, the function returns true.
+ @pre @a result must be set to 0 initially.
+
+ @post Either the string between @a digit_pointer and m_cursor is
+ processed completely, @a result contains the parsed number, and the
+ function returns false; or parsing was interrupted prematurely,
+ because an overflow was detected. Then, the function returns true.
*/
template<typename T>
- bool get_uint(T& result, bool skip_first) const
+ bool get_uint(T& result, const lexer_char_t* digit_pointer) const
{
- assert(m_start != nullptr);
- assert(m_start != m_cursor);
-
- // initially, set the result to 0
- result = 0;
+ assert(digit_pointer != nullptr);
+ assert(digit_pointer != m_cursor);
+ assert(result == 0);
// maximal possible value for number_unsigned_t
static constexpr T max_value = std::numeric_limits<T>::max();
// maximal intermediate value before multiplying by 10
static constexpr T max_intermediate = max_value / 10;
- /// pointer to the first digit (possibly skipping a '-')
- const auto first_digit = skip_first ? (m_start + 1) : m_start;
-
// after re2c successfully parsed a number, the digits are between
- // first_digit and m_cursor
- for (auto p = first_digit; p != m_cursor; ++p)
+ // digit_pointer and m_cursor
+ for (; digit_pointer != m_cursor; ++digit_pointer)
{
// check if multiplying by 10 would result in overflow
if (result > max_intermediate)
@@ -8849,7 +8846,8 @@
result *= 10;
// the current digit
- const T digit = static_cast<T>(*reinterpret_cast<typename string_t::const_pointer>(p) - '0');
+ const T digit = static_cast<T>(*reinterpret_cast<typename string_t::const_pointer>
+ (digit_pointer) - '0');
// check if adding the digit would result in overflow
if (digit > (max_value - result))
@@ -8880,9 +8878,10 @@
{
// optimistically set result to unsigned int
result.m_type = value_t::number_unsigned;
+ result.m_value = value_t::number_unsigned;
// parse the number
- const bool overflow = get_uint(result.m_value.number_unsigned, false);
+ const bool overflow = get_uint(result.m_value.number_unsigned, m_start);
// if an overflow occurred, try again parsing the number to float
if (overflow)
@@ -8908,7 +8907,7 @@
// parse as unsigned integer while skipping the leading '-'
number_unsigned_t unsigned_value = 0;
- const bool overflow = get_uint(unsigned_value, true);
+ const bool overflow = get_uint(unsigned_value, m_start + 1);
// store negated number
result.m_value.number_integer = static_cast<number_integer_t>(-unsigned_value);
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index e37fe68..4668d02 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -8019,44 +8019,41 @@
the value is in the responsability of the caller.
@param[out] result the result of the conversion
- @param skip_first whether the first character should be skipped
+ @param[in] digit_pointer the first digit to parse (is m_start for
+ unsigned integers and m_start+1 for signed
+ integers to skip the leading `-`)
@tparam T an unsigned integer type
@return true iff overflow occurred; false if conversion succeeded
- @pre The re2c lexer has successfully parsed an integer number. Only
- two cases are valid: (1) all characters between m_start and m_cursor
- are digits (unsigned integer) and @a skip_first is set to false, or
- (2) the character at m_start is a '-' which will be ignored (@a
- skip_first is set to true) and all other characters until m_cursor
- are digits (signed integer).
+ @pre The re2c lexer has successfully parsed an integer number. In this
+ case, all characters between @a digit_pointer and m_cursor are digits.
+ For unsigned integers, digits_pointer == m_start. For signed integers,
+ digits_pointer == m_start+1, because the `-` needs to be skipped.
- @post Either the string between m_start and m_cursor is processed
- completely, @a result contains the parsed number, and the function
- returns false; or parsing was interrupted prematurely, because an
- overflow was detected. Then, the function returns true.
+ @pre @a result must be set to 0 initially.
+
+ @post Either the string between @a digit_pointer and m_cursor is
+ processed completely, @a result contains the parsed number, and the
+ function returns false; or parsing was interrupted prematurely,
+ because an overflow was detected. Then, the function returns true.
*/
template<typename T>
- bool get_uint(T& result, bool skip_first) const
+ bool get_uint(T& result, const lexer_char_t* digit_pointer) const
{
- assert(m_start != nullptr);
- assert(m_start != m_cursor);
-
- // initially, set the result to 0
- result = 0;
+ assert(digit_pointer != nullptr);
+ assert(digit_pointer != m_cursor);
+ assert(result == 0);
// maximal possible value for number_unsigned_t
static constexpr T max_value = std::numeric_limits<T>::max();
// maximal intermediate value before multiplying by 10
static constexpr T max_intermediate = max_value / 10;
- /// pointer to the first digit (possibly skipping a '-')
- const auto first_digit = skip_first ? (m_start + 1) : m_start;
-
// after re2c successfully parsed a number, the digits are between
- // first_digit and m_cursor
- for (auto p = first_digit; p != m_cursor; ++p)
+ // digit_pointer and m_cursor
+ for (; digit_pointer != m_cursor; ++digit_pointer)
{
// check if multiplying by 10 would result in overflow
if (result > max_intermediate)
@@ -8068,7 +8065,8 @@
result *= 10;
// the current digit
- const T digit = static_cast<T>(*reinterpret_cast<typename string_t::const_pointer>(p) - '0');
+ const T digit = static_cast<T>(*reinterpret_cast<typename string_t::const_pointer>
+ (digit_pointer) - '0');
// check if adding the digit would result in overflow
if (digit > (max_value - result))
@@ -8099,9 +8097,10 @@
{
// optimistically set result to unsigned int
result.m_type = value_t::number_unsigned;
+ result.m_value = value_t::number_unsigned;
// parse the number
- const bool overflow = get_uint(result.m_value.number_unsigned, false);
+ const bool overflow = get_uint(result.m_value.number_unsigned, m_start);
// if an overflow occurred, try again parsing the number to float
if (overflow)
@@ -8127,7 +8126,7 @@
// parse as unsigned integer while skipping the leading '-'
number_unsigned_t unsigned_value = 0;
- const bool overflow = get_uint(unsigned_value, true);
+ const bool overflow = get_uint(unsigned_value, m_start + 1);
// store negated number
result.m_value.number_integer = static_cast<number_integer_t>(-unsigned_value);