diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2024-12-02 09:23:45 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2024-12-02 16:34:26 -0500 |
commit | 9606eabd82e6523ffb8ab8b3eeb405f24e3e2346 (patch) | |
tree | fc7e21688361bc15f8492b30cd7b381a07ba0fec | |
parent | 46e0c0bccbee21903efc9c924874970e251dde48 (diff) | |
download | bfs-9606eabd82e6523ffb8ab8b3eeb405f24e3e2346.tar.xz |
bfstd: Add more strto*() wrappers
-rw-r--r-- | src/bfstd.c | 66 | ||||
-rw-r--r-- | src/bfstd.h | 27 |
2 files changed, 69 insertions, 24 deletions
diff --git a/src/bfstd.c b/src/bfstd.c index b58d69e..738c956 100644 --- a/src/bfstd.c +++ b/src/bfstd.c @@ -211,35 +211,77 @@ const char *xgetprogname(void) { return cmd; } -int xstrtoll(const char *str, char **end, int base, long long *value) { - // strtoll() skips leading spaces, but we want to reject them +/** Common prologue for xstrto*() wrappers. */ +static int xstrtox_prologue(const char *str) { + // strto*() skips leading spaces, but we want to reject them if (xisspace(str[0])) { errno = EINVAL; return -1; } - // If end is NULL, make sure the entire string is valid - bool entire = !end; - char *endp; - if (!end) { - end = &endp; - } - errno = 0; - long long result = strtoll(str, end, base); + return 0; +} + +/** Common epilogue for xstrto*() wrappers. */ +static int xstrtox_epilogue(const char *str, char **end, char *endp) { if (errno != 0) { return -1; } - if (*end == str || (entire && **end != '\0')) { + if (end) { + *end = endp; + } + + // If end is NULL, make sure the entire string is valid + if (endp == str || (!end && *endp != '\0')) { errno = EINVAL; return -1; } - *value = result; return 0; } +int xstrtol(const char *str, char **end, int base, long *value) { + if (xstrtox_prologue(str) != 0) { + return -1; + } + + char *endp; + *value = strtol(str, &endp, base); + return xstrtox_epilogue(str, end, endp); +} + +int xstrtoll(const char *str, char **end, int base, long long *value) { + if (xstrtox_prologue(str) != 0) { + return -1; + } + + char *endp; + *value = strtoll(str, &endp, base); + return xstrtox_epilogue(str, end, endp); +} + +int xstrtof(const char *str, char **end, float *value) { + if (xstrtox_prologue(str) != 0) { + return -1; + } + + char *endp; + *value = strtof(str, &endp); + return xstrtox_epilogue(str, end, endp); +} + +int xstrtod(const char *str, char **end, double *value) { + if (xstrtox_prologue(str) != 0) { + return -1; + } + + char *endp; + *value = strtod(str, &endp); + return xstrtox_epilogue(str, end, endp); +} + /** Compile and execute a regular expression for xrpmatch(). */ static int xrpregex(nl_item item, const char *response) { const char *pattern = nl_langinfo(item); diff --git a/src/bfstd.h b/src/bfstd.h index 97867fd..84f92ec 100644 --- a/src/bfstd.h +++ b/src/bfstd.h @@ -179,23 +179,26 @@ int open_cterm(int flags); const char *xgetprogname(void); /** + * Wrapper for strtol() that forbids leading spaces. + */ +int xstrtol(const char *str, char **end, int base, long *value); + +/** * Wrapper for strtoll() that forbids leading spaces. - * - * @str - * The string to parse. - * @end - * If non-NULL, will hold a pointer to the first invalid character. - * If NULL, the entire string must be valid. - * @base - * The base for the conversion, or 0 to auto-detect. - * @value - * Will hold the parsed integer value, on success. - * @return - * 0 on success, -1 on failure. */ int xstrtoll(const char *str, char **end, int base, long long *value); /** + * Wrapper for strtof() that forbids leading spaces. + */ +int xstrtof(const char *str, char **end, float *value); + +/** + * Wrapper for strtod() that forbids leading spaces. + */ +int xstrtod(const char *str, char **end, double *value); + +/** * Process a yes/no prompt. * * @return 1 for yes, 0 for no, and -1 for unknown. |