4#ifndef TETL_STRINGS_TO_INTEGER_HPP
5#define TETL_STRINGS_TO_INTEGER_HPP
7#include <etl/_cctype/isalpha.hpp>
8#include <etl/_cctype/isdigit.hpp>
9#include <etl/_cctype/isspace.hpp>
10#include <etl/_cctype/tolower.hpp>
11#include <etl/_concepts/integral.hpp>
12#include <etl/_concepts/signed_integral.hpp>
13#include <etl/_cstddef/size_t.hpp>
14#include <etl/_iterator/next.hpp>
15#include <etl/_limits/numeric_limits.hpp>
16#include <etl/_numeric/abs.hpp>
17#include <etl/_string_view/basic_string_view.hpp>
18#include <etl/_type_traits/conditional.hpp>
24template <integral Int>
25struct nop_overflow_checker {
26 explicit constexpr nop_overflow_checker(Int )
noexcept { }
28 [[nodiscard]]
constexpr auto operator()(Int , Int )
const noexcept ->
bool
34template <integral Int>
35struct unsigned_overflow_checker {
36 explicit constexpr unsigned_overflow_checker(Int base)
noexcept
42 [[nodiscard]]
constexpr auto operator()(Int value, Int digit)
const noexcept ->
bool
44 return value > _maxDivBase
or (value == _maxDivBase
and digit > _maxModBase);
52template <integral Int>
53struct signed_overflow_checker {
54 explicit constexpr signed_overflow_checker(Int base)
noexcept
56 , _minModBase{abs(
static_cast<Int>(
numeric_limits<Int>::min() % base))}
60 [[nodiscard]]
constexpr auto operator()(Int value, Int digit)
const noexcept ->
bool
62 return value < _minDivBase
or (value == _minDivBase
and digit > _minModBase);
70template <integral Int,
bool Check>
71using overflow_checker = conditional_t<
73 conditional_t<signed_integral<Int>, signed_overflow_checker<Int>, unsigned_overflow_checker<Int>>,
74 nop_overflow_checker<Int>
90template <integral Int>
92 char const*
end{
nullptr};
100 auto const length = str
.size();
101 auto const wouldOverflow = detail::overflow_checker<Int, Options
.check_overflow>{base};
103 auto const parseDigit = [](
int ch) -> Int {
105 return static_cast<Int>(ch -
int{
'0'});
108 return static_cast<Int>(
static_cast<Int>(
etl::tolower(ch
)) - Int{
'a'} + Int{10});
113 auto const invalidInputError = [end
= str
.data()] {
120 auto const overflowError = [&]<
bool MatchRestOfPattern>(
auto pos, bool_constant<MatchRestOfPattern> ) {
121 if constexpr (MatchRestOfPattern) {
122 for (; pos != length; ++pos) {
123 auto const digit = parseDigit(
static_cast<
int>(str[pos]));
144 return invalidInputError();
148 [[maybe_unused]]
auto positive =
true;
149 if constexpr (signed_integral<Int>) {
150 if (str
[pos
] ==
'-') {
152 if (++pos == length) {
154 return invalidInputError();
161 auto const ch =
static_cast<
int>(str
[pos++
]);
162 auto const digit =
static_cast<Int>(parseDigit(ch));
163 if constexpr (signed_integral<Int>) {
164 return static_cast<Int>(-digit);
170 if (
etl::abs(value) >= base) {
171 return invalidInputError();
175 for (; pos != length; ++pos) {
176 auto const digit = parseDigit(
static_cast<
int>(str
[pos
]));
181 if (wouldOverflow(value, digit)) {
182 return overflowError(pos,
etl::true_type{});
185 if constexpr (signed_integral<Int>) {
186 value =
static_cast<Int>(value * base - digit);
188 value =
static_cast<Int>(value * base + digit);
192 if constexpr (signed_integral<Int>) {
195 return overflowError(pos,
etl::false_type{});
constexpr auto isalpha(int ch) noexcept -> int
Checks if the given character is an alphabetic character as classified by the default C locale.
Definition isalpha.hpp:19
constexpr auto isdigit(int ch) noexcept -> int
Checks if the given character is one of the 10 decimal digits: 0123456789.
Definition isdigit.hpp:16
constexpr auto isspace(int ch) noexcept -> int
Checks if the given character is whitespace character as classified by the default C locale.
Definition isspace.hpp:20
constexpr auto tolower(int ch) noexcept -> int
Converts the given character to lowercase according to the character conversion rules defined by the ...
Definition tolower.hpp:27
constexpr auto next(InputIt it, typename iterator_traits< InputIt >::difference_type n=1) -> InputIt
Return the nth successor of iterator it.
Definition next.hpp:15
to_integer_error
Definition to_integer.hpp:84
constexpr auto to_integer(string_view str, Int base=Int(10)) noexcept -> to_integer_result< Int >
Definition to_integer.hpp:98
Definition adjacent_find.hpp:9
constexpr auto operator[](size_type pos) const -> const_reference
Returns a const reference to the character at specified location pos.
Definition basic_string_view.hpp:165
constexpr auto data() const noexcept -> const_pointer
Returns a pointer to the underlying character array. The pointer is such that the range [data(); data...
Definition basic_string_view.hpp:190
constexpr auto size() const noexcept -> size_type
Returns the number of Char elements in the view, i.e. etl::distance(begin(), end()).
Definition basic_string_view.hpp:196
Definition numeric_limits.hpp:18
Definition to_integer.hpp:79
bool check_overflow
Definition to_integer.hpp:81
bool skip_whitespace
Definition to_integer.hpp:80
Definition to_integer.hpp:91
to_integer_error error
Definition to_integer.hpp:93
Int value
Definition to_integer.hpp:94
char const * end
Definition to_integer.hpp:92