GNU libmicrohttpd  0.9.72
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
62 isasciilower (char c)
63 {
64  return (c >= 'a') && (c <= 'z');
65 }
66 
67 
68 #endif /* Disable unused functions. */
69 
70 
77 _MHD_static_inline bool
78 isasciiupper (char c)
79 {
80  return (c >= 'A') && (c <= 'Z');
81 }
82 
83 
84 #if 0 /* Disable unused functions. */
91 _MHD_static_inline bool
92 isasciialpha (char c)
93 {
94  return isasciilower (c) || isasciiupper (c);
95 }
96 
97 
98 #endif /* Disable unused functions. */
99 
100 
107 _MHD_static_inline bool
108 isasciidigit (char c)
109 {
110  return (c >= '0') && (c <= '9');
111 }
112 
113 
114 #if 0 /* Disable unused functions. */
121 _MHD_static_inline bool
122 isasciixdigit (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
137 isasciialnum (char c)
138 {
139  return isasciialpha (c) || isasciidigit (c);
140 }
141 
142 
143 #endif /* Disable unused functions. */
144 
145 
155 _MHD_static_inline char
156 toasciilower (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
173 toasciiupper (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
190 todigitvalue (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
209 toxdigitvalue (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
345 int
346 MHD_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 
377 int
378 MHD_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 
411 bool
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 
472 size_t
473 MHD_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 
514 size_t
515 MHD_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 
557 size_t
558 MHD_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 
604 size_t
605 MHD_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 
645 size_t
646 MHD_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 
691 size_t
692 MHD_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 
741 size_t
742 MHD_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.