Browse files

Convert float to ascii using g_fmt and zend_dtoa.

This procudes much smaller textual representations and also ignores
locales.
  • Loading branch information...
1 parent 37e46ec commit df20b8a3c8ea1a565657764020b50a6d9bc7805c @tricky tricky committed May 2, 2011
Showing with 161 additions and 20 deletions.
  1. +1 −1 config.m4
  2. +99 −0 g_fmt.c
  3. +34 −0 g_fmt.h
  4. +27 −19 php_memcached.c
View
2 config.m4
@@ -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"
View
99 g_fmt.c
@@ -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;
+}
View
34 g_fmt.h
@@ -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
46 php_memcached.c
@@ -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,27 +2482,28 @@ 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);
+ php_memcached_g_fmt(dstr, Z_DVAL_P(value));
+ smart_str_appends(&buf, dstr);
+ MEMC_VAL_SET_TYPE(*flags, MEMC_VAL_IS_DOUBLE);
+ break;
+ }
- *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);
+ 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) {
@@ -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');

0 comments on commit df20b8a

Please sign in to comment.