DPDK patches and discussions
 help / color / mirror / Atom feed
From: Konstantin Ananyev <konstantin.ananyev@huawei.com>
To: Anatoly Burakov <anatoly.burakov@intel.com>,
	"dev@dpdk.org" <dev@dpdk.org>
Subject: RE: [PATCH v4 1/2] cmdline: add floating point support
Date: Wed, 7 May 2025 10:35:57 +0000	[thread overview]
Message-ID: <73248ba4775b4b95b117890851b8257e@huawei.com> (raw)
In-Reply-To: <e8234c26b5dd91aaa9e7b1e38887b1d6fdb2d053.1746612074.git.anatoly.burakov@intel.com>



> Add support for parsing floating point numbers in cmdline library, as well
> as unit tests for the new functionality. The parser supports single and
> double precision floats, and will understand decimal fractions as well as
> scientific notation.

There are standard functions for that: strtod/strtof - can't we simply use them?  

> 
> Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
> ---
> 
> Notes:
>     v3 -> v4:
>     - Removed unnecessary check for integer overflow when parsing negative
>       floats (as we convert to double before changing sign)
>     - Make naming of float exponent states more consistent
> 
>     v2 -> v3:
>     - Fixed a bug where a free-standing negative exponent ("1e-") would attempt to be
>       parsed, and added unit tests for this case
>     - Added support for floats in dpdk-cmdline-gen script
>     - Added documentation updates to call out float support
> 
>  app/test/test_cmdline_num.c            | 203 +++++++++++++++++-
>  buildtools/dpdk-cmdline-gen.py         |  24 ++-
>  doc/guides/prog_guide/cmdline.rst      |   3 +
>  doc/guides/rel_notes/release_25_07.rst |   5 +
>  lib/cmdline/cmdline_parse_num.c        | 273 +++++++++++++++++++++++++
>  lib/cmdline/cmdline_parse_num.h        |   4 +-
>  6 files changed, 497 insertions(+), 15 deletions(-)
> 
> diff --git a/app/test/test_cmdline_num.c b/app/test/test_cmdline_num.c
> index 9276de59bd..e4038271c9 100644
> --- a/app/test/test_cmdline_num.c
> +++ b/app/test/test_cmdline_num.c
> @@ -5,6 +5,8 @@
>  #include <stdio.h>
>  #include <string.h>
>  #include <inttypes.h>
> +#include <float.h>
> +#include <math.h>
> 
>  #include <rte_string_fns.h>
> 
> @@ -23,6 +25,11 @@ struct num_signed_str {
>  	int64_t result;
>  };
> 
> +struct num_float_str {
> +	const char * str;
> +	double result;
> +};
> +
>  const struct num_unsigned_str num_valid_positive_strs[] = {
>  		/* decimal positive */
>  		{"0", 0 },
> @@ -141,6 +148,63 @@ const struct num_signed_str num_valid_negative_strs[] = {
>  		{"-9223372036854775808", INT64_MIN },
>  };
> 
> +const struct num_float_str num_valid_float_strs[] = {
> +		/* zero */
> +		{"0", 0},
> +		/* parse int as float */
> +		{"1", 1},
> +		{"-1", -1},
> +		/* fractional */
> +		{"1.23", 1.23},
> +		{"-1.23", -1.23},
> +		{"0.123", 0.123},
> +		{"-0.123", -0.123},
> +		{"123.456", 123.456},
> +		{"-123.456", -123.456},
> +		/* positive exponent */
> +		{"1e2", 1e2},
> +		{"-1e2", -1e2},
> +		{"1E2", 1E2},
> +		{"-1E2", -1E2},
> +		{"0.12e3", 0.12e3},
> +		{"-0.12e3", -0.12e3},
> +		{"1.23e4", 1.23e4},
> +		{"-1.23e4", -1.23e4},
> +		{"1.23E4", 1.23E4},
> +		{"-1.23E4", -1.23E4},
> +		{"123.456e7", 123.456e7},
> +		{"-123.456e7", -123.456e7},
> +		{"123.456E7", 123.456E7},
> +		{"-123.456E7", -123.456E7},
> +		/* negative exponent */
> +		{"1e-2", 1e-2},
> +		{"-1e-2", -1e-2},
> +		{"1E-2", 1E-2},
> +		{"-1E-2", -1E-2},
> +		{"0.12e-3", 0.12e-3},
> +		{"-0.12e-3", -0.12e-3},
> +		{"1.23e-4", 1.23e-4},
> +		{"-1.23e-4", -1.23e-4},
> +		{"1.23E-4", 1.23E-4},
> +		{"-1.23E-4", -1.23E-4},
> +		{"123.456e-7", 123.456e-7},
> +		{"-123.456e-7", -123.456e-7},
> +		{"123.456E-7", 123.456E-7},
> +		{"-123.456E-7", -123.456E-7},
> +		/* try overflowing float */
> +		{"2e63", 2e63},
> +		{"-2e63", -2e63},
> +		{"2E63", 2E63},
> +		{"-2E63", -2E63},
> +		{"18446744073709551615", (double) UINT64_MAX},
> +		{"-9223372036854775808", (double) INT64_MIN},
> +		/* try overflowing double */
> +		{"2e308", HUGE_VAL},
> +		{"-2e308", -HUGE_VAL},
> +		{"2E308", HUGE_VAL},
> +		{"-2E308", HUGE_VAL},
> +};
> +
>  const struct num_unsigned_str num_garbage_positive_strs[] = {
>  		/* valid strings with garbage on the end, should still be valid */
>  		/* decimal */
> @@ -183,6 +247,30 @@ const struct num_signed_str num_garbage_negative_strs[] = {
>  		{"-9223372036854775808 garbage", INT64_MIN },
>  };
> 
> +const char *float_invalid_strs[] = {
> +	"0.",
> +	".1",
> +	"1.1.",
> +	"1.1.1",
> +	"-0.",
> +	"-.1",
> +	"-1.1.",
> +	"-1.1.1",
> +	"e",
> +	"1e",
> +	"-1e",
> +	"0.1e",
> +	"-0.1e",
> +	"1.e",
> +	"-1.e",
> +	"1.23e3.4",
> +	"-1.23e3.4",
> +	"1e1e",
> +	"1e1e1",
> +	"1e-",
> +	"-1e-"
> +};
> +
>  const char * num_invalid_strs[] = {
>  		"18446744073709551616", /* out of range unsigned */
>  		"-9223372036854775809", /* out of range negative signed */
> @@ -202,7 +290,16 @@ const char * num_invalid_strs[] = {
>  		/* too long (128+ chars) */
>  		("0b1111000011110000111100001111000011110000111100001111000011110000"
>  		  "1111000011110000111100001111000011110000111100001111000011110000"),
> +		/* valid float values but should fail to parse as ints */
>  		"1E3",
> +		"-1E3",
> +		"1.23",
> +		"-1.23",
> +		"1E-3",
> +		"-1E-3",
> +		"1.23E4",
> +		"-1.23E4",
> +		/* misc invalid values */
>  		"0A",
>  		"-B",
>  		"+4",
> @@ -216,6 +313,47 @@ const char * num_invalid_strs[] = {
>  		"\0",
>  };
> 
> +static int
> +float_cmp(double expected, void *actual_p, enum cmdline_numtype type)
> +{
> +	double eps;
> +	double actual_d;
> +
> +	if (type == RTE_FLOAT_SINGLE) {
> +		/* read as float, convert to double */
> +		actual_d = (double)*(float *)actual_p;
> +		/* FLT_EPSILON is too small for some tests */
> +		eps = 1e-5f;
> +	} else {
> +		/* read as double */
> +		actual_d = *(double *)actual_p;
> +		eps = DBL_EPSILON;
> +	}
> +	/* compare using epsilon value */
> +	if (fabs(expected - actual_d) < eps)
> +		return 0;
> +	/* not equal */
> +	return expected < actual_d ? -1 : 1;
> +}
> +
> +static int
> +can_parse_float(double expected_result, enum cmdline_numtype type)
> +{
> +	switch (type) {
> +	case RTE_FLOAT_SINGLE:
> +		if (expected_result > FLT_MAX || expected_result < -FLT_MAX)
> +			return 0;
> +		break;
> +	case RTE_FLOAT_DOUBLE:
> +		if (expected_result > DBL_MAX || expected_result < -DBL_MAX)
> +			return 0;
> +		break;
> +	default:
> +		return 1;
> +	}
> +	return 1;
> +}
> +
>  static int
>  can_parse_unsigned(uint64_t expected_result, enum cmdline_numtype type)
>  {
> @@ -371,11 +509,11 @@ test_parse_num_invalid_data(void)
>  	int ret = 0;
>  	unsigned i;
>  	char buf[CMDLINE_TEST_BUFSIZE];
> -	uint64_t result; /* pick largest buffer */
>  	cmdline_parse_token_num_t token;
> 
> -	/* cycle through all possible parsed types */
> +	/* cycle through all possible integer types */
>  	for (type = RTE_UINT8; type <= RTE_INT64; type++) {
> +		uint64_t result; /* pick largest buffer */
>  		token.num_data.type = type;
> 
>  		/* test full strings */
> @@ -397,6 +535,31 @@ test_parse_num_invalid_data(void)
>  			}
>  		}
>  	}
> +
> +	/* cycle through all possible float types */
> +	for (type = RTE_FLOAT_SINGLE; type <= RTE_FLOAT_DOUBLE; type++) {
> +		double result; /* pick largest buffer */
> +		token.num_data.type = type;
> +
> +		/* test full strings */
> +		for (i = 0; i < RTE_DIM(float_invalid_strs); i++) {
> +
> +			memset(&result, 0, sizeof(double));
> +			memset(&buf, 0, sizeof(buf));
> +
> +			ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token,
> +					float_invalid_strs[i], (void*)&result, sizeof(result));
> +			if (ret != -1) {
> +				/* get some info about what we are trying to parse */
> +				cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
> +						buf, sizeof(buf));
> +
> +				printf("Error: parsing %s as %s succeeded!\n",
> +						float_invalid_strs[i], buf);
> +				return -1;
> +			}
> +		}
> +	}
>  	return 0;
>  }
> 
> @@ -408,13 +571,13 @@ test_parse_num_valid(void)
>  	enum cmdline_numtype type;
>  	unsigned i;
>  	char buf[CMDLINE_TEST_BUFSIZE];
> -	uint64_t result;
>  	cmdline_parse_token_num_t token;
> 
>  	/** valid strings **/
> 
>  	/* cycle through all possible parsed types */
>  	for (type = RTE_UINT8; type <= RTE_INT64; type++) {
> +		uint64_t result;
>  		token.num_data.type = type;
> 
>  		/* test positive strings */
> @@ -489,10 +652,44 @@ test_parse_num_valid(void)
>  		}
>  	}
> 
> +	/* float values */
> +	for (type = RTE_FLOAT_SINGLE; type <= RTE_FLOAT_DOUBLE; type++) {
> +		double result;
> +		token.num_data.type = type;
> +
> +		/* test all valid strings */
> +		for (i = 0; i < RTE_DIM(num_valid_float_strs); i++) {
> +			result = 0;
> +			memset(&buf, 0, sizeof(buf));
> +
> +
> +			cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
> +					buf, sizeof(buf));
> +
> +			ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
> +				num_valid_float_strs[i].str,
> +				(void*)&result, sizeof(result));
> +
> +			/* if it should have passed but didn't, or if it should have failed but didn't */
> +			if ((ret < 0) == (can_parse_float(num_valid_float_strs[i].result, type) > 0)) {
> +				printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
> +						num_valid_float_strs[i].str, buf);
> +				return -1;
> +			}
> +			/* check if result matches */
> +			if (ret > 0 && float_cmp(num_valid_float_strs[i].result, &result, type) != 0) {
> +				printf("Error: parsing %s as %s failed: result mismatch!\n",
> +						num_valid_float_strs[i].str, buf);
> +				return -1;
> +			}
> +		}
> +	}
> +
>  	/** garbage strings **/
> 
>  	/* cycle through all possible parsed types */
>  	for (type = RTE_UINT8; type <= RTE_INT64; type++) {
> +		uint64_t result;
>  		token.num_data.type = type;
> 
>  		/* test positive garbage strings */
> diff --git a/buildtools/dpdk-cmdline-gen.py b/buildtools/dpdk-cmdline-gen.py
> index 7dadded783..6c76d7116a 100755
> --- a/buildtools/dpdk-cmdline-gen.py
> +++ b/buildtools/dpdk-cmdline-gen.py
> @@ -17,16 +17,18 @@
>      RTE_SET_USED(cl);
>      RTE_SET_USED(data);
>  """
> -NUMERIC_TYPES = [
> -    "UINT8",
> -    "UINT16",
> -    "UINT32",
> -    "UINT64",
> -    "INT8",
> -    "INT16",
> -    "INT32",
> -    "INT64",
> -]
> +NUMERIC_TYPES = {
> +    "UINT8": "uint8_t",
> +    "UINT16": "uint16_t",
> +    "UINT32": "uint32_t",
> +    "UINT64": "uint64_t",
> +    "INT8": "int8_t",
> +    "INT16": "int16_t",
> +    "INT32": "int32_t",
> +    "INT64": "int64_t",
> +    "FLOAT_SINGLE": "float",
> +    "FLOAT_DOUBLE": "double",
> +}
> 
> 
>  def process_command(lineno, tokens, comment):
> @@ -70,7 +72,7 @@ def process_command(lineno, tokens, comment):
>                  f"\tTOKEN_STRING_INITIALIZER(struct cmd_{name}_result, {t_name}, {t_val});"
>              )
>          elif t_type in NUMERIC_TYPES:
> -            result_struct.append(f"\t{t_type.lower()}_t {t_name};")
> +            result_struct.append(f"\t{NUMERIC_TYPES[t_type]} {t_name};")
>              initializers.append(
>                  f"static cmdline_parse_token_num_t cmd_{name}_{t_name}_tok =\n"
>                  f"\tTOKEN_NUM_INITIALIZER(struct cmd_{name}_result, {t_name}, RTE_{t_type});"
> diff --git a/doc/guides/prog_guide/cmdline.rst b/doc/guides/prog_guide/cmdline.rst
> index e20281ceb5..447a90e32e 100644
> --- a/doc/guides/prog_guide/cmdline.rst
> +++ b/doc/guides/prog_guide/cmdline.rst
> @@ -22,6 +22,7 @@ The DPDK command-line library supports the following features:
> 
>     * Strings
>     * Signed/unsigned 16/32/64-bit integers
> +   * Single/double precision floats
>     * IP Addresses
>     * Ethernet Addresses
> 
> @@ -68,6 +69,8 @@ The format of the list file must be:
> 
>    * ``<UINT16>port_id``
> 
> +  * ``<FLOAT_SINGLE>ratio``
> +
>    * ``<IP>src_ip``
> 
>    * ``<IPv4>dst_ip4``
> diff --git a/doc/guides/rel_notes/release_25_07.rst b/doc/guides/rel_notes/release_25_07.rst
> index 093b85d206..54bc545110 100644
> --- a/doc/guides/rel_notes/release_25_07.rst
> +++ b/doc/guides/rel_notes/release_25_07.rst
> @@ -55,6 +55,11 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =======================================================
> 
> +* **Added floating point numbers support to cmdline library.**
> +
> +  The cmdline library now supports parsing single- and double-precision
> +  floating point numbers in interactive user commands.
> +
> 
>  Removed Items
>  -------------
> diff --git a/lib/cmdline/cmdline_parse_num.c b/lib/cmdline/cmdline_parse_num.c
> index f21796bedb..9e4d559325 100644
> --- a/lib/cmdline/cmdline_parse_num.c
> +++ b/lib/cmdline/cmdline_parse_num.c
> @@ -7,6 +7,8 @@
>  #include <stdio.h>
>  #include <stdint.h>
>  #include <inttypes.h>
> +#include <float.h>
> +#include <math.h>
>  #include <string.h>
>  #include <eal_export.h>
>  #include <rte_string_fns.h>
> @@ -34,6 +36,10 @@ enum num_parse_state_t {
>  	DEC_NEG,
>  	BIN,
>  	HEX,
> +	FLOAT_POS,
> +	FLOAT_NEG,
> +	FLOAT_EXP_POS,
> +	FLOAT_EXP_NEG,
> 
>  	ERROR,
> 
> @@ -44,12 +50,27 @@ enum num_parse_state_t {
>  	BIN_OK,
>  	DEC_NEG_OK,
>  	DEC_POS_OK,
> +	FLOAT_POS_OK,
> +	FLOAT_NEG_OK,
> +	FLOAT_EXP_POS_OK,
> +	FLOAT_EXP_NEG_OK,
> +};
> +
> +struct float_parse_state {
> +	uint64_t dec;
> +	uint64_t frac;
> +	uint64_t frac_exp;
> +	uint64_t exp;
> +#define FLOAT_FLAG_NEG_RES     (1 << 0)
> +#define FLOAT_FLAG_NEG_EXP     (1 << 1)
> +	int flags;
>  };
> 
>  /* Keep it sync with enum in .h */
>  static const char * num_help[] = {
>  	"UINT8", "UINT16", "UINT32", "UINT64",
>  	"INT8", "INT16", "INT32", "INT64",
> +	"SINGLE", "DOUBLE"
>  };
> 
>  static inline int
> @@ -63,6 +84,50 @@ add_to_res(unsigned int c, uint64_t *res, unsigned int base)
>  	return 0;
>  }
> 
> +static inline int
> +check_float_result(enum cmdline_numtype res_type, struct float_parse_state *fps,
> +		void *res)
> +{
> +	double dec, frac, exp, result;
> +
> +	/* extract parts */
> +	dec = (double) fps->dec;
> +	frac = (double) fps->frac * pow(10.0, -(double)fps->frac_exp);
> +	exp = (double) fps->exp;
> +
> +	/* exponent might be negative */
> +	if (fps->flags & FLOAT_FLAG_NEG_EXP)
> +		exp = pow(10.0, -exp);
> +	else
> +		exp = pow(10.0, exp);
> +
> +	/* combine decimal, fractional, and exponent parts */
> +	result = (dec + frac) * exp;
> +
> +	/* check for any overflows */
> +	if (isinf(frac) || isinf(exp) || isinf(result))
> +		return -1;
> +
> +	/* result is a valid double */
> +
> +	/* check if result needs to be negative */
> +	if (fps->flags & FLOAT_FLAG_NEG_RES)
> +		result = -result;
> +
> +	if (res_type == RTE_FLOAT_SINGLE) {
> +		/* float can overflow from conversion */
> +		float flt = (float)result;
> +		if (isinf(flt))
> +			return -1;
> +		if (res) *(float *)res = flt;
> +	} else if (res_type == RTE_FLOAT_DOUBLE) {
> +		if (res) *(double *)res = result;
> +	} else {
> +		return -1;
> +	}
> +	return 0;
> +}
> +
>  static int
>  check_res_size(struct cmdline_token_num_data *nd, unsigned ressize)
>  {
> @@ -87,6 +152,14 @@ check_res_size(struct cmdline_token_num_data *nd, unsigned ressize)
>  		if (ressize < sizeof(int64_t))
>  			return -1;
>  		break;
> +	case RTE_FLOAT_SINGLE:
> +		if (ressize < sizeof(float))
> +			return -1;
> +		break;
> +	case RTE_FLOAT_DOUBLE:
> +		if (ressize < sizeof(double))
> +			return -1;
> +		break;
>  	default:
>  		return -1;
>  	}
> @@ -104,6 +177,7 @@ cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res,
>  	const char * buf;
>  	char c;
>  	uint64_t res1 = 0;
> +	struct float_parse_state fps = {};
> 
>  	if (!tk)
>  		return -1;
> @@ -156,6 +230,10 @@ cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res,
>  				else
>  					st = OCTAL_OK;
>  			}
> +			else if (c == '.') {
> +				st = FLOAT_POS;
> +				break;
> +			}
>  			else  {
>  				st = ERROR;
>  			}
> @@ -173,11 +251,80 @@ cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res,
>  			}
>  			break;
> 
> +		case FLOAT_POS:
> +			if (c >= '0' && c <= '9') {
> +				if (add_to_res(c - '0', &res1, 10) < 0)
> +					st = ERROR;
> +				else {
> +					st = FLOAT_POS_OK;
> +					fps.frac_exp++;
> +				}
> +			}
> +			else {
> +				st = ERROR;
> +			}
> +			break;
> +
> +		case FLOAT_NEG:
> +			if (c >= '0' && c <= '9') {
> +				if (add_to_res(c - '0', &res1, 10) < 0)
> +					st = ERROR;
> +				else {
> +					st = FLOAT_NEG_OK;
> +					fps.frac_exp++;
> +				}
> +			}
> +			else {
> +				st = ERROR;
> +			}
> +			break;
> +
> +		case FLOAT_EXP_POS:
> +			if (c >= '0' && c <= '9') {
> +				if (add_to_res(c - '0', &res1, 10) < 0)
> +					st = ERROR;
> +				else
> +					st = FLOAT_EXP_POS_OK;
> +			}
> +			else if (c == '-') {
> +				st = FLOAT_EXP_NEG;
> +				fps.flags |= FLOAT_FLAG_NEG_EXP;
> +			}
> +			else {
> +				st = ERROR;
> +			}
> +			break;
> +
> +		case FLOAT_EXP_NEG:
> +			if (c >= '0' && c <= '9') {
> +				if (add_to_res(c - '0', &res1, 10) < 0)
> +					st = ERROR;
> +				else
> +					st = FLOAT_EXP_NEG_OK;
> +			}
> +			else {
> +				st = ERROR;
> +			}
> +			break;
> +
>  		case DEC_NEG_OK:
>  			if (c >= '0' && c <= '9') {
>  				if (add_to_res(c - '0', &res1, 10) < 0)
>  					st = ERROR;
>  			}
> +			else if (c == '.') {
> +				fps.dec = res1;
> +				fps.flags |= FLOAT_FLAG_NEG_RES;
> +				st = FLOAT_NEG;
> +				/* erase result */
> +				res1 = 0;
> +			} else if (c == 'e' || c == 'E') {
> +				fps.dec = res1;
> +				fps.flags |= FLOAT_FLAG_NEG_RES;
> +				st = FLOAT_EXP_POS;
> +				/* erase result */
> +				res1 = 0;
> +			}
>  			else {
>  				st = ERROR;
>  			}
> @@ -188,11 +335,75 @@ cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res,
>  				if (add_to_res(c - '0', &res1, 10) < 0)
>  					st = ERROR;
>  			}
> +			else if (c == '.') {
> +				fps.dec = res1;
> +				st = FLOAT_POS;
> +				/* erase result */
> +				res1 = 0;
> +			}
> +			else if (c == 'e' || c == 'E') {
> +				fps.dec = res1;
> +				st = FLOAT_EXP_POS;
> +				/* erase result */
> +				res1 = 0;
> +			}
>  			else {
>  				st = ERROR;
>  			}
>  			break;
> 
> +		case FLOAT_POS_OK:
> +			if (c >= '0' && c <= '9') {
> +				if (add_to_res(c - '0', &res1, 10) < 0)
> +					st = ERROR;
> +				else
> +					fps.frac_exp++;
> +			} else if (c == 'e' || c == 'E') {
> +				fps.frac = res1;
> +				st = FLOAT_EXP_POS;
> +				/* erase result */
> +				res1 = 0;
> +			} else {
> +				st = ERROR;
> +			}
> +			break;
> +
> +		case FLOAT_NEG_OK:
> +			if (c >= '0' && c <= '9') {
> +				if (add_to_res(c - '0', &res1, 10) < 0)
> +					st = ERROR;
> +				else
> +					fps.frac_exp++;
> +			} else if (c == 'e' || c == 'E') {
> +				fps.frac = res1;
> +				st = FLOAT_EXP_POS;
> +				/* erase result */
> +				res1 = 0;
> +			} else {
> +				st = ERROR;
> +			}
> +			break;
> +
> +		case FLOAT_EXP_POS_OK:
> +			/* exponent is always whole */
> +			if (c >= '0' && c <= '9') {
> +				if (add_to_res(c - '0', &res1, 10) < 0)
> +					st = ERROR;
> +			} else {
> +				st = ERROR;
> +			}
> +			break;
> +
> +		case FLOAT_EXP_NEG_OK:
> +			/* exponent is always whole */
> +			if (c >= '0' && c <= '9') {
> +				if (add_to_res(c - '0', &res1, 10) < 0)
> +					st = ERROR;
> +			} else {
> +				st = ERROR;
> +			}
> +			break;
> +
>  		case HEX:
>  			st = HEX_OK;
>  			/* fall-through */
> @@ -282,6 +493,12 @@ cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res,
>  		} else if (nd.type == RTE_UINT64) {
>  			if (res) *(uint64_t *)res = res1;
>  			return buf-srcbuf;
> +		} else if (nd.type == RTE_FLOAT_SINGLE || nd.type == RTE_FLOAT_DOUBLE) {
> +			/* parsed double from integer */
> +			fps.dec = res1;
> +			if (check_float_result(nd.type, &fps, res) < 0)
> +				return -1;
> +			return buf-srcbuf;
>  		} else {
>  			return -1;
>  		}
> @@ -304,6 +521,62 @@ cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res,
>  				res1 <= (uint64_t)INT64_MAX + 1) {
>  			if (res) *(int64_t *)res = (int64_t) (-res1);
>  			return buf-srcbuf;
> +		} else if (nd.type == RTE_FLOAT_SINGLE || nd.type == RTE_FLOAT_DOUBLE) {
> +			/* parsed double from negative integer */
> +			fps.dec = res1;
> +			fps.flags |= FLOAT_FLAG_NEG_RES;
> +			if (check_float_result(nd.type, &fps, res) < 0)
> +				return -1;
> +			return buf-srcbuf;
> +		} else {
> +			return -1;
> +		}
> +		break;
> +
> +	case FLOAT_POS_OK:
> +		if (nd.type == RTE_FLOAT_SINGLE || nd.type == RTE_FLOAT_DOUBLE) {
> +			fps.frac = res1;
> +
> +			if (check_float_result(nd.type, &fps, res) < 0)
> +				return -1;
> +			return buf-srcbuf;
> +		} else {
> +			return -1;
> +		}
> +		break;
> +
> +	case FLOAT_NEG_OK:
> +		if (nd.type == RTE_FLOAT_SINGLE || nd.type == RTE_FLOAT_DOUBLE) {
> +			fps.frac = res1;
> +
> +			if (check_float_result(nd.type, &fps, res) < 0)
> +				return -1;
> +			return buf-srcbuf;
> +		} else {
> +			return -1;
> +		}
> +		break;
> +
> +	case FLOAT_EXP_POS_OK:
> +		/* watch for overflow in the exponent */
> +		if (nd.type == RTE_FLOAT_SINGLE || nd.type == RTE_FLOAT_DOUBLE) {
> +			fps.exp = res1;
> +
> +			if (check_float_result(nd.type, &fps, res) < 0)
> +				return -1;
> +			return buf-srcbuf;
> +		} else {
> +			return -1;
> +		}
> +		break;
> +
> +	case FLOAT_EXP_NEG_OK:
> +		if (nd.type == RTE_FLOAT_SINGLE || nd.type == RTE_FLOAT_DOUBLE) {
> +			fps.exp = res1;
> +
> +			if (check_float_result(nd.type, &fps, res) < 0)
> +				return -1;
> +			return buf-srcbuf;
>  		} else {
>  			return -1;
>  		}
> diff --git a/lib/cmdline/cmdline_parse_num.h b/lib/cmdline/cmdline_parse_num.h
> index bdd0267612..b2792a2d11 100644
> --- a/lib/cmdline/cmdline_parse_num.h
> +++ b/lib/cmdline/cmdline_parse_num.h
> @@ -22,7 +22,9 @@ enum cmdline_numtype {
>  	RTE_INT8,
>  	RTE_INT16,
>  	RTE_INT32,
> -	RTE_INT64
> +	RTE_INT64,
> +	RTE_FLOAT_SINGLE,
> +	RTE_FLOAT_DOUBLE,
>  };
> 
>  struct cmdline_token_num_data {
> --
> 2.47.1


  parent reply	other threads:[~2025-05-07 10:36 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-02 12:27 [PATCH v1 1/1] app/testpmd: add sleep command Anatoly Burakov
2025-05-02 12:37 ` Bruce Richardson
2025-05-02 14:35   ` Burakov, Anatoly
2025-05-02 14:43     ` Bruce Richardson
2025-05-02 15:33       ` Morten Brørup
2025-05-02 15:42 ` Stephen Hemminger
2025-05-06 12:36   ` Burakov, Anatoly
2025-05-06 13:08 ` [PATCH v2 1/2] cmdline: add floating point support Anatoly Burakov
2025-05-06 13:08   ` [PATCH v2 2/2] app/testpmd: add sleep command Anatoly Burakov
2025-05-06 13:38   ` [PATCH v2 1/2] cmdline: add floating point support Bruce Richardson
2025-05-07  9:02     ` Burakov, Anatoly
2025-05-07  9:50 ` [PATCH v3 " Anatoly Burakov
2025-05-07  9:50   ` [PATCH v3 2/2] app/testpmd: add sleep command Anatoly Burakov
2025-05-07  9:53   ` [PATCH v3 1/2] cmdline: add floating point support Burakov, Anatoly
2025-05-07 10:01 ` [PATCH v4 " Anatoly Burakov
2025-05-07 10:01   ` [PATCH v4 2/2] app/testpmd: add sleep command Anatoly Burakov
2025-05-07 10:35   ` Konstantin Ananyev [this message]
2025-05-07 11:06     ` [PATCH v4 1/2] cmdline: add floating point support Burakov, Anatoly
2025-05-07 12:24       ` Konstantin Ananyev
2025-05-07 14:06         ` Burakov, Anatoly
2025-05-07 15:22 ` [PATCH v5 1/3] cmdline: use C standard library as number parser Anatoly Burakov
2025-05-07 15:22   ` [PATCH v5 2/3] cmdline: add floating point support Anatoly Burakov
2025-05-07 15:22   ` [PATCH v5 3/3] app/testpmd: add sleep command Anatoly Burakov
2025-05-08  7:27   ` [PATCH v5 1/3] cmdline: use C standard library as number parser Bruce Richardson
2025-05-08  8:35     ` Burakov, Anatoly
2025-05-08  9:53 ` [PATCH v6 " Anatoly Burakov
2025-05-08  9:53   ` [PATCH v6 2/3] cmdline: add floating point support Anatoly Burakov
2025-05-08  9:53   ` [PATCH v6 3/3] app/testpmd: add sleep command Anatoly Burakov
2025-05-08 10:01 ` [PATCH v7 1/3] cmdline: use C standard library as number parser Anatoly Burakov
2025-05-08 10:01   ` [PATCH v7 2/3] cmdline: add floating point support Anatoly Burakov
2025-05-08 10:09     ` Burakov, Anatoly
2025-05-08 10:01   ` [PATCH v7 3/3] app/testpmd: add sleep command Anatoly Burakov
2025-05-08 13:16 ` [PATCH v8 1/3] cmdline: use C standard library as number parser Anatoly Burakov
2025-05-08 13:16   ` [PATCH v8 2/3] cmdline: add floating point support Anatoly Burakov
2025-05-08 13:16   ` [PATCH v8 3/3] app/testpmd: add sleep command Anatoly Burakov
2025-05-09 13:02   ` [PATCH v8 1/3] cmdline: use C standard library as number parser Burakov, Anatoly
2025-05-09 13:08     ` Burakov, Anatoly
2025-05-09 13:27       ` Burakov, Anatoly
2025-05-09 13:39 ` [PATCH v9 " Anatoly Burakov
2025-05-09 13:39   ` [PATCH v9 2/3] cmdline: add floating point support Anatoly Burakov
2025-05-09 13:39   ` [PATCH v9 3/3] app/testpmd: add sleep command Anatoly Burakov
2025-05-09 13:42   ` [PATCH v9 1/3] cmdline: use C standard library as number parser Burakov, Anatoly
2025-05-09 14:41 ` [PATCH v10 " Anatoly Burakov
2025-05-09 14:41   ` [PATCH v10 2/3] cmdline: add floating point support Anatoly Burakov
2025-05-09 14:41   ` [PATCH v10 3/3] app/testpmd: add sleep command Anatoly Burakov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=73248ba4775b4b95b117890851b8257e@huawei.com \
    --to=konstantin.ananyev@huawei.com \
    --cc=anatoly.burakov@intel.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).