Skip to content

Commit 93b0c5d

Browse files
committed
liboptparse: add get_size and get_size_int accessors
Problem: It would be convenient to support options with size arguments specified using the k, K, M, G, etc suffixes, but liboptparse offers no such interface. Add optparse_get_size() and optparse_get_size_int() which parse option arguments using libutil's parse_size() and return a uint64_t or int respectively. The optparse_get_size_int() variant raises a fatal error if the argument overflows MAX_INT.
1 parent b9e8c5f commit 93b0c5d

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

src/common/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ libflux_optparse_la_LIBADD = \
111111
$(builddir)/libczmqcontainers/libczmqcontainers.la \
112112
$(builddir)/liblsd/liblsd.la \
113113
$(builddir)/libutil/fsd.lo \
114+
$(builddir)/libutil/parse_size.lo \
114115
$(LIBPTHREAD)
115116
libflux_optparse_la_LDFLAGS = \
116117
-Wl,--version-script=$(srcdir)/libflux-optparse.map \

src/common/liboptparse/optparse.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
#include <ctype.h>
2020
#include <stdarg.h>
2121
#include <argz.h>
22+
#include <math.h>
2223

2324
#include "src/common/libczmqcontainers/czmq_containers.h"
2425
#include "src/common/libutil/fsd.h"
26+
#include "src/common/libutil/parse_size.h"
2527
#include "ccan/str/str.h"
2628

2729
#include "optparse.h"
@@ -950,6 +952,59 @@ double optparse_get_duration (optparse_t *p, const char *name,
950952
return d;
951953
}
952954

955+
uint64_t optparse_get_size (optparse_t *p,
956+
const char *name,
957+
const char *default_value)
958+
{
959+
int n;
960+
uint64_t result;
961+
const char *s = NULL;
962+
963+
if (default_value == NULL)
964+
default_value = "0";
965+
966+
if ((n = optparse_getopt (p, name, &s)) < 0) {
967+
optparse_fatalmsg (p, 1,
968+
"%s: optparse error: no such argument '%s'\n",
969+
p->program_name, name);
970+
return (uint64_t) -1;
971+
}
972+
if (n == 0)
973+
s = default_value;
974+
if (parse_size (s, &result) < 0) {
975+
optparse_fatalmsg (p, 1,
976+
"%s: invalid argument for option '%s': %s: %s\n",
977+
p->program_name,
978+
name,
979+
s,
980+
strerror (errno));
981+
return (uint64_t) -1;
982+
}
983+
return result;
984+
}
985+
986+
int optparse_get_size_int (optparse_t *p,
987+
const char *name,
988+
const char *default_value)
989+
{
990+
uint64_t val = optparse_get_size (p, name, default_value);
991+
if (val == (uint64_t)-1)
992+
return -1;
993+
if (val > INT_MAX) {
994+
const char *s;
995+
optparse_getopt (p, name, &s);
996+
optparse_fatalmsg (p,
997+
1,
998+
"%s: %s: value %s too large (must be < %s)\n",
999+
p->program_name,
1000+
name,
1001+
s,
1002+
encode_size (INT_MAX+1UL));
1003+
return -1;
1004+
}
1005+
return (int)val;
1006+
}
1007+
9531008
const char *optparse_get_str (optparse_t *p, const char *name,
9541009
const char *default_value)
9551010
{

src/common/liboptparse/optparse.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#define _UTIL_OPTPARSE_H
1313

1414
#include <stdbool.h>
15+
#include <stdint.h>
1516

1617
#ifdef __cplusplus
1718
extern "C" {
@@ -381,6 +382,27 @@ int optparse_get_int (optparse_t *p, const char *name, int default_value);
381382
double optparse_get_duration (optparse_t *p, const char *name,
382383
double default_value);
383384

385+
/*
386+
* Return the option argument parsed as a size in bytes (or other unit)
387+
* with optional multiplicative suffix: k or K=1024, M=1024*1024,
388+
* G=1024*1024*1024, and so on for T, P, and E. The end result is
389+
* truncated and returned as uint64_t. If there was an error parsing
390+
* the size string, then the fatal error function is called.
391+
*
392+
* Return default value if option was unused. default_value=NULL
393+
* is equivalent to default_value="0".
394+
*/
395+
uint64_t optparse_get_size (optparse_t *p, const char *name,
396+
const char *default_value);
397+
398+
/*
399+
* Like optparse_get_size(), but return an int and ensure the provided
400+
* argument does not overflow INT_MAX (calls fatal error function if so).
401+
*/
402+
int optparse_get_size_int (optparse_t *p,
403+
const char *name,
404+
const char *default_value);
405+
384406
/*
385407
* Return the option argument as a double if 'name' was used,
386408
* 'default_value' if not. If the option is unknown, or the argument

0 commit comments

Comments
 (0)