diff --git a/includes/cli.h b/includes/cli.h deleted file mode 100644 index 617a116..0000000 --- a/includes/cli.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef CLI_H -#define CLI_H - -#include -#include - -enum cli_code { - CLI_EXIT_SUCCESS = -1, - CLI_SUCCESS = 0, - CLI_ERROR = 1 -}; - -typedef int (*t_option_handler)(const char *arg, void *config); - -enum option_arg_type -{ - OPT_ARG_NONE = 0, - OPT_ARG_INT, - OPT_ARG_UINT, - OPT_ARG_SECONDS, - OPT_ARG_BYTES, - OPT_ARG_TTL, - OPT_ARG_STRING -}; - -struct option_descriptor -{ - char short_opt; - const char *long_opt; - int has_arg; - t_option_handler handler; - enum option_arg_type arg_type; - const char *description; -}; - -enum cli_code cli_parse(int argc, char **argv, void *config, - const struct option_descriptor *opts, size_t nb_opts, - char *opt_str, struct option *long_opts); - -#endif diff --git a/includes/internal/cli/options.h b/includes/internal/cli/options.h index 0d86ad7..83b5000 100644 --- a/includes/internal/cli/options.h +++ b/includes/internal/cli/options.h @@ -2,6 +2,14 @@ #define PING_CLI_OPT_H #include +#include "cli.h" + +/* Ping-specific arg types, extending libcli's base enum */ +enum { + OPT_ARG_SECONDS = OPT_ARG_STRING + 1, + OPT_ARG_BYTES, + OPT_ARG_TTL, +}; #define PING_OPTIONS_LIST \ X( \ diff --git a/includes/internal/cli/parse_utils.h b/includes/internal/cli/parse_utils.h index 8b54717..ab25ace 100644 --- a/includes/internal/cli/parse_utils.h +++ b/includes/internal/cli/parse_utils.h @@ -5,5 +5,6 @@ int cli_parse_uint64(const char *s, uint64_t *out); int cli_parse_float(const char *s, float *out); +int cli_parse_ufloat(const char *s, float *out); #endif diff --git a/includes/ping/cli.h b/includes/ping/cli.h index 36f4fdb..3e26845 100644 --- a/includes/ping/cli.h +++ b/includes/ping/cli.h @@ -1,7 +1,7 @@ #ifndef PING_CLI_H #define PING_CLI_H -#include "../cli.h" +#include #include "ping/ping.h" enum cli_code cli_parse_arguments(int argc, char **argv, diff --git a/src/cli/parse.c b/src/cli/parse.c deleted file mode 100644 index 85965f2..0000000 --- a/src/cli/parse.c +++ /dev/null @@ -1,119 +0,0 @@ -#include -#include - -#include "internal/cli/messages.h" -#include "ping/ft_ping_flags.h" - -/* Map -? to -h to support help shortcut */ -#define HANDLE_QUESTION_MARK(opt) \ - do { \ - if (opt == '?' && (optopt) == '?') \ - opt = 'h'; \ - } while (0) - -/* Forward declarations */ -static void build_long_options(struct option *long_opts, size_t nb_opts, - const struct option_descriptor *src); -static void build_optstr(char *dest, const struct option_descriptor *opts, - size_t nb_opts); -static const struct option_descriptor *find_option_handler(int opt, - const struct option_descriptor *opts, size_t nb_opts); -static int handle_one_option(int opt, char **argv, void *config, - uint64_t *opt_tracker, - const struct option_descriptor *opts, size_t nb_opts); -/* ------------------- */ - -enum cli_code -cli_parse(int argc, char **argv, void *config, - const struct option_descriptor *opts, size_t nb_opts, - char *opt_str, struct option *long_opts) -{ - uint64_t tracker = 0; - int opt; - int res; - - build_optstr(opt_str, opts, nb_opts); - build_long_options(long_opts, nb_opts, opts); - while (-1 != (opt = getopt_long(argc, argv, opt_str, long_opts, NULL))) - { - HANDLE_QUESTION_MARK(opt); - res = handle_one_option(opt, argv, config, &tracker, opts, nb_opts); - if (CLI_SUCCESS != res) - return (enum cli_code)res; - } - return CLI_SUCCESS; -} - -static void -build_optstr(char *dest, const struct option_descriptor *opts, size_t nb_opts) -{ - size_t str_i = 1; - - /* Mute default error messages */ - dest[0] = ':'; - - for (size_t opt_i = 0; opt_i < nb_opts; ++opt_i) - { - dest[str_i++] = opts[opt_i].short_opt; - switch (opts[opt_i].has_arg) - { - case optional_argument: dest[str_i++] = ':'; /* fall through */ - case required_argument: dest[str_i++] = ':'; break; - default: break; - } - } - dest[str_i] = '\0'; -} - -static int -handle_one_option(int opt, char **argv, void *config, - uint64_t *opt_tracker, - const struct option_descriptor *opts, size_t nb_opts) -{ - const char *current_opt = argv[optind - 1]; - const struct option_descriptor *desc; - size_t bitmask_index; - int res; - - if ('?' == opt) - return error_unknown_opt(current_opt); - else if (':' == opt) - return error_invalid_opt(current_opt); - - desc = find_option_handler(opt, opts, nb_opts); - bitmask_index = (size_t)(desc - opts); - if (HAS_FLAG(*opt_tracker, (1ULL << bitmask_index))) - return error_duplicate_opt(current_opt); - - SET_FLAG(*opt_tracker, (1ULL << bitmask_index)); - res = desc->handler(optarg, config); - if (CLI_ERROR == res) - return error_invalid_opt(current_opt); - return res; -} - -static void -build_long_options(struct option *long_opts, size_t nb_opts, - const struct option_descriptor *src) -{ - for (size_t i = 0; i < nb_opts; ++i) - { - long_opts[i].name = src[i].long_opt; - long_opts[i].has_arg = src[i].has_arg; - long_opts[i].flag = NULL; - long_opts[i].val = src[i].short_opt; - } - long_opts[nb_opts] = (struct option){0}; -} - -static const struct option_descriptor * -find_option_handler(int opt, const struct option_descriptor *opts, - size_t nb_opts) -{ - for (size_t i = 0; i < nb_opts; ++i) - { - if (opts[i].short_opt == opt) - return &opts[i]; - } - return NULL; -} diff --git a/src/cli/parse_utils/parse_float.c b/src/cli/parse_utils/parse_float.c deleted file mode 100644 index 85de590..0000000 --- a/src/cli/parse_utils/parse_float.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include - -int -cli_parse_float(const char *s, float *out) -{ - char *end; - - if (NULL == s || '\0' == *s || '-' == *s) - return 1; - - errno = 0; - float v = strtof(s, &end); - - if (s == end || ERANGE == errno || '\0' != *end || 0 == isfinite(v)) - return 1; - - *out = v; - return 0; -} diff --git a/src/cli/parse_utils/parse_int.c b/src/cli/parse_utils/parse_int.c deleted file mode 100644 index 9a3cdeb..0000000 --- a/src/cli/parse_utils/parse_int.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include - -int -cli_parse_uint64(const char *s, uint64_t *out) -{ - char *end; - - if ( NULL == s || '\0' == *s || '-' == *s) - return 1; - - errno = 0; - const uintmax_t v = (uintmax_t)strtoumax(s, &end, 10); - - if (s == end || ERANGE == errno || '\0' != *end || v > UINT64_MAX) - return 1; - - *out = (uint64_t)v; - return 0; -} diff --git a/src/ping/cli/handlers/handle_deadline.c b/src/ping/cli/handlers/handle_deadline.c index b707147..c45179b 100644 --- a/src/ping/cli/handlers/handle_deadline.c +++ b/src/ping/cli/handlers/handle_deadline.c @@ -7,7 +7,7 @@ cli_handle_deadline(const char *arg, void *config_void) struct ping_config *config = (struct ping_config *)config_void; float deadline; - if (0 != cli_parse_float(arg, &deadline)) + if (0 != cli_parse_ufloat(arg, &deadline)) return CLI_ERROR; config->deadline = deadline; return CLI_SUCCESS; diff --git a/src/ping/cli/handlers/handle_interval.c b/src/ping/cli/handlers/handle_interval.c index 8e72067..0952b5f 100644 --- a/src/ping/cli/handlers/handle_interval.c +++ b/src/ping/cli/handlers/handle_interval.c @@ -7,7 +7,7 @@ cli_handle_interval(const char *arg, void *config_void) struct ping_config *config = (struct ping_config *)config_void; float interval; - if (0 != cli_parse_float(arg, &interval)) + if (0 != cli_parse_ufloat(arg, &interval)) return CLI_ERROR; config->interval = interval; diff --git a/src/ping/cli/handlers/handle_timeout.c b/src/ping/cli/handlers/handle_timeout.c index 959acc3..d23ae9c 100644 --- a/src/ping/cli/handlers/handle_timeout.c +++ b/src/ping/cli/handlers/handle_timeout.c @@ -7,7 +7,7 @@ cli_handle_timeout(const char *arg, void *config_void) struct ping_config *config = (struct ping_config *)config_void; float TO; - if (0 != cli_parse_float(arg, &TO)) + if (0 != cli_parse_ufloat(arg, &TO)) return CLI_ERROR; config->timeout = TO; diff --git a/src/ping/cli/messages/help.c b/src/ping/cli/messages/help.c index cbf5f18..548bd0f 100644 --- a/src/ping/cli/messages/help.c +++ b/src/ping/cli/messages/help.c @@ -4,7 +4,7 @@ #include "internal/cli/options.h" /* Forward declarations */ -static inline const char * option_arg_type_to_str(enum option_arg_type type); +static inline const char * option_arg_type_to_str(int type); /* -------------------- */ void @@ -29,7 +29,7 @@ print_help(void) } static inline const char * -option_arg_type_to_str(enum option_arg_type type) +option_arg_type_to_str(int type) { switch (type) { diff --git a/tests/cli/parse_utils/test_parse_float.c b/tests/cli/parse_utils/test_parse_float.c index 4af92cf..453b6c8 100644 --- a/tests/cli/parse_utils/test_parse_float.c +++ b/tests/cli/parse_utils/test_parse_float.c @@ -39,13 +39,14 @@ Test(parse_float, empty_string) cr_assert_eq(ret, 1); } -/* Test 5: Negative number */ +/* Test 5: Negative number (cli_parse_float accepts negatives; use cli_parse_ufloat to reject) */ Test(parse_float, negative_number) { float result; int ret = cli_parse_float("-42", &result); - - cr_assert_eq(ret, 1); + + cr_assert_eq(ret, 0); + cr_assert_float_eq(result, -42.0f, 0.001f); } /* Test 6: Invalid characters */