GNU libmicrohttpd  0.9.29
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_inline
36 #undef _MHD_inline
37 #endif /* _MHD_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_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 
59 _MHD_inline _MHD_bool
60 isasciilower (char c)
61 {
62  return (c >= 'a') && (c <= 'z');
63 }
64 
65 
72 _MHD_inline _MHD_bool
73 isasciiupper (char c)
74 {
75  return (c >= 'A') && (c <= 'Z');
76 }
77 
78 
85 _MHD_inline _MHD_bool
86 isasciialpha (char c)
87 {
88  return isasciilower (c) || isasciiupper (c);
89 }
90 
91 
98 _MHD_inline _MHD_bool
99 isasciidigit (char c)
100 {
101  return (c >= '0') && (c <= '9');
102 }
103 
104 
111 _MHD_inline _MHD_bool
112 isasciixdigit (char c)
113 {
114  return isasciidigit (c) ||
115  ( (c >= 'A') && (c <= 'F') ) ||
116  ( (c >= 'a') && (c <= 'f') );
117 }
118 
119 
126 _MHD_inline _MHD_bool
127 isasciialnum (char c)
128 {
129  return isasciialpha (c) || isasciidigit (c);
130 }
131 
132 
142 _MHD_inline char
143 toasciilower (char c)
144 {
145  return isasciiupper (c) ? (c - 'A' + 'a') : c;
146 }
147 
148 
158 _MHD_inline char
159 toasciiupper (char c)
160 {
161  return isasciilower (c) ? (c - 'a' + 'A') : c;
162 }
163 
164 
171 _MHD_inline int
172 todigitvalue (char c)
173 {
174  if (isasciidigit (c))
175  return (unsigned char)(c - '0');
176 
177  return -1;
178 }
179 
180 
187 _MHD_inline int
188 toxdigitvalue (char c)
189 {
190  if (isasciidigit (c))
191  return (unsigned char)(c - '0');
192  if ( (c >= 'A') && (c <= 'F') )
193  return (unsigned char)(c - 'A' + 10);
194  if ( (c >= 'a') && (c <= 'f') )
195  return (unsigned char)(c - 'a' + 10);
196 
197  return -1;
198 }
199 #else /* !INLINE_FUNC */
200 
201 
209 #define isasciilower(c) (((char)(c)) >= 'a' && ((char)(c)) <= 'z')
210 
211 
219 #define isasciiupper(c) (((char)(c)) >= 'A' && ((char)(c)) <= 'Z')
220 
221 
229 #define isasciialpha(c) (isasciilower(c) || isasciiupper(c))
230 
231 
239 #define isasciidigit(c) (((char)(c)) >= '0' && ((char)(c)) <= '9')
240 
241 
249 #define isasciixdigit(c) (isasciidigit((c)) || \
250  (((char)(c)) >= 'A' && ((char)(c)) <= 'F') || \
251  (((char)(c)) >= 'a' && ((char)(c)) <= 'f') )
252 
253 
261 #define isasciialnum(c) (isasciialpha(c) || isasciidigit(c))
262 
263 
273 #define toasciilower(c) ((isasciiupper(c)) ? (((char)(c)) - 'A' + 'a') : ((char)(c)))
274 
275 
285 #define toasciiupper(c) ((isasciilower(c)) ? (((char)(c)) - 'a' + 'A') : ((char)(c)))
286 
287 
294 #define todigitvalue(c) (isasciidigit(c) ? (int)(((char)(c)) - '0') : (int)(-1))
295 
296 
302 #define toxdigitvalue(c) ( isasciidigit(c) ? (int)(((char)(c)) - '0') : \
303  ( (((char)(c)) >= 'A' && ((char)(c)) <= 'F') ? \
304  (int)(((unsigned char)(c)) - 'A' + 10) : \
305  ( (((char)(c)) >= 'a' && ((char)(c)) <= 'f') ? \
306  (int)(((unsigned char)(c)) - 'a' + 10) : (int)(-1) )))
307 #endif /* !INLINE_FUNC */
308 
309 
310 #ifndef MHD_FAVOR_SMALL_CODE
311 
318 int
319 MHD_str_equal_caseless_ (const char * str1,
320  const char * str2)
321 {
322  while (0 != (*str1))
323  {
324  const char c1 = *str1;
325  const char c2 = *str2;
326  if ( (c1 != c2) &&
327  (toasciilower (c1) != toasciilower (c2)) )
328  return 0;
329  str1++;
330  str2++;
331  }
332  return 0 == (*str2);
333 }
334 #endif /* ! MHD_FAVOR_SMALL_CODE */
335 
336 
348 int
349 MHD_str_equal_caseless_n_ (const char * const str1,
350  const char * const str2,
351  size_t maxlen)
352 {
353  size_t i;
354 
355  for (i = 0; i < maxlen; ++i)
356  {
357  const char c1 = str1[i];
358  const char c2 = str2[i];
359  if (0 == c2)
360  return 0 == c1;
361  if ( (c1 != c2) &&
362  (toasciilower (c1) != toasciilower (c2)) )
363  return 0;
364  }
365  return !0;
366 }
367 
368 #ifndef MHD_FAVOR_SMALL_CODE
369 /* Use individual function for each case */
370 
381 size_t
382 MHD_str_to_uint64_ (const char *str,
383  uint64_t *out_val)
384 {
385  const char * const start = str;
386  uint64_t res;
387 
388  if (!str || !out_val || !isasciidigit(str[0]))
389  return 0;
390 
391  res = 0;
392  do
393  {
394  const int digit = (unsigned char)(*str) - '0';
395  if ( (res > (UINT64_MAX / 10)) ||
396  ( (res == (UINT64_MAX / 10)) &&
397  ((uint64_t)digit > (UINT64_MAX % 10)) ) )
398  return 0;
399 
400  res *= 10;
401  res += digit;
402  str++;
403  } while (isasciidigit (*str));
404 
405  *out_val = res;
406  return str - start;
407 }
408 
409 
423 size_t
424 MHD_str_to_uint64_n_ (const char * str,
425  size_t maxlen,
426  uint64_t *out_val)
427 {
428  uint64_t res;
429  size_t i;
430 
431  if (!str || !maxlen || !out_val || !isasciidigit (str[0]))
432  return 0;
433 
434  res = 0;
435  i = 0;
436  do
437  {
438  const int digit = (unsigned char)str[i] - '0';
439 
440  if ( (res > (UINT64_MAX / 10)) ||
441  ( (res == (UINT64_MAX / 10)) &&
442  ((uint64_t)digit > (UINT64_MAX % 10)) ) )
443  return 0;
444 
445  res *= 10;
446  res += digit;
447  i++;
448  } while ( (i < maxlen) &&
449  isasciidigit (str[i]) );
450 
451  *out_val= res;
452  return i;
453 }
454 
455 
466 size_t
467 MHD_strx_to_sizet_ (const char *str,
468  size_t *out_val)
469 {
470  const char * const start = str;
471  size_t res;
472  int digit;
473 
474  if (!str || !out_val)
475  return 0;
476 
477  res = 0;
478  digit = toxdigitvalue (*str);
479  while (digit >= 0)
480  {
481  if ( (res < (SIZE_MAX / 16)) ||
482  ( (res == (SIZE_MAX / 16)) &&
483  ((size_t)digit <= (SIZE_MAX % 16)) ) )
484  {
485  res *= 16;
486  res += digit;
487  }
488  else
489  return 0;
490  str++;
491  digit = toxdigitvalue (*str);
492  }
493 
494  if (str - start > 0)
495  *out_val = res;
496  return str - start;
497 }
498 
499 
513 size_t
514 MHD_strx_to_sizet_n_ (const char * str,
515  size_t maxlen,
516  size_t *out_val)
517 {
518  size_t i;
519  size_t res;
520  int digit;
521  if (!str || !out_val)
522  return 0;
523 
524  res = 0;
525  i = 0;
526  while ( (i < maxlen) &&
527  ((digit = toxdigitvalue (str[i])) >= 0) )
528  {
529  if ( (res > (SIZE_MAX / 16)) ||
530  ( (res == (SIZE_MAX / 16)) &&
531  ((size_t)digit > (SIZE_MAX % 16)) ) )
532  return 0;
533 
534  res *= 16;
535  res += digit;
536  i++;
537  }
538 
539  if (i)
540  *out_val = res;
541  return i;
542 }
543 
544 
555 size_t
556 MHD_strx_to_uint32_ (const char * str,
557  uint32_t *out_val)
558 {
559  const char * const start = str;
560  uint32_t res;
561  int digit;
562 
563  if (!str || !out_val)
564  return 0;
565 
566  res = 0;
567  digit = toxdigitvalue (*str);
568  while (digit >= 0)
569  {
570  if ( (res < (UINT32_MAX / 16)) ||
571  (res == (UINT32_MAX / 16) && (uint32_t)digit <= (UINT32_MAX % 16)) )
572  {
573  res *= 16;
574  res += digit;
575  }
576  else
577  return 0;
578  str++;
579  digit = toxdigitvalue (*str);
580  }
581 
582  if (str - start > 0)
583  *out_val = res;
584  return str - start;
585 }
586 
587 
601 size_t
602 MHD_strx_to_uint32_n_ (const char *str,
603  size_t maxlen,
604  uint32_t *out_val)
605 {
606  size_t i;
607  uint32_t res;
608  int digit;
609  if (!str || !out_val)
610  return 0;
611 
612  res = 0;
613  i = 0;
614  while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
615  {
616  if ( (res > (UINT32_MAX / 16)) ||
617  (res == (UINT32_MAX / 16) && (uint32_t)digit > (UINT32_MAX % 16)) )
618  return 0;
619 
620  res *= 16;
621  res += digit;
622  i++;
623  }
624 
625  if (i)
626  *out_val = res;
627  return i;
628 }
629 
630 
641 size_t
642 MHD_strx_to_uint64_ (const char *str,
643  uint64_t *out_val)
644 {
645  const char * const start = str;
646  uint64_t res;
647  int digit;
648  if (!str || !out_val)
649  return 0;
650 
651  res = 0;
652  digit = toxdigitvalue (*str);
653  while (digit >= 0)
654  {
655  if ( (res < (UINT64_MAX / 16)) ||
656  (res == (UINT64_MAX / 16) && (uint64_t)digit <= (UINT64_MAX % 16)) )
657  {
658  res *= 16;
659  res += digit;
660  }
661  else
662  return 0;
663  str++;
664  digit = toxdigitvalue (*str);
665  }
666 
667  if (str - start > 0)
668  *out_val = res;
669  return str - start;
670 }
671 
672 
686 size_t
687 MHD_strx_to_uint64_n_ (const char * str,
688  size_t maxlen,
689  uint64_t *out_val)
690 {
691  size_t i;
692  uint64_t res;
693  int digit;
694  if (!str || !out_val)
695  return 0;
696 
697  res = 0;
698  i = 0;
699  while (i < maxlen && (digit = toxdigitvalue (str[i])) >= 0)
700  {
701  if ( (res > (UINT64_MAX / 16)) ||
702  (res == (UINT64_MAX / 16) && (uint64_t)digit > (UINT64_MAX % 16)) )
703  return 0;
704 
705  res *= 16;
706  res += digit;
707  i++;
708  }
709 
710  if (i)
711  *out_val = res;
712  return i;
713 }
714 
715 #else /* MHD_FAVOR_SMALL_CODE */
716 
734 size_t
735 MHD_str_to_uvalue_n_ (const char *str,
736  size_t maxlen,
737  void * out_val,
738  size_t val_size,
739  uint64_t max_val,
740  int base)
741 {
742  size_t i;
743  uint64_t res;
744  int digit;
745  const uint64_t max_v_div_b = max_val / base;
746  const uint64_t max_v_mod_b = max_val % base;
747  /* 'digit->value' must be function, not macro */
748  int (*const dfunc)(char) = (base == 16) ?
750 
751  if ( !str || !out_val ||
752  (base != 16 && base != 10) )
753  return 0;
754 
755  res = 0;
756  i = 0;
757  while (maxlen > i && 0 <= (digit = dfunc (str[i])))
758  {
759  if ( ((max_v_div_b) < res) ||
760  ((max_v_div_b) == res && (max_v_mod_b) < (uint64_t)digit) )
761  return 0;
762 
763  res *= base;
764  res += digit;
765  i++;
766  }
767 
768  if (i)
769  {
770  if (8 == val_size)
771  *(uint64_t*)out_val = res;
772  else if (4 == val_size)
773  *(uint32_t*)out_val = (uint32_t)res;
774  else
775  return 0;
776  }
777  return i;
778 }
779 #endif /* MHD_FAVOR_SMALL_CODE */
size_t MHD_strx_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:642
#define toasciilower(c)
Definition: mhd_str.c:273
int MHD_str_equal_caseless_n_(const char *const str1, const char *const str2, size_t maxlen)
Definition: mhd_str.c:349
size_t MHD_strx_to_sizet_n_(const char *str, size_t maxlen, size_t *out_val)
Definition: mhd_str.c:514
#define UINT64_MAX
Definition: mhd_limits.h:75
size_t MHD_strx_to_uint32_n_(const char *str, size_t maxlen, uint32_t *out_val)
Definition: mhd_str.c:602
#define isasciixdigit(c)
Definition: mhd_str.c:249
#define toasciiupper(c)
Definition: mhd_str.c:285
#define UINT32_MAX
Definition: mhd_limits.h:67
size_t MHD_strx_to_uint32_(const char *str, uint32_t *out_val)
Definition: mhd_str.c:556
limits values definitions
#define isasciilower(c)
Definition: mhd_str.c:209
#define isasciiupper(c)
Definition: mhd_str.c:219
Header for string manipulating helpers.
#define isasciidigit(c)
Definition: mhd_str.c:239
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:319
#define isasciialpha(c)
Definition: mhd_str.c:229
#define toxdigitvalue(c)
Definition: mhd_str.c:302
size_t MHD_strx_to_sizet_(const char *str, size_t *out_val)
Definition: mhd_str.c:467
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:687
#define isasciialnum(c)
Definition: mhd_str.c:261
#define SIZE_MAX
Definition: mhd_limits.h:83
size_t MHD_str_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:424
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:382
#define todigitvalue(c)
Definition: mhd_str.c:294