48
48
#ifdef HAVE_MEMCACHED_IGBINARY
49
49
#include "ext/igbinary/igbinary.h"
50
50
#endif
51
+ #ifdef HAVE_MEMCACHED_IGBINARY
52
+ #include "ext/json/php_json.h"
53
+ #endif
51
54
52
55
/****************************************
53
56
Custom options
64
67
/****************************************
65
68
Payload value flags
66
69
****************************************/
67
- #define MEMC_VAL_SERIALIZED (1<<0)
68
- #define MEMC_VAL_COMPRESSED (1<<1)
69
- #define MEMC_VAL_IS_LONG (1<<2)
70
- #define MEMC_VAL_IS_DOUBLE (1<<3)
71
- #define MEMC_VAL_IGBINARY (1<<4)
72
- #define MEMC_VAL_IS_BOOL (1<<5)
70
+ #define MEMC_VAL_TYPE_MASK 0xf
71
+ #define MEMC_VAL_GET_TYPE (flags ) ((flags) & MEMC_VAL_TYPE_MASK)
72
+ #define MEMC_VAL_SET_TYPE (flags , type ) ((flags) |= ((type) & MEMC_VAL_TYPE_MASK))
73
+
74
+ #define MEMC_VAL_IS_STRING 0
75
+ #define MEMC_VAL_IS_LONG 1
76
+ #define MEMC_VAL_IS_DOUBLE 2
77
+ #define MEMC_VAL_IS_BOOL 3
78
+ #define MEMC_VAL_IS_SERIALIZED 4
79
+ #define MEMC_VAL_IS_IGBINARY 5
80
+ #define MEMC_VAL_IS_JSON 6
81
+
82
+ #define MEMC_VAL_COMPRESSED (1<<4)
73
83
74
84
/****************************************
75
85
"get" operation flags
117
127
enum memcached_serializer {
118
128
SERIALIZER_PHP = 1 ,
119
129
SERIALIZER_IGBINARY = 2 ,
130
+ SERIALIZER_JSON = 3 ,
120
131
};
121
132
122
133
static int le_memc ;
@@ -167,7 +178,7 @@ ZEND_GET_MODULE(memcached)
167
178
****************************************/
168
179
static int php_memc_list_entry (void );
169
180
static int php_memc_handle_error (memcached_return status TSRMLS_DC );
170
- static char * php_memc_zval_to_payload (zval * value , size_t * payload_len , uint32_t * flags TSRMLS_DC );
181
+ static char * php_memc_zval_to_payload (zval * value , size_t * payload_len , uint32_t * flags , enum memcached_serializer serializer TSRMLS_DC );
171
182
static int php_memc_zval_from_payload (zval * value , char * payload , size_t payload_len , uint32_t flags TSRMLS_DC );
172
183
static void php_memc_get_impl (INTERNAL_FUNCTION_PARAMETERS , zend_bool by_key );
173
184
static void php_memc_getMulti_impl (INTERNAL_FUNCTION_PARAMETERS , zend_bool by_key );
@@ -945,7 +956,7 @@ static void php_memc_setMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_ke
945
956
flags |= MEMC_VAL_COMPRESSED ;
946
957
}
947
958
948
- payload = php_memc_zval_to_payload (* entry , & payload_len , & flags TSRMLS_CC );
959
+ payload = php_memc_zval_to_payload (* entry , & payload_len , & flags , i_obj -> serializer TSRMLS_CC );
949
960
if (payload == NULL ) {
950
961
MEMC_G (rescode ) = MEMC_RES_PAYLOAD_FAILURE ;
951
962
RETURN_FALSE ;
@@ -1102,11 +1113,7 @@ static void php_memc_store_impl(INTERNAL_FUNCTION_PARAMETERS, int op, zend_bool
1102
1113
flags |= MEMC_VAL_COMPRESSED ;
1103
1114
}
1104
1115
1105
- if (i_obj -> serializer == SERIALIZER_IGBINARY ) {
1106
- flags |= MEMC_VAL_IGBINARY ;
1107
- }
1108
-
1109
- payload = php_memc_zval_to_payload (value , & payload_len , & flags TSRMLS_CC );
1116
+ payload = php_memc_zval_to_payload (value , & payload_len , & flags , i_obj -> serializer TSRMLS_CC );
1110
1117
if (op == MEMC_OP_APPEND || op == MEMC_OP_PREPEND ) {
1111
1118
zval_ptr_dtor (& value );
1112
1119
}
@@ -1217,11 +1224,7 @@ static void php_memc_cas_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
1217
1224
flags |= MEMC_VAL_COMPRESSED ;
1218
1225
}
1219
1226
1220
- if (i_obj -> serializer == SERIALIZER_IGBINARY ) {
1221
- flags |= MEMC_VAL_IGBINARY ;
1222
- }
1223
-
1224
- payload = php_memc_zval_to_payload (value , & payload_len , & flags TSRMLS_CC );
1227
+ payload = php_memc_zval_to_payload (value , & payload_len , & flags , i_obj -> serializer TSRMLS_CC );
1225
1228
if (payload == NULL ) {
1226
1229
MEMC_G (rescode ) = MEMC_RES_PAYLOAD_FAILURE ;
1227
1230
RETURN_FALSE ;
@@ -1791,6 +1794,12 @@ static PHP_METHOD(Memcached, setOption)
1791
1794
i_obj -> serializer = SERIALIZER_IGBINARY ;
1792
1795
} else
1793
1796
#endif
1797
+ #if HAVE_JSON_API
1798
+ if (Z_LVAL_P (value ) == SERIALIZER_JSON ) {
1799
+ i_obj -> serializer = SERIALIZER_JSON ;
1800
+ } else
1801
+ #endif
1802
+
1794
1803
/* php serializer */
1795
1804
if (Z_LVAL_P (value ) == SERIALIZER_PHP ) {
1796
1805
i_obj -> serializer = SERIALIZER_PHP ;
@@ -1912,7 +1921,7 @@ static int php_memc_handle_error(memcached_return status TSRMLS_DC)
1912
1921
return result ;
1913
1922
}
1914
1923
1915
- static char * php_memc_zval_to_payload (zval * value , size_t * payload_len , uint32_t * flags TSRMLS_DC )
1924
+ static char * php_memc_zval_to_payload (zval * value , size_t * payload_len , uint32_t * flags , enum memcached_serializer serializer TSRMLS_DC )
1916
1925
{
1917
1926
char * payload ;
1918
1927
smart_str buf = {0 };
@@ -1921,7 +1930,7 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t
1921
1930
1922
1931
case IS_STRING :
1923
1932
smart_str_appendl (& buf , Z_STRVAL_P (value ), Z_STRLEN_P (value ));
1924
- * flags &= ~ MEMC_VAL_IGBINARY ;
1933
+ MEMC_VAL_SET_TYPE ( * flags , MEMC_VAL_IS_STRING ) ;
1925
1934
break ;
1926
1935
1927
1936
case IS_LONG :
@@ -1937,42 +1946,53 @@ static char *php_memc_zval_to_payload(zval *value, size_t *payload_len, uint32_t
1937
1946
zval_dtor (& value_copy );
1938
1947
1939
1948
* flags &= ~MEMC_VAL_COMPRESSED ;
1940
- * flags &= ~MEMC_VAL_IGBINARY ;
1941
1949
if (Z_TYPE_P (value ) == IS_LONG ) {
1942
- * flags |= MEMC_VAL_IS_LONG ;
1950
+ MEMC_VAL_SET_TYPE ( * flags , MEMC_VAL_IS_LONG ) ;
1943
1951
} else if (Z_TYPE_P (value ) == IS_DOUBLE ) {
1944
- * flags |= MEMC_VAL_IS_DOUBLE ;
1952
+ MEMC_VAL_SET_TYPE ( * flags , MEMC_VAL_IS_DOUBLE ) ;
1945
1953
} else if (Z_TYPE_P (value ) == IS_BOOL ) {
1946
- * flags |= MEMC_VAL_IS_BOOL ;
1954
+ MEMC_VAL_SET_TYPE ( * flags , MEMC_VAL_IS_BOOL ) ;
1947
1955
}
1948
1956
break ;
1949
1957
}
1950
1958
1951
1959
default :
1952
- {
1960
+ switch ( serializer ) {
1953
1961
#if HAVE_MEMCACHED_IGBINARY
1954
- if (* flags & MEMC_VAL_IGBINARY ) {
1955
- igbinary_serialize ((uint8_t * * ) & buf .c , & buf .len , value );
1962
+ case SERIALIZER_IGBINARY :
1963
+ igbinary_serialize ((uint8_t * * ) & buf .c , & buf .len , value );
1964
+ MEMC_VAL_SET_TYPE (* flags , MEMC_VAL_IS_IGBINARY );
1965
+ break ;
1966
+ #endif
1956
1967
1957
- } else {
1968
+ #if HAVE_JSON_API
1969
+ case SERIALIZER_JSON :
1970
+ {
1971
+ php_json_encode (& buf , value TSRMLS_CC );
1972
+ buf .c [buf .len ] = 0 ;
1973
+ MEMC_VAL_SET_TYPE (* flags , MEMC_VAL_IS_JSON );
1974
+ break ;
1975
+ }
1958
1976
#endif
1959
- php_serialize_data_t var_hash ;
1960
- PHP_VAR_SERIALIZE_INIT (var_hash );
1961
- php_var_serialize (& buf , & value , & var_hash TSRMLS_CC );
1962
- PHP_VAR_SERIALIZE_DESTROY (var_hash );
1963
-
1964
- if (!buf .c ) {
1965
- php_error_docref (NULL TSRMLS_CC , E_WARNING , "could not serialize value" );
1966
- smart_str_free (& buf );
1967
- return NULL ;
1977
+ default :
1978
+ {
1979
+ php_serialize_data_t var_hash ;
1980
+ PHP_VAR_SERIALIZE_INIT (var_hash );
1981
+ php_var_serialize (& buf , & value , & var_hash TSRMLS_CC );
1982
+ PHP_VAR_SERIALIZE_DESTROY (var_hash );
1983
+
1984
+ if (!buf .c ) {
1985
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "could not serialize value" );
1986
+ smart_str_free (& buf );
1987
+ return NULL ;
1988
+ }
1989
+
1990
+ MEMC_VAL_SET_TYPE (* flags , MEMC_VAL_IS_SERIALIZED );
1991
+ break ;
1968
1992
}
1969
- #if HAVE_MEMCACHED_IGBINARY
1970
1993
}
1971
- #endif
1972
1994
1973
- * flags |= MEMC_VAL_SERIALIZED ;
1974
1995
break ;
1975
- }
1976
1996
}
1977
1997
1978
1998
/* turn off compression for values below the threshold */
@@ -2051,25 +2071,31 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload
2051
2071
}
2052
2072
}
2053
2073
2054
- if ( flags & MEMC_VAL_SERIALIZED ) {
2074
+ payload [ payload_len ] = 0 ;
2055
2075
2056
- if (flags & MEMC_VAL_IGBINARY ) {
2057
- #if HAVE_MEMCACHED_IGBINARY
2058
- if (igbinary_unserialize ((uint8_t * )payload , payload_len , & value )) {
2059
- ZVAL_FALSE (value );
2076
+ switch (MEMC_VAL_GET_TYPE (flags )) {
2060
2077
2061
- if (flags & MEMC_VAL_COMPRESSED ) {
2062
- efree (payload );
2063
- }
2078
+ case MEMC_VAL_IS_STRING :
2079
+ ZVAL_STRINGL (value , payload , payload_len , 1 );
2080
+ break ;
2081
+ case MEMC_VAL_IS_LONG :
2082
+ {
2083
+ long lval = strtol (payload , NULL , 10 );
2084
+ ZVAL_LONG (value , lval );
2085
+ break ;
2086
+ }
2087
+ case MEMC_VAL_IS_DOUBLE :
2088
+ {
2089
+ double dval = zend_strtod (payload , NULL );
2090
+ ZVAL_DOUBLE (value , dval );
2091
+ break ;
2092
+ }
2093
+ case MEMC_VAL_IS_BOOL :
2094
+ ZVAL_BOOL (value , payload_len > 0 && payload [0 ] == '1' );
2095
+ break ;
2064
2096
2065
- php_error_docref (NULL TSRMLS_CC , E_WARNING , "could not unserialize value with igbinary" );
2066
- return -1 ;
2067
- }
2068
- #else
2069
- php_error_docref (NULL TSRMLS_CC , E_WARNING , "could not unserialize value, no igbinary support" );
2070
- return -1 ;
2071
- #endif
2072
- } else {
2097
+ case MEMC_VAL_IS_SERIALIZED :
2098
+ {
2073
2099
const char * payload_tmp = payload ;
2074
2100
php_unserialize_data_t var_hash ;
2075
2101
@@ -2084,20 +2110,42 @@ static int php_memc_zval_from_payload(zval *value, char *payload, size_t payload
2084
2110
return -1 ;
2085
2111
}
2086
2112
PHP_VAR_UNSERIALIZE_DESTROY (var_hash );
2113
+ break ;
2087
2114
}
2088
- } else {
2089
- payload [payload_len ] = 0 ;
2090
- if (flags & MEMC_VAL_IS_LONG ) {
2091
- long lval = strtol (payload , NULL , 10 );
2092
- ZVAL_LONG (value , lval );
2093
- } else if (flags & MEMC_VAL_IS_DOUBLE ) {
2094
- double dval = zend_strtod (payload , NULL );
2095
- ZVAL_DOUBLE (value , dval );
2096
- } else if (flags & MEMC_VAL_IS_BOOL ) {
2097
- ZVAL_BOOL (value , payload_len > 0 && payload [0 ] == '1' );
2098
- } else {
2099
- ZVAL_STRINGL (value , payload , payload_len , 1 );
2100
- }
2115
+
2116
+ case MEMC_VAL_IS_IGBINARY :
2117
+ #if HAVE_MEMCACHED_IGBINARY
2118
+ if (igbinary_unserialize ((uint8_t * )payload , payload_len , & value )) {
2119
+ ZVAL_FALSE (value );
2120
+
2121
+ if (flags & MEMC_VAL_COMPRESSED ) {
2122
+ efree (payload );
2123
+ }
2124
+
2125
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "could not unserialize value with igbinary" );
2126
+ return -1 ;
2127
+ }
2128
+ #else
2129
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "could not unserialize value, no igbinary support" );
2130
+ return -1 ;
2131
+ #endif
2132
+ break ;
2133
+
2134
+ case MEMC_VAL_IS_JSON :
2135
+ #if HAVE_JSON_API
2136
+ php_json_decode (value , payload , payload_len , 0 TSRMLS_CC );
2137
+ #else
2138
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "could not unserialize value, no json support" );
2139
+ return -1 ;
2140
+ #endif
2141
+ break ;
2142
+
2143
+ default :
2144
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "unknown payload type ");
2145
+ if (flags & MEMC_VAL_COMPRESSED ) {
2146
+ efree (payload );
2147
+ }
2148
+ return -1 ;
2101
2149
}
2102
2150
2103
2151
if (flags & MEMC_VAL_COMPRESSED ) {
@@ -2199,7 +2247,7 @@ static memcached_return php_memc_do_cache_callback(zval *memc_obj, zend_fcall_in
2199
2247
2200
2248
convert_to_boolean (retval );
2201
2249
if (Z_BVAL_P (retval ) == 1 ) {
2202
- payload = php_memc_zval_to_payload (value , & payload_len , & flags TSRMLS_CC );
2250
+ payload = php_memc_zval_to_payload (value , & payload_len , & flags , i_obj -> serializer TSRMLS_CC );
2203
2251
if (payload == NULL ) {
2204
2252
status = MEMC_RES_PAYLOAD_FAILURE ;
2205
2253
} else {
@@ -2827,6 +2875,7 @@ static void php_memc_register_constants(INIT_FUNC_ARGS)
2827
2875
*/
2828
2876
REGISTER_MEMC_CLASS_CONST_LONG (SERIALIZER_PHP , SERIALIZER_PHP );
2829
2877
REGISTER_MEMC_CLASS_CONST_LONG (SERIALIZER_IGBINARY , SERIALIZER_IGBINARY );
2878
+ REGISTER_MEMC_CLASS_CONST_LONG (SERIALIZER_JSON , SERIALIZER_JSON );
2830
2879
2831
2880
/*
2832
2881
* Flags.
0 commit comments