GNU libmicrohttpd  0.9.65
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. */
55 
61 _MHD_static_inline bool
62 isasciilower (char c)
63 {
64  return (c >= 'a') && (c <= 'z');
65 }
66 #endif /* Disable unused functions. */
67 
68 
75 _MHD_static_inline bool
76 isasciiupper (char c)
77 {
78  return (c >= 'A') && (c <= 'Z');
79 }
80 
81 
82 #if 0 /* Disable unused functions. */
83 
89 _MHD_static_inline bool
90 isasciialpha (char c)
91 {
92  return isasciilower (c) || isasciiupper (c);
93 }
94 #endif /* Disable unused functions. */
95 
96 
103 _MHD_static_inline bool
104 isasciidigit (char c)
105 {
106  return (c >= '0') && (c <= '9');
107 }
108 
109 #if 0 /* Disable unused functions. */
110 
116 _MHD_static_inline bool
117 isasciixdigit (char c)
118 {
119  return isasciidigit (c) ||
120  ( (c >= 'A') && (c <= 'F') ) ||
121  ( (c >= 'a') && (c <= 'f') );
122 }
123 
124 
131 _MHD_static_inline bool
132 isasciialnum (char c)
133 {
134  return isasciialpha (c) || isasciidigit (c);
135 }
136 #endif /* Disable unused functions. */
137 
138 
148 _MHD_static_inline char
149 toasciilower (char c)
150 {
151  return isasciiupper (c) ? (c - 'A' + 'a') : c;
152 }
153 
154 
155 #if 0 /* Disable unused functions. */
156 
165 _MHD_static_inline char
166 toasciiupper (char c)
167 {
168  return isasciilower (c) ? (c - 'a' + 'A') : c;
169 }
170 #endif /* Disable unused functions. */
171 
172 
173 #if defined(MHD_FAVOR_SMALL_CODE) /* Used only in MHD_str_to_uvalue_n_() */
174 
180 _MHD_static_inline int
181 todigitvalue (char c)
182 {
183  if (isasciidigit (c))
184  return (unsigned char)(c - '0');
185 
186  return -1;
187 }
188 #endif /* MHD_FAVOR_SMALL_CODE */
189 
190 
197 _MHD_static_inline int
198 toxdigitvalue (char c)
199 {
200  if (isasciidigit (c))
201  return (unsigned char)(c - '0');
202  if ( (c >= 'A') && (c <= 'F') )
203  return (unsigned char)(c - 'A' + 10);
204  if ( (c >= 'a') && (c <= 'f') )
205  return (unsigned char)(c - 'a' + 10);
206 
207  return -1;
208 }
209 #else /* !INLINE_FUNC */
210 
211 
219 #define isasciilower(c) (((char)(c)) >= 'a' && ((char)(c)) <= 'z')
220 
221 
229 #define isasciiupper(c) (((char)(c)) >= 'A' && ((char)(c)) <= 'Z')
230 
231 
239 #define isasciialpha(c) (isasciilower(c) || isasciiupper(c))
240 
241 
249 #define isasciidigit(c) (((char)(c)) >= '0' && ((char)(c)) <= '9')
250 
251 
259 #define isasciixdigit(c) (isasciidigit((c)) || \
260  (((char)(c)) >= 'A' && ((char)(c)) <= 'F') || \
261  (((char)(c)) >= 'a' && ((char)(c)) <= 'f') )
262 
263 
271 #define isasciialnum(c) (isasciialpha(c) || isasciidigit(c))
272 
273 
283 #define toasciilower(c) ((isasciiupper(c)) ? (((char)(c)) - 'A' + 'a') : ((char)(c)))
284 
285 
295 #define toasciiupper(c) ((isasciilower(c)) ? (((char)(c)) - 'a' + 'A') : ((char)(c)))
296 
297 
304 #define todigitvalue(c) (isasciidigit(c) ? (int)(((char)(c)) - '0') : (int)(-1))
305 
306 
312 #define toxdigitvalue(c) ( isasciidigit(c) ? (int)(((char)(c)) - '0') : \
313  ( (((char)(c)) >= 'A' && ((char)(c)) <= 'F') ? \
314  (int)(((unsigned char)(c)) - 'A' + 10) : \
315  ( (((char)(c)) >= 'a' && ((char)(c)) <= 'f') ? \
316  (int)(((unsigned char)(c)) - 'a' + 10) : (int)(-1) )))
317 #endif /* !INLINE_FUNC */
318 
319 
320 #ifndef MHD_FAVOR_SMALL_CODE
321 
328 int
329 MHD_str_equal_caseless_ (const char * str1,
330  const char * str2)
331 {
332  while (0 != (*str1))
333  {
334  const char c1 = *str1;
335  const char c2 = *str2;
336  if ( (c1 != c2) &&
337  (toasciilower (c1) != toasciilower (c2)) )
338  return 0;
339  str1++;
340  str2++;
341  }
342  return 0 == (*str2);
343 }
344 #endif /* ! MHD_FAVOR_SMALL_CODE */
345 
346 
358 int
359 MHD_str_equal_caseless_n_ (const char * const str1,
360  const char * const str2,
361  size_t maxlen)
362 {
363  size_t i;
364 
365  for (i = 0; i < maxlen; ++i)
366  {
367  const char c1 = str1[i];
368  const char c2 = str2[i];
369  if (0 == c2)
370  return 0 == c1;
371  if ( (c1 != c2) &&
372  (toasciilower (c1) != toasciilower (c2)) )
373  return 0;
374  }
375  return !0;
376 }
377 
378 
388 bool
389 MHD_str_equal_caseless_bin_n_ (const char * const str1,
390  const char * const str2,
391  size_t len)
392 {
393  size_t i;
394 
395  for (i = 0; i < len; ++i)
396  {
397  const char c1 = str1[i];
398  const char c2 = str2[i];
399  if ( (c1 != c2) &&
400  (toasciilower (c1) != toasciilower (c2)) )
401  return 0;
402  }
403  return !0;
404 }
405 
406 
407 
421 bool
422 MHD_str_has_token_caseless_ (const char * str,
423  const char * const token,
424  size_t token_len)
425 {
426  if (0 == token_len)
427  return false;
428 
429  while (0 != *str)
430  {
431  size_t i;
432  /* Skip all whitespaces and empty tokens. */
433  while (' ' == *str || '\t' == *str || ',' == *str) str++;
434 
435  /* Check for token match. */
436  i = 0;
437  while (1)
438  {
439  const char sc = *(str++);
440  const char tc = token[i++];
441 
442  if (0 == sc)
443  return false;
444  if ( (sc != tc) &&
445  (toasciilower (sc) != toasciilower (tc)) )
446  break;
447  if (i >= token_len)
448  {
449  /* Check whether substring match token fully or
450  * has additional unmatched chars at tail. */
451  while (' ' == *str || '\t' == *str) str++;
452  /* End of (sub)string? */
453  if (0 == *str || ',' == *str)
454  return true;
455  /* Unmatched chars at end of substring. */
456  break;
457  }
458  }
459  /* Find next substring. */
460  while (0 != *str && ',' != *str) str++;
461  }
462  return false;
463 }
464 
465 #ifndef MHD_FAVOR_SMALL_CODE
466 /* Use individual function for each case */
467 
478 size_t
479 MHD_str_to_uint64_ (const char *str,
480  uint64_t *out_val)
481 {
482  const char * const start = str;
483  uint64_t res;
484 
485  if (!str || !out_val || !isasciidigit(str[0]))
486  return 0;
487 
488  res = 0;
489  do
490  {
491  const int digit = (unsigned char)(*str) - '0';
492  if ( (res > (UINT64_MAX / 10)) ||
493  ( (res == (UINT64_MAX / 10)) &&
494  ((uint64_t)digit > (UINT64_MAX % 10)) ) )
495  return 0;
496 
497  res *= 10;
498  res += digit;
499  str++;
500  } while (isasciidigit (*str));
501 
502  *out_val = res;
503  return str - start;
504 }
505 
506 
520 size_t
521 MHD_str_to_uint64_n_ (const char * str,
522  size_t maxlen,
523  uint64_t *out_val)
524 {
525  uint64_t res;
526  size_t i;
527 
528  if (!str || !maxlen || !out_val || !isasciidigit (str[0]))
529  return 0;
530 
531  res = 0;
532  i = 0;
533  do
534  {
535  const int digit = (unsigned char)str[i] - '0';
536 
537  if ( (res > (UINT64_MAX / 10)) ||
538  ( (res == (UINT64_MAX / 10)) &&
539  ((uint64_t)digit > (UINT64_MAX % 10)) ) )
540  return 0;
541 
542  res *= 10;
543  res += digit;
544  i++;
545  } while ( (i < maxlen) &&
546  isasciidigit (str[i]) );
547 
548  *out_val= res;
549  return i;
550 }
551 
552 
563 size_t
564 MHD_strx_to_uint32_ (const char * str,
565  uint32_t *out_val)
566 {
567  const char * const start = str;
568  uint32_t res;
569  int digit;
570 
571  if (!str || !out_val)
572  return 0;
573 
574  res = 0;
575  digit = toxdigitvalue (*str);
576  while (digit >= 0)
577  {
578  if ( (res < (UINT32_MAX / 16)) ||
579  (res == (UINT32_MAX / 16) && (uint32_t)digit <= (UINT32_MAX % 16)) )
580  {
581  res *= 16;
582  res += digit;
583  }
584  else
585  return 0;
586  str++;
587  digit = toxdigitvalue (*str);
588  }
589 
590  if (str - start > 0)
591  *out_val = res;
592  return str - start;
593 }
594 
595 
609 size_t
610 MHD_strx_to_uint32_n_ (const char *str,
611  size_t maxlen,
612  uint32_t *out_val)
613 {
614  size_t i;
615  uint32_t res;
616  int digit;
617  if (!str || !out_val)
618  return 0;
619 
620  res = 0;
621  i = 0;
622  while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
623  {
624  if ( (res > (UINT32_MAX / 16)) ||
625  (res == (UINT32_MAX / 16) && (uint32_t)digit > (UINT32_MAX % 16)) )
626  return 0;
627 
628  res *= 16;
629  res += digit;
630  i++;
631  }
632 
633  if (i)
634  *out_val = res;
635  return i;
636 }
637 
638 
649 size_t
650 MHD_strx_to_uint64_ (const char *str,
651  uint64_t *out_val)
652 {
653  const char * const start = str;
654  uint64_t res;
655  int digit;
656  if (!str || !out_val)
657  return 0;
658 
659  res = 0;
660  digit = toxdigitvalue (*str);
661  while (digit >= 0)
662  {
663  if ( (res < (UINT64_MAX / 16)) ||
664  (res == (UINT64_MAX / 16) && (uint64_t)digit <= (UINT64_MAX % 16)) )
665  {
666  res *= 16;
667  res += digit;
668  }
669  else
670  return 0;
671  str++;
672  digit = toxdigitvalue (*str);
673  }
674 
675  if (str - start > 0)
676  *out_val = res;
677  return str - start;
678 }
679 
680 
694 size_t
695 MHD_strx_to_uint64_n_ (const char * str,
696  size_t maxlen,
697  uint64_t *out_val)
698 {
699  size_t i;
700  uint64_t res;
701  int digit;
702  if (!str || !out_val)
703  return 0;
704 
705  res = 0;
706  i = 0;
707  while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
708  {
709  if ( (res > (UINT64_MAX / 16)) ||
710  (res == (UINT64_MAX / 16) && (uint64_t)digit > (UINT64_MAX % 16)) )
711  return 0;
712 
713  res *= 16;
714  res += digit;
715  i++;
716  }
717 
718  if (i)
719  *out_val = res;
720  return i;
721 }
722 
723 #else /* MHD_FAVOR_SMALL_CODE */
724 
742 size_t
743 MHD_str_to_uvalue_n_ (const char *str,
744  size_t maxlen,
745  void * out_val,
746  size_t val_size,
747  uint64_t max_val,
748  int base)
749 {
750  size_t i;
751  uint64_t res;
752  int digit;
753  const uint64_t max_v_div_b = max_val / base;
754  const uint64_t max_v_mod_b = max_val % base;
755  /* 'digit->value' must be function, not macro */
756  int (*const dfunc)(char) = (base == 16) ?
758 
759  if ( !str || !out_val ||
760  (base != 16 && base != 10) )
761  return 0;
762 
763  res = 0;
764  i = 0;
765  while (maxlen > i && 0 <= (digit = dfunc (str[i])))
766  {
767  if ( ((max_v_div_b) < res) ||
768  ((max_v_div_b) == res && (max_v_mod_b) < (uint64_t)digit) )
769  return 0;
770 
771  res *= base;
772  res += digit;
773  i++;
774  }
775 
776  if (i)
777  {
778  if (8 == val_size)
779  *(uint64_t*)out_val = res;
780  else if (4 == val_size)
781  *(uint32_t*)out_val = (uint32_t)res;
782  else
783  return 0;
784  }
785  return i;
786 }
787 #endif /* MHD_FAVOR_SMALL_CODE */
#define toasciiupper(c)
Definition: mhd_str.c:295
int MHD_str_equal_caseless_n_(const char *const str1, const char *const str2, size_t maxlen)
Definition: mhd_str.c:359
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:450
size_t MHD_str_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:492
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:393
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:329
size_t MHD_strx_to_uint32_(const char *str, uint32_t *out_val)
Definition: mhd_str.c:535
#define toxdigitvalue(c)
Definition: mhd_str.c:312
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:666
#define isasciiupper(c)
Definition: mhd_str.c:229
Header for string manipulating helpers.
#define UINT32_MAX
Definition: mhd_limits.h:73
#define todigitvalue(c)
Definition: mhd_str.c:304
#define UINT64_MAX
Definition: mhd_limits.h:81
#define isasciialnum(c)
Definition: mhd_str.c:271
size_t MHD_strx_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:621
#define isasciialpha(c)
Definition: mhd_str.c:239
#define isasciilower(c)
Definition: mhd_str.c:219
#define toasciilower(c)
Definition: mhd_str.c:283
#define isasciidigit(c)
Definition: mhd_str.c:249
#define isasciixdigit(c)
Definition: mhd_str.c:259
limits values definitions
size_t MHD_strx_to_uint32_n_(const char *str, size_t maxlen, uint32_t *out_val)
Definition: mhd_str.c:581
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Definition: mhd_str.c:389