GNU libmicrohttpd 0.9.71
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
407bool
408MHD_str_equal_caseless_bin_n_ (const char *const str1,
409 const char *const str2,
410 size_t len)
411{
412 size_t i;
413
414 for (i = 0; i < len; ++i)
415 {
416 const char c1 = str1[i];
417 const char c2 = str2[i];
418 if ( (c1 != c2) &&
419 (toasciilower (c1) != toasciilower (c2)) )
420 return 0;
421 }
422 return ! 0;
423}
424
425
439bool
441 const char *const token,
442 size_t token_len)
443{
444 if (0 == token_len)
445 return false;
446
447 while (0 != *str)
448 {
449 size_t i;
450 /* Skip all whitespaces and empty tokens. */
451 while (' ' == *str || '\t' == *str || ',' == *str)
452 str++;
453
454 /* Check for token match. */
455 i = 0;
456 while (1)
457 {
458 const char sc = *(str++);
459 const char tc = token[i++];
460
461 if (0 == sc)
462 return false;
463 if ( (sc != tc) &&
464 (toasciilower (sc) != toasciilower (tc)) )
465 break;
466 if (i >= token_len)
467 {
468 /* Check whether substring match token fully or
469 * has additional unmatched chars at tail. */
470 while (' ' == *str || '\t' == *str)
471 str++;
472 /* End of (sub)string? */
473 if ((0 == *str) || (',' == *str) )
474 return true;
475 /* Unmatched chars at end of substring. */
476 break;
477 }
478 }
479 /* Find next substring. */
480 while (0 != *str && ',' != *str)
481 str++;
482 }
483 return false;
484}
485
486
487#ifndef MHD_FAVOR_SMALL_CODE
488/* Use individual function for each case */
489
500size_t
501MHD_str_to_uint64_ (const char *str,
502 uint64_t *out_val)
503{
504 const char *const start = str;
505 uint64_t res;
506
507 if (! str || ! out_val || ! isasciidigit (str[0]))
508 return 0;
509
510 res = 0;
511 do
512 {
513 const int digit = (unsigned char) (*str) - '0';
514 if ( (res > (UINT64_MAX / 10)) ||
515 ( (res == (UINT64_MAX / 10)) &&
516 ((uint64_t) digit > (UINT64_MAX % 10)) ) )
517 return 0;
518
519 res *= 10;
520 res += digit;
521 str++;
522 } while (isasciidigit (*str));
523
524 *out_val = res;
525 return str - start;
526}
527
528
542size_t
543MHD_str_to_uint64_n_ (const char *str,
544 size_t maxlen,
545 uint64_t *out_val)
546{
547 uint64_t res;
548 size_t i;
549
550 if (! str || ! maxlen || ! out_val || ! isasciidigit (str[0]))
551 return 0;
552
553 res = 0;
554 i = 0;
555 do
556 {
557 const int digit = (unsigned char) str[i] - '0';
558
559 if ( (res > (UINT64_MAX / 10)) ||
560 ( (res == (UINT64_MAX / 10)) &&
561 ((uint64_t) digit > (UINT64_MAX % 10)) ) )
562 return 0;
563
564 res *= 10;
565 res += digit;
566 i++;
567 } while ( (i < maxlen) &&
568 isasciidigit (str[i]) );
569
570 *out_val = res;
571 return i;
572}
573
574
585size_t
586MHD_strx_to_uint32_ (const char *str,
587 uint32_t *out_val)
588{
589 const char *const start = str;
590 uint32_t res;
591 int digit;
592
593 if (! str || ! out_val)
594 return 0;
595
596 res = 0;
597 digit = toxdigitvalue (*str);
598 while (digit >= 0)
599 {
600 if ( (res < (UINT32_MAX / 16)) ||
601 ((res == (UINT32_MAX / 16)) && ( (uint32_t) digit <= (UINT32_MAX
602 % 16)) ) )
603 {
604 res *= 16;
605 res += digit;
606 }
607 else
608 return 0;
609 str++;
610 digit = toxdigitvalue (*str);
611 }
612
613 if (str - start > 0)
614 *out_val = res;
615 return str - start;
616}
617
618
632size_t
633MHD_strx_to_uint32_n_ (const char *str,
634 size_t maxlen,
635 uint32_t *out_val)
636{
637 size_t i;
638 uint32_t res;
639 int digit;
640 if (! str || ! out_val)
641 return 0;
642
643 res = 0;
644 i = 0;
645 while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
646 {
647 if ( (res > (UINT32_MAX / 16)) ||
648 ((res == (UINT32_MAX / 16)) && ( (uint32_t) digit > (UINT32_MAX
649 % 16)) ) )
650 return 0;
651
652 res *= 16;
653 res += digit;
654 i++;
655 }
656
657 if (i)
658 *out_val = res;
659 return i;
660}
661
662
673size_t
674MHD_strx_to_uint64_ (const char *str,
675 uint64_t *out_val)
676{
677 const char *const start = str;
678 uint64_t res;
679 int digit;
680 if (! str || ! out_val)
681 return 0;
682
683 res = 0;
684 digit = toxdigitvalue (*str);
685 while (digit >= 0)
686 {
687 if ( (res < (UINT64_MAX / 16)) ||
688 ((res == (UINT64_MAX / 16)) && ( (uint64_t) digit <= (UINT64_MAX
689 % 16)) ) )
690 {
691 res *= 16;
692 res += digit;
693 }
694 else
695 return 0;
696 str++;
697 digit = toxdigitvalue (*str);
698 }
699
700 if (str - start > 0)
701 *out_val = res;
702 return str - start;
703}
704
705
719size_t
720MHD_strx_to_uint64_n_ (const char *str,
721 size_t maxlen,
722 uint64_t *out_val)
723{
724 size_t i;
725 uint64_t res;
726 int digit;
727 if (! str || ! out_val)
728 return 0;
729
730 res = 0;
731 i = 0;
732 while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
733 {
734 if ( (res > (UINT64_MAX / 16)) ||
735 ((res == (UINT64_MAX / 16)) && ( (uint64_t) digit > (UINT64_MAX
736 % 16)) ) )
737 return 0;
738
739 res *= 16;
740 res += digit;
741 i++;
742 }
743
744 if (i)
745 *out_val = res;
746 return i;
747}
748
749
750#else /* MHD_FAVOR_SMALL_CODE */
751
769size_t
770MHD_str_to_uvalue_n_ (const char *str,
771 size_t maxlen,
772 void *out_val,
773 size_t val_size,
774 uint64_t max_val,
775 int base)
776{
777 size_t i;
778 uint64_t res;
779 int digit;
780 const uint64_t max_v_div_b = max_val / base;
781 const uint64_t max_v_mod_b = max_val % base;
782 /* 'digit->value' must be function, not macro */
783 int (*const dfunc)(char) = (base == 16) ?
785
786 if (! str || ! out_val ||
787 ((base != 16) && (base != 10)) )
788 return 0;
789
790 res = 0;
791 i = 0;
792 while (maxlen > i && 0 <= (digit = dfunc (str[i])))
793 {
794 if ( ((max_v_div_b) < res) ||
795 (( (max_v_div_b) == res) && ( (max_v_mod_b) < (uint64_t) digit) ) )
796 return 0;
797
798 res *= base;
799 res += digit;
800 i++;
801 }
802
803 if (i)
804 {
805 if (8 == val_size)
806 *(uint64_t*) out_val = res;
807 else if (4 == val_size)
808 *(uint32_t*) out_val = (uint32_t) res;
809 else
810 return 0;
811 }
812 return i;
813}
814
815
816#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
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
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:412
size_t MHD_strx_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:646
size_t MHD_strx_to_uint32_n_(const char *str, size_t maxlen, uint32_t *out_val)
Definition: mhd_str.c:605
limits values definitions
#define toasciilower(c)
Definition: mhd_str.c:296
#define isasciialnum(c)
Definition: mhd_str.c:284
#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
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Definition: mhd_str.c:408
#define isasciiupper(c)
Definition: mhd_str.c:242
#define isasciialpha(c)
Definition: mhd_str.c:252
#define isasciixdigit(c)
Definition: mhd_str.c:272
#define todigitvalue(c)
Definition: mhd_str.c:319
Header for string manipulating helpers.