summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2024-12-02 09:23:45 -0500
committerTavian Barnes <tavianator@tavianator.com>2024-12-02 16:34:26 -0500
commit9606eabd82e6523ffb8ab8b3eeb405f24e3e2346 (patch)
treefc7e21688361bc15f8492b30cd7b381a07ba0fec
parent46e0c0bccbee21903efc9c924874970e251dde48 (diff)
downloadbfs-9606eabd82e6523ffb8ab8b3eeb405f24e3e2346.tar.xz
bfstd: Add more strto*() wrappers
-rw-r--r--src/bfstd.c66
-rw-r--r--src/bfstd.h27
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.