@@ -32,8 +32,14 @@ PHPAPI int usleep(unsigned int useconds);
3232#define  usleep  Sleep
3333#endif 
3434
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
3743
3844extern  zend_class_entry  * redis_ce ;
3945extern  zend_class_entry  * redis_exception_ce ;
@@ -115,7 +121,7 @@ PHP_REDIS_API int redis_check_eof(RedisSock *redis_sock TSRMLS_DC)
115121}
116122
117123
118- PHP_REDIS_API  int   
124+ PHP_REDIS_API  int 
119125redis_sock_read_scan_reply (INTERNAL_FUNCTION_PARAMETERS , RedisSock  * redis_sock ,
120126                           REDIS_SCAN_TYPE  type , long  * iter )
121127{
@@ -150,13 +156,13 @@ redis_sock_read_scan_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
150156       scan command this is.  They all come back in slightly different ways */ 
151157    switch (type ) {
152158        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 );
154160        case  TYPE_SSCAN :
155161            return  redis_sock_read_multibulk_reply (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
156162        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 );
158164        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 );
160166        default :
161167            return  -1 ;
162168    }
@@ -189,9 +195,10 @@ PHP_REDIS_API zval *redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAM
189195    MAKE_STD_ZVAL (z_tab );
190196    array_init (z_tab );
191197
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 ;
195202}
196203
197204/** 
@@ -944,15 +951,90 @@ PHP_REDIS_API void redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *
944951    }
945952}
946953
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 );
947999
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+         }*/ 
9481023
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 );
9501030
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+ }
9551033
1034+ static  int 
1035+ redis_mbulk_reply_zipped (INTERNAL_FUNCTION_PARAMETERS , RedisSock  * redis_sock ,
1036+                          zval  * z_tab , int  unserialize , int  decode )
1037+ {
9561038    char  inbuf [1024 ];
9571039	int  numElems ;
9581040    zval  * z_multi_result ;
@@ -982,10 +1064,12 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_zipped_with_flag(INTERNAL_FUNC
9821064    MAKE_STD_ZVAL (z_multi_result );
9831065    array_init (z_multi_result ); /* pre-allocate array for multi's results. */ 
9841066
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 );
9871070
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 );
9891073
9901074    IF_MULTI_OR_PIPELINE () {
9911075        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
9991083    return  0 ;
10001084}
10011085
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+ }
10031092
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 );
10051099}
10061100
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 );
10091115}
10101116
10111117PHP_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 *
10901196}
10911197
10921198/* 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 ,
10941200                                        zval  * z_tab , void  * ctx )
10951201{
10961202    char  * resp , * p , * p2 , * p3 , * p4 ;
@@ -1116,7 +1222,7 @@ PHP_REDIS_API void redis_debug_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock
11161222    while ((p2  =  strchr (p , ':' ))!= NULL ) {
11171223        /* Null terminate at the ':' */ 
11181224        * p2 ++  =  '\0' ;
1119-         
1225+ 
11201226        /* Null terminate at the space if we have one */ 
11211227        if ((p3  =  strchr (p2 , ' ' ))!= NULL ) {
11221228            * p3 ++  =  '\0' ;
@@ -1138,7 +1244,7 @@ PHP_REDIS_API void redis_debug_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock
11381244        } else  {
11391245            add_assoc_string (z_result , p , p2 , 1 );
11401246        }
1141-     
1247+ 
11421248        p  =  p3 ;
11431249    }
11441250
@@ -1421,8 +1527,8 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply(INTERNAL_FUNCTION_PARAMETERS,
14211527    MAKE_STD_ZVAL (z_multi_result );
14221528    array_init (z_multi_result ); /* pre-allocate array for multi's results. */ 
14231529
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 );
14261532
14271533    IF_MULTI_OR_PIPELINE () {
14281534        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,
14371543/** 
14381544 * Like multibulk reply, but don't touch the values, they won't be compressed. (this is used by HKEYS). 
14391545 */ 
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 )
14411547{
14421548    char  inbuf [1024 ];
14431549	int  numElems ;
@@ -1468,8 +1574,8 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_raw(INTERNAL_FUNCTION_PARAMETE
14681574    MAKE_STD_ZVAL (z_multi_result );
14691575    array_init (z_multi_result ); /* pre-allocate array for multi's results. */ 
14701576
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 );
14731579
14741580    IF_MULTI_OR_PIPELINE () {
14751581        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
14811587    return  0 ;
14821588}
14831589
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+ /* 
14841626PHP_REDIS_API int 
14851627redis_sock_read_multibulk_reply_loop(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, 
14861628                                     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
15091651    } 
15101652    return 0; 
15111653} 
1654+ */ 
15121655
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 )
15171659{
15181660    char  inbuf [1024 ], * response ;
15191661    int  response_len ;
1520- 	 int  i , numElems ;
1521- 	 zval  * z_multi_result ;
1662+      int  i , numElems ;
1663+      zval  * z_multi_result ;
15221664
15231665    zval  * * z_keys  =  ctx ;
15241666
15251667    if (-1  ==  redis_check_eof (redis_sock  TSRMLS_CC )) {
15261668        return  -1 ;
15271669    }
15281670    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 );
15301672        redis_sock -> stream  =  NULL ;
15311673        redis_sock -> status  =  REDIS_SOCK_STATUS_FAILED ;
15321674        redis_sock -> mode  =  ATOMIC ;
@@ -1550,30 +1692,30 @@ PHP_REDIS_API int redis_sock_read_multibulk_reply_assoc(INTERNAL_FUNCTION_PARAME
15501692    for (i  =  0 ; i  <  numElems ; ++ i ) {
15511693        response  =  redis_sock_read (redis_sock , & response_len  TSRMLS_CC );
15521694        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 ]);
15651707    }
15661708    efree (z_keys );
15671709
15681710    IF_MULTI_OR_PIPELINE () {
15691711        add_next_index_zval (z_tab , z_multi_result );
15701712    } 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+      }
15771719    return  0 ;
15781720}
15791721
0 commit comments