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 
396 bool
398  const char *const token,
399  size_t token_len)
400 {
401  if (0 == token_len)
402  return false;
403 
404  while (0 != *str)
405  {
406  size_t i;
407  /* Skip all whitespaces and empty tokens. */
408  while (' ' == *str || '\t' == *str || ',' == *str)
409  str++;
410 
411  /* Check for token match. */
412  i = 0;
413  while (1)
414  {
415  const char sc = *(str++);
416  const char tc = token[i++];
417 
418  if (0 == sc)
419  return false;
420  if ( (sc != tc) &&
421  (toasciilower (sc) != toasciilower (tc)) )
422  break;
423  if (i >= token_len)
424  {
425  /* Check whether substring match token fully or
426  * has additional unmatched chars at tail. */
427  while (' ' == *str || '\t' == *str)
428  str++;
429  /* End of (sub)string? */
430  if ((0 == *str) ||(',' == *str) )
431  return true;
432  /* Unmatched chars at end of substring. */
433  break;
434  }
435  }
436  /* Find next substring. */
437  while (0 != *str && ',' != *str)
438  str++;
439  }
440  return false;
441 }
442 
443 #ifndef MHD_FAVOR_SMALL_CODE
444 /* Use individual function for each case */
445 
456 size_t
457 MHD_str_to_uint64_ (const char *str,
458  uint64_t *out_val)
459 {
460  const char *const start = str;
461  uint64_t res;
462 
463  if (! str || ! out_val || ! isasciidigit (str[0]))
464  return 0;
465 
466  res = 0;
467  do
468  {
469  const int digit = (unsigned char) (*str) - '0';
470  if ( (res > (UINT64_MAX / 10)) ||
471  ( (res == (UINT64_MAX / 10)) &&
472  ((uint64_t) digit > (UINT64_MAX % 10)) ) )
473  return 0;
474 
475  res *= 10;
476  res += digit;
477  str++;
478  } while (isasciidigit (*str));
479 
480  *out_val = res;
481  return str - start;
482 }
483 
484 
498 size_t
499 MHD_str_to_uint64_n_ (const char *str,
500  size_t maxlen,
501  uint64_t *out_val)
502 {
503  uint64_t res;
504  size_t i;
505 
506  if (! str || ! maxlen || ! out_val || ! isasciidigit (str[0]))
507  return 0;
508 
509  res = 0;
510  i = 0;
511  do
512  {
513  const int digit = (unsigned char) str[i] - '0';
514 
515  if ( (res > (UINT64_MAX / 10)) ||
516  ( (res == (UINT64_MAX / 10)) &&
517  ((uint64_t) digit > (UINT64_MAX % 10)) ) )
518  return 0;
519 
520  res *= 10;
521  res += digit;
522  i++;
523  } while ( (i < maxlen) &&
524  isasciidigit (str[i]) );
525 
526  *out_val = res;
527  return i;
528 }
529 
530 
541 size_t
542 MHD_strx_to_uint32_ (const char *str,
543  uint32_t *out_val)
544 {
545  const char *const start = str;
546  uint32_t res;
547  int digit;
548 
549  if (! str || ! out_val)
550  return 0;
551 
552  res = 0;
553  digit = toxdigitvalue (*str);
554  while (digit >= 0)
555  {
556  if ( (res < (UINT32_MAX / 16)) ||
557  ((res == (UINT32_MAX / 16)) &&( (uint32_t) digit <= (UINT32_MAX
558  % 16)) ) )
559  {
560  res *= 16;
561  res += digit;
562  }
563  else
564  return 0;
565  str++;
566  digit = toxdigitvalue (*str);
567  }
568 
569  if (str - start > 0)
570  *out_val = res;
571  return str - start;
572 }
573 
574 
588 size_t
589 MHD_strx_to_uint32_n_ (const char *str,
590  size_t maxlen,
591  uint32_t *out_val)
592 {
593  size_t i;
594  uint32_t res;
595  int digit;
596  if (! str || ! out_val)
597  return 0;
598 
599  res = 0;
600  i = 0;
601  while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
602  {
603  if ( (res > (UINT32_MAX / 16)) ||
604  ((res == (UINT32_MAX / 16)) &&( (uint32_t) digit > (UINT32_MAX
605  % 16)) ) )
606  return 0;
607 
608  res *= 16;
609  res += digit;
610  i++;
611  }
612 
613  if (i)
614  *out_val = res;
615  return i;
616 }
617 
618 
629 size_t
630 MHD_strx_to_uint64_ (const char *str,
631  uint64_t *out_val)
632 {
633  const char *const start = str;
634  uint64_t res;
635  int digit;
636  if (! str || ! out_val)
637  return 0;
638 
639  res = 0;
640  digit = toxdigitvalue (*str);
641  while (digit >= 0)
642  {
643  if ( (res < (UINT64_MAX / 16)) ||
644  ((res == (UINT64_MAX / 16)) &&( (uint64_t) digit <= (UINT64_MAX
645  % 16)) ) )
646  {
647  res *= 16;
648  res += digit;
649  }
650  else
651  return 0;
652  str++;
653  digit = toxdigitvalue (*str);
654  }
655 
656  if (str - start > 0)
657  *out_val = res;
658  return str - start;
659 }
660 
661 
675 size_t
676 MHD_strx_to_uint64_n_ (const char *str,
677  size_t maxlen,
678  uint64_t *out_val)
679 {
680  size_t i;
681  uint64_t res;
682  int digit;
683  if (! str || ! out_val)
684  return 0;
685 
686  res = 0;
687  i = 0;
688  while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
689  {
690  if ( (res > (UINT64_MAX / 16)) ||
691  ((res == (UINT64_MAX / 16)) &&( (uint64_t) digit > (UINT64_MAX
692  % 16)) ) )
693  return 0;
694 
695  res *= 16;
696  res += digit;
697  i++;
698  }
699 
700  if (i)
701  *out_val = res;
702  return i;
703 }
704 
705 #else /* MHD_FAVOR_SMALL_CODE */
706 
724 size_t
725 MHD_str_to_uvalue_n_ (const char *str,
726  size_t maxlen,
727  void *out_val,
728  size_t val_size,
729  uint64_t max_val,
730  int base)
731 {
732  size_t i;
733  uint64_t res;
734  int digit;
735  const uint64_t max_v_div_b = max_val / base;
736  const uint64_t max_v_mod_b = max_val % base;
737  /* 'digit->value' must be function, not macro */
738  int (*const dfunc)(char) = (base == 16) ?
740 
741  if ( ! str || ! out_val ||
742  ((base != 16)&&(base != 10)) )
743  return 0;
744 
745  res = 0;
746  i = 0;
747  while (maxlen > i && 0 <= (digit = dfunc (str[i])))
748  {
749  if ( ((max_v_div_b) < res) ||
750  (( (max_v_div_b) == res) &&( (max_v_mod_b) < (uint64_t) digit) ) )
751  return 0;
752 
753  res *= base;
754  res += digit;
755  i++;
756  }
757 
758  if (i)
759  {
760  if (8 == val_size)
761  *(uint64_t*) out_val = res;
762  else if (4 == val_size)
763  *(uint32_t*) out_val = (uint32_t) res;
764  else
765  return 0;
766  }
767  return i;
768 }
769 #endif /* MHD_FAVOR_SMALL_CODE */
#define toxdigitvalue(c)
Definition: mhd_str.c:315
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
#define isasciilower(c)
Definition: mhd_str.c:219
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
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:676
#define isasciixdigit(c)
Definition: mhd_str.c:259
#define todigitvalue(c)
Definition: mhd_str.c:306
#define isasciidigit(c)
Definition: mhd_str.c:249
#define UINT32_MAX
Definition: mhd_limits.h:73
#define isasciiupper(c)
Definition: mhd_str.c:229
#define UINT64_MAX
Definition: mhd_limits.h:81
size_t MHD_strx_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:630
#define toasciiupper(c)
Definition: mhd_str.c:296
#define toasciilower(c)
Definition: mhd_str.c:283
#define isasciialpha(c)
Definition: mhd_str.c:239
#define isasciialnum(c)
Definition: mhd_str.c:271
size_t MHD_strx_to_uint32_n_(const char *str, size_t maxlen, uint32_t *out_val)
Definition: mhd_str.c:589