[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 01/07: Added internal functions for printing decimal and
From: |
gnunet |
Subject: |
[libmicrohttpd] 01/07: Added internal functions for printing decimal and hex numbers |
Date: |
Wed, 28 Jul 2021 10:37:00 +0200 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit ee3f32220038303ebf1bfcf1494c9badf6d3adc4
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Mon Jun 7 19:46:46 2021 +0300
Added internal functions for printing decimal and hex numbers
---
src/microhttpd/.gitignore | 1 +
src/microhttpd/Makefile.am | 4 +
src/microhttpd/mhd_str.c | 68 ++++++++++
src/microhttpd/mhd_str.h | 30 +++++
src/microhttpd/test_str.c | 310 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 413 insertions(+)
diff --git a/src/microhttpd/.gitignore b/src/microhttpd/.gitignore
index 3b0d8ce4..11f4f587 100644
--- a/src/microhttpd/.gitignore
+++ b/src/microhttpd/.gitignore
@@ -48,6 +48,7 @@ test_http_reasons
/test_shutdown_select_ignore
/test_str_compare
/test_str_to_value
+/test_str_from_value
/test_upgrade
/test_upgrade_ssl
/test_options
diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am
index e610c1df..fb10b0a2 100644
--- a/src/microhttpd/Makefile.am
+++ b/src/microhttpd/Makefile.am
@@ -157,6 +157,7 @@ endif
check_PROGRAMS = \
test_str_compare \
test_str_to_value \
+ test_str_from_value \
test_str_token \
test_str_token_remove \
test_str_tokens_remove \
@@ -358,6 +359,9 @@ test_str_compare_SOURCES = \
test_str_to_value_SOURCES = \
test_str.c test_helpers.h mhd_str.c mhd_str.h
+test_str_from_value_SOURCES = \
+ test_str.c test_helpers.h mhd_str.c mhd_str.h
+
test_str_token_SOURCES = \
test_str_token.c mhd_str.c mhd_str.h
diff --git a/src/microhttpd/mhd_str.c b/src/microhttpd/mhd_str.c
index 60c198bc..1d4b9257 100644
--- a/src/microhttpd/mhd_str.c
+++ b/src/microhttpd/mhd_str.c
@@ -32,6 +32,7 @@
#include "mhd_assert.h"
#include "mhd_limits.h"
+#include "mhd_assert.h"
#ifdef MHD_FAVOR_SMALL_CODE
#ifdef _MHD_static_inline
@@ -1184,3 +1185,70 @@ MHD_str_to_uvalue_n_ (const char *str,
#endif /* MHD_FAVOR_SMALL_CODE */
+
+
+size_t
+MHD_uint32_to_strx (uint32_t val,
+ char *buf,
+ size_t buf_size)
+{
+ char *chr; /**< pointer to the current printed digit */
+ int digit_pos = 7; /** zero-based, digit position in @a 'val' */
+ int digit;
+
+ chr = buf;
+ digit = (int) (((val) >> (4 * digit_pos)) & 0xf);
+
+ /* Skip leading zeros */
+ while ((0 == digit) && (0 != digit_pos))
+ digit = (int) (((val) >> (4 * --digit_pos)) & 0xf);
+
+ while (0 != buf_size)
+ {
+ *chr = (digit <= 9) ? ('0' + (char) digit) : ('A' + (char) digit - 10);
+ chr++;
+ buf_size--;
+ if (0 == digit_pos)
+ return (size_t) (chr - buf);
+ digit = (int) (((val) >> (4 * --digit_pos)) & 0xf);
+ }
+ return 0; /* The buffer is too small */
+}
+
+
+size_t
+MHD_uint16_to_str (uint16_t val,
+ char *buf,
+ size_t buf_size)
+{
+ char *chr; /**< pointer to the current printed digit */
+ /* The biggest printable number is 65535 */
+ uint16_t divisor = UINT16_C (10000);
+ int digit;
+
+ chr = buf;
+ digit = (int) (val / divisor);
+ mhd_assert (digit < 10);
+
+ /* Do not print leading zeros */
+ while ((0 == digit) && (1 < divisor))
+ {
+ divisor /= 10;
+ digit = (int) (val / divisor);
+ mhd_assert (digit < 10);
+ }
+
+ while (0 != buf_size)
+ {
+ *chr = (char) digit + '0';
+ chr++;
+ buf_size--;
+ if (1 == divisor)
+ return (size_t) (chr - buf);
+ val %= divisor;
+ divisor /= 10;
+ digit = (int) (val / divisor);
+ mhd_assert (digit < 10);
+ }
+ return 0; /* The buffer is too small */
+}
diff --git a/src/microhttpd/mhd_str.h b/src/microhttpd/mhd_str.h
index 0bd46444..27764f01 100644
--- a/src/microhttpd/mhd_str.h
+++ b/src/microhttpd/mhd_str.h
@@ -361,4 +361,34 @@ MHD_str_to_uvalue_n_ (const char *str,
#endif /* MHD_FAVOR_SMALL_CODE */
+
+/**
+ * Convert uint32_t value to hexdecimal US-ASCII string.
+ * @note: result is NOT zero-terminated.
+ * @param val the value to convert
+ * @param buf the buffer to result to
+ * @param buf_size size of the @a buffer
+ * @return number of charters has been put to the @a buf,
+ * zero if buffer is too small (buffer may be modified).
+ */
+size_t
+MHD_uint32_to_strx (uint32_t val,
+ char *buf,
+ size_t buf_size);
+
+
+/**
+ * Convert uint16_t value to decimal US-ASCII string.
+ * @note: result is NOT zero-terminated.
+ * @param val the value to convert
+ * @param buf the buffer to result to
+ * @param buf_size size of the @a buffer
+ * @return number of charters has been put to the @a buf,
+ * zero if buffer is too small (buffer may be modified).
+ */
+size_t
+MHD_uint16_to_str (uint16_t val,
+ char *buf,
+ size_t buf_size);
+
#endif /* MHD_STR_H */
diff --git a/src/microhttpd/test_str.c b/src/microhttpd/test_str.c
index 1e140cb6..81ba378f 100644
--- a/src/microhttpd/test_str.c
+++ b/src/microhttpd/test_str.c
@@ -3314,6 +3314,313 @@ run_str_to_X_tests (void)
}
+int
+check_str_from_uint16 (void)
+{
+ size_t t_failed = 0;
+ size_t i, j;
+ char buf[70];
+ const char *erase =
+ "-@=sd#+&(pdiren456qwe#@C3S!DAS45AOIPUQWESAdFzxcv1s*()&#$%34`"
+ "32452d098poiden45SADFFDA3S4D3SDFdfgsdfgsSADFzxdvs$*()द`"
+ "adsf##$$@&*^%*^&56qwe#3C@S!DAScFAOIP$#%#$Ad1zs3v1$*()ӌ`";
+ static const size_t n_checks = sizeof(dstrs_w_values)
+ / sizeof(dstrs_w_values[0]);
+ int c_failed[n_checks];
+
+ memset (c_failed, 0, sizeof(c_failed));
+
+ for (j = 0; j < locale_name_count; j++)
+ {
+ set_test_locale (j); /* setlocale() can be slow! */
+ for (i = 0; i < n_checks; i++)
+ {
+ const struct str_with_value *const t = dstrs_w_values + i;
+ size_t b_size;
+ size_t rs;
+
+ if (c_failed[i])
+ continue; /* skip already failed checks */
+
+ if (t->str.len < t->num_of_digt)
+ {
+ fprintf (stderr,
+ "ERROR: dstrs_w_values[%u] has wrong num_of_digt (%u):
num_of_digt is expected"
+ " to be less or equal to str.len (%u).\n",
+ (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned
+ int) t->str.
+ len);
+ return -1;
+ }
+ if ('0' == t->str.str[0])
+ continue; /* Skip strings prefixed with zeros */
+ if (t->num_of_digt != t->str.len)
+ continue; /* Skip strings with suffixes */
+ if (UINT16_MAX < t->val)
+ continue; /* Too large value to convert */
+ if (sizeof(buf) < t->str.len + 1)
+ {
+ fprintf (stderr,
+ "ERROR: dstrs_w_values[%u] has too long (%u) string, "
+ "size of 'buf' should be increased.\n",
+ (unsigned int) i, (unsigned int) t->str.len);
+ return -1;
+ }
+ for (b_size = 0; b_size <= t->str.len + 1; ++b_size)
+ {
+ /* fill buffer with pseudo-random values */
+ memcpy (buf, erase, sizeof(buf));
+
+ rs = MHD_uint16_to_str (t->val, buf, b_size);
+
+ if (t->num_of_digt > b_size)
+ {
+ /* Must fail, buffer is too small for result */
+ if (0 != rs)
+ {
+ if (0 == c_failed[i])
+ t_failed++;
+ c_failed[i] = ! 0;
+ fprintf (stderr,
+ "FAILED: MHD_uint16_to_str(%" PRIu64 ", -> buf,"
+ " %d) returned %" PRIuPTR
+ ", while expecting 0."
+ " Locale: %s\n", t->val, (int) b_size, (intptr_t) rs,
+ get_current_locale_str ());
+ }
+ }
+ else
+ {
+ if (t->num_of_digt != rs)
+ {
+ if (0 == c_failed[i])
+ t_failed++;
+ c_failed[i] = ! 0;
+ fprintf (stderr,
+ "FAILED: MHD_uint16_to_str(%" PRIu64 ", -> buf,"
+ " %d) returned %" PRIuPTR
+ ", while expecting %d."
+ " Locale: %s\n", t->val, (int) b_size, (intptr_t) rs,
+ (int) t->num_of_digt, get_current_locale_str ());
+ }
+ else if (0 != memcmp (buf, t->str.str, t->num_of_digt))
+ {
+ if (0 == c_failed[i])
+ t_failed++;
+ c_failed[i] = ! 0;
+ fprintf (stderr,
+ "FAILED: MHD_uint16_to_str(%" PRIu64 ", -> \"%.*s\","
+ " %d) returned %" PRIuPTR "."
+ " Locale: %s\n", t->val, (int) rs, buf, (int) b_size,
+ (intptr_t) rs, get_current_locale_str ());
+ }
+ else if (0 != memcmp (buf + rs, erase + rs, sizeof(buf) - rs))
+ {
+ if (0 == c_failed[i])
+ t_failed++;
+ c_failed[i] = ! 0;
+ fprintf (stderr,
+ "FAILED: MHD_uint16_to_str(%" PRIu64 ", -> \"%.*s\","
+ " %d) returned %" PRIuPTR
+ " and touched data after the resulting string."
+ " Locale: %s\n", t->val, (int) rs, buf, (int) b_size,
+ (intptr_t) rs, get_current_locale_str ());
+ }
+ }
+ }
+ if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i])
+ printf ("PASSED: MHD_uint16_to_str(%" PRIu64 ", -> \"%.*s\", %d) "
+ "== %" PRIuPTR "\n",
+ t->val, (int) rs, buf, (int) b_size - 1, (intptr_t) rs);
+ }
+ }
+ return t_failed;
+}
+
+
+int
+check_strx_from_uint32 (void)
+{
+ size_t t_failed = 0;
+ size_t i, j;
+ char buf[70];
+ const char *erase =
+ "jrlkjssfhjfvrjntJHLJ$@%$#adsfdkj;k$##$%#$%FGDF%$#^FDFG%$#$D`"
+ ";skjdhjflsdkjhdjfalskdjhdfalkjdhf$%##%$$#%FSDGFSDDGDFSSDSDF`"
+ "#5#$%#$#$DFSFDDFSGSDFSDF354FDDSGFDFfdssfddfswqemn,.zxih,.sx`";
+ static const size_t n_checks = sizeof(xdstrs_w_values)
+ / sizeof(xdstrs_w_values[0]);
+ int c_failed[n_checks];
+
+ memset (c_failed, 0, sizeof(c_failed));
+
+ for (j = 0; j < locale_name_count; j++)
+ {
+ set_test_locale (j); /* setlocale() can be slow! */
+ for (i = 0; i < n_checks; i++)
+ {
+ const struct str_with_value *const t = xdstrs_w_values + i;
+ size_t b_size;
+ size_t rs;
+
+ if (c_failed[i])
+ continue; /* skip already failed checks */
+
+ if (t->str.len < t->num_of_digt)
+ {
+ fprintf (stderr,
+ "ERROR: dstrs_w_values[%u] has wrong num_of_digt (%u):
num_of_digt is expected"
+ " to be less or equal to str.len (%u).\n",
+ (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned
+ int) t->str.
+ len);
+ return -1;
+ }
+ if ('0' == t->str.str[0])
+ continue; /* Skip strings prefixed with zeros */
+ if (t->num_of_digt != t->str.len)
+ continue; /* Skip strings with suffixes */
+ if (UINT32_MAX < t->val)
+ continue; /* Too large value to convert */
+ if (sizeof(buf) < t->str.len + 1)
+ {
+ fprintf (stderr,
+ "ERROR: dstrs_w_values[%u] has too long (%u) string, "
+ "size of 'buf' should be increased.\n",
+ (unsigned int) i, (unsigned int) t->str.len);
+ return -1;
+ }
+ for (b_size = 0; b_size <= t->str.len + 1; ++b_size)
+ {
+ /* fill buffer with pseudo-random values */
+ memcpy (buf, erase, sizeof(buf));
+
+ rs = MHD_uint32_to_strx (t->val, buf, b_size);
+
+ if (t->num_of_digt > b_size)
+ {
+ /* Must fail, buffer is too small for result */
+ if (0 != rs)
+ {
+ if (0 == c_failed[i])
+ t_failed++;
+ c_failed[i] = ! 0;
+ fprintf (stderr,
+ "FAILED: MHD_uint32_to_strx(0x%" PRIXPTR ", -> buf,"
+ " %d) returned %" PRIuPTR
+ ", while expecting 0."
+ " Locale: %s\n", t->val, (int) b_size, (intptr_t) rs,
+ get_current_locale_str ());
+ }
+ }
+ else
+ {
+ if (t->num_of_digt != rs)
+ {
+ if (0 == c_failed[i])
+ t_failed++;
+ c_failed[i] = ! 0;
+ fprintf (stderr,
+ "FAILED: MHD_uint32_to_strx(0x%" PRIXPTR ", -> buf,"
+ " %d) returned %" PRIuPTR
+ ", while expecting %d."
+ " Locale: %s\n", t->val, (int) b_size, (intptr_t) rs,
+ (int) t->num_of_digt, get_current_locale_str ());
+ }
+ else if (0 == MHD_str_equal_caseless_bin_n_ (buf, t->str.str,
+ t->num_of_digt))
+ {
+ if (0 == c_failed[i])
+ t_failed++;
+ c_failed[i] = ! 0;
+ fprintf (stderr,
+ "FAILED: MHD_uint32_to_strx(0x%" PRIXPTR ", -> \"%.*s\","
+ " %d) returned %" PRIuPTR "."
+ " Locale: %s\n", t->val, (int) rs, buf, (int) b_size,
+ (intptr_t) rs, get_current_locale_str ());
+ }
+ else if (0 != memcmp (buf + rs, erase + rs, sizeof(buf) - rs))
+ {
+ if (0 == c_failed[i])
+ t_failed++;
+ c_failed[i] = ! 0;
+ fprintf (stderr,
+ "FAILED: MHD_uint32_to_strx(0x%" PRIXPTR ", -> \"%.*s\","
+ " %d) returned %" PRIuPTR
+ " and touched data after the resulting string."
+ " Locale: %s\n", t->val, (int) rs, buf, (int) b_size,
+ (intptr_t) rs, get_current_locale_str ());
+ }
+ }
+ }
+ if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i])
+ printf ("PASSED: MHD_uint32_to_strx(0x%" PRIXPTR ", -> \"%.*s\", %d) "
+ "== %" PRIuPTR "\n",
+ t->val, (int) rs, buf, (int) b_size - 1, (intptr_t) rs);
+ }
+ }
+ return t_failed;
+}
+
+
+int
+run_str_from_X_tests (void)
+{
+ int str_from_uint16;
+ int strx_from_uint32;
+ int failures;
+
+ failures = 0;
+
+ str_from_uint16 = check_str_from_uint16 ();
+ if (str_from_uint16 != 0)
+ {
+ if (str_from_uint16 < 0)
+ {
+ fprintf (stderr,
+ "ERROR: test internal error in check_str_from_uint16().\n");
+ return 99;
+ }
+ fprintf (stderr,
+ "FAILED: testcase check_str_from_uint16() failed.\n\n");
+ failures += str_from_uint16;
+ }
+ else if (verbose > 1)
+ printf (
+ "PASSED: testcase check_str_from_uint16() successfully passed.\n\n");
+
+ strx_from_uint32 = check_strx_from_uint32 ();
+ if (strx_from_uint32 != 0)
+ {
+ if (strx_from_uint32 < 0)
+ {
+ fprintf (stderr,
+ "ERROR: test internal error in check_strx_from_uint32().\n");
+ return 99;
+ }
+ fprintf (stderr,
+ "FAILED: testcase check_strx_from_uint32() failed.\n\n");
+ failures += strx_from_uint32;
+ }
+ else if (verbose > 1)
+ printf (
+ "PASSED: testcase check_strx_from_uint32() successfully passed.\n\n");
+
+ if (failures)
+ {
+ if (verbose > 0)
+ printf ("At least one test failed.\n");
+
+ return 1;
+ }
+
+ if (verbose > 0)
+ printf ("All tests passed successfully.\n");
+
+ return 0;
+}
+
+
int
main (int argc, char *argv[])
{
@@ -3328,5 +3635,8 @@ main (int argc, char *argv[])
if (has_in_name (argv[0], "_to_value"))
return run_str_to_X_tests ();
+ if (has_in_name (argv[0], "_from_value"))
+ return run_str_from_X_tests ();
+
return run_eq_neq_str_tests ();
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [libmicrohttpd] branch master updated (237aebfa -> 182ed3a0), gnunet, 2021/07/28
- [libmicrohttpd] 02/07: try_ready_chunked_body: use new string function, fixes., gnunet, 2021/07/28
- [libmicrohttpd] 03/07: response: use auto flag for chunked encoding header, gnunet, 2021/07/28
- [libmicrohttpd] 07/07: response: use macro instead of string for connection header, gnunet, 2021/07/28
- [libmicrohttpd] 05/07: Re-written chunk footer generation function as a separate function, gnunet, 2021/07/28
- [libmicrohttpd] 01/07: Added internal functions for printing decimal and hex numbers,
gnunet <=
- [libmicrohttpd] 04/07: keepalive_possible(): check whether app requested close, gnunet, 2021/07/28
- [libmicrohttpd] 06/07: Added new public API function MHD_get_reason_phrase_len_for(), gnunet, 2021/07/28