GNU libmicrohttpd 0.9.77
Loading...
Searching...
No Matches
mhd_str.c
Go to the documentation of this file.
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2015, 2016 Karlson2k (Evgeny Grin)
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19
26#include "mhd_str.h"
27
28#ifdef HAVE_STDBOOL_H
29#include <stdbool.h>
30#endif
31
32#include "mhd_limits.h"
33
34#ifdef MHD_FAVOR_SMALL_CODE
35#ifdef _MHD_static_inline
36#undef _MHD_static_inline
37#endif /* _MHD_static_inline */
38/* Do not force inlining and do not use macro functions, use normal static
39 functions instead.
40 This may give more flexibility for size optimizations. */
41#define _MHD_static_inline static
42#ifndef INLINE_FUNC
43#define INLINE_FUNC 1
44#endif /* !INLINE_FUNC */
45#endif /* MHD_FAVOR_SMALL_CODE */
46
47/*
48 * Block of functions/macros that use US-ASCII charset as required by HTTP
49 * standards. Not affected by current locale settings.
50 */
51
52#ifdef INLINE_FUNC
53
54#if 0 /* Disable unused functions. */
61_MHD_static_inline bool
62isasciilower (char c)
63{
64 return (c >= 'a') && (c <= 'z');
65}
66
67
68#endif /* Disable unused functions. */
69
70
77_MHD_static_inline bool
78isasciiupper (char c)
79{
80 return (c >= 'A') && (c <= 'Z');
81}
82
83
84#if 0 /* Disable unused functions. */
91_MHD_static_inline bool
92isasciialpha (char c)
93{
94 return isasciilower (c) || isasciiupper (c);
95}
96
97
98#endif /* Disable unused functions. */
99
100
107_MHD_static_inline bool
108isasciidigit (char c)
109{
110 return (c >= '0') && (c <= '9');
111}
112
113
114#if 0 /* Disable unused functions. */
121_MHD_static_inline bool
122isasciixdigit (char c)
123{
124 return isasciidigit (c) ||
125 ( (c >= 'A') && (c <= 'F') ) ||
126 ( (c >= 'a') && (c <= 'f') );
127}
128
129
136_MHD_static_inline bool
137isasciialnum (char c)
138{
139 return isasciialpha (c) || isasciidigit (c);
140}
141
142
143#endif /* Disable unused functions. */
144
145
155_MHD_static_inline char
156toasciilower (char c)
157{
158 return isasciiupper (c) ? (c - 'A' + 'a') : c;
159}
160
161
162#if 0 /* Disable unused functions. */
172_MHD_static_inline char
173toasciiupper (char c)
174{
175 return isasciilower (c) ? (c - 'a' + 'A') : c;
176}
177
178
179#endif /* Disable unused functions. */
180
181
182#if defined(MHD_FAVOR_SMALL_CODE) /* Used only in MHD_str_to_uvalue_n_() */
189_MHD_static_inline int
190todigitvalue (char c)
191{
192 if (isasciidigit (c))
193 return (unsigned char) (c - '0');
194
195 return -1;
196}
197
198
199#endif /* MHD_FAVOR_SMALL_CODE */
200
201
208_MHD_static_inline int
209toxdigitvalue (char c)
210{
211 if (isasciidigit (c))
212 return (unsigned char) (c - '0');
213 if ( (c >= 'A') && (c <= 'F') )
214 return (unsigned char) (c - 'A' + 10);
215 if ( (c >= 'a') && (c <= 'f') )
216 return (unsigned char) (c - 'a' + 10);
217
218 return -1;
219}
220
221
222#else /* !INLINE_FUNC */
223
224
232#define isasciilower(c) (((char) (c)) >= 'a' && ((char) (c)) <= 'z')
233
234
242#define isasciiupper(c) (((char) (c)) >= 'A' && ((char) (c)) <= 'Z')
243
244
252#define isasciialpha(c) (isasciilower (c) || isasciiupper (c))
253
254
262#define isasciidigit(c) (((char) (c)) >= '0' && ((char) (c)) <= '9')
263
264
272#define isasciixdigit(c) (isasciidigit ((c)) || \
273 (((char) (c)) >= 'A' && ((char) (c)) <= 'F') || \
274 (((char) (c)) >= 'a' && ((char) (c)) <= 'f') )
275
276
284#define isasciialnum(c) (isasciialpha (c) || isasciidigit (c))
285
286
296#define toasciilower(c) ((isasciiupper (c)) ? (((char) (c)) - 'A' + 'a') : \
297 ((char) (c)))
298
299
309#define toasciiupper(c) ((isasciilower (c)) ? (((char) (c)) - 'a' + 'A') : \
310 ((char) (c)))
311
312
319#define todigitvalue(c) (isasciidigit (c) ? (int) (((char) (c)) - '0') : \
320 (int) (-1))
321
322
328#define toxdigitvalue(c) (isasciidigit (c) ? (int) (((char) (c)) - '0') : \
329 ( (((char) (c)) >= 'A' && ((char) (c)) <= 'F') ? \
330 (int) (((unsigned char) (c)) - 'A' + 10) : \
331 ( (((char) (c)) >= 'a' && ((char) (c)) <= 'f') ? \
332 (int) (((unsigned char) (c)) - 'a' + 10) : \
333 (int) (-1) )))
334#endif /* !INLINE_FUNC */
335
336
337#ifndef MHD_FAVOR_SMALL_CODE
345int
346MHD_str_equal_caseless_ (const char *str1,
347 const char *str2)
348{
349 while (0 != (*str1))
350 {
351 const char c1 = *str1;
352 const char c2 = *str2;
353 if ( (c1 != c2) &&
354 (toasciilower (c1) != toasciilower (c2)) )
355 return 0;
356 str1++;
357 str2++;
358 }
359 return 0 == (*str2);
360}
361
362
363#endif /* ! MHD_FAVOR_SMALL_CODE */
364
365
377int
378MHD_str_equal_caseless_n_ (const char *const str1,
379 const char *const str2,
380 size_t maxlen)
381{
382 size_t i;
383
384 for (i = 0; i < maxlen; ++i)
385 {
386 const char c1 = str1[i];
387 const char c2 = str2[i];
388 if (0 == c2)
389 return 0 == c1;
390 if ( (c1 != c2) &&
391 (toasciilower (c1) != toasciilower (c2)) )
392 return 0;
393 }
394 return ! 0;
395}
396
397
411bool
413 const char *const token,
414 size_t token_len)
415{
416 if (0 == token_len)
417 return false;
418
419 while (0 != *str)
420 {
421 size_t i;
422 /* Skip all whitespaces and empty tokens. */
423 while (' ' == *str || '\t' == *str || ',' == *str)
424 str++;
425
426 /* Check for token match. */
427 i = 0;
428 while (1)
429 {
430 const char sc = *(str++);
431 const char tc = token[i++];
432
433 if (0 == sc)
434 return false;
435 if ( (sc != tc) &&
436 (toasciilower (sc) != toasciilower (tc)) )
437 break;
438 if (i >= token_len)
439 {
440 /* Check whether substring match token fully or
441 * has additional unmatched chars at tail. */
442 while (' ' == *str || '\t' == *str)
443 str++;
444 /* End of (sub)string? */
445 if ((0 == *str) || (',' == *str) )
446 return true;
447 /* Unmatched chars at end of substring. */
448 break;
449 }
450 }
451 /* Find next substring. */
452 while (0 != *str && ',' != *str)
453 str++;
454 }
455 return false;
456}
457
458
459#ifndef MHD_FAVOR_SMALL_CODE
460/* Use individual function for each case */
461
472size_t
473MHD_str_to_uint64_ (const char *str,
474 uint64_t *out_val)
475{
476 const char *const start = str;
477 uint64_t res;
478
479 if (! str || ! out_val || ! isasciidigit (str[0]))
480 return 0;
481
482 res = 0;
483 do
484 {
485 const int digit = (unsigned char) (*str) - '0';
486 if ( (res > (UINT64_MAX / 10)) ||
487 ( (res == (UINT64_MAX / 10)) &&
488 ((uint64_t) digit > (UINT64_MAX % 10)) ) )
489 return 0;
490
491 res *= 10;
492 res += digit;
493 str++;
494 } while (isasciidigit (*str));
495
496 *out_val = res;
497 return str - start;
498}
499
500
514size_t
515MHD_str_to_uint64_n_ (const char *str,
516 size_t maxlen,
517 uint64_t *out_val)
518{
519 uint64_t res;
520 size_t i;
521
522 if (! str || ! maxlen || ! out_val || ! isasciidigit (str[0]))
523 return 0;
524
525 res = 0;
526 i = 0;
527 do
528 {
529 const int digit = (unsigned char) str[i] - '0';
530
531 if ( (res > (UINT64_MAX / 10)) ||
532 ( (res == (UINT64_MAX / 10)) &&
533 ((uint64_t) digit > (UINT64_MAX % 10)) ) )
534 return 0;
535
536 res *= 10;
537 res += digit;
538 i++;
539 } while ( (i < maxlen) &&
540 isasciidigit (str[i]) );
541
542 *out_val = res;
543 return i;
544}
545
546
557size_t
558MHD_strx_to_uint32_ (const char *str,
559 uint32_t *out_val)
560{
561 const char *const start = str;
562 uint32_t res;
563 int digit;
564
565 if (! str || ! out_val)
566 return 0;
567
568 res = 0;
569 digit = toxdigitvalue (*str);
570 while (digit >= 0)
571 {
572 if ( (res < (UINT32_MAX / 16)) ||
573 ((res == (UINT32_MAX / 16)) && ( (uint32_t) digit <= (UINT32_MAX
574 % 16)) ) )
575 {
576 res *= 16;
577 res += digit;
578 }
579 else
580 return 0;
581 str++;
582 digit = toxdigitvalue (*str);
583 }
584
585 if (str - start > 0)
586 *out_val = res;
587 return str - start;
588}
589
590
604size_t
605MHD_strx_to_uint32_n_ (const char *str,
606 size_t maxlen,
607 uint32_t *out_val)
608{
609 size_t i;
610 uint32_t res;
611 int digit;
612 if (! str || ! out_val)
613 return 0;
614
615 res = 0;
616 i = 0;
617 while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
618 {
619 if ( (res > (UINT32_MAX / 16)) ||
620 ((res == (UINT32_MAX / 16)) && ( (uint32_t) digit > (UINT32_MAX
621 % 16)) ) )
622 return 0;
623
624 res *= 16;
625 res += digit;
626 i++;
627 }
628
629 if (i)
630 *out_val = res;
631 return i;
632}
633
634
645size_t
646MHD_strx_to_uint64_ (const char *str,
647 uint64_t *out_val)
648{
649 const char *const start = str;
650 uint64_t res;
651 int digit;
652 if (! str || ! out_val)
653 return 0;
654
655 res = 0;
656 digit = toxdigitvalue (*str);
657 while (digit >= 0)
658 {
659 if ( (res < (UINT64_MAX / 16)) ||
660 ((res == (UINT64_MAX / 16)) && ( (uint64_t) digit <= (UINT64_MAX
661 % 16)) ) )
662 {
663 res *= 16;
664 res += digit;
665 }
666 else
667 return 0;
668 str++;
669 digit = toxdigitvalue (*str);
670 }
671
672 if (str - start > 0)
673 *out_val = res;
674 return str - start;
675}
676
677
691size_t
692MHD_strx_to_uint64_n_ (const char *str,
693 size_t maxlen,
694 uint64_t *out_val)
695{
696 size_t i;
697 uint64_t res;
698 int digit;
699 if (! str || ! out_val)
700 return 0;
701
702 res = 0;
703 i = 0;
704 while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
705 {
706 if ( (res > (UINT64_MAX / 16)) ||
707 ((res == (UINT64_MAX / 16)) && ( (uint64_t) digit > (UINT64_MAX
708 % 16)) ) )
709 return 0;
710
711 res *= 16;
712 res += digit;
713 i++;
714 }
715
716 if (i)
717 *out_val = res;
718 return i;
719}
720
721
722#else /* MHD_FAVOR_SMALL_CODE */
723
741size_t
742MHD_str_to_uvalue_n_ (const char *str,
743 size_t maxlen,
744 void *out_val,
745 size_t val_size,
746 uint64_t max_val,
747 int base)
748{
749 size_t i;
750 uint64_t res;
751 int digit;
752 const uint64_t max_v_div_b = max_val / base;
753 const uint64_t max_v_mod_b = max_val % base;
754 /* 'digit->value' must be function, not macro */
755 int (*const dfunc)(char) = (base == 16) ?
757
758 if (! str || ! out_val ||
759 ((base != 16) && (base != 10)) )
760 return 0;
761
762 res = 0;
763 i = 0;
764 while (maxlen > i && 0 <= (digit = dfunc (str[i])))
765 {
766 if ( ((max_v_div_b) < res) ||
767 (( (max_v_div_b) == res) && ( (max_v_mod_b) < (uint64_t) digit) ) )
768 return 0;
769
770 res *= base;
771 res += digit;
772 i++;
773 }
774
775 if (i)
776 {
777 if (8 == val_size)
778 *(uint64_t *) out_val = res;
779 else if (4 == val_size)
780 *(uint32_t *) out_val = (uint32_t) res;
781 else
782 return 0;
783 }
784 return i;
785}
786
787
788#endif /* MHD_FAVOR_SMALL_CODE */
#define UINT64_MAX
Definition mhd_limits.h:81
#define UINT32_MAX
Definition mhd_limits.h:73
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition mhd_str.c:346
size_t MHD_strx_to_uint32_(const char *str, uint32_t *out_val)
Definition mhd_str.c:558
#define toasciilower(c)
Definition mhd_str.c:296
size_t MHD_str_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition mhd_str.c:515
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition mhd_str.c:692
int MHD_str_equal_caseless_n_(const char *const str1, const char *const str2, size_t maxlen)
Definition mhd_str.c:378
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition mhd_str.c:473
#define isasciialnum(c)
Definition mhd_str.c:284
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition mhd_str.c:412
#define toxdigitvalue(c)
Definition mhd_str.c:328
#define toasciiupper(c)
Definition mhd_str.c:309
#define isasciilower(c)
Definition mhd_str.c:232
#define isasciidigit(c)
Definition mhd_str.c:262
size_t MHD_strx_to_uint64_(const char *str, uint64_t *out_val)
Definition mhd_str.c:646
#define isasciiupper(c)
Definition mhd_str.c:242
#define isasciialpha(c)
Definition mhd_str.c:252
size_t MHD_strx_to_uint32_n_(const char *str, size_t maxlen, uint32_t *out_val)
Definition mhd_str.c:605
#define isasciixdigit(c)
Definition mhd_str.c:272
#define todigitvalue(c)
Definition mhd_str.c:319
limits values definitions
Header for string manipulating helpers.