util: add a helper function for parsing capacities (1K, 128M, 2G)
Also used it in parsing `-m` SPDK app param, meaning that it can now accept numbers followed by a binary prefix - like 512M or 2G. Change-Id: If458dc08429237f2cb3f3f661bcaf382468df0f0 Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com> Reviewed-on: https://review.gerrithub.io/391670 Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com> Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
e0e8f53cc0
commit
ec6a1afbdb
@ -148,6 +148,21 @@ size_t spdk_strlen_pad(const void *str, size_t size, int pad);
|
||||
*/
|
||||
int spdk_parse_ip_addr(char *ip, char **host, char **port);
|
||||
|
||||
/**
|
||||
* Parse a string representing a number possibly followed by a binary prefix.
|
||||
* The string can contain a trailing "B" (KB,MB,GB) but it's not necessary.
|
||||
* "128K" = 128 * 1024; "2G" = 2 * 1024 * 1024; "2GB" = 2 * 1024 * 1024;
|
||||
* Additionally, lowercase "k", "m", "g" are parsed as well. They are processed
|
||||
* the same as their uppercase equivalents.
|
||||
*
|
||||
* \param cap_str null terminated string
|
||||
* \param cap pointer where the parsed capacity (in bytes) will be put
|
||||
* \param has_prefix pointer to a flag that will be set to describe whether given
|
||||
* string contains a binary prefix
|
||||
* \returned 0 on success, negative errno otherwise
|
||||
*/
|
||||
int spdk_parse_capacity(const char *cap_str, uint64_t *cap, bool *has_prefix);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -538,9 +538,33 @@ spdk_app_parse_args(int argc, char **argv, struct spdk_app_opts *opts,
|
||||
case 'r':
|
||||
opts->rpc_addr = optarg;
|
||||
break;
|
||||
case 's':
|
||||
opts->mem_size = atoi(optarg);
|
||||
case 's': {
|
||||
uint64_t mem_size_mb;
|
||||
bool mem_size_has_prefix;
|
||||
|
||||
rc = spdk_parse_capacity(optarg, &mem_size_mb, &mem_size_has_prefix);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "invalid memory pool size `-s %s`\n", optarg);
|
||||
usage(argv[0], &default_opts, app_usage);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (mem_size_has_prefix) {
|
||||
/* the mem size is in MB by default, so if a prefix was
|
||||
* specified, we need to manually convert to MB.
|
||||
*/
|
||||
mem_size_mb /= 1024 * 1024;
|
||||
}
|
||||
|
||||
if (mem_size_mb > INT_MAX) {
|
||||
fprintf(stderr, "invalid memory pool size `-s %s`\n", optarg);
|
||||
usage(argv[0], &default_opts, app_usage);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
opts->mem_size = (int) mem_size_mb;
|
||||
break;
|
||||
}
|
||||
case 't':
|
||||
rc = spdk_log_set_trace_flag(optarg);
|
||||
if (rc < 0) {
|
||||
|
@ -342,3 +342,44 @@ spdk_strerror_r(int errnum, char *buf, size_t buflen)
|
||||
return strerror_r(errnum, buf, buflen);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
spdk_parse_capacity(const char *cap_str, uint64_t *cap, bool *has_prefix)
|
||||
{
|
||||
int rc;
|
||||
char bin_prefix;
|
||||
|
||||
rc = sscanf(cap_str, "%"SCNu64"%c", cap, &bin_prefix);
|
||||
if (rc == 1) {
|
||||
*has_prefix = false;
|
||||
return 0;
|
||||
} else if (rc == 0) {
|
||||
if (errno == 0) {
|
||||
/* No scanf matches - the string does not start with a digit */
|
||||
return -EINVAL;
|
||||
} else {
|
||||
/* Parsing error */
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
*has_prefix = true;
|
||||
switch (bin_prefix) {
|
||||
case 'k':
|
||||
case 'K':
|
||||
*cap *= 1024;
|
||||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
*cap *= 1024 * 1024;
|
||||
break;
|
||||
case 'g':
|
||||
case 'G':
|
||||
*cap *= 1024 * 1024 * 1024;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -136,6 +136,72 @@ test_str_chomp(void)
|
||||
CU_ASSERT(strcmp(s, "a") == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_parse_capacity(void)
|
||||
{
|
||||
char str[128];
|
||||
uint64_t cap;
|
||||
int rc;
|
||||
bool has_prefix;
|
||||
|
||||
rc = spdk_parse_capacity("472", &cap, &has_prefix);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(cap == 472);
|
||||
CU_ASSERT(has_prefix == false);
|
||||
|
||||
sprintf(str, "%"PRIu64, UINT64_MAX);
|
||||
rc = spdk_parse_capacity(str, &cap, &has_prefix);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(cap == UINT64_MAX);
|
||||
CU_ASSERT(has_prefix == false);
|
||||
|
||||
rc = spdk_parse_capacity("12k", &cap, &has_prefix);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(cap == 12 * 1024);
|
||||
CU_ASSERT(has_prefix == true);
|
||||
|
||||
rc = spdk_parse_capacity("12K", &cap, &has_prefix);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(cap == 12 * 1024);
|
||||
CU_ASSERT(has_prefix == true);
|
||||
|
||||
rc = spdk_parse_capacity("12KB", &cap, &has_prefix);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(cap == 12 * 1024);
|
||||
CU_ASSERT(has_prefix == true);
|
||||
|
||||
rc = spdk_parse_capacity("100M", &cap, &has_prefix);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(cap == 100 * 1024 * 1024);
|
||||
CU_ASSERT(has_prefix == true);
|
||||
|
||||
rc = spdk_parse_capacity("128M", &cap, &has_prefix);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(cap == 128 * 1024 * 1024);
|
||||
CU_ASSERT(has_prefix == true);
|
||||
|
||||
rc = spdk_parse_capacity("4G", &cap, &has_prefix);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(cap == 4ULL * 1024 * 1024 * 1024);
|
||||
CU_ASSERT(has_prefix == true);
|
||||
|
||||
rc = spdk_parse_capacity("100M 512k", &cap, &has_prefix);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(cap == 100ULL * 1024 * 1024);
|
||||
|
||||
rc = spdk_parse_capacity("12k8K", &cap, &has_prefix);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(cap == 12 * 1024);
|
||||
CU_ASSERT(has_prefix == true);
|
||||
|
||||
/* Non-number */
|
||||
rc = spdk_parse_capacity("G", &cap, &has_prefix);
|
||||
CU_ASSERT(rc != 0);
|
||||
|
||||
rc = spdk_parse_capacity("darsto", &cap, &has_prefix);
|
||||
CU_ASSERT(rc != 0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -154,7 +220,8 @@ main(int argc, char **argv)
|
||||
|
||||
if (
|
||||
CU_add_test(suite, "test_parse_ip_addr", test_parse_ip_addr) == NULL ||
|
||||
CU_add_test(suite, "test_str_chomp", test_str_chomp) == NULL) {
|
||||
CU_add_test(suite, "test_str_chomp", test_str_chomp) == NULL ||
|
||||
CU_add_test(suite, "test_parse_capacity", test_parse_capacity) == NULL) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user