From e8f32d09348b2e7504d3c33c97f3c854f3f75dec Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Wed, 19 Aug 2015 14:04:36 +0200 Subject: add strict_atoj and strict_atouj MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/libmdsserver/util.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ src/libmdsserver/util.h | 24 +++++++++++-- 2 files changed, 117 insertions(+), 2 deletions(-) (limited to 'src') 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 @@ -240,6 +240,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 * 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 @@ -109,6 +109,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 * @@ -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 -- cgit v1.2.3-70-g09d2