GNU libmicrohttpd  0.9.68
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') : \
284  ((char) (c)))
285 
286 
296 #define toasciiupper(c) ((isasciilower (c)) ? (((char) (c)) - 'a' + 'A') : \
297  ((char) (c)))
298 
299 
306 #define todigitvalue(c) (isasciidigit (c) ? (int) (((char) (c)) - '0') : \
307  (int) (-1))
308 
309 
315 #define toxdigitvalue(c) (isasciidigit (c) ? (int) (((char) (c)) - '0') : \
316  ( (((char) (c)) >= 'A' && ((char) (c)) <= 'F') ? \
317  (int) (((unsigned char) (c)) - 'A' + 10) : \
318  ( (((char) (c)) >= 'a' && ((char) (c)) <= 'f') ? \
319  (int) (((unsigned char) (c)) - 'a' + 10) : \
320  (int) (-1) )))
321 #endif /* !INLINE_FUNC */
322 
323 
324 #ifndef MHD_FAVOR_SMALL_CODE
325 
332 int
333 MHD_str_equal_caseless_ (const char *str1,
334  const char *str2)
335 {
336  while (0 != (*str1))
337  {
338  const char c1 = *str1;
339  const char c2 = *str2;
340  if ( (c1 != c2) &&
341  (toasciilower (c1) != toasciilower (c2)) )
342  return 0;
343  str1++;
344  str2++;
345  }
346  return 0 == (*str2);
347 }
348 #endif /* ! MHD_FAVOR_SMALL_CODE */
349 
350 
362 int
363 MHD_str_equal_caseless_n_ (const char *const str1,
364  const char *const str2,
365  size_t maxlen)
366 {
367  size_t i;
368 
369  for (i = 0; i < maxlen; ++i)
370  {
371  const char c1 = str1[i];
372  const char c2 = str2[i];
373  if (0 == c2)
374  return 0 == c1;
375  if ( (c1 != c2) &&
376  (toasciilower (c1) != toasciilower (c2)) )
377  return 0;
378  }
379  return ! 0;
380 }
381 
382 
392 bool
393 MHD_str_equal_caseless_bin_n_ (const char *const str1,
394  const char *const str2,
395  size_t len)
396 {
397  size_t i;
398 
399  for (i = 0; i < len; ++i)
400  {
401  const char c1 = str1[i];
402  const char c2 = str2[i];
403  if ( (c1 != c2) &&
404  (toasciilower (c1) != toasciilower (c2)) )
405  return 0;
406  }
407  return ! 0;
408 }
409 
410 
411 
425 bool
427  const char *const token,
428  size_t token_len)
429 {
430  if (0 == token_len)
431  return false;
432 
433  while (0 != *str)
434  {
435  size_t i;
436  /* Skip all whitespaces and empty tokens. */
437  while (' ' == *str || '\t' == *str || ',' == *str)
438  str++;
439 
440  /* Check for token match. */
441  i = 0;
442  while (1)
443  {
444  const char sc = *(str++);
445  const char tc = token[i++];
446 
447  if (0 == sc)
448  return false;
449  if ( (sc != tc) &&
450  (toasciilower (sc) != toasciilower (tc)) )
451  break;
452  if (i >= token_len)
453  {
454  /* Check whether substring match token fully or
455  * has additional unmatched chars at tail. */
456  while (' ' == *str || '\t' == *str)
457  str++;
458  /* End of (sub)string? */
459  if ((0 == *str) ||(',' == *str) )
460  return true;
461  /* Unmatched chars at end of substring. */
462  break;
463  }
464  }
465  /* Find next substring. */
466  while (0 != *str && ',' != *str)
467  str++;
468  }
469  return false;
470 }
471 
472 #ifndef MHD_FAVOR_SMALL_CODE
473 /* Use individual function for each case */
474 
485 size_t
486 MHD_str_to_uint64_ (const char *str,
487  uint64_t *out_val)
488 {
489  const char *const start = str;
490  uint64_t res;
491 
492  if (! str || ! out_val || ! isasciidigit (str[0]))
493  return 0;
494 
495  res = 0;
496  do
497  {
498  const int digit = (unsigned char) (*str) - '0';
499  if ( (res > (UINT64_MAX / 10)) ||
500  ( (res == (UINT64_MAX / 10)) &&
501  ((uint64_t) digit > (UINT64_MAX % 10)) ) )
502  return 0;
503 
504  res *= 10;
505  res += digit;
506  str++;
507  } while (isasciidigit (*str));
508 
509  *out_val = res;
510  return str - start;
511 }
512 
513 
527 size_t
528 MHD_str_to_uint64_n_ (const char *str,
529  size_t maxlen,
530  uint64_t *out_val)
531 {
532  uint64_t res;
533  size_t i;
534 
535  if (! str || ! maxlen || ! out_val || ! isasciidigit (str[0]))
536  return 0;
537 
538  res = 0;
539  i = 0;
540  do
541  {
542  const int digit = (unsigned char) str[i] - '0';
543 
544  if ( (res > (UINT64_MAX / 10)) ||
545  ( (res == (UINT64_MAX / 10)) &&
546  ((uint64_t) digit > (UINT64_MAX % 10)) ) )
547  return 0;
548 
549  res *= 10;
550  res += digit;
551  i++;
552  } while ( (i < maxlen) &&
553  isasciidigit (str[i]) );
554 
555  *out_val = res;
556  return i;
557 }
558 
559 
570 size_t
571 MHD_strx_to_uint32_ (const char *str,
572  uint32_t *out_val)
573 {
574  const char *const start = str;
575  uint32_t res;
576  int digit;
577 
578  if (! str || ! out_val)
579  return 0;
580 
581  res = 0;
582  digit = toxdigitvalue (*str);
583  while (digit >= 0)
584  {
585  if ( (res < (UINT32_MAX / 16)) ||
586  ((res == (UINT32_MAX / 16)) &&( (uint32_t) digit <= (UINT32_MAX
587  % 16)) ) )
588  {
589  res *= 16;
590  res += digit;
591  }
592  else
593  return 0;
594  str++;
595  digit = toxdigitvalue (*str);
596  }
597 
598  if (str - start > 0)
599  *out_val = res;
600  return str - start;
601 }
602 
603 
617 size_t
618 MHD_strx_to_uint32_n_ (const char *str,
619  size_t maxlen,
620  uint32_t *out_val)
621 {
622  size_t i;
623  uint32_t res;
624  int digit;
625  if (! str || ! out_val)
626  return 0;
627 
628  res = 0;
629  i = 0;
630  while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
631  {
632  if ( (res > (UINT32_MAX / 16)) ||
633  ((res == (UINT32_MAX / 16)) &&( (uint32_t) digit > (UINT32_MAX
634  % 16)) ) )
635  return 0;
636 
637  res *= 16;
638  res += digit;
639  i++;
640  }
641 
642  if (i)
643  *out_val = res;
644  return i;
645 }
646 
647 
658 size_t
659 MHD_strx_to_uint64_ (const char *str,
660  uint64_t *out_val)
661 {
662  const char *const start = str;
663  uint64_t res;
664  int digit;
665  if (! str || ! out_val)
666  return 0;
667 
668  res = 0;
669  digit = toxdigitvalue (*str);
670  while (digit >= 0)
671  {
672  if ( (res < (UINT64_MAX / 16)) ||
673  ((res == (UINT64_MAX / 16)) &&( (uint64_t) digit <= (UINT64_MAX
674  % 16)) ) )
675  {
676  res *= 16;
677  res += digit;
678  }
679  else
680  return 0;
681  str++;
682  digit = toxdigitvalue (*str);
683  }
684 
685  if (str - start > 0)
686  *out_val = res;
687  return str - start;
688 }
689 
690 
704 size_t
705 MHD_strx_to_uint64_n_ (const char *str,
706  size_t maxlen,
707  uint64_t *out_val)
708 {
709  size_t i;
710  uint64_t res;
711  int digit;
712  if (! str || ! out_val)
713  return 0;
714 
715  res = 0;
716  i = 0;
717  while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
718  {
719  if ( (res > (UINT64_MAX / 16)) ||
720  ((res == (UINT64_MAX / 16)) &&( (uint64_t) digit > (UINT64_MAX
721  % 16)) ) )
722  return 0;
723 
724  res *= 16;
725  res += digit;
726  i++;
727  }
728 
729  if (i)
730  *out_val = res;
731  return i;
732 }
733 
734 #else /* MHD_FAVOR_SMALL_CODE */
735 
753 size_t
754 MHD_str_to_uvalue_n_ (const char *str,
755  size_t maxlen,
756  void *out_val,
757  size_t val_size,
758  uint64_t max_val,
759  int base)
760 {
761  size_t i;
762  uint64_t res;
763  int digit;
764  const uint64_t max_v_div_b = max_val / base;
765  const uint64_t max_v_mod_b = max_val % base;
766  /* 'digit->value' must be function, not macro */
767  int (*const dfunc)(char) = (base == 16) ?
769 
770  if ( ! str || ! out_val ||
771  ((base != 16)&&(base != 10)) )
772  return 0;
773 
774  res = 0;
775  i = 0;
776  while (maxlen > i && 0 <= (digit = dfunc (str[i])))
777  {
778  if ( ((max_v_div_b) < res) ||
779  (( (max_v_div_b) == res) &&( (max_v_mod_b) < (uint64_t) digit) ) )
780  return 0;
781 
782  res *= base;
783  res += digit;
784  i++;
785  }
786 
787  if (i)
788  {
789  if (8 == val_size)
790  *(uint64_t*) out_val = res;
791  else if (4 == val_size)
792  *(uint32_t*) out_val = (uint32_t) res;
793  else
794  return 0;
795  }
796  return i;
797 }
798 #endif /* MHD_FAVOR_SMALL_CODE */
#define toasciiupper(c)
Definition: mhd_str.c:296
int MHD_str_equal_caseless_n_(const char *const str1, const char *const str2, size_t maxlen)
Definition: mhd_str.c:363
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:457
size_t MHD_str_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:499
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:397
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:333
size_t MHD_strx_to_uint32_(const char *str, uint32_t *out_val)
Definition: mhd_str.c:542
#define toxdigitvalue(c)
Definition: mhd_str.c:315
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:676
#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:306
#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:630
#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:589
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Definition: mhd_str.c:393