Convert float to ascii using g_fmt and zend_dtoa.

This procudes much smaller textual representations and also ignores
locales.
This commit is contained in:
Teddy Grenman
2011-05-03 01:33:15 +03:00
parent 37e46ecd52
commit df20b8a3c8
4 changed files with 162 additions and 21 deletions

View File

@@ -242,7 +242,7 @@ if test "$PHP_MEMCACHED" != "no"; then
PHP_SUBST(MEMCACHED_SHARED_LIBADD)
PHP_MEMCACHED_FILES="php_memcached.c fastlz/fastlz.c"
PHP_MEMCACHED_FILES="php_memcached.c fastlz/fastlz.c g_fmt.c"
if test "$PHP_MEMCACHED_SESSION" != "no"; then
PHP_MEMCACHED_FILES="${PHP_MEMCACHED_FILES} php_memcached_session.c"

99
g_fmt.c Normal file
View File

@@ -0,0 +1,99 @@
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991, 1996 by Lucent Technologies.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
/* g_fmt(buf,x) stores the closest decimal approximation to x in buf;
* it suffices to declare buf
* char buf[32];
*/
/* Modified for use with php in the memcached client extension.
*
* // Teddy Grenman <teddy.grenman@iki.fi>, 2010-05-18.
*/
#include <zend_operators.h>
char *php_memcached_g_fmt(register char *b, double x) {
register int i, k;
register char *s;
int decpt, j, sign;
char *b0, *s0, *se;
b0 = b;
#ifdef IGNORE_ZERO_SIGN
if (!x) {
*b++ = '0';
*b = 0;
goto done;
}
#endif
s = s0 = zend_dtoa(x, 0, 0, &decpt, &sign, &se);
if (sign)
*b++ = '-';
if (decpt == 9999) /* Infinity or Nan */ {
while(*b++ = *s++);
goto done0;
}
if (decpt <= -4 || decpt > se - s + 5) {
*b++ = *s++;
if (*s) {
*b++ = '.';
while(*b = *s++)
b++;
}
*b++ = 'e';
/* sprintf(b, "%+.2d", decpt - 1); */
if (--decpt < 0) {
*b++ = '-';
decpt = -decpt;
}
else
*b++ = '+';
for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10);
for(;;) {
i = decpt / k;
*b++ = i + '0';
if (--j <= 0)
break;
decpt -= i*k;
decpt *= 10;
}
*b = 0;
} else if (decpt <= 0) {
*b++ = '.';
for(; decpt < 0; decpt++)
*b++ = '0';
while(*b++ = *s++);
} else {
while(*b = *s++) {
b++;
if (--decpt == 0 && *s)
*b++ = '.';
}
for(; decpt > 0; decpt--)
*b++ = '0';
*b = 0;
}
done0:
zend_freedtoa(s0);
done:
return b0;
}

34
g_fmt.h Normal file
View File

@@ -0,0 +1,34 @@
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991, 1996 by Lucent Technologies.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
/* g_fmt(buf,x) stores the closest decimal approximation to x in buf;
* it suffices to declare buf
* char buf[32];
*/
/* Modified for use with php in the memcached client
* extension by Teddy Grenman, 2010.
*/
#ifndef MEMC_G_FMT_H
#define MEMC_G_FMT_H
char *php_memcached_g_fmt(register char *b, double x);
#endif

View File

@@ -42,9 +42,11 @@
#include <zend_exceptions.h>
#include <ext/standard/php_smart_str.h>
#include <ext/standard/php_var.h>
#include <ext/standard/basic_functions.h>
#include <libmemcached/memcached.h>
#include "php_memcached.h"
#include "g_fmt.h"
#ifdef HAVE_MEMCACHED_SESSION
# include "php_memcached_session.h"
@@ -2480,28 +2482,29 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t
break;
case IS_LONG:
smart_str_append_long(&buf, Z_LVAL_P(value));
MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG);
break;
case IS_DOUBLE:
case IS_BOOL:
{
zval value_copy;
char dstr[40] = {0};
value_copy = *value;
zval_copy_ctor(&value_copy);
convert_to_string(&value_copy);
smart_str_appendl(&buf, Z_STRVAL(value_copy), Z_STRLEN(value_copy));
zval_dtor(&value_copy);
*flags &= ~MEMC_VAL_COMPRESSED;
if (Z_TYPE_P(value) == IS_LONG) {
MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_LONG);
} else if (Z_TYPE_P(value) == IS_DOUBLE) {
MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE);
} else if (Z_TYPE_P(value) == IS_BOOL) {
MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL);
}
php_memcached_g_fmt(dstr, Z_DVAL_P(value));
smart_str_appends(&buf, dstr);
MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE);
break;
}
case IS_BOOL:
if (Z_BVAL_P(value)) {
smart_str_appendc(&buf, '1');
} else {
smart_str_appendl(&buf, "", 0);
}
MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_BOOL);
break;
default:
switch (serializer) {
#ifdef HAVE_MEMCACHED_IGBINARY
@@ -2690,11 +2693,16 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload
}
case MEMC_VAL_IS_DOUBLE:
{
double dval = zend_strtod(payload, NULL);
ZVAL_DOUBLE(value, dval);
if (payload_len == 8 && memcmp(payload, "Infinity", 8) == 0) {
ZVAL_DOUBLE(value, php_get_inf());
} else if (payload_len == 9 && memcmp(payload, "-Infinity", 9) == 0) {
ZVAL_DOUBLE(value, -php_get_inf());
} else if (payload_len == 3 && memcmp(payload, "NaN", 3) == 0) {
ZVAL_DOUBLE(value, php_get_nan());
} else {
ZVAL_DOUBLE(value, zend_strtod(payload, NULL));
}
break;
}
case MEMC_VAL_IS_BOOL:
ZVAL_BOOL(value, payload_len > 0 && payload[0] == '1');