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 
407 bool
408 MHD_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 
439 bool
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 
500 size_t
501 MHD_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 
542 size_t
543 MHD_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 
585 size_t
586 MHD_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 
632 size_t
633 MHD_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 
673 size_t
674 MHD_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 
719 size_t
720 MHD_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 
769 size_t
770 MHD_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.