From 3e7bfc7d35e18fcfe6ab0da538efaa622b2ef402 Mon Sep 17 00:00:00 2001 From: doursse Date: Tue, 25 Sep 2007 18:26:49 +0000 Subject: [PATCH] * Add conversion functions to replace the use of snprintf with %a * remove useless defines * minor cleanups fixes bugs #181 and #182 git-svn-id: http://svn.enlightenment.org/svn/e/trunk/e17/libs/eet@31805 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- configure.in | 29 +-------- eet.pc.in | 2 +- src/lib/Eet_private.h | 8 ++- src/lib/Makefile.am | 5 +- src/lib/eet_data.c | 60 ++++++++---------- src/lib/eet_lib.c | 22 +------ src/lib/eet_utils.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 203 insertions(+), 87 deletions(-) diff --git a/configure.in b/configure.in index 2aa0e61..e5684b5 100644 --- a/configure.in +++ b/configure.in @@ -72,28 +72,6 @@ int main (int argc, char **argv) { ], AC_MSG_WARN([Cannot check when cross-compiling -- assuming null is okay]) ) -AC_MSG_CHECKING([OS libc C99 '%a' support]) -AC_TRY_RUN([ -#include -int main(int argc, char **argv) { - char buf[4096]; - float ival = 0.1234, oval = 0.0; - snprintf(buf, sizeof(buf), "%a", (double)ival); - sscanf(buf, "%a", &oval); - if (ival != oval) return -1; - return 0; -} -], AC_MSG_RESULT([yes]), [ - AC_MSG_RESULT([no]) - AC_MSG_ERROR([Unsupported Operating System! -Your OS does not support C99's '%a' string format. Eet cannot function without -it. Please contact your OS vendor to get updates for C99 '%a' floating point -format read/write support or change operating systems for one with support -for an already very old standard. (Linux is known to support this, as is -Solaris 10)]) -], AC_MSG_WARN([Cannot check when cross-compiling -- assuming C99 '%a' support is OK]) -) - if test "x${bindir}" = 'xNONE'; then if test "x${prefix}" = "xNONE"; then PACKAGE_BIN_DIR="${ac_default_prefix}/bin" @@ -115,7 +93,7 @@ else PACKAGE_LIB_DIR="${libdir}" fi AC_SUBST(PACKAGE_LIB_DIR) - + if test "x${prefix}" = "xNONE"; then PACKAGE_DATA_DIR="${ac_default_prefix}/share/${PACKAGE}" else @@ -156,9 +134,6 @@ echo " Compilation..........: make" echo echo " Installation.........: make install" echo -echo " prefix.........: $prefix" -echo " binaries.......: $bindir" -echo " libraries......: $libdir" -echo " headers........: $includedir" +echo " prefix.............: $prefix" #echo " documentation..: $datadir/$PACKAGE/doc" echo diff --git a/eet.pc.in b/eet.pc.in index 2c10601..9d2f37c 100644 --- a/eet.pc.in +++ b/eet.pc.in @@ -7,5 +7,5 @@ Name: eet Description: Library for speedy data storage, retrieval, and compression Version: @VERSION@ Libs: -L${libdir} -leet -Libs.private: -lz -ljpeg +Libs.private: -lz -ljpeg @fnmatch_libs@ @winsock_libs@ -lm Cflags: -I${includedir} diff --git a/src/lib/Eet_private.h b/src/lib/Eet_private.h index e73f290..0d53d87 100644 --- a/src/lib/Eet_private.h +++ b/src/lib/Eet_private.h @@ -18,9 +18,9 @@ #include #ifdef HAVE_NETINET_IN_H -#include -#elif __MINGW32__ -#include +# include +#elif _WIN32 +# include #endif #include @@ -43,6 +43,8 @@ FILE *_eet_memfile_write_open(void **data, size_t *size); void _eet_memfile_write_close(FILE *f); void _eet_memfile_shutdown(void); int _eet_hash_gen(const char *key, int hash_size); +int _eet_string_to_double_convert(const char *src, long long *m, long *e); +void _eet_double_to_string_convert(char *des, double d); #ifndef PATH_MAX #define PATH_MAX 4096 diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index c17c496..8792672 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -6,8 +6,7 @@ AUTOMAKE_OPTIONS = 1.4 foreign MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I. \ - -I$(top_srcdir)/src/lib \ - -I$(top_srcdir)/src/lib/include + -I$(top_srcdir)/src/lib lib_LTLIBRARIES = libeet.la include_HEADERS = Eet.h @@ -19,6 +18,6 @@ eet_memfile.c \ eet_utils.c \ Eet_private.h -libeet_la_LIBADD = -lz -ljpeg @fnmatch_libs@ @winsock_libs@ +libeet_la_LIBADD = -lz -ljpeg @fnmatch_libs@ @winsock_libs@ -lm libeet_la_DEPENDENCIES = $(top_builddir)/config.h libeet_la_LDFLAGS = @create_shared_lib@ -version-info 9:10:9 diff --git a/src/lib/eet_data.c b/src/lib/eet_data.c index 72f688b..4f8b884 100644 --- a/src/lib/eet_data.c +++ b/src/lib/eet_data.c @@ -1,3 +1,5 @@ +#include + #include "Eet.h" #include "Eet_private.h" @@ -358,8 +360,9 @@ static int eet_data_get_float(void *src, void *src_end, void *dst) { float *d; - float tf; - char *s, *str, *p, *prev_locale; + long long mantisse; + long exponent; + char *s, *str, *p; int len; s = (char *)src; @@ -369,14 +372,10 @@ eet_data_get_float(void *src, void *src_end, void *dst) while ((p < (char *)src_end) && (*p != 0)) {len++; p++;} str = alloca(len + 1); memcpy(str, s, len); - str[len] = 0; - - prev_locale = setlocale(LC_NUMERIC, "C"); -/* solaris atof is broken and doesnt understand %a format as a float */ -/* *d = (float)atof(str); */ - sscanf(str, "%a", &tf); - *d = (float)tf; - if (prev_locale) setlocale(LC_NUMERIC, prev_locale); + str[len] = '\0'; + + _eet_string_to_double_convert(str, &mantisse, &exponent); + *d = (float)ldexp((double)mantisse, exponent); return len + 1; } @@ -384,19 +383,17 @@ eet_data_get_float(void *src, void *src_end, void *dst) static void * eet_data_put_float(const void *src, int *size_ret) { - float *s; - char *d, buf[64], *prev_locale; - int len; + char buf[64]; + char *d; + int len; - s = (float *)src; - prev_locale = setlocale(LC_NUMERIC, "C"); - snprintf(buf, sizeof(buf), "%a", (double)(*s)); - if (prev_locale) setlocale(LC_NUMERIC, prev_locale); + _eet_double_to_string_convert(buf, (double)(*(float *)src)); len = strlen(buf); d = malloc(len + 1); if (!d) return NULL; strcpy(d, buf); *size_ret = len + 1; + return d; } @@ -404,9 +401,10 @@ eet_data_put_float(const void *src, int *size_ret) static int eet_data_get_double(void *src, void *src_end, void *dst) { - double *d; - float tf; - char *s, *str, *p, *prev_locale; + double *d; + long long mantisse; + long exponent; + char *s, *str, *p; int len; s = (char *)src; @@ -416,14 +414,10 @@ eet_data_get_double(void *src, void *src_end, void *dst) while ((p < (char *)src_end) && (*p != 0)) {len++; p++;} str = alloca(len + 1); memcpy(str, s, len); - str[len] = 0; + str[len] = '\0'; - prev_locale = setlocale(LC_NUMERIC, "C"); -/* solaris atof is broken and doesnt understand %a format as a float */ -/* *d = (double)atof(str); */ - sscanf(str, "%a", &tf); - *d = (double)tf; - if (prev_locale) setlocale(LC_NUMERIC, prev_locale); + _eet_string_to_double_convert(str, &mantisse, &exponent); + *d = ldexp((double)mantisse, exponent); return len + 1; } @@ -431,19 +425,17 @@ eet_data_get_double(void *src, void *src_end, void *dst) static void * eet_data_put_double(const void *src, int *size_ret) { - double *s; - char *d, buf[128], *prev_locale; - int len; + char buf[128]; + char *d; + int len; - s = (double *)src; - prev_locale = setlocale(LC_NUMERIC, "C"); - snprintf(buf, sizeof(buf), "%a", (double)(*s)); - if (prev_locale) setlocale(LC_NUMERIC, prev_locale); + _eet_double_to_string_convert(buf, (double)(*(double *)src)); len = strlen(buf); d = malloc(len + 1); if (!d) return NULL; strcpy(d, buf); *size_ret = len + 1; + return d; } diff --git a/src/lib/eet_lib.c b/src/lib/eet_lib.c index e74aca5..4a36836 100644 --- a/src/lib/eet_lib.c +++ b/src/lib/eet_lib.c @@ -14,22 +14,6 @@ #undef HAVE_REALPATH #endif -#ifdef _WIN32 - -#ifndef F_SETFD -#define F_SETFD 2 -#endif - -#ifndef PROT_READ -#define PROT_READ 1 -#endif - -#ifndef FD_CLOEXEC -#define FD_CLOEXEC 1 -#endif - -#endif - #define EET_MAGIC_FILE 0x1ee7ff00 #define EET_MAGIC_FILE_HEADER 0x1ee7ff01 @@ -711,10 +695,10 @@ eet_open(const char *file, Eet_File_Mode mode) } /* This code is useless if we dont want backward compatibility */ - for (k = name_size; k > 0 && ((uint8_t) * (p + HEADER_SIZE + k)) != 0; --k) + for (k = name_size; k > 0 && ((unsigned char) * (p + HEADER_SIZE + k)) != 0; --k) ; - efn->free_name = ((uint8_t) * (p + HEADER_SIZE + k)) != 0; + efn->free_name = ((unsigned char) * (p + HEADER_SIZE + k)) != 0; if (efn->free_name) { @@ -732,7 +716,7 @@ eet_open(const char *file, Eet_File_Mode mode) } else /* The only really usefull peace of code for efn->name (no backward compatibility) */ - efn->name = (char*)((uint8_t*)(p + HEADER_SIZE)); + efn->name = (char*)((unsigned char *)(p + HEADER_SIZE)); /* get hash bucket it should go in */ hash = _eet_hash_gen(efn->name, ef->header->directory->size); diff --git a/src/lib/eet_utils.c b/src/lib/eet_utils.c index 898d87f..d4bac8a 100644 --- a/src/lib/eet_utils.c +++ b/src/lib/eet_utils.c @@ -1,3 +1,6 @@ +#include +#include + int _eet_hash_gen(const char *key, int hash_size) { @@ -33,3 +36,164 @@ _eet_hash_gen(const char *key, int hash_size) return hash_num; } +/* On Windows (using MinGW or VC++), printf-like functions */ +/* rely on MSVCRT, which does not fully support the C99 */ +/* specifications. In particular, they do not support the */ +/* modifier character %a. */ + + +/* That function converts a string created by a valid %a */ +/* modifier to a double. */ +/* */ +/* The string must have the following format: */ +/* */ +/* [-]0xh.hhhhhp[+-]e */ +/* */ +/* where e is a decimal number. */ +/* If n is the number of cyphers after the point, the */ +/* returned mantisse and exponents are */ +/* */ +/* mantisse: [-]hhhhhh */ +/* exponent: 2^([+-]e - 4 * n) */ +int +_eet_string_to_double_convert(const char *src, long long *m, long *e) +{ + const char *str; + double val; + long long mantisse; + long exponent; + int nbr_decimals; + char sign; + + str = src; + sign = +1; + + if (*str == '-') + { + sign = -1; + str++; + } + else if (*str == '0') + { + str++; + if (*str == 'x') + str++; + else + { + fprintf(stderr, "[Eet] Error during conversion\n"); + return 0; + } + } + else + { + fprintf(stderr, "[Eet] Error during conversion\n"); + return 0; + } + + nbr_decimals = 0; + mantisse = (*str >= 'a') ? *str - 'a' + 10 : *str - '0'; + str++; + if (*str == '.') + { + str++; + while (*str != 'p') + { + mantisse <<= 4; + mantisse += (*str >= 'a') ? *str - 'a' + 10 : *str - '0'; + str++; + nbr_decimals++; + } + } + if (sign < 0) + mantisse = -mantisse; + if (*str != 'p') + { + fprintf(stderr, "[Eet] Error during conversion\n"); + return 0; + } + sign = +1; + str++; + if (*str == '-') + { + sign = -1; + str++; + } + else if (*str == '+') str++; + + exponent = 0; + while (*str != '\0') + { + exponent *= 10; + exponent += *str - '0'; + str++; + } + + if (sign < 0) + exponent = -exponent; + + *m = mantisse; + *e = exponent - (nbr_decimals << 2); + + return 1; +} + +/* That function converts a double to a string that as the */ +/* following format: */ +/* */ +/* [-]0xh.hhhhhp[+-]e */ +/* */ +/* where h is a hexadecimal number and e a decimal number. */ +void +_eet_double_to_string_convert(char *des, double d) +{ + static const char look_up_table[] = {'0', '1', '2', '3', '4', + '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f'}; + int p; + int i; + + char *str = des; + + if (d < 0.0) + { + *(des++) = '-'; + d = -d; + } + + d = frexp(d, &p); + + if (p) + { + d *= 2; + p -= 1; + } + + *(des++) = '0'; + *(des++) = 'x'; + *(des++) = look_up_table[(size_t)d]; + *(des++) = '.'; + + for (i = 0; i < 16; i++) + { + d -= floor(d); + d *= 16; + *(des++) = look_up_table[(size_t)d]; + } + + while (*(des - 1) == '0') + des--; + + if (*(des - 1) == '.') + des--; + + *(des++) = 'p'; + if (p < 0) + { + *(des++) = '-'; + p = -p; + } + else + *(des++) = '+'; + + sprintf(des, "%d", p); +} -- 2.7.4