diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2016-04-11 20:07:36 +0000 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2016-04-11 20:07:36 +0000 |
commit | aff8b7214bae150c5aac8544396cd938ebc21e47 (patch) | |
tree | 2bd24ef20561e51d9f1fc1b760fdedec52c20a25 | |
parent | dc1eb9a9d79d4272d8d29348ca37a10634eb7e8f (diff) |
mhd_str: added MHD_str_to_uint64_() and MHD_str_to_uint64_n_() functions for US-ASCII-only
operations, independently on locale
-rw-r--r-- | src/microhttpd/mhd_limits.h | 4 | ||||
-rw-r--r-- | src/microhttpd/mhd_str.c | 104 | ||||
-rw-r--r-- | src/microhttpd/mhd_str.h | 35 |
3 files changed, 143 insertions, 0 deletions
diff --git a/src/microhttpd/mhd_limits.h b/src/microhttpd/mhd_limits.h index 5ce2f9c4..c8eff094 100644 --- a/src/microhttpd/mhd_limits.h +++ b/src/microhttpd/mhd_limits.h @@ -44,6 +44,10 @@ #define INT32_MAX ((int32_t)0x7FFFFFFF) #endif /* !INT32_MAX */ +#ifndef UINT64_MAX +#define UINT64_MAX ((uint64_t)0xFFFFFFFFFFFFFFFF) +#endif /* !INT32_MAX */ + #ifndef SIZE_MAX #define SIZE_MAX ((size_t) ~((size_t)0)) #endif /* !SIZE_MAX */ diff --git a/src/microhttpd/mhd_str.c b/src/microhttpd/mhd_str.c index 1e9154ba..61e5604b 100644 --- a/src/microhttpd/mhd_str.c +++ b/src/microhttpd/mhd_str.c @@ -31,6 +31,8 @@ #include <stdbool.h> #endif +#include "mhd_limits.h" + /* * Block of functions/macros that use US-ASCII charset as required by HTTP * standards. Not affected by current locale settings. @@ -229,3 +231,105 @@ MHD_str_equal_caseless_n_ (const char * const str1, const char * const str2, siz } return !0; } + +/** + * Convert decimal US-ASCII digits in string to number in uint64_t. + * Conversion stopped at first non-digit character. + * @param str string to convert + * @param out_val pointer to uint64_t to store result of conversion + * @param next_char pointer to store pointer to character next to last + * converted digit, ignored if NULL + * @return non-zero if conversion succeed; zero if no digit is found, + * value is larger then possible to store in uint64_t or + * @a out_val or @a str is NULL + */ +int +MHD_str_to_uint64_ (const char * str, uint64_t * out_val, const char ** next_char) +{ + uint64_t res; + if (!str || !isasciidigit(str[0])) + { + if (next_char) + *next_char = str; + return 0; + } + + res = 0; + do + { + const int digit = str[0] - '0'; + if ( (res < (UINT64_MAX / 10)) || + (res == (UINT64_MAX / 10) && digit <= (UINT64_MAX % 10)) ) + { + res *= 10; + res += digit; + } + else + { + if (next_char) + *next_char = str; + return 0; + } + str++; + } while (isasciidigit (str[0])); + + *out_val = res; + if (next_char) + *next_char = str; + + return !0; +} + + +/** + * Convert not more then @a maxlen decimal US-ASCII digits in string to + * number in uint64_t. + * Conversion stopped at first non-digit character or after @a maxlen + * digits. + * @param str string to convert + * @param out_val pointer to uint64_t to store result of conversion + * @param next_char pointer to store pointer to character next to last + * converted digit, ignored if NULL + * @return non-zero if conversion succeed; zero if no digit is found, + * value is larger then possible to store in uint64_t or + * @a out_val is NULL + */ +int +MHD_str_to_uint64_n_ (const char * str, size_t maxlen, uint64_t * out_val, + const char ** next_char) +{ + uint64_t res; + size_t i; + if (!str || !maxlen || !isasciidigit (str[0])) + { + if (next_char) + *next_char = str; + return 0; + } + + res = 0; + i = 0; + do + { + const int digit = str[i] - '0'; + if ( (res < (UINT64_MAX / 10)) || + (res == (UINT64_MAX / 10) && digit <= (UINT64_MAX % 10)) ) + { + res *= 10; + res += digit; + } + else + { + if (next_char) + *next_char = str + i; + return 0; + } + + } while(i < maxlen && isasciidigit(str[i])); + + *out_val = res; + if (next_char) + *next_char = str + i; + + return !0; +} diff --git a/src/microhttpd/mhd_str.h b/src/microhttpd/mhd_str.h index 6975d6b8..22d09cff 100644 --- a/src/microhttpd/mhd_str.h +++ b/src/microhttpd/mhd_str.h @@ -60,4 +60,39 @@ MHD_str_equal_caseless_n_ (const char * const str1, const char * const str2, size_t maxlen); +/** + * Convert decimal US-ASCII digits in string to number in uint64_t. + * Conversion stopped at first non-digit character. + * @param str string to convert + * @param out_val pointer to uint64_t to store result of conversion + * @param next_char pointer to store pointer to character next to last + * converted digit, ignored if NULL + * @return non-zero if conversion succeed; zero if no digit is found, + * value is larger then possible to store in uint64_t or + * @a out_val is NULL + */ +int +MHD_str_to_uint64_ (const char * str, + uint64_t * out_val, + const char ** next_char); + +/** + * Convert not more then @a maxlen decimal US-ASCII digits in string to + * number in uint64_t. + * Conversion stopped at first non-digit character or after @a maxlen + * digits. + * @param str string to convert + * @param out_val pointer to uint64_t to store result of conversion + * @param next_char pointer to store pointer to character next to last + * converted digit, ignored if NULL + * @return non-zero if conversion succeed; zero if no digit is found, + * value is larger then possible to store in uint64_t or + * @a out_val is NULL + */ +int +MHD_str_to_uint64_n_ (const char * str, + size_t maxlen, + uint64_t * out_val, + const char ** next_char); + #endif /* MHD_STR_H */ |