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);