@@ -32,8 +32,14 @@ PHPAPI int usleep(unsigned int useconds);
32
32
#define usleep Sleep
33
33
#endif
34
34
35
- #define UNSERIALIZE_ONLY_VALUES 0
36
- #define UNSERIALIZE_ALL 1
35
+ #define UNSERIALIZE_NONE 0
36
+ #define UNSERIALIZE_KEYS 1
37
+ #define UNSERIALIZE_VALS 2
38
+ #define UNSERIALIZE_ALL 3
39
+
40
+ #define SCORE_DECODE_NONE 0
41
+ #define SCORE_DECODE_INT 1
42
+ #define SCORE_DECODE_DOUBLE 2
37
43
38
44
extern zend_class_entry * redis_ce ;
39
45
extern zend_class_entry * redis_exception_ce ;
@@ -115,7 +121,7 @@ PHP_REDIS_API int redis_check_eof(RedisSock *redis_sock TSRMLS_DC)
115
121
}
116
122
117
123
118
- PHP_REDIS_API int
124
+ PHP_REDIS_API int
119
125
redis_sock_read_scan_reply (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
120
126
REDIS_SCAN_TYPE type , long * iter )
121
127
{
@@ -150,13 +156,13 @@ redis_sock_read_scan_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
150
156
scan command this is. They all come back in slightly different ways */
151
157
switch (type ) {
152
158
case TYPE_SCAN :
153
- return redis_sock_read_multibulk_reply_raw (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
159
+ return redis_mbulk_reply_raw (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
154
160
case TYPE_SSCAN :
155
161
return redis_sock_read_multibulk_reply (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
156
162
case TYPE_ZSCAN :
157
- return redis_sock_read_multibulk_reply_zipped (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
163
+ return redis_mbulk_reply_zipped_keys_dbl (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
158
164
case TYPE_HSCAN :
159
- return redis_sock_read_multibulk_reply_zipped_strings (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
165
+ return redis_mbulk_reply_zipped_vals (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
160
166
default :
161
167
return -1 ;
162
168
}
@@ -189,9 +195,10 @@ PHP_REDIS_API zval *redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAM
189
195
MAKE_STD_ZVAL (z_tab );
190
196
array_init (z_tab );
191
197
192
- redis_sock_read_multibulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU ,
193
- redis_sock , z_tab , numElems , 1 , UNSERIALIZE_ALL );
194
- return z_tab ;
198
+ redis_mbulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , z_tab ,
199
+ numElems , UNSERIALIZE_ALL );
200
+
201
+ return z_tab ;
195
202
}
196
203
197
204
/**
@@ -944,15 +951,90 @@ PHP_REDIS_API void redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *
944
951
}
945
952
}
946
953
954
+ /* Helper method to convert [key, value, key, value] into [key => value,
955
+ * key => value] when returning data to the caller. Depending on our decode
956
+ * flag we'll convert the value data types */
957
+ static void array_zip_values_and_scores (RedisSock * redis_sock , zval * z_tab ,
958
+ int decode TSRMLS_DC )
959
+ {
960
+
961
+ zval * z_ret ;
962
+ HashTable * keytable ;
963
+
964
+ MAKE_STD_ZVAL (z_ret );
965
+ array_init (z_ret );
966
+ keytable = Z_ARRVAL_P (z_tab );
967
+
968
+ for (zend_hash_internal_pointer_reset (keytable );
969
+ zend_hash_has_more_elements (keytable ) == SUCCESS ;
970
+ zend_hash_move_forward (keytable )) {
971
+
972
+ char * tablekey , * hkey , * hval ;
973
+ unsigned int tablekey_len ;
974
+ int hkey_len ;
975
+ unsigned long idx ;
976
+ zval * * z_key_pp , * * z_value_pp ;
977
+
978
+ zend_hash_get_current_key_ex (keytable , & tablekey , & tablekey_len , & idx , 0 , NULL );
979
+ if (zend_hash_get_current_data (keytable , (void * * )& z_key_pp ) == FAILURE ) {
980
+ continue ; /* this should never happen, according to the PHP people. */
981
+ }
982
+
983
+ /* get current value, a key */
984
+ convert_to_string (* z_key_pp );
985
+ hkey = Z_STRVAL_PP (z_key_pp );
986
+ hkey_len = Z_STRLEN_PP (z_key_pp );
987
+
988
+ /* move forward */
989
+ zend_hash_move_forward (keytable );
990
+
991
+ /* fetch again */
992
+ zend_hash_get_current_key_ex (keytable , & tablekey , & tablekey_len , & idx , 0 , NULL );
993
+ if (zend_hash_get_current_data (keytable , (void * * )& z_value_pp ) == FAILURE ) {
994
+ continue ; /* this should never happen, according to the PHP people. */
995
+ }
996
+
997
+ /* get current value, a hash value now. */
998
+ hval = Z_STRVAL_PP (z_value_pp );
947
999
1000
+ /* Decode the score depending on flag */
1001
+ if (decode == SCORE_DECODE_INT && Z_STRLEN_PP (z_value_pp ) > 0 ) {
1002
+ add_assoc_long_ex (z_ret , hkey , 1 + hkey_len , atoi (hval + 1 ));
1003
+ } else if (decode == SCORE_DECODE_DOUBLE ) {
1004
+ add_assoc_double_ex (z_ret , hkey , 1 + hkey_len , atof (hval ));
1005
+ } else {
1006
+ zval * z = NULL ;
1007
+ MAKE_STD_ZVAL (z );
1008
+ * z = * * z_value_pp ;
1009
+ zval_copy_ctor (z );
1010
+ add_assoc_zval_ex (z_ret , hkey , 1 + hkey_len , z );
1011
+ }
1012
+
1013
+ /*
1014
+ if(use_atof) {
1015
+ add_assoc_double_ex(z_ret, hkey, 1+hkey_len, atof(hval));
1016
+ } else {
1017
+ zval *z = NULL;
1018
+ MAKE_STD_ZVAL(z);
1019
+ *z = **z_value_pp;
1020
+ zval_copy_ctor(z);
1021
+ add_assoc_zval_ex(z_ret, hkey, 1+hkey_len, z);
1022
+ }*/
948
1023
949
- PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped_with_flag (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , int flag ) {
1024
+ }
1025
+ /* replace */
1026
+ zval_dtor (z_tab );
1027
+ * z_tab = * z_ret ;
1028
+ zval_copy_ctor (z_tab );
1029
+ zval_dtor (z_ret );
950
1030
951
- /*
952
- int ret = redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, z_tab TSRMLS_CC);
953
- array_zip_values_and_scores(return_value, 0);
954
- */
1031
+ efree (z_ret );
1032
+ }
955
1033
1034
+ static int
1035
+ redis_mbulk_reply_zipped (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
1036
+ zval * z_tab , int unserialize , int decode )
1037
+ {
956
1038
char inbuf [1024 ];
957
1039
int numElems ;
958
1040
zval * z_multi_result ;
@@ -982,10 +1064,12 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNC
982
1064
MAKE_STD_ZVAL (z_multi_result );
983
1065
array_init (z_multi_result ); /* pre-allocate array for multi's results. */
984
1066
985
- redis_sock_read_multibulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU ,
986
- redis_sock , z_multi_result , numElems , 1 , flag ? UNSERIALIZE_ALL : UNSERIALIZE_ONLY_VALUES );
1067
+ /* Grab our key, value, key, value array */
1068
+ redis_mbulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1069
+ z_multi_result , numElems , unserialize );
987
1070
988
- array_zip_values_and_scores (redis_sock , z_multi_result , 0 TSRMLS_CC );
1071
+ /* Zip keys and values */
1072
+ array_zip_values_and_scores (redis_sock , z_multi_result , decode TSRMLS_CC );
989
1073
990
1074
IF_MULTI_OR_PIPELINE () {
991
1075
add_next_index_zval (z_tab , z_multi_result );
@@ -999,13 +1083,35 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNC
999
1083
return 0 ;
1000
1084
}
1001
1085
1002
- PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx ) {
1086
+ /* Zipped key => value reply but we don't touch anything (e.g. CONFIG GET) */
1087
+ PHP_REDIS_API int redis_mbulk_reply_zipped_raw (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx )
1088
+ {
1089
+ return redis_mbulk_reply_zipped (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1090
+ z_tab , UNSERIALIZE_NONE , SCORE_DECODE_NONE );
1091
+ }
1003
1092
1004
- return redis_sock_read_multibulk_reply_zipped_with_flag (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , z_tab , 1 );
1093
+ /* Zipped key => value reply unserializing keys and decoding the score as an integer (PUBSUB) */
1094
+ PHP_REDIS_API int redis_mbulk_reply_zipped_keys_int (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
1095
+ zval * z_tab , void * ctx )
1096
+ {
1097
+ return redis_mbulk_reply_zipped (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1098
+ z_tab , UNSERIALIZE_KEYS , SCORE_DECODE_INT );
1005
1099
}
1006
1100
1007
- PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped_strings (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx ) {
1008
- return redis_sock_read_multibulk_reply_zipped_with_flag (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , z_tab , 0 );
1101
+ /* Zipped key => value reply unserializing keys and decoding the score as a double (ZSET commands) */
1102
+ PHP_REDIS_API int redis_mbulk_reply_zipped_keys_dbl (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
1103
+ zval * z_tab , void * ctx )
1104
+ {
1105
+ return redis_mbulk_reply_zipped (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1106
+ z_tab , UNSERIALIZE_KEYS , SCORE_DECODE_DOUBLE );
1107
+ }
1108
+
1109
+ /* Zipped key => value reply where only the values are unserialized (e.g. HMGET) */
1110
+ PHP_REDIS_API int redis_mbulk_reply_zipped_vals (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
1111
+ zval * z_tab , void * ctx )
1112
+ {
1113
+ return redis_mbulk_reply_zipped (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1114
+ z_tab , UNSERIALIZE_VALS , SCORE_DECODE_NONE );
1009
1115
}
1010
1116
1011
1117
PHP_REDIS_API void redis_1_response (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx ) {
@@ -1090,7 +1196,7 @@ PHP_REDIS_API void redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *
1090
1196
}
1091
1197
1092
1198
/* Response for DEBUG object which is a formatted single line reply */
1093
- PHP_REDIS_API void redis_debug_response (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
1199
+ PHP_REDIS_API void redis_debug_response (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
1094
1200
zval * z_tab , void * ctx )
1095
1201
{
1096
1202
char * resp , * p , * p2 , * p3 , * p4 ;
@@ -1116,7 +1222,7 @@ PHP_REDIS_API void redis_debug_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock
1116
1222
while ((p2 = strchr (p , ':' ))!= NULL ) {
1117
1223
/* Null terminate at the ':' */
1118
1224
* p2 ++ = '\0' ;
1119
-
1225
+
1120
1226
/* Null terminate at the space if we have one */
1121
1227
if ((p3 = strchr (p2 , ' ' ))!= NULL ) {
1122
1228
* p3 ++ = '\0' ;
@@ -1138,7 +1244,7 @@ PHP_REDIS_API void redis_debug_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock
1138
1244
} else {
1139
1245
add_assoc_string (z_result , p , p2 , 1 );
1140
1246
}
1141
-
1247
+
1142
1248
p = p3 ;
1143
1249
}
1144
1250
@@ -1421,8 +1527,8 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS,
1421
1527
MAKE_STD_ZVAL (z_multi_result );
1422
1528
array_init (z_multi_result ); /* pre-allocate array for multi's results. */
1423
1529
1424
- redis_sock_read_multibulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1425
- redis_sock , z_multi_result , numElems , 1 , UNSERIALIZE_ALL );
1530
+ redis_mbulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1531
+ z_multi_result , numElems , UNSERIALIZE_ALL );
1426
1532
1427
1533
IF_MULTI_OR_PIPELINE () {
1428
1534
add_next_index_zval (z_tab , z_multi_result );
@@ -1437,7 +1543,7 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS,
1437
1543
/**
1438
1544
* Like multibulk reply, but don't touch the values, they won't be compressed. (this is used by HKEYS).
1439
1545
*/
1440
- PHP_REDIS_API int redis_sock_read_multibulk_reply_raw (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx )
1546
+ PHP_REDIS_API int redis_mbulk_reply_raw (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx )
1441
1547
{
1442
1548
char inbuf [1024 ];
1443
1549
int numElems ;
@@ -1468,8 +1574,8 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_raw(INTERNAL_FUNCTION_PARAMETE
1468
1574
MAKE_STD_ZVAL (z_multi_result );
1469
1575
array_init (z_multi_result ); /* pre-allocate array for multi's results. */
1470
1576
1471
- redis_sock_read_multibulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU ,
1472
- redis_sock , z_multi_result , numElems , 0 , UNSERIALIZE_ALL );
1577
+ redis_mbulk_reply_loop (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock ,
1578
+ z_multi_result , numElems , UNSERIALIZE_NONE );
1473
1579
1474
1580
IF_MULTI_OR_PIPELINE () {
1475
1581
add_next_index_zval (z_tab , z_multi_result );
@@ -1481,6 +1587,42 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_raw(INTERNAL_FUNCTION_PARAMETE
1481
1587
return 0 ;
1482
1588
}
1483
1589
1590
+ PHP_REDIS_API void
1591
+ redis_mbulk_reply_loop (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
1592
+ zval * z_tab , int count , int unserialize )
1593
+ {
1594
+ char * line ;
1595
+ int len ;
1596
+
1597
+ while (count > 0 ) {
1598
+ line = redis_sock_read (redis_sock , & len TSRMLS_CC );
1599
+ if (line != NULL ) {
1600
+ zval * z = NULL ;
1601
+ int unwrap ;
1602
+
1603
+ /* We will attempt unserialization, if we're unserializing everything,
1604
+ * or if we're unserializing keys and we're on a key, or we're
1605
+ * unserializing values and we're on a value! */
1606
+ unwrap = unserialize == UNSERIALIZE_ALL ||
1607
+ (unserialize == UNSERIALIZE_KEYS && count % 2 == 0 ) ||
1608
+ (unserialize == UNSERIALIZE_VALS && count % 2 != 0 );
1609
+
1610
+ if (unwrap && redis_unserialize (redis_sock , line , len , & z TSRMLS_CC )) {
1611
+ efree (line );
1612
+ add_next_index_zval (z_tab , z );
1613
+ } else {
1614
+ add_next_index_stringl (z_tab , line , len , 0 );
1615
+ }
1616
+ } else {
1617
+ add_next_index_bool (z_tab , 0 );
1618
+ }
1619
+
1620
+ count -- ;
1621
+ }
1622
+ }
1623
+
1624
+
1625
+ /*
1484
1626
PHP_REDIS_API int
1485
1627
redis_sock_read_multibulk_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
1486
1628
zval *z_tab, int numElems, int unwrap_key, int unserialize_even_only)
@@ -1509,24 +1651,24 @@ redis_sock_read_multibulk_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *re
1509
1651
}
1510
1652
return 0;
1511
1653
}
1654
+ */
1512
1655
1513
- /**
1514
- * redis_sock_read_multibulk_reply_assoc
1515
- */
1516
- PHP_REDIS_API int redis_sock_read_multibulk_reply_assoc (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx )
1656
+ /* Specialized multibulk processing for HMGET where we need to pair requested
1657
+ * keys with their returned values */
1658
+ PHP_REDIS_API int redis_mbulk_reply_assoc (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock , zval * z_tab , void * ctx )
1517
1659
{
1518
1660
char inbuf [1024 ], * response ;
1519
1661
int response_len ;
1520
- int i , numElems ;
1521
- zval * z_multi_result ;
1662
+ int i , numElems ;
1663
+ zval * z_multi_result ;
1522
1664
1523
1665
zval * * z_keys = ctx ;
1524
1666
1525
1667
if (-1 == redis_check_eof (redis_sock TSRMLS_CC )) {
1526
1668
return -1 ;
1527
1669
}
1528
1670
if (php_stream_gets (redis_sock -> stream , inbuf , 1024 ) == NULL ) {
1529
- redis_stream_close (redis_sock TSRMLS_CC );
1671
+ redis_stream_close (redis_sock TSRMLS_CC );
1530
1672
redis_sock -> stream = NULL ;
1531
1673
redis_sock -> status = REDIS_SOCK_STATUS_FAILED ;
1532
1674
redis_sock -> mode = ATOMIC ;
@@ -1550,30 +1692,30 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAME
1550
1692
for (i = 0 ; i < numElems ; ++ i ) {
1551
1693
response = redis_sock_read (redis_sock , & response_len TSRMLS_CC );
1552
1694
if (response != NULL ) {
1553
- zval * z = NULL ;
1554
- if (redis_unserialize (redis_sock , response , response_len , & z TSRMLS_CC ) == 1 ) {
1555
- efree (response );
1556
- add_assoc_zval_ex (z_multi_result , Z_STRVAL_P (z_keys [i ]), 1 + Z_STRLEN_P (z_keys [i ]), z );
1557
- } else {
1558
- add_assoc_stringl_ex (z_multi_result , Z_STRVAL_P (z_keys [i ]), 1 + Z_STRLEN_P (z_keys [i ]), response , response_len , 0 );
1559
- }
1560
- } else {
1561
- add_assoc_bool_ex (z_multi_result , Z_STRVAL_P (z_keys [i ]), 1 + Z_STRLEN_P (z_keys [i ]), 0 );
1562
- }
1563
- zval_dtor (z_keys [i ]);
1564
- efree (z_keys [i ]);
1695
+ zval * z = NULL ;
1696
+ if (redis_unserialize (redis_sock , response , response_len , & z TSRMLS_CC ) == 1 ) {
1697
+ efree (response );
1698
+ add_assoc_zval_ex (z_multi_result , Z_STRVAL_P (z_keys [i ]), 1 + Z_STRLEN_P (z_keys [i ]), z );
1699
+ } else {
1700
+ add_assoc_stringl_ex (z_multi_result , Z_STRVAL_P (z_keys [i ]), 1 + Z_STRLEN_P (z_keys [i ]), response , response_len , 0 );
1701
+ }
1702
+ } else {
1703
+ add_assoc_bool_ex (z_multi_result , Z_STRVAL_P (z_keys [i ]), 1 + Z_STRLEN_P (z_keys [i ]), 0 );
1704
+ }
1705
+ zval_dtor (z_keys [i ]);
1706
+ efree (z_keys [i ]);
1565
1707
}
1566
1708
efree (z_keys );
1567
1709
1568
1710
IF_MULTI_OR_PIPELINE () {
1569
1711
add_next_index_zval (z_tab , z_multi_result );
1570
1712
} else {
1571
- * return_value = * z_multi_result ;
1572
- zval_copy_ctor (return_value );
1573
- INIT_PZVAL (return_value );
1574
- zval_dtor (z_multi_result );
1575
- efree (z_multi_result );
1576
- }
1713
+ * return_value = * z_multi_result ;
1714
+ zval_copy_ctor (return_value );
1715
+ INIT_PZVAL (return_value );
1716
+ zval_dtor (z_multi_result );
1717
+ efree (z_multi_result );
1718
+ }
1577
1719
return 0 ;
1578
1720
}
1579
1721
0 commit comments