Skip to content

Commit 96f98ce

Browse files
committed
bfstd: Add some more integer parsing functions
1 parent f9fd4b9 commit 96f98ce

File tree

7 files changed

+218
-54
lines changed

7 files changed

+218
-54
lines changed

bench/ioq.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,9 @@ int main(int argc, char *argv[]) {
177177
setlocale(LC_ALL, "");
178178

179179
// -d: queue depth
180-
long depth = 4096;
180+
unsigned int depth = 4096;
181181
// -j: threads
182-
long threads = 0;
182+
unsigned int threads = 0;
183183
// -t: timeout
184184
double timeout = 5.0;
185185
// -L|-H: ioq_nop() type
@@ -190,13 +190,13 @@ int main(int argc, char *argv[]) {
190190
while (c = getopt(argc, argv, ":d:j:t:LH"), c != -1) {
191191
switch (c) {
192192
case 'd':
193-
if (xstrtol(optarg, NULL, 10, &depth) != 0) {
193+
if (xstrtoui(optarg, NULL, 10, &depth) != 0) {
194194
fprintf(stderr, "%s: Bad depth '%s': %s\n", cmd, optarg, errstr());
195195
return EXIT_FAILURE;
196196
}
197197
break;
198198
case 'j':
199-
if (xstrtol(optarg, NULL, 10, &threads) != 0) {
199+
if (xstrtoui(optarg, NULL, 10, &threads) != 0) {
200200
fprintf(stderr, "%s: Bad thread count '%s': %s\n", cmd, optarg, errstr());
201201
return EXIT_FAILURE;
202202
}
@@ -222,7 +222,7 @@ int main(int argc, char *argv[]) {
222222
}
223223
}
224224

225-
if (threads <= 0) {
225+
if (!threads) {
226226
threads = nproc();
227227
if (threads > 8) {
228228
threads = 8;
@@ -238,8 +238,8 @@ int main(int argc, char *argv[]) {
238238

239239
printf("I/O queue benchmark (%s)\n\n", bfs_version);
240240

241-
printf("[-d] depth: %ld\n", depth);
242-
printf("[-j] threads: %ld (including main)\n", threads + 1);
241+
printf("[-d] depth: %u\n", depth);
242+
printf("[-j] threads: %u (including main)\n", threads + 1);
243243
if (type == IOQ_NOP_HEAVY) {
244244
printf("[-H] type: heavy (with syscalls)\n");
245245
} else {
@@ -252,7 +252,7 @@ int main(int argc, char *argv[]) {
252252
fflush(stdout);
253253

254254
struct ioq *ioq = ioq_create(depth, threads);
255-
bfs_everify(ioq, "ioq_create(%ld, %ld)", depth, threads);
255+
bfs_everify(ioq, "ioq_create(%u, %u)", depth, threads);
256256

257257
// Pre-allocate all the requests
258258
while (ioq_capacity(ioq) > 0) {

src/bfstd.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,36 @@ static int xstrtox_epilogue(const char *str, char **end, char *endp) {
235235
return 0;
236236
}
237237

238+
int xstrtos(const char *str, char **end, int base, short *value) {
239+
long n;
240+
if (xstrtol(str, end, base, &n) != 0) {
241+
return -1;
242+
}
243+
244+
if (n < SHRT_MIN || n > SHRT_MAX) {
245+
errno = ERANGE;
246+
return -1;
247+
}
248+
249+
*value = n;
250+
return 0;
251+
}
252+
253+
int xstrtoi(const char *str, char **end, int base, int *value) {
254+
long n;
255+
if (xstrtol(str, end, base, &n) != 0) {
256+
return -1;
257+
}
258+
259+
if (n < INT_MIN || n > INT_MAX) {
260+
errno = ERANGE;
261+
return -1;
262+
}
263+
264+
*value = n;
265+
return 0;
266+
}
267+
238268
int xstrtol(const char *str, char **end, int base, long *value) {
239269
if (xstrtox_prologue(str) != 0) {
240270
return -1;
@@ -275,6 +305,70 @@ int xstrtod(const char *str, char **end, double *value) {
275305
return xstrtox_epilogue(str, end, endp);
276306
}
277307

308+
int xstrtous(const char *str, char **end, int base, unsigned short *value) {
309+
unsigned long n;
310+
if (xstrtoul(str, end, base, &n) != 0) {
311+
return -1;
312+
}
313+
314+
if (n > USHRT_MAX) {
315+
errno = ERANGE;
316+
return -1;
317+
}
318+
319+
*value = n;
320+
return 0;
321+
}
322+
323+
int xstrtoui(const char *str, char **end, int base, unsigned int *value) {
324+
unsigned long n;
325+
if (xstrtoul(str, end, base, &n) != 0) {
326+
return -1;
327+
}
328+
329+
if (n > UINT_MAX) {
330+
errno = ERANGE;
331+
return -1;
332+
}
333+
334+
*value = n;
335+
return 0;
336+
}
337+
338+
/** Common epilogue for xstrtou*() wrappers. */
339+
static int xstrtoux_epilogue(const char *str, char **end, char *endp) {
340+
if (xstrtox_epilogue(str, end, endp) != 0) {
341+
return -1;
342+
}
343+
344+
if (str[0] == '-') {
345+
errno = ERANGE;
346+
return -1;
347+
}
348+
349+
return 0;
350+
}
351+
352+
int xstrtoul(const char *str, char **end, int base, unsigned long *value) {
353+
if (xstrtox_prologue(str) != 0) {
354+
return -1;
355+
}
356+
357+
char *endp;
358+
*value = strtoul(str, &endp, base);
359+
return xstrtoux_epilogue(str, end, endp);
360+
}
361+
362+
int xstrtoull(const char *str, char **end, int base, unsigned long long *value) {
363+
if (xstrtox_prologue(str) != 0) {
364+
return -1;
365+
}
366+
367+
char *endp;
368+
*value = strtoull(str, &endp, base);
369+
return xstrtoux_epilogue(str, end, endp);
370+
}
371+
278372
/** Compile and execute a regular expression for xrpmatch(). */
279373
static int xrpregex(nl_item item, const char *response) {
280374
const char *pattern = nl_langinfo(item);

src/bfstd.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,16 @@ char *xgetdelim(FILE *file, char delim);
168168
*/
169169
const char *xgetprogname(void);
170170

171+
/**
172+
* Like xstrtol(), but for short.
173+
*/
174+
int xstrtos(const char *str, char **end, int base, short *value);
175+
176+
/**
177+
* Like xstrtol(), but for int.
178+
*/
179+
int xstrtoi(const char *str, char **end, int base, int *value);
180+
171181
/**
172182
* Wrapper for strtol() that forbids leading spaces.
173183
*/
@@ -178,6 +188,26 @@ int xstrtol(const char *str, char **end, int base, long *value);
178188
*/
179189
int xstrtoll(const char *str, char **end, int base, long long *value);
180190

191+
/**
192+
* Like xstrtoul(), but for unsigned short.
193+
*/
194+
int xstrtous(const char *str, char **end, int base, unsigned short *value);
195+
196+
/**
197+
* Like xstrtoul(), but for unsigned int.
198+
*/
199+
int xstrtoui(const char *str, char **end, int base, unsigned int *value);
200+
201+
/**
202+
* Wrapper for strtoul() that forbids leading spaces, negatives.
203+
*/
204+
int xstrtoul(const char *str, char **end, int base, unsigned long *value);
205+
206+
/**
207+
* Wrapper for strtoull() that forbids leading spaces, negatives.
208+
*/
209+
int xstrtoull(const char *str, char **end, int base, unsigned long long *value);
210+
181211
/**
182212
* Wrapper for strtof() that forbids leading spaces.
183213
*/

tests/bfstd.c

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include "tests.h"
55

66
#include "bfstd.h"
7-
#include "bit.h"
87
#include "diag.h"
98

109
#include <errno.h>
@@ -95,37 +94,74 @@ static void check_wordescs(void) {
9594

9695
/** xstrto*() test cases. */
9796
static void check_strtox(void) {
97+
short s;
98+
unsigned short us;
99+
int i;
100+
unsigned int ui;
98101
long l;
102+
unsigned long ul;
99103
long long ll;
104+
unsigned long long ull;
100105
char *end;
101106

107+
#define check_strtouerr(err, str, end, base) \
108+
do { \
109+
bfs_echeck(xstrtous(str, end, base, &us) != 0 && errno == err); \
110+
bfs_echeck(xstrtoui(str, end, base, &ui) != 0 && errno == err); \
111+
bfs_echeck(xstrtoul(str, end, base, &ul) != 0 && errno == err); \
112+
bfs_echeck(xstrtoull(str, end, base, &ull) != 0 && errno == err); \
113+
} while (0)
114+
115+
check_strtouerr(ERANGE, "-1", NULL, 0);
116+
check_strtouerr(ERANGE, "-0x1", NULL, 0);
117+
118+
check_strtouerr(EINVAL, "-", NULL, 0);
119+
check_strtouerr(EINVAL, "-q", NULL, 0);
120+
check_strtouerr(EINVAL, "-1q", NULL, 0);
121+
check_strtouerr(EINVAL, "-0x", NULL, 0);
122+
102123
#define check_strtoerr(err, str, end, base) \
103-
bfs_echeck(xstrtol(str, end, base, &l) != 0 && errno == err); \
104-
bfs_echeck(xstrtoll(str, end, base, &ll) != 0 && errno == err)
124+
do { \
125+
bfs_echeck(xstrtos(str, end, base, &s) != 0 && errno == err); \
126+
bfs_echeck(xstrtoi(str, end, base, &i) != 0 && errno == err); \
127+
bfs_echeck(xstrtol(str, end, base, &l) != 0 && errno == err); \
128+
bfs_echeck(xstrtoll(str, end, base, &ll) != 0 && errno == err); \
129+
check_strtouerr(err, str, end, base); \
130+
} while (0)
105131

106132
check_strtoerr(EINVAL, "", NULL, 0);
107133
check_strtoerr(EINVAL, "", &end, 0);
108134
check_strtoerr(EINVAL, " 1 ", &end, 0);
135+
check_strtoerr(EINVAL, " -1", NULL, 0);
109136
check_strtoerr(EINVAL, " 123", NULL, 0);
110137
check_strtoerr(EINVAL, "123 ", NULL, 0);
111138
check_strtoerr(EINVAL, "0789", NULL, 0);
112139
check_strtoerr(EINVAL, "789A", NULL, 0);
113140
check_strtoerr(EINVAL, "0x", NULL, 0);
114141
check_strtoerr(EINVAL, "0x789A", NULL, 10);
115-
116-
if (LLONG_WIDTH == 64) {
117-
check_strtoerr(ERANGE, "9223372036854775808", NULL, 0);
118-
}
142+
check_strtoerr(EINVAL, "0x-1", NULL, 0);
143+
144+
#define check_strtotype(type, min, max, fmt, fn, str, base, v, n) \
145+
do { \
146+
if ((n) >= min && (n) <= max) { \
147+
bfs_echeck(fn(str, NULL, base, &v) == 0); \
148+
bfs_check(v == (type)(n), "%s('%s') == " fmt " (!= " fmt ")", #fn, str, v, (type)(n)); \
149+
} else { \
150+
bfs_echeck(fn(str, NULL, base, &v) != 0 && errno == ERANGE); \
151+
} \
152+
} while (0)
119153

120154
#define check_strtoint(str, base, n) \
121-
if ((n) >= LONG_MIN && (n) <= LONG_MAX) { \
122-
bfs_echeck(xstrtol(str, NULL, base, &l) == 0); \
123-
bfs_check(l == (n), "xstrtol('%s') == %ld (!= %ld)", str, l, (long)(n)); \
124-
} else { \
125-
bfs_echeck(xstrtol(str, NULL, base, &l) != 0 && errno == ERANGE); \
126-
} \
127-
bfs_echeck(xstrtoll(str, NULL, base, &ll) == 0); \
128-
bfs_check(ll == (n), "xstrtoll('%s') == %lld (!= %lld)", str, ll, (long long)(n)) \
155+
do { \
156+
check_strtotype( signed short, SHRT_MIN, SHRT_MAX, "%d", xstrtos, str, base, s, n); \
157+
check_strtotype( signed int, INT_MIN, INT_MAX, "%d", xstrtoi, str, base, i, n); \
158+
check_strtotype( signed long, LONG_MIN, LONG_MAX, "%ld", xstrtol, str, base, l, n); \
159+
check_strtotype( signed long long, LLONG_MIN, LLONG_MAX, "%lld", xstrtoll, str, base, ll, n); \
160+
check_strtotype(unsigned short, 0, USHRT_MAX, "%u", xstrtous, str, base, us, n); \
161+
check_strtotype(unsigned int, 0, UINT_MAX, "%u", xstrtoui, str, base, ui, n); \
162+
check_strtotype(unsigned long, 0, ULONG_MAX, "%lu", xstrtoul, str, base, ul, n); \
163+
check_strtotype(unsigned long long, 0, ULLONG_MAX, "%llu", xstrtoull, str, base, ull, n); \
164+
} while (0)
129165

130166
check_strtoint("123", 0, 123);
131167
check_strtoint("+123", 0, 123);
@@ -139,13 +175,21 @@ static void check_strtox(void) {
139175

140176
check_strtoint("123", 16, 0x123);
141177

142-
check_strtoint("9223372036854775807", 0, 9223372036854775807LL);
143-
check_strtoint("-9223372036854775808", 0, -9223372036854775807LL - 1);
178+
check_strtoint("0x7FFF", 0, 0x7FFF);
179+
check_strtoint("-0x8000", 0, -0x8000);
180+
181+
check_strtoint("0x7FFFFFFF", 0, 0x7FFFFFFFL);
182+
check_strtoint("-0x80000000", 0, -0x7FFFFFFFL - 1);
183+
184+
check_strtoint("0x7FFFFFFFFFFFFFFF", 0, 0x7FFFFFFFFFFFFFFFLL);
185+
check_strtoint("-0x8000000000000000", 0, -0x7FFFFFFFFFFFFFFFLL - 1);
144186

145187
#define check_strtoend(str, estr, base, n) \
146-
bfs_echeck(xstrtoll(str, &end, base, &ll) == 0); \
147-
bfs_check(ll == (n), "xstrtoll('%s') == %lld (!= %lld)", str, ll, (long long)(n)); \
148-
bfs_check(strcmp(end, estr) == 0, "xstrtoll('%s'): end == '%s' (!= '%s')", str, end, estr) \
188+
do { \
189+
bfs_echeck(xstrtoll(str, &end, base, &ll) == 0); \
190+
bfs_check(ll == (n), "xstrtoll('%s') == %lld (!= %lld)", str, ll, (long long)(n)); \
191+
bfs_check(strcmp(end, estr) == 0, "xstrtoll('%s'): end == '%s' (!= '%s')", str, end, estr); \
192+
} while (0)
149193

150194
check_strtoend("123 ", " ", 0, 123);
151195
check_strtoend("0789", "89", 0, 07);

tests/main.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,15 +222,15 @@ int main(int argc, char *argv[]) {
222222
}
223223
tzset();
224224

225-
long jobs = 0;
225+
unsigned int jobs = 0;
226226

227227
const char *cmd = argc > 0 ? argv[0] : "units";
228228
int c;
229229
while (c = getopt(argc, argv, ":j:"), c != -1) {
230230
switch (c) {
231231
case 'j':
232-
if (xstrtol(optarg, NULL, 10, &jobs) != 0 || jobs <= 0) {
233-
fprintf(stderr, "%s: Bad job count '%s'\n", cmd, optarg);
232+
if (xstrtoui(optarg, NULL, 10, &jobs) != 0) {
233+
fprintf(stderr, "%s: Bad job count '%s': %s\n", cmd, optarg, errstr());
234234
return EXIT_FAILURE;
235235
}
236236
break;
@@ -243,7 +243,7 @@ int main(int argc, char *argv[]) {
243243
}
244244
}
245245

246-
if (jobs == 0) {
246+
if (!jobs) {
247247
jobs = nproc();
248248
}
249249

0 commit comments

Comments
 (0)