diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libmdsserver/util.c | 95 | ||||
-rw-r--r-- | src/libmdsserver/util.h | 24 |
2 files changed, 117 insertions, 2 deletions
diff --git a/src/libmdsserver/util.c b/src/libmdsserver/util.c index eb79bff..f62abd2 100644 --- a/src/libmdsserver/util.c +++ b/src/libmdsserver/util.c @@ -241,6 +241,101 @@ int strict_atoi(const char* str, int* value, int min, int max) /** + * A version of `atoj` that is strict about the syntax and bounds + * + * @param str The text to parse + * @param value Slot in which to store the value + * @param min The minimum accepted value + * @param max The maximum accepted value + * @return Zero on success, -1 on syntax error + */ +int strict_atoj(const char* str, intmax_t* value, intmax_t min, intmax_t max) +{ + static char minstr[3 * sizeof(intmax_t) + 2] = { '\0' }; + intmax_t r = 0; + char c; + int neg = 0; + + if (*str == '-') + { + if (*minstr == '\0') + sprintf(minstr, "%j", INTMAX_MIN); + if (!strcmp(str, minstr)) + { + r = INTMAX_MIN; + goto done; + } + neg = 1, str++; + } + + if (*str == '\0') + return -1; + + while ((c = *str)) + if (('0' <= c) && (c <= '9')) + { + if (r > INTMAX_MAX / 10) + return -1; + else if (r == INTMAX_MAX / 10) + if ((c & 15) > INTMAX_MAX % 10) + return -1; + r = r * 10 + (c & 15); + } + else + return -1; + + if (neg) + r = -r; + + done: + + if ((r < min) || (r > max)) + return -1; + + *value = r; + return 0; +} + + +/** + * A version of `atouj` that is strict about the syntax and bounds + * + * @param str The text to parse + * @param value Slot in which to store the value + * @param min The minimum accepted value + * @param max The maximum accepted value + * @return Zero on success, -1 on syntax error + */ +int strict_atouj(const char* str, uintmax_t* value, uintmax_t min, uintmax_t max) +{ + uintmax_t r = 0; + char c; + + if (*str == '\0') + return -1; + + while ((c = *str)) + if (('0' <= c) && (c <= '9')) + { + if (r > INTMAX_MAX / 10) + return -1; + else if (r == INTMAX_MAX / 10) + if ((c & 15) > INTMAX_MAX % 10) + return -1; + r = r * 10 + (c & 15); + } + else + return -1; + + if ((r < min) || (r > max)) + return -1; + + *value = r; + return 0; +} + + +/** * Send a buffer into a file and ignore interruptions * * @param fd The file descriptor diff --git a/src/libmdsserver/util.h b/src/libmdsserver/util.h index accf038..c84156d 100644 --- a/src/libmdsserver/util.h +++ b/src/libmdsserver/util.h @@ -110,6 +110,28 @@ size_t send_message(int socket, const char* message, size_t length); int strict_atoi(const char* str, int* value, int min, int max); /** + * A version of `atoj` that is strict about the syntax and bounds + * + * @param str The text to parse + * @param value Slot in which to store the value + * @param min The minimum accepted value + * @param max The maximum accepted value + * @return Zero on success, -1 on syntax error + */ +int strict_atoj(const char* str, intmax_t* value, intmax_t min, intmax_t max); + +/** + * A version of `atouj` that is strict about the syntax and bounds + * + * @param str The text to parse + * @param value Slot in which to store the value + * @param min The minimum accepted value + * @param max The maximum accepted value + * @return Zero on success, -1 on syntax error + */ +int strict_atouj(const char* str, uintmax_t* value, uintmax_t min, uintmax_t max); + +/** * Send a buffer into a file and ignore interruptions * * @param fd The file descriptor @@ -128,7 +150,6 @@ int full_write(int fd, const char* buffer, size_t length); */ char* full_read(int fd, size_t* length); - /** * Send a full message even if interrupted * @@ -139,7 +160,6 @@ char* full_read(int fd, size_t* length); */ int full_send(int socket, const char* message, size_t length); - /** * Check whether a string begins with a specific string, * where neither of the strings are necessarily NUL-terminated |