diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2016-07-23 18:55:09 +0000 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2016-07-23 18:55:09 +0000 |
commit | 43bb6196b0d76d04afca8dd478a47f38352b6e29 (patch) | |
tree | 19d5c9f9a016bdb94e96f0503e74a982f56af080 | |
parent | abdd48c5f2ca74db2501a4e52245dfc8bd470710 (diff) |
Added MHD_FAVOR_FAST_CODE and MHD_FAVOR_SMALL_CODE automatic macros.
Macros can be forced by external define.
Added versions of mhd_str functions for smaller resulting code.
-rw-r--r-- | src/include/mhd_options.h | 21 | ||||
-rw-r--r-- | src/microhttpd/mhd_str.c | 103 | ||||
-rw-r--r-- | src/microhttpd/mhd_str.h | 69 |
3 files changed, 189 insertions, 4 deletions
diff --git a/src/include/mhd_options.h b/src/include/mhd_options.h index 3541c4b8..2e798ebf 100644 --- a/src/include/mhd_options.h +++ b/src/include/mhd_options.h @@ -93,4 +93,25 @@ #define __STDC_WANT_LIB_EXT1__ 1 #endif /* HAVE_C11_GMTIME_S */ +#if defined(MHD_FAVOR_FAST_CODE) && defined(MHD_FAVOR_SMALL_CODE) +#error MHD_FAVOR_FAST_CODE and MHD_FAVOR_SMALL_CODE are both defined. Cannot favor speed and size at the same time. +#endif /* MHD_FAVOR_FAST_CODE && MHD_FAVOR_SMALL_CODE */ + +/* Define MHD_FAVOR_FAST_CODE to force fast code path or + define MHD_FAVOR_SMALL_CODE to choose compact code path */ +#if !defined(MHD_FAVOR_FAST_CODE) && !defined(MHD_FAVOR_SMALL_CODE) +/* Try to detect user preferences */ +/* Defined by GCC and many compatible compilers */ +#ifdef __OPTIMIZE_SIZE__ +#define MHD_FAVOR_SMALL_CODE 1 +#elif __OPTIMIZE__ +#define MHD_FAVOR_FAST_CODE 1 +#endif /* __OPTIMIZE__ */ +#endif /* !MHD_FAVOR_FAST_CODE && !MHD_FAVOR_SMALL_CODE */ + +#if !defined(MHD_FAVOR_FAST_CODE) && !defined(MHD_FAVOR_SMALL_CODE) +/* Use faster code by default */ +#define MHD_FAVOR_FAST_CODE 1 +#endif /* !MHD_FAVOR_FAST_CODE && !MHD_FAVOR_SMALL_CODE */ + #endif /* MHD_OPTIONS_H */ diff --git a/src/microhttpd/mhd_str.c b/src/microhttpd/mhd_str.c index c0f1d271..8e6ff92e 100644 --- a/src/microhttpd/mhd_str.c +++ b/src/microhttpd/mhd_str.c @@ -1,6 +1,6 @@ /* This file is part of libmicrohttpd - Copyright (C) 2015 Karlson2k (Evgeny Grin) + Copyright (C) 2015, 2016 Karlson2k (Evgeny Grin) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -25,14 +25,25 @@ #include "mhd_str.h" -#include "mhd_options.h" - #ifdef HAVE_STDBOOL_H #include <stdbool.h> #endif #include "mhd_limits.h" +#ifdef MHD_FAVOR_SMALL_CODE +#ifdef _MHD_inline +#undef _MHD_inline +#endif /* _MHD_inline */ +/* Do not force inlining and do not use macro functions, use normal static + functions instead. + This may give more flexibility for size optimizations. */ +#define _MHD_inline static +#ifndef INLINE_FUNC +#define INLINE_FUNC 1 +#endif /* !INLINE_FUNC */ +#endif /* MHD_FAVOR_SMALL_CODE */ + /* * Block of functions/macros that use US-ASCII charset as required by HTTP * standards. Not affected by current locale settings. @@ -136,6 +147,20 @@ toasciiupper (char c) } /** + * Convert US-ASCII decimal digit to its value. + * @param c character to convert + * @return value of hexadecimal digit or -1 if @ c is not hexadecimal digit + */ +_MHD_inline int +todigitvalue (char c) +{ + if (isasciidigit (c)) + return (unsigned char)(c - '0'); + + return -1; +} + +/** * Convert US-ASCII hexadecimal digit to its value. * @param c character to convert * @return value of hexadecimal digit or -1 if @ c is not hexadecimal digit @@ -225,6 +250,13 @@ toxdigitvalue (char c) #define toasciiupper(c) ((isasciilower(c)) ? (((char)(c)) - 'a' + 'A') : ((char)(c))) /** + * Convert US-ASCII decimal digit to its value. + * @param c character to convert + * @return value of hexadecimal digit or -1 if @ c is not hexadecimal digit + */ +#define todigitvalue(c) (isasciidigit(c) ? (int)(((char)(c)) - '0') : (int)(-1)) + +/** * Convert US-ASCII hexadecimal digit to its value. * @param c character to convert * @return value of hexadecimal digit or -1 if @ c is not hexadecimal digit @@ -236,6 +268,7 @@ toxdigitvalue (char c) (int)(((unsigned char)(c)) - 'a' + 10) : (int)(-1) ))) #endif /* !INLINE_FUNC */ +#ifndef MHD_FAVOR_SMALL_CODE /** * Check two string for equality, ignoring case of US-ASCII letters. * @param str1 first string to compare @@ -256,6 +289,7 @@ MHD_str_equal_caseless_ (const char * str1, const char * str2) } return 0 == (*str2); } +#endif /* ! MHD_FAVOR_SMALL_CODE */ /** @@ -284,6 +318,9 @@ MHD_str_equal_caseless_n_ (const char * const str1, const char * const str2, siz return !0; } +#ifndef MHD_FAVOR_SMALL_CODE +/* Use individual function for each case */ + /** * Convert decimal US-ASCII digits in string to number in uint64_t. * Conversion stopped at first non-digit character. @@ -596,3 +633,63 @@ MHD_strx_to_uint64_n_ (const char * str, size_t maxlen, uint64_t * out_val) *out_val = res; return i; } + +#else /* MHD_FAVOR_SMALL_CODE */ + +/** + * Generic function for converting not more then @a maxlen + * hexadecimal or decimal US-ASCII digits in string to number. + * Conversion stopped at first non-digit character or after @a maxlen + * digits. + * To be used only within macro. + * @param str the string to convert + * @param maxlen the maximum number of characters to process + * @param out_val the pointer to variable to store result of conversion + * @param val_size the size of variable pointed by @a out_val, in bytes, 4 or 8 + * @param max_val the maximum decoded number + * @param base the numeric base, 10 or 16 + * @return non-zero number of characters processed on succeed, + * zero if no digit is found, resulting value is larger + * then @max_val, @val_size is not 16/32 or @a out_val is NULL + */ +size_t +MHD_str_to_uvalue_n_ (const char * str, size_t maxlen, + void * out_val, size_t val_size, uint64_t max_val, int base) +{ + size_t i; + uint64_t res; + int digit; + const uint64_t max_v_div_b = max_val / base; + const uint64_t max_v_mod_b = max_val % base; + /* 'digit->value' must be function, not macro */ + int (*const dfunc)(char) = (base == 16) ? + toxdigitvalue : todigitvalue; + if ( !str || !out_val || + (base != 16 && base != 10) ) + return 0; + + res = 0; + i = 0; + while (maxlen > i && 0 <= (digit = dfunc (str[i]))) + { + if ( ((max_v_div_b) < res) || + ((max_v_div_b) == res && (max_v_mod_b) < (uint64_t)digit) ) + return 0; + + res *= base; + res += digit; + i++; + } + + if (i) + { + if (8 == val_size) + *(uint64_t*)out_val = res; + else if (4 == val_size) + *(uint32_t*)out_val = (uint32_t)res; + else + return 0; + } + return i; +} +#endif /* MHD_FAVOR_SMALL_CODE */ diff --git a/src/microhttpd/mhd_str.h b/src/microhttpd/mhd_str.h index c0649a2f..880970ca 100644 --- a/src/microhttpd/mhd_str.h +++ b/src/microhttpd/mhd_str.h @@ -1,6 +1,6 @@ /* This file is part of libmicrohttpd - Copyright (C) 2015 Karlson2k (Evgeny Grin) + Copyright (C) 2015, 2016 Karlson2k (Evgeny Grin) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -26,14 +26,21 @@ #ifndef MHD_STR_H #define MHD_STR_H 1 +#include "mhd_options.h" + #include <stdint.h> #include <stdlib.h> +#ifdef MHD_FAVOR_SMALL_CODE +#include "mhd_limits.h" +#endif /* MHD_FAVOR_SMALL_CODE */ + /* * Block of functions/macros that use US-ASCII charset as required by HTTP * standards. Not affected by current locale settings. */ +#ifndef MHD_FAVOR_SMALL_CODE /** * Check two string for equality, ignoring case of US-ASCII letters. * @param str1 first string to compare @@ -43,6 +50,10 @@ int MHD_str_equal_caseless_ (const char * str1, const char * str2); +#else /* MHD_FAVOR_SMALL_CODE */ +/* Reuse MHD_str_equal_caseless_n_() to reduce size */ +#define MHD_str_equal_caseless_(s1,s2) MHD_str_equal_caseless_n_((s1),(s2), SIZE_MAX) +#endif /* MHD_FAVOR_SMALL_CODE */ /** @@ -60,6 +71,9 @@ MHD_str_equal_caseless_n_ (const char * const str1, const char * const str2, size_t maxlen); +#ifndef MHD_FAVOR_SMALL_CODE +/* Use individual function for each case to improve speed */ + /** * Convert decimal US-ASCII digits in string to number in uint64_t. * Conversion stopped at first non-digit character. @@ -186,4 +200,57 @@ MHD_strx_to_uint64_n_ (const char * str, size_t maxlen, uint64_t * out_val); +#else /* MHD_FAVOR_SMALL_CODE */ +/* Use one universal function and macros to reduce size */ + +/** + * Generic function for converting not more then @a maxlen + * hexadecimal or decimal US-ASCII digits in string to number. + * Conversion stopped at first non-digit character or after @a maxlen + * digits. + * To be used only within macro. + * @param str the string to convert + * @param maxlen the maximum number of characters to process + * @param out_val the pointer to uint64_t to store result of conversion + * @param val_size the size of variable pointed by @a out_val + * @param max_val the maximum decoded number + * @param base the numeric base, 10 or 16 + * @return non-zero number of characters processed on succeed, + * zero if no digit is found, resulting value is larger + * then @ max_val or @a out_val is NULL + */ +size_t +MHD_str_to_uvalue_n_ (const char * str, + size_t maxlen, + void * out_val, + size_t val_size, + uint64_t max_val, + int base); + +#define MHD_str_to_uint64_(s,ov) MHD_str_to_uvalue_n_((s),SIZE_MAX,(ov),\ + sizeof(uint64_t),UINT64_MAX,10) + +#define MHD_str_to_uint64_n_(s,ml,ov) MHD_str_to_uvalue_n_((s),(ml),(ov),\ + sizeof(uint64_t),UINT64_MAX,10) + +#define MHD_strx_to_sizet_(s,ov) MHD_str_to_uvalue_n_((s),SIZE_MAX,(ov),\ + sizeof(size_t),SIZE_MAX,16) + +#define MHD_strx_to_sizet_n_(s,ml,ov) MHD_str_to_uvalue_n_((s),(ml),(ov),\ + sizeof(size_t),SIZE_MAX,16) + +#define MHD_strx_to_uint32_(s,ov) MHD_str_to_uvalue_n_((s),SIZE_MAX,(ov),\ + sizeof(uint32_t),UINT32_MAX,16) + +#define MHD_strx_to_uint32_n_(s,ml,ov) MHD_str_to_uvalue_n_((s),(ml),(ov),\ + sizeof(uint32_t),UINT32_MAX,16) + +#define MHD_strx_to_uint64_(s,ov) MHD_str_to_uvalue_n_((s),SIZE_MAX,(ov),\ + sizeof(uint64_t),UINT64_MAX,16) + +#define MHD_strx_to_uint64_n_(s,ml,ov) MHD_str_to_uvalue_n_((s),(ml),(ov),\ + sizeof(uint64_t),UINT64_MAX,16) + +#endif /* MHD_FAVOR_SMALL_CODE */ + #endif /* MHD_STR_H */ |