summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2016-04-11 20:07:36 +0000
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2016-04-11 20:07:36 +0000
commitaff8b7214bae150c5aac8544396cd938ebc21e47 (patch)
tree2bd24ef20561e51d9f1fc1b760fdedec52c20a25
parentdc1eb9a9d79d4272d8d29348ca37a10634eb7e8f (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.h4
-rw-r--r--src/microhttpd/mhd_str.c104
-rw-r--r--src/microhttpd/mhd_str.h35
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 */