aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2021-06-07 19:46:46 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2021-07-27 11:00:42 +0300
commitee3f32220038303ebf1bfcf1494c9badf6d3adc4 (patch)
tree91079f739729967a371efc96234f2be18375fc94
parent237aebfade9f51cfb3c0071b71b8875fb9eba335 (diff)
downloadlibmicrohttpd-ee3f32220038303ebf1bfcf1494c9badf6d3adc4.tar.gz
libmicrohttpd-ee3f32220038303ebf1bfcf1494c9badf6d3adc4.zip
Added internal functions for printing decimal and hex numbers
-rw-r--r--src/microhttpd/.gitignore1
-rw-r--r--src/microhttpd/Makefile.am4
-rw-r--r--src/microhttpd/mhd_str.c68
-rw-r--r--src/microhttpd/mhd_str.h30
-rw-r--r--src/microhttpd/test_str.c310
5 files changed, 413 insertions, 0 deletions
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
48/test_shutdown_select_ignore 48/test_shutdown_select_ignore
49/test_str_compare 49/test_str_compare
50/test_str_to_value 50/test_str_to_value
51/test_str_from_value
51/test_upgrade 52/test_upgrade
52/test_upgrade_ssl 53/test_upgrade_ssl
53/test_options 54/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
157check_PROGRAMS = \ 157check_PROGRAMS = \
158 test_str_compare \ 158 test_str_compare \
159 test_str_to_value \ 159 test_str_to_value \
160 test_str_from_value \
160 test_str_token \ 161 test_str_token \
161 test_str_token_remove \ 162 test_str_token_remove \
162 test_str_tokens_remove \ 163 test_str_tokens_remove \
@@ -358,6 +359,9 @@ test_str_compare_SOURCES = \
358test_str_to_value_SOURCES = \ 359test_str_to_value_SOURCES = \
359 test_str.c test_helpers.h mhd_str.c mhd_str.h 360 test_str.c test_helpers.h mhd_str.c mhd_str.h
360 361
362test_str_from_value_SOURCES = \
363 test_str.c test_helpers.h mhd_str.c mhd_str.h
364
361test_str_token_SOURCES = \ 365test_str_token_SOURCES = \
362 test_str_token.c mhd_str.c mhd_str.h 366 test_str_token.c mhd_str.c mhd_str.h
363 367
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 @@
32 32
33#include "mhd_assert.h" 33#include "mhd_assert.h"
34#include "mhd_limits.h" 34#include "mhd_limits.h"
35#include "mhd_assert.h"
35 36
36#ifdef MHD_FAVOR_SMALL_CODE 37#ifdef MHD_FAVOR_SMALL_CODE
37#ifdef _MHD_static_inline 38#ifdef _MHD_static_inline
@@ -1184,3 +1185,70 @@ MHD_str_to_uvalue_n_ (const char *str,
1184 1185
1185 1186
1186#endif /* MHD_FAVOR_SMALL_CODE */ 1187#endif /* MHD_FAVOR_SMALL_CODE */
1188
1189
1190size_t
1191MHD_uint32_to_strx (uint32_t val,
1192 char *buf,
1193 size_t buf_size)
1194{
1195 char *chr; /**< pointer to the current printed digit */
1196 int digit_pos = 7; /** zero-based, digit position in @a 'val' */
1197 int digit;
1198
1199 chr = buf;
1200 digit = (int) (((val) >> (4 * digit_pos)) & 0xf);
1201
1202 /* Skip leading zeros */
1203 while ((0 == digit) && (0 != digit_pos))
1204 digit = (int) (((val) >> (4 * --digit_pos)) & 0xf);
1205
1206 while (0 != buf_size)
1207 {
1208 *chr = (digit <= 9) ? ('0' + (char) digit) : ('A' + (char) digit - 10);
1209 chr++;
1210 buf_size--;
1211 if (0 == digit_pos)
1212 return (size_t) (chr - buf);
1213 digit = (int) (((val) >> (4 * --digit_pos)) & 0xf);
1214 }
1215 return 0; /* The buffer is too small */
1216}
1217
1218
1219size_t
1220MHD_uint16_to_str (uint16_t val,
1221 char *buf,
1222 size_t buf_size)
1223{
1224 char *chr; /**< pointer to the current printed digit */
1225 /* The biggest printable number is 65535 */
1226 uint16_t divisor = UINT16_C (10000);
1227 int digit;
1228
1229 chr = buf;
1230 digit = (int) (val / divisor);
1231 mhd_assert (digit < 10);
1232
1233 /* Do not print leading zeros */
1234 while ((0 == digit) && (1 < divisor))
1235 {
1236 divisor /= 10;
1237 digit = (int) (val / divisor);
1238 mhd_assert (digit < 10);
1239 }
1240
1241 while (0 != buf_size)
1242 {
1243 *chr = (char) digit + '0';
1244 chr++;
1245 buf_size--;
1246 if (1 == divisor)
1247 return (size_t) (chr - buf);
1248 val %= divisor;
1249 divisor /= 10;
1250 digit = (int) (val / divisor);
1251 mhd_assert (digit < 10);
1252 }
1253 return 0; /* The buffer is too small */
1254}
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,
361 361
362#endif /* MHD_FAVOR_SMALL_CODE */ 362#endif /* MHD_FAVOR_SMALL_CODE */
363 363
364
365/**
366 * Convert uint32_t value to hexdecimal US-ASCII string.
367 * @note: result is NOT zero-terminated.
368 * @param val the value to convert
369 * @param buf the buffer to result to
370 * @param buf_size size of the @a buffer
371 * @return number of charters has been put to the @a buf,
372 * zero if buffer is too small (buffer may be modified).
373 */
374size_t
375MHD_uint32_to_strx (uint32_t val,
376 char *buf,
377 size_t buf_size);
378
379
380/**
381 * Convert uint16_t value to decimal US-ASCII string.
382 * @note: result is NOT zero-terminated.
383 * @param val the value to convert
384 * @param buf the buffer to result to
385 * @param buf_size size of the @a buffer
386 * @return number of charters has been put to the @a buf,
387 * zero if buffer is too small (buffer may be modified).
388 */
389size_t
390MHD_uint16_to_str (uint16_t val,
391 char *buf,
392 size_t buf_size);
393
364#endif /* MHD_STR_H */ 394#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
@@ -3315,6 +3315,313 @@ run_str_to_X_tests (void)
3315 3315
3316 3316
3317int 3317int
3318check_str_from_uint16 (void)
3319{
3320 size_t t_failed = 0;
3321 size_t i, j;
3322 char buf[70];
3323 const char *erase =
3324 "-@=sd#+&(pdiren456qwe#@C3S!DAS45AOIPUQWESAdFzxcv1s*()&#$%34`"
3325 "32452d098poiden45SADFFDA3S4D3SDFdfgsdfgsSADFzxdvs$*()&#2342`"
3326 "adsf##$$@&*^%*^&56qwe#3C@S!DAScFAOIP$#%#$Ad1zs3v1$*()&#1228`";
3327 static const size_t n_checks = sizeof(dstrs_w_values)
3328 / sizeof(dstrs_w_values[0]);
3329 int c_failed[n_checks];
3330
3331 memset (c_failed, 0, sizeof(c_failed));
3332
3333 for (j = 0; j < locale_name_count; j++)
3334 {
3335 set_test_locale (j); /* setlocale() can be slow! */
3336 for (i = 0; i < n_checks; i++)
3337 {
3338 const struct str_with_value *const t = dstrs_w_values + i;
3339 size_t b_size;
3340 size_t rs;
3341
3342 if (c_failed[i])
3343 continue; /* skip already failed checks */
3344
3345 if (t->str.len < t->num_of_digt)
3346 {
3347 fprintf (stderr,
3348 "ERROR: dstrs_w_values[%u] has wrong num_of_digt (%u): num_of_digt is expected"
3349 " to be less or equal to str.len (%u).\n",
3350 (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned
3351 int) t->str.
3352 len);
3353 return -1;
3354 }
3355 if ('0' == t->str.str[0])
3356 continue; /* Skip strings prefixed with zeros */
3357 if (t->num_of_digt != t->str.len)
3358 continue; /* Skip strings with suffixes */
3359 if (UINT16_MAX < t->val)
3360 continue; /* Too large value to convert */
3361 if (sizeof(buf) < t->str.len + 1)
3362 {
3363 fprintf (stderr,
3364 "ERROR: dstrs_w_values[%u] has too long (%u) string, "
3365 "size of 'buf' should be increased.\n",
3366 (unsigned int) i, (unsigned int) t->str.len);
3367 return -1;
3368 }
3369 for (b_size = 0; b_size <= t->str.len + 1; ++b_size)
3370 {
3371 /* fill buffer with pseudo-random values */
3372 memcpy (buf, erase, sizeof(buf));
3373
3374 rs = MHD_uint16_to_str (t->val, buf, b_size);
3375
3376 if (t->num_of_digt > b_size)
3377 {
3378 /* Must fail, buffer is too small for result */
3379 if (0 != rs)
3380 {
3381 if (0 == c_failed[i])
3382 t_failed++;
3383 c_failed[i] = ! 0;
3384 fprintf (stderr,
3385 "FAILED: MHD_uint16_to_str(%" PRIu64 ", -> buf,"
3386 " %d) returned %" PRIuPTR
3387 ", while expecting 0."
3388 " Locale: %s\n", t->val, (int) b_size, (intptr_t) rs,
3389 get_current_locale_str ());
3390 }
3391 }
3392 else
3393 {
3394 if (t->num_of_digt != rs)
3395 {
3396 if (0 == c_failed[i])
3397 t_failed++;
3398 c_failed[i] = ! 0;
3399 fprintf (stderr,
3400 "FAILED: MHD_uint16_to_str(%" PRIu64 ", -> buf,"
3401 " %d) returned %" PRIuPTR
3402 ", while expecting %d."
3403 " Locale: %s\n", t->val, (int) b_size, (intptr_t) rs,
3404 (int) t->num_of_digt, get_current_locale_str ());
3405 }
3406 else if (0 != memcmp (buf, t->str.str, t->num_of_digt))
3407 {
3408 if (0 == c_failed[i])
3409 t_failed++;
3410 c_failed[i] = ! 0;
3411 fprintf (stderr,
3412 "FAILED: MHD_uint16_to_str(%" PRIu64 ", -> \"%.*s\","
3413 " %d) returned %" PRIuPTR "."
3414 " Locale: %s\n", t->val, (int) rs, buf, (int) b_size,
3415 (intptr_t) rs, get_current_locale_str ());
3416 }
3417 else if (0 != memcmp (buf + rs, erase + rs, sizeof(buf) - rs))
3418 {
3419 if (0 == c_failed[i])
3420 t_failed++;
3421 c_failed[i] = ! 0;
3422 fprintf (stderr,
3423 "FAILED: MHD_uint16_to_str(%" PRIu64 ", -> \"%.*s\","
3424 " %d) returned %" PRIuPTR
3425 " and touched data after the resulting string."
3426 " Locale: %s\n", t->val, (int) rs, buf, (int) b_size,
3427 (intptr_t) rs, get_current_locale_str ());
3428 }
3429 }
3430 }
3431 if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i])
3432 printf ("PASSED: MHD_uint16_to_str(%" PRIu64 ", -> \"%.*s\", %d) "
3433 "== %" PRIuPTR "\n",
3434 t->val, (int) rs, buf, (int) b_size - 1, (intptr_t) rs);
3435 }
3436 }
3437 return t_failed;
3438}
3439
3440
3441int
3442check_strx_from_uint32 (void)
3443{
3444 size_t t_failed = 0;
3445 size_t i, j;
3446 char buf[70];
3447 const char *erase =
3448 "jrlkjssfhjfvrjntJHLJ$@%$#adsfdkj;k$##$%#$%FGDF%$#^FDFG%$#$D`"
3449 ";skjdhjflsdkjhdjfalskdjhdfalkjdhf$%##%$$#%FSDGFSDDGDFSSDSDF`"
3450 "#5#$%#$#$DFSFDDFSGSDFSDF354FDDSGFDFfdssfddfswqemn,.zxih,.sx`";
3451 static const size_t n_checks = sizeof(xdstrs_w_values)
3452 / sizeof(xdstrs_w_values[0]);
3453 int c_failed[n_checks];
3454
3455 memset (c_failed, 0, sizeof(c_failed));
3456
3457 for (j = 0; j < locale_name_count; j++)
3458 {
3459 set_test_locale (j); /* setlocale() can be slow! */
3460 for (i = 0; i < n_checks; i++)
3461 {
3462 const struct str_with_value *const t = xdstrs_w_values + i;
3463 size_t b_size;
3464 size_t rs;
3465
3466 if (c_failed[i])
3467 continue; /* skip already failed checks */
3468
3469 if (t->str.len < t->num_of_digt)
3470 {
3471 fprintf (stderr,
3472 "ERROR: dstrs_w_values[%u] has wrong num_of_digt (%u): num_of_digt is expected"
3473 " to be less or equal to str.len (%u).\n",
3474 (unsigned int) i, (unsigned int) t->num_of_digt, (unsigned
3475 int) t->str.
3476 len);
3477 return -1;
3478 }
3479 if ('0' == t->str.str[0])
3480 continue; /* Skip strings prefixed with zeros */
3481 if (t->num_of_digt != t->str.len)
3482 continue; /* Skip strings with suffixes */
3483 if (UINT32_MAX < t->val)
3484 continue; /* Too large value to convert */
3485 if (sizeof(buf) < t->str.len + 1)
3486 {
3487 fprintf (stderr,
3488 "ERROR: dstrs_w_values[%u] has too long (%u) string, "
3489 "size of 'buf' should be increased.\n",
3490 (unsigned int) i, (unsigned int) t->str.len);
3491 return -1;
3492 }
3493 for (b_size = 0; b_size <= t->str.len + 1; ++b_size)
3494 {
3495 /* fill buffer with pseudo-random values */
3496 memcpy (buf, erase, sizeof(buf));
3497
3498 rs = MHD_uint32_to_strx (t->val, buf, b_size);
3499
3500 if (t->num_of_digt > b_size)
3501 {
3502 /* Must fail, buffer is too small for result */
3503 if (0 != rs)
3504 {
3505 if (0 == c_failed[i])
3506 t_failed++;
3507 c_failed[i] = ! 0;
3508 fprintf (stderr,
3509 "FAILED: MHD_uint32_to_strx(0x%" PRIXPTR ", -> buf,"
3510 " %d) returned %" PRIuPTR
3511 ", while expecting 0."
3512 " Locale: %s\n", t->val, (int) b_size, (intptr_t) rs,
3513 get_current_locale_str ());
3514 }
3515 }
3516 else
3517 {
3518 if (t->num_of_digt != rs)
3519 {
3520 if (0 == c_failed[i])
3521 t_failed++;
3522 c_failed[i] = ! 0;
3523 fprintf (stderr,
3524 "FAILED: MHD_uint32_to_strx(0x%" PRIXPTR ", -> buf,"
3525 " %d) returned %" PRIuPTR
3526 ", while expecting %d."
3527 " Locale: %s\n", t->val, (int) b_size, (intptr_t) rs,
3528 (int) t->num_of_digt, get_current_locale_str ());
3529 }
3530 else if (0 == MHD_str_equal_caseless_bin_n_ (buf, t->str.str,
3531 t->num_of_digt))
3532 {
3533 if (0 == c_failed[i])
3534 t_failed++;
3535 c_failed[i] = ! 0;
3536 fprintf (stderr,
3537 "FAILED: MHD_uint32_to_strx(0x%" PRIXPTR ", -> \"%.*s\","
3538 " %d) returned %" PRIuPTR "."
3539 " Locale: %s\n", t->val, (int) rs, buf, (int) b_size,
3540 (intptr_t) rs, get_current_locale_str ());
3541 }
3542 else if (0 != memcmp (buf + rs, erase + rs, sizeof(buf) - rs))
3543 {
3544 if (0 == c_failed[i])
3545 t_failed++;
3546 c_failed[i] = ! 0;
3547 fprintf (stderr,
3548 "FAILED: MHD_uint32_to_strx(0x%" PRIXPTR ", -> \"%.*s\","
3549 " %d) returned %" PRIuPTR
3550 " and touched data after the resulting string."
3551 " Locale: %s\n", t->val, (int) rs, buf, (int) b_size,
3552 (intptr_t) rs, get_current_locale_str ());
3553 }
3554 }
3555 }
3556 if ((verbose > 1) && (j == locale_name_count - 1) && ! c_failed[i])
3557 printf ("PASSED: MHD_uint32_to_strx(0x%" PRIXPTR ", -> \"%.*s\", %d) "
3558 "== %" PRIuPTR "\n",
3559 t->val, (int) rs, buf, (int) b_size - 1, (intptr_t) rs);
3560 }
3561 }
3562 return t_failed;
3563}
3564
3565
3566int
3567run_str_from_X_tests (void)
3568{
3569 int str_from_uint16;
3570 int strx_from_uint32;
3571 int failures;
3572
3573 failures = 0;
3574
3575 str_from_uint16 = check_str_from_uint16 ();
3576 if (str_from_uint16 != 0)
3577 {
3578 if (str_from_uint16 < 0)
3579 {
3580 fprintf (stderr,
3581 "ERROR: test internal error in check_str_from_uint16().\n");
3582 return 99;
3583 }
3584 fprintf (stderr,
3585 "FAILED: testcase check_str_from_uint16() failed.\n\n");
3586 failures += str_from_uint16;
3587 }
3588 else if (verbose > 1)
3589 printf (
3590 "PASSED: testcase check_str_from_uint16() successfully passed.\n\n");
3591
3592 strx_from_uint32 = check_strx_from_uint32 ();
3593 if (strx_from_uint32 != 0)
3594 {
3595 if (strx_from_uint32 < 0)
3596 {
3597 fprintf (stderr,
3598 "ERROR: test internal error in check_strx_from_uint32().\n");
3599 return 99;
3600 }
3601 fprintf (stderr,
3602 "FAILED: testcase check_strx_from_uint32() failed.\n\n");
3603 failures += strx_from_uint32;
3604 }
3605 else if (verbose > 1)
3606 printf (
3607 "PASSED: testcase check_strx_from_uint32() successfully passed.\n\n");
3608
3609 if (failures)
3610 {
3611 if (verbose > 0)
3612 printf ("At least one test failed.\n");
3613
3614 return 1;
3615 }
3616
3617 if (verbose > 0)
3618 printf ("All tests passed successfully.\n");
3619
3620 return 0;
3621}
3622
3623
3624int
3318main (int argc, char *argv[]) 3625main (int argc, char *argv[])
3319{ 3626{
3320 if (has_param (argc, argv, "-v") || has_param (argc, argv, "--verbose") || 3627 if (has_param (argc, argv, "-v") || has_param (argc, argv, "--verbose") ||
@@ -3328,5 +3635,8 @@ main (int argc, char *argv[])
3328 if (has_in_name (argv[0], "_to_value")) 3635 if (has_in_name (argv[0], "_to_value"))
3329 return run_str_to_X_tests (); 3636 return run_str_to_X_tests ();
3330 3637
3638 if (has_in_name (argv[0], "_from_value"))
3639 return run_str_from_X_tests ();
3640
3331 return run_eq_neq_str_tests (); 3641 return run_eq_neq_str_tests ();
3332} 3642}