GNU libmicrohttpd  0.9.29
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_inline
36 #undef _MHD_inline
37 #endif /* _MHD_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_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 
59 _MHD_inline bool
60 isasciilower (char c)
61 {
62  return (c >= 'a') && (c <= 'z');
63 }
64 
65 
72 _MHD_inline bool
73 isasciiupper (char c)
74 {
75  return (c >= 'A') && (c <= 'Z');
76 }
77 
78 
85 _MHD_inline bool
86 isasciialpha (char c)
87 {
88  return isasciilower (c) || isasciiupper (c);
89 }
90 
91 
98 _MHD_inline bool
99 isasciidigit (char c)
100 {
101  return (c >= '0') && (c <= '9');
102 }
103 
104 
111 _MHD_inline bool
112 isasciixdigit (char c)
113 {
114  return isasciidigit (c) ||
115  ( (c >= 'A') && (c <= 'F') ) ||
116  ( (c >= 'a') && (c <= 'f') );
117 }
118 
119 
126 _MHD_inline bool
127 isasciialnum (char c)
128 {
129  return isasciialpha (c) || isasciidigit (c);
130 }
131 
132 
142 _MHD_inline char
143 toasciilower (char c)
144 {
145  return isasciiupper (c) ? (c - 'A' + 'a') : c;
146 }
147 
148 
158 _MHD_inline char
159 toasciiupper (char c)
160 {
161  return isasciilower (c) ? (c - 'a' + 'A') : c;
162 }
163 
164 
171 _MHD_inline int
172 todigitvalue (char c)
173 {
174  if (isasciidigit (c))
175  return (unsigned char)(c - '0');
176 
177  return -1;
178 }
179 
180 
187 _MHD_inline int
188 toxdigitvalue (char c)
189 {
190  if (isasciidigit (c))
191  return (unsigned char)(c - '0');
192  if ( (c >= 'A') && (c <= 'F') )
193  return (unsigned char)(c - 'A' + 10);
194  if ( (c >= 'a') && (c <= 'f') )
195  return (unsigned char)(c - 'a' + 10);
196 
197  return -1;
198 }
199 #else /* !INLINE_FUNC */
200 
201 
209 #define isasciilower(c) (((char)(c)) >= 'a' && ((char)(c)) <= 'z')
210 
211 
219 #define isasciiupper(c) (((char)(c)) >= 'A' && ((char)(c)) <= 'Z')
220 
221 
229 #define isasciialpha(c) (isasciilower(c) || isasciiupper(c))
230 
231 
239 #define isasciidigit(c) (((char)(c)) >= '0' && ((char)(c)) <= '9')
240 
241 
249 #define isasciixdigit(c) (isasciidigit((c)) || \
250  (((char)(c)) >= 'A' && ((char)(c)) <= 'F') || \
251  (((char)(c)) >= 'a' && ((char)(c)) <= 'f') )
252 
253 
261 #define isasciialnum(c) (isasciialpha(c) || isasciidigit(c))
262 
263 
273 #define toasciilower(c) ((isasciiupper(c)) ? (((char)(c)) - 'A' + 'a') : ((char)(c)))
274 
275 
285 #define toasciiupper(c) ((isasciilower(c)) ? (((char)(c)) - 'a' + 'A') : ((char)(c)))
286 
287 
294 #define todigitvalue(c) (isasciidigit(c) ? (int)(((char)(c)) - '0') : (int)(-1))
295 
296 
302 #define toxdigitvalue(c) ( isasciidigit(c) ? (int)(((char)(c)) - '0') : \
303  ( (((char)(c)) >= 'A' && ((char)(c)) <= 'F') ? \
304  (int)(((unsigned char)(c)) - 'A' + 10) : \
305  ( (((char)(c)) >= 'a' && ((char)(c)) <= 'f') ? \
306  (int)(((unsigned char)(c)) - 'a' + 10) : (int)(-1) )))
307 #endif /* !INLINE_FUNC */
308 
309 
310 #ifndef MHD_FAVOR_SMALL_CODE
311 
318 int
319 MHD_str_equal_caseless_ (const char * str1,
320  const char * str2)
321 {
322  while (0 != (*str1))
323  {
324  const char c1 = *str1;
325  const char c2 = *str2;
326  if ( (c1 != c2) &&
327  (toasciilower (c1) != toasciilower (c2)) )
328  return 0;
329  str1++;
330  str2++;
331  }
332  return 0 == (*str2);
333 }
334 #endif /* ! MHD_FAVOR_SMALL_CODE */
335 
336 
348 int
349 MHD_str_equal_caseless_n_ (const char * const str1,
350  const char * const str2,
351  size_t maxlen)
352 {
353  size_t i;
354 
355  for (i = 0; i < maxlen; ++i)
356  {
357  const char c1 = str1[i];
358  const char c2 = str2[i];
359  if (0 == c2)
360  return 0 == c1;
361  if ( (c1 != c2) &&
362  (toasciilower (c1) != toasciilower (c2)) )
363  return 0;
364  }
365  return !0;
366 }
367 
368 
382 bool
383 MHD_str_has_token_caseless_ (const char * str,
384  const char * const token,
385  size_t token_len)
386 {
387  if (0 == token_len)
388  return false;
389 
390  while (0 != *str)
391  {
392  size_t i;
393  /* Skip all whitespaces and empty tokens. */
394  while (' ' == *str || '\t' == *str || ',' == *str) str++;
395 
396  /* Check for token match. */
397  i = 0;
398  while (1)
399  {
400  const char sc = *(str++);
401  const char tc = token[i++];
402 
403  if (0 == sc)
404  return false;
405  if ( (sc != tc) &&
406  (toasciilower (sc) != toasciilower (tc)) )
407  break;
408  if (i >= token_len)
409  {
410  /* Check whether substring match token fully or
411  * has additional unmatched chars at tail. */
412  while (' ' == *str || '\t' == *str) str++;
413  /* End of (sub)string? */
414  if (0 == *str || ',' == *str)
415  return true;
416  /* Unmatched chars at end of substring. */
417  break;
418  }
419  }
420  /* Find next substring. */
421  while (0 != *str && ',' != *str) str++;
422  }
423  return false;
424 }
425 
426 #ifndef MHD_FAVOR_SMALL_CODE
427 /* Use individual function for each case */
428 
439 size_t
440 MHD_str_to_uint64_ (const char *str,
441  uint64_t *out_val)
442 {
443  const char * const start = str;
444  uint64_t res;
445 
446  if (!str || !out_val || !isasciidigit(str[0]))
447  return 0;
448 
449  res = 0;
450  do
451  {
452  const int digit = (unsigned char)(*str) - '0';
453  if ( (res > (UINT64_MAX / 10)) ||
454  ( (res == (UINT64_MAX / 10)) &&
455  ((uint64_t)digit > (UINT64_MAX % 10)) ) )
456  return 0;
457 
458  res *= 10;
459  res += digit;
460  str++;
461  } while (isasciidigit (*str));
462 
463  *out_val = res;
464  return str - start;
465 }
466 
467 
481 size_t
482 MHD_str_to_uint64_n_ (const char * str,
483  size_t maxlen,
484  uint64_t *out_val)
485 {
486  uint64_t res;
487  size_t i;
488 
489  if (!str || !maxlen || !out_val || !isasciidigit (str[0]))
490  return 0;
491 
492  res = 0;
493  i = 0;
494  do
495  {
496  const int digit = (unsigned char)str[i] - '0';
497 
498  if ( (res > (UINT64_MAX / 10)) ||
499  ( (res == (UINT64_MAX / 10)) &&
500  ((uint64_t)digit > (UINT64_MAX % 10)) ) )
501  return 0;
502 
503  res *= 10;
504  res += digit;
505  i++;
506  } while ( (i < maxlen) &&
507  isasciidigit (str[i]) );
508 
509  *out_val= res;
510  return i;
511 }
512 
513 
524 size_t
525 MHD_strx_to_uint32_ (const char * str,
526  uint32_t *out_val)
527 {
528  const char * const start = str;
529  uint32_t res;
530  int digit;
531 
532  if (!str || !out_val)
533  return 0;
534 
535  res = 0;
536  digit = toxdigitvalue (*str);
537  while (digit >= 0)
538  {
539  if ( (res < (UINT32_MAX / 16)) ||
540  (res == (UINT32_MAX / 16) && (uint32_t)digit <= (UINT32_MAX % 16)) )
541  {
542  res *= 16;
543  res += digit;
544  }
545  else
546  return 0;
547  str++;
548  digit = toxdigitvalue (*str);
549  }
550 
551  if (str - start > 0)
552  *out_val = res;
553  return str - start;
554 }
555 
556 
570 size_t
571 MHD_strx_to_uint32_n_ (const char *str,
572  size_t maxlen,
573  uint32_t *out_val)
574 {
575  size_t i;
576  uint32_t res;
577  int digit;
578  if (!str || !out_val)
579  return 0;
580 
581  res = 0;
582  i = 0;
583  while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
584  {
585  if ( (res > (UINT32_MAX / 16)) ||
586  (res == (UINT32_MAX / 16) && (uint32_t)digit > (UINT32_MAX % 16)) )
587  return 0;
588 
589  res *= 16;
590  res += digit;
591  i++;
592  }
593 
594  if (i)
595  *out_val = res;
596  return i;
597 }
598 
599 
610 size_t
611 MHD_strx_to_uint64_ (const char *str,
612  uint64_t *out_val)
613 {
614  const char * const start = str;
615  uint64_t res;
616  int digit;
617  if (!str || !out_val)
618  return 0;
619 
620  res = 0;
621  digit = toxdigitvalue (*str);
622  while (digit >= 0)
623  {
624  if ( (res < (UINT64_MAX / 16)) ||
625  (res == (UINT64_MAX / 16) && (uint64_t)digit <= (UINT64_MAX % 16)) )
626  {
627  res *= 16;
628  res += digit;
629  }
630  else
631  return 0;
632  str++;
633  digit = toxdigitvalue (*str);
634  }
635 
636  if (str - start > 0)
637  *out_val = res;
638  return str - start;
639 }
640 
641 
655 size_t
656 MHD_strx_to_uint64_n_ (const char * str,
657  size_t maxlen,
658  uint64_t *out_val)
659 {
660  size_t i;
661  uint64_t res;
662  int digit;
663  if (!str || !out_val)
664  return 0;
665 
666  res = 0;
667  i = 0;
668  while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
669  {
670  if ( (res > (UINT64_MAX / 16)) ||
671  (res == (UINT64_MAX / 16) && (uint64_t)digit > (UINT64_MAX % 16)) )
672  return 0;
673 
674  res *= 16;
675  res += digit;
676  i++;
677  }
678 
679  if (i)
680  *out_val = res;
681  return i;
682 }
683 
684 #else /* MHD_FAVOR_SMALL_CODE */
685 
703 size_t
704 MHD_str_to_uvalue_n_ (const char *str,
705  size_t maxlen,
706  void * out_val,
707  size_t val_size,
708  uint64_t max_val,
709  int base)
710 {
711  size_t i;
712  uint64_t res;
713  int digit;
714  const uint64_t max_v_div_b = max_val / base;
715  const uint64_t max_v_mod_b = max_val % base;
716  /* 'digit->value' must be function, not macro */
717  int (*const dfunc)(char) = (base == 16) ?
719 
720  if ( !str || !out_val ||
721  (base != 16 && base != 10) )
722  return 0;
723 
724  res = 0;
725  i = 0;
726  while (maxlen > i && 0 <= (digit = dfunc (str[i])))
727  {
728  if ( ((max_v_div_b) < res) ||
729  ((max_v_div_b) == res && (max_v_mod_b) < (uint64_t)digit) )
730  return 0;
731 
732  res *= base;
733  res += digit;
734  i++;
735  }
736 
737  if (i)
738  {
739  if (8 == val_size)
740  *(uint64_t*)out_val = res;
741  else if (4 == val_size)
742  *(uint32_t*)out_val = (uint32_t)res;
743  else
744  return 0;
745  }
746  return i;
747 }
748 #endif /* MHD_FAVOR_SMALL_CODE */
size_t MHD_strx_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:611
#define toasciilower(c)
Definition: mhd_str.c:273
int MHD_str_equal_caseless_n_(const char *const str1, const char *const str2, size_t maxlen)
Definition: mhd_str.c:349
#define UINT64_MAX
Definition: mhd_limits.h:75
size_t MHD_strx_to_uint32_n_(const char *str, size_t maxlen, uint32_t *out_val)
Definition: mhd_str.c:571
#define isasciixdigit(c)
Definition: mhd_str.c:249
#define toasciiupper(c)
Definition: mhd_str.c:285
#define UINT32_MAX
Definition: mhd_limits.h:67
size_t MHD_strx_to_uint32_(const char *str, uint32_t *out_val)
Definition: mhd_str.c:525
limits values definitions
#define isasciilower(c)
Definition: mhd_str.c:209
#define isasciiupper(c)
Definition: mhd_str.c:219
Header for string manipulating helpers.
#define isasciidigit(c)
Definition: mhd_str.c:239
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:383
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:319
#define isasciialpha(c)
Definition: mhd_str.c:229
#define toxdigitvalue(c)
Definition: mhd_str.c:302
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:656
#define isasciialnum(c)
Definition: mhd_str.c:261
size_t MHD_str_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:482
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:440
#define todigitvalue(c)
Definition: mhd_str.c:294