* Add conversion functions to replace the use of snprintf with %a

* remove useless defines
 * minor cleanups

fixes bugs #181 and #182


SVN revision: 31805
This commit is contained in:
doursse 2007-09-25 18:26:49 +00:00 committed by doursse
parent cba48d38b5
commit e769f25d10
7 changed files with 202 additions and 86 deletions

View File

@ -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 <stdio.h>
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

View File

@ -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}

View File

@ -18,9 +18,9 @@
#include <ctype.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#elif __MINGW32__
#include <winsock.h>
# include <netinet/in.h>
#elif _WIN32
# include <winsock2.h>
#endif
#include <zlib.h>
@ -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

View File

@ -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

View File

@ -1,3 +1,5 @@
#include <math.h>
#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;
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);
_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;
}

View File

@ -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);

View File

@ -1,3 +1,6 @@
#include <stdio.h>
#include <math.h>
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);
}