summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2016-07-23 18:55:09 +0000
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2016-07-23 18:55:09 +0000
commit43bb6196b0d76d04afca8dd478a47f38352b6e29 (patch)
tree19d5c9f9a016bdb94e96f0503e74a982f56af080
parentabdd48c5f2ca74db2501a4e52245dfc8bd470710 (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.h21
-rw-r--r--src/microhttpd/mhd_str.c103
-rw-r--r--src/microhttpd/mhd_str.h69
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 */