1111#ifdef HAVE_REDIS_IGBINARY
1212#include "igbinary/igbinary.h"
1313#endif
14+ #ifdef HAVE_REDIS_LZF
15+ #include <lzf.h>
16+ #endif
1417#include <zend_exceptions.h>
1518#include "php_redis.h"
1619#include "library.h"
@@ -602,7 +605,7 @@ redis_spprintf(RedisSock *redis_sock, short *slot TSRMLS_DC, char **ret, char *k
602605 break ;
603606 case 'v' :
604607 arg .zv = va_arg (ap , zval * );
605- argfree = redis_serialize (redis_sock , arg .zv , & dup , & arglen TSRMLS_CC );
608+ argfree = redis_pack (redis_sock , arg .zv , & dup , & arglen TSRMLS_CC );
606609 redis_cmd_append_sstr (& cmd , dup , arglen );
607610 if (argfree ) efree (dup );
608611 break ;
@@ -710,7 +713,7 @@ int redis_cmd_append_sstr_zval(smart_string *str, zval *z, RedisSock *redis_sock
710713 strlen_t vallen ;
711714 int valfree , retval ;
712715
713- valfree = redis_serialize (redis_sock , z , & val , & vallen TSRMLS_CC );
716+ valfree = redis_pack (redis_sock , z , & val , & vallen TSRMLS_CC );
714717 retval = redis_cmd_append_sstr (str , val , vallen );
715718 if (valfree ) efree (val );
716719
@@ -1248,7 +1251,7 @@ PHP_REDIS_API void redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock
12481251 }
12491252 IF_NOT_ATOMIC () {
12501253 zval zv , * z = & zv ;
1251- if (redis_unserialize (redis_sock , response , response_len , z TSRMLS_CC )) {
1254+ if (redis_unpack (redis_sock , response , response_len , z TSRMLS_CC )) {
12521255#if (PHP_MAJOR_VERSION < 7 )
12531256 MAKE_STD_ZVAL (z );
12541257 * z = zv ;
@@ -1258,7 +1261,7 @@ PHP_REDIS_API void redis_string_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock
12581261 add_next_index_stringl (z_tab , response , response_len );
12591262 }
12601263 } else {
1261- if (!redis_unserialize (redis_sock , response , response_len , return_value TSRMLS_CC )) {
1264+ if (!redis_unpack (redis_sock , response , response_len , return_value TSRMLS_CC )) {
12621265 RETVAL_STRINGL (response , response_len );
12631266 }
12641267 }
@@ -1386,6 +1389,7 @@ redis_sock_create(char *host, int host_len, unsigned short port,
13861389 redis_sock -> read_timeout = read_timeout ;
13871390
13881391 redis_sock -> serializer = REDIS_SERIALIZER_NONE ;
1392+ redis_sock -> compression = REDIS_COMPRESSION_NONE ;
13891393 redis_sock -> mode = ATOMIC ;
13901394 redis_sock -> head = NULL ;
13911395 redis_sock -> current = NULL ;
@@ -1661,7 +1665,7 @@ redis_mbulk_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
16611665 (unserialize == UNSERIALIZE_VALS && i % 2 != 0 )
16621666 );
16631667 zval zv , * z = & zv ;
1664- if (unwrap && redis_unserialize (redis_sock , line , len , z TSRMLS_CC )) {
1668+ if (unwrap && redis_unpack (redis_sock , line , len , z TSRMLS_CC )) {
16651669#if (PHP_MAJOR_VERSION < 7 )
16661670 MAKE_STD_ZVAL (z );
16671671 * z = zv ;
@@ -1709,7 +1713,7 @@ PHP_REDIS_API int redis_mbulk_reply_assoc(INTERNAL_FUNCTION_PARAMETERS, RedisSoc
17091713 response = redis_sock_read (redis_sock , & response_len TSRMLS_CC );
17101714 if (response != NULL ) {
17111715 zval zv0 , * z = & zv0 ;
1712- if (redis_unserialize (redis_sock , response , response_len , z TSRMLS_CC )) {
1716+ if (redis_unpack (redis_sock , response , response_len , z TSRMLS_CC )) {
17131717#if (PHP_MAJOR_VERSION < 7 )
17141718 MAKE_STD_ZVAL (z );
17151719 * z = zv0 ;
@@ -1778,6 +1782,66 @@ PHP_REDIS_API void redis_free_socket(RedisSock *redis_sock)
17781782 efree (redis_sock );
17791783}
17801784
1785+ PHP_REDIS_API int
1786+ redis_pack (RedisSock * redis_sock , zval * z , char * * val , strlen_t * val_len TSRMLS_DC )
1787+ {
1788+ char * buf , * data ;
1789+ int valfree ;
1790+ strlen_t len ;
1791+ uint32_t res ;
1792+
1793+ valfree = redis_serialize (redis_sock , z , & buf , & len TSRMLS_CC );
1794+ switch (redis_sock -> compression ) {
1795+ case REDIS_COMPRESSION_LZF :
1796+ #ifdef HAVE_REDIS_LZF
1797+ data = emalloc (len );
1798+ res = lzf_compress (buf , len , data , len - 1 );
1799+ if (res > 0 && res < len ) {
1800+ if (valfree ) efree (buf );
1801+ * val = data ;
1802+ * val_len = res ;
1803+ return 1 ;
1804+ }
1805+ efree (data );
1806+ #endif
1807+ break ;
1808+ }
1809+ * val = buf ;
1810+ * val_len = len ;
1811+ return valfree ;
1812+ }
1813+
1814+ PHP_REDIS_API int
1815+ redis_unpack (RedisSock * redis_sock , const char * val , int val_len , zval * z_ret TSRMLS_DC )
1816+ {
1817+ char * data ;
1818+ int i , ret ;
1819+ uint32_t res ;
1820+
1821+ switch (redis_sock -> compression ) {
1822+ case REDIS_COMPRESSION_LZF :
1823+ #ifdef HAVE_REDIS_LZF
1824+ errno = E2BIG ;
1825+ /* start from two-times bigger buffer and
1826+ * increase it exponentially if needed */
1827+ for (i = 2 ; errno == E2BIG ; i *= 2 ) {
1828+ data = emalloc (i * val_len );
1829+ if ((res = lzf_decompress (val , val_len , data , i * val_len )) == 0 ) {
1830+ /* errno != E2BIG will brake for loop */
1831+ efree (data );
1832+ continue ;
1833+ } else if (redis_unserialize (redis_sock , data , res , z_ret TSRMLS_CC ) == 0 ) {
1834+ ZVAL_STRINGL (z_ret , data , res );
1835+ }
1836+ efree (data );
1837+ return 1 ;
1838+ }
1839+ #endif
1840+ break ;
1841+ }
1842+ return redis_unserialize (redis_sock , val , val_len , z_ret TSRMLS_CC );
1843+ }
1844+
17811845PHP_REDIS_API int
17821846redis_serialize (RedisSock * redis_sock , zval * z , char * * val , strlen_t * val_len
17831847 TSRMLS_DC )
0 commit comments