4040#include < string_view>
4141#include < system_error>
4242#include < tuple>
43+ #include < type_traits>
4344#include < utility>
4445
4546enum class argument : uint8_t {
@@ -127,6 +128,47 @@ namespace detail {
127128 throw 5 ;
128129 }
129130
131+ template <std::integral T>
132+ inline void read_value (std::string_view parameter, T& value) {
133+ bool const starts_with_minus = parameter.starts_with (' -' );
134+ if (starts_with_minus || parameter.starts_with (' +' )) {
135+ parameter.remove_prefix (1 );
136+ }
137+
138+ if constexpr (std::is_unsigned_v<T>) {
139+ if (starts_with_minus) {
140+ std::cerr << " Cannot parse negative value for unsigned type!\n " ;
141+ throw 5 ;
142+ }
143+ }
144+ size_t const base = [&]() {
145+ if (parameter.starts_with (" 0x" ) || parameter.starts_with (" 0X" )) {
146+ parameter.remove_prefix (2 );
147+ return 16U ;
148+ }
149+ if (parameter.starts_with (" 0b" ) || parameter.starts_with (" 0B" )) {
150+ parameter.remove_prefix (2 );
151+ return 2U ;
152+ }
153+ if (parameter.starts_with (" 0o" ) || parameter.starts_with (" 0O" )) {
154+ parameter.remove_prefix (2 );
155+ return 8U ;
156+ }
157+ return 10U ;
158+ }();
159+ auto [ptr, ec] = std::from_chars (
160+ std::ranges::cbegin (parameter), std::ranges::cend (parameter), value,
161+ base);
162+ if (ec != std::errc{} || ptr != std::ranges::cend (parameter)) {
163+ print_error (ec, " value" , parameter.data ());
164+ }
165+ if constexpr (std::is_signed_v<T>) {
166+ if (starts_with_minus) {
167+ value = -value;
168+ }
169+ }
170+ }
171+
130172 template <typename options_t >
131173 concept has_crunch = requires (options_t opt) {
132174 { opt.crunch } -> std::same_as<bool &>;
@@ -220,13 +262,11 @@ namespace detail {
220262 inline void parse_extract (options_t & options, char const * parameter_in) {
221263 options.extract = true ;
222264 if (parameter_in != nullptr ) {
223- std::string_view const parameter (parameter_in);
224- auto [ptr, ec] = std::from_chars (
225- std::ranges::cbegin (parameter), std::ranges::cend (parameter),
226- options.pointer );
227- if (ec != std::errc{}) {
228- print_error (ec, " pointer" , parameter_in);
229- }
265+ read_value ({parameter_in}, options.pointer );
266+ }
267+ if (options.pointer < 0 ) {
268+ std::cerr << " Error: specified file offset must be a positive number.\n " ;
269+ throw 4 ;
230270 }
231271 }
232272
@@ -248,13 +288,7 @@ namespace detail {
248288 inline void parse_padding (options_t & options, char const * parameter_in) {
249289 if constexpr (has_padding<options_t >) {
250290 if (parameter_in != nullptr ) {
251- std::string_view const parameter (parameter_in);
252- auto [ptr, ec] = std::from_chars (
253- std::ranges::cbegin (parameter), std::ranges::cend (parameter),
254- options.padding );
255- if (ec != std::errc{}) {
256- print_error (ec, " padding" , optarg);
257- }
291+ read_value ({parameter_in}, options.padding );
258292 }
259293 if ((options.padding == 0U ) || !std::has_single_bit (options.padding )) {
260294 options.padding = options_t ::format_t ::MODULE_PADDING;
@@ -270,10 +304,10 @@ namespace detail {
270304 }
271305
272306 template <typename options_t >
273- inline void parse_size (options_t & options, char const * parameter ) {
307+ inline void parse_size (options_t & options, char const * parameter_in ) {
274308 if constexpr (has_size<options_t >) {
275- if (parameter != nullptr ) {
276- options. size = strtoul (parameter, nullptr , 0 );
309+ if (parameter_in != nullptr ) {
310+ read_value ({parameter_in}, options. size );
277311 }
278312 if (options.size == 0 ) {
279313 std::cerr << " Error: specified size must be a positive number.\n " ;
0 commit comments