GNU libmicrohttpd  0.9.59
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 
392 bool
393 MHD_str_has_token_caseless_ (const char * str,
394  const char * const token,
395  size_t token_len)
396 {
397  if (0 == token_len)
398  return false;
399 
400  while (0 != *str)
401  {
402  size_t i;
403  /* Skip all whitespaces and empty tokens. */
404  while (' ' == *str || '\t' == *str || ',' == *str) str++;
405 
406  /* Check for token match. */
407  i = 0;
408  while (1)
409  {
410  const char sc = *(str++);
411  const char tc = token[i++];
412 
413  if (0 == sc)
414  return false;
415  if ( (sc != tc) &&
416  (toasciilower (sc) != toasciilower (tc)) )
417  break;
418  if (i >= token_len)
419  {
420  /* Check whether substring match token fully or
421  * has additional unmatched chars at tail. */
422  while (' ' == *str || '\t' == *str) str++;
423  /* End of (sub)string? */
424  if (0 == *str || ',' == *str)
425  return true;
426  /* Unmatched chars at end of substring. */
427  break;
428  }
429  }
430  /* Find next substring. */
431  while (0 != *str && ',' != *str) str++;
432  }
433  return false;
434 }
435 
436 #ifndef MHD_FAVOR_SMALL_CODE
437 /* Use individual function for each case */
438 
449 size_t
450 MHD_str_to_uint64_ (const char *str,
451  uint64_t *out_val)
452 {
453  const char * const start = str;
454  uint64_t res;
455 
456  if (!str || !out_val || !isasciidigit(str[0]))
457  return 0;
458 
459  res = 0;
460  do
461  {
462  const int digit = (unsigned char)(*str) - '0';
463  if ( (res > (UINT64_MAX / 10)) ||
464  ( (res == (UINT64_MAX / 10)) &&
465  ((uint64_t)digit > (UINT64_MAX % 10)) ) )
466  return 0;
467 
468  res *= 10;
469  res += digit;
470  str++;
471  } while (isasciidigit (*str));
472 
473  *out_val = res;
474  return str - start;
475 }
476 
477 
491 size_t
492 MHD_str_to_uint64_n_ (const char * str,
493  size_t maxlen,
494  uint64_t *out_val)
495 {
496  uint64_t res;
497  size_t i;
498 
499  if (!str || !maxlen || !out_val || !isasciidigit (str[0]))
500  return 0;
501 
502  res = 0;
503  i = 0;
504  do
505  {
506  const int digit = (unsigned char)str[i] - '0';
507 
508  if ( (res > (UINT64_MAX / 10)) ||
509  ( (res == (UINT64_MAX / 10)) &&
510  ((uint64_t)digit > (UINT64_MAX % 10)) ) )
511  return 0;
512 
513  res *= 10;
514  res += digit;
515  i++;
516  } while ( (i < maxlen) &&
517  isasciidigit (str[i]) );
518 
519  *out_val= res;
520  return i;
521 }
522 
523 
534 size_t
535 MHD_strx_to_uint32_ (const char * str,
536  uint32_t *out_val)
537 {
538  const char * const start = str;
539  uint32_t res;
540  int digit;
541 
542  if (!str || !out_val)
543  return 0;
544 
545  res = 0;
546  digit = toxdigitvalue (*str);
547  while (digit >= 0)
548  {
549  if ( (res < (UINT32_MAX / 16)) ||
550  (res == (UINT32_MAX / 16) && (uint32_t)digit <= (UINT32_MAX % 16)) )
551  {
552  res *= 16;
553  res += digit;
554  }
555  else
556  return 0;
557  str++;
558  digit = toxdigitvalue (*str);
559  }
560 
561  if (str - start > 0)
562  *out_val = res;
563  return str - start;
564 }
565 
566 
580 size_t
581 MHD_strx_to_uint32_n_ (const char *str,
582  size_t maxlen,
583  uint32_t *out_val)
584 {
585  size_t i;
586  uint32_t res;
587  int digit;
588  if (!str || !out_val)
589  return 0;
590 
591  res = 0;
592  i = 0;
593  while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
594  {
595  if ( (res > (UINT32_MAX / 16)) ||
596  (res == (UINT32_MAX / 16) && (uint32_t)digit > (UINT32_MAX % 16)) )
597  return 0;
598 
599  res *= 16;
600  res += digit;
601  i++;
602  }
603 
604  if (i)
605  *out_val = res;
606  return i;
607 }
608 
609 
620 size_t
621 MHD_strx_to_uint64_ (const char *str,
622  uint64_t *out_val)
623 {
624  const char * const start = str;
625  uint64_t res;
626  int digit;
627  if (!str || !out_val)
628  return 0;
629 
630  res = 0;
631  digit = toxdigitvalue (*str);
632  while (digit >= 0)
633  {
634  if ( (res < (UINT64_MAX / 16)) ||
635  (res == (UINT64_MAX / 16) && (uint64_t)digit <= (UINT64_MAX % 16)) )
636  {
637  res *= 16;
638  res += digit;
639  }
640  else
641  return 0;
642  str++;
643  digit = toxdigitvalue (*str);
644  }
645 
646  if (str - start > 0)
647  *out_val = res;
648  return str - start;
649 }
650 
651 
665 size_t
666 MHD_strx_to_uint64_n_ (const char * str,
667  size_t maxlen,
668  uint64_t *out_val)
669 {
670  size_t i;
671  uint64_t res;
672  int digit;
673  if (!str || !out_val)
674  return 0;
675 
676  res = 0;
677  i = 0;
678  while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
679  {
680  if ( (res > (UINT64_MAX / 16)) ||
681  (res == (UINT64_MAX / 16) && (uint64_t)digit > (UINT64_MAX % 16)) )
682  return 0;
683 
684  res *= 16;
685  res += digit;
686  i++;
687  }
688 
689  if (i)
690  *out_val = res;
691  return i;
692 }
693 
694 #else /* MHD_FAVOR_SMALL_CODE */
695 
713 size_t
714 MHD_str_to_uvalue_n_ (const char *str,
715  size_t maxlen,
716  void * out_val,
717  size_t val_size,
718  uint64_t max_val,
719  int base)
720 {
721  size_t i;
722  uint64_t res;
723  int digit;
724  const uint64_t max_v_div_b = max_val / base;
725  const uint64_t max_v_mod_b = max_val % base;
726  /* 'digit->value' must be function, not macro */
727  int (*const dfunc)(char) = (base == 16) ?
729 
730  if ( !str || !out_val ||
731  (base != 16 && base != 10) )
732  return 0;
733 
734  res = 0;
735  i = 0;
736  while (maxlen > i && 0 <= (digit = dfunc (str[i])))
737  {
738  if ( ((max_v_div_b) < res) ||
739  ((max_v_div_b) == res && (max_v_mod_b) < (uint64_t)digit) )
740  return 0;
741 
742  res *= base;
743  res += digit;
744  i++;
745  }
746 
747  if (i)
748  {
749  if (8 == val_size)
750  *(uint64_t*)out_val = res;
751  else if (4 == val_size)
752  *(uint32_t*)out_val = (uint32_t)res;
753  else
754  return 0;
755  }
756  return i;
757 }
758 #endif /* MHD_FAVOR_SMALL_CODE */
size_t MHD_strx_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:621
#define toasciilower(c)
Definition: mhd_str.c:283
int MHD_str_equal_caseless_n_(const char *const str1, const char *const str2, size_t maxlen)
Definition: mhd_str.c:359
#define UINT64_MAX
Definition: mhd_limits.h:81
size_t MHD_strx_to_uint32_n_(const char *str, size_t maxlen, uint32_t *out_val)
Definition: mhd_str.c:581
#define isasciixdigit(c)
Definition: mhd_str.c:259
#define toasciiupper(c)
Definition: mhd_str.c:295
#define UINT32_MAX
Definition: mhd_limits.h:73
size_t MHD_strx_to_uint32_(const char *str, uint32_t *out_val)
Definition: mhd_str.c:535
limits values definitions
#define isasciilower(c)
Definition: mhd_str.c:219
#define isasciiupper(c)
Definition: mhd_str.c:229
Header for string manipulating helpers.
#define isasciidigit(c)
Definition: mhd_str.c:249
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
#define isasciialpha(c)
Definition: mhd_str.c:239
#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 isasciialnum(c)
Definition: mhd_str.c:271
size_t MHD_str_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:492
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:450
#define todigitvalue(c)
Definition: mhd_str.c:304