@@ -154,6 +154,8 @@ static zend_function_entry redis_functions[] = {
154
154
PHP_ME (Redis , bgrewriteaof , NULL , ZEND_ACC_PUBLIC )
155
155
PHP_ME (Redis , slaveof , NULL , ZEND_ACC_PUBLIC )
156
156
PHP_ME (Redis , object , NULL , ZEND_ACC_PUBLIC )
157
+ PHP_ME (Redis , bitop , NULL , ZEND_ACC_PUBLIC )
158
+ PHP_ME (Redis , bitcount , NULL , ZEND_ACC_PUBLIC )
157
159
158
160
PHP_ME (Redis , eval , NULL , ZEND_ACC_PUBLIC )
159
161
PHP_ME (Redis , evalsha , NULL , ZEND_ACC_PUBLIC )
@@ -599,6 +601,127 @@ PHPAPI int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
599
601
return SUCCESS ;
600
602
}
601
603
604
+ /* {{{ proto boolean Redis::bitop(string op, string key, ...)
605
+ */
606
+ PHP_METHOD (Redis , bitop )
607
+ {
608
+ char * cmd ;
609
+ int cmd_len ;
610
+
611
+ zval * * z_args ;
612
+ char * * keys ;
613
+ int * keys_len ;
614
+ int argc = ZEND_NUM_ARGS (), i ;
615
+ RedisSock * redis_sock = NULL ;
616
+ smart_str buf = {0 };
617
+ int key_free = 0 ;
618
+
619
+ /* get redis socket */
620
+ if (redis_sock_get (getThis (), & redis_sock TSRMLS_CC , 0 ) < 0 ) {
621
+ RETURN_FALSE ;
622
+ }
623
+
624
+ /* fetch args */
625
+ z_args = emalloc (argc * sizeof (zval * ));
626
+ if (zend_get_parameters_array (ht , argc , z_args ) == FAILURE
627
+ || argc < 3 /* 3 args min. */
628
+ || Z_TYPE_P (z_args [0 ]) != IS_STRING /* operation must be a string. */
629
+ ) {
630
+ efree (z_args );
631
+ RETURN_FALSE ;
632
+ }
633
+
634
+
635
+ keys = emalloc (argc * sizeof (char * ));
636
+ keys_len = emalloc (argc * sizeof (int ));
637
+
638
+ /* prefix keys */
639
+ for (i = 0 ; i < argc ; ++ i ) {
640
+ convert_to_string (z_args [i ]);
641
+
642
+ keys [i ] = Z_STRVAL_P (z_args [i ]);
643
+ keys_len [i ] = Z_STRLEN_P (z_args [i ]);
644
+ if (i != 0 )
645
+ key_free = redis_key_prefix (redis_sock , & keys [i ], & keys_len [i ] TSRMLS_CC );
646
+ }
647
+
648
+ /* start building the command */
649
+ smart_str_appendc (& buf , '*' );
650
+ smart_str_append_long (& buf , argc + 1 ); /* +1 for BITOP command */
651
+ smart_str_appendl (& buf , _NL , sizeof (_NL ) - 1 );
652
+
653
+ /* add command name */
654
+ smart_str_appendc (& buf , '$' );
655
+ smart_str_append_long (& buf , 5 );
656
+ smart_str_appendl (& buf , _NL , sizeof (_NL ) - 1 );
657
+ smart_str_appendl (& buf , "BITOP" , 5 );
658
+ smart_str_appendl (& buf , _NL , sizeof (_NL ) - 1 );
659
+
660
+ /* add keys */
661
+ for (i = 0 ; i < argc ; ++ i ) {
662
+ smart_str_appendc (& buf , '$' );
663
+ smart_str_append_long (& buf , keys_len [i ]);
664
+ smart_str_appendl (& buf , _NL , sizeof (_NL ) - 1 );
665
+ smart_str_appendl (& buf , keys [i ], keys_len [i ]);
666
+ smart_str_appendl (& buf , _NL , sizeof (_NL ) - 1 );
667
+ }
668
+ /* end string */
669
+ smart_str_0 (& buf );
670
+ cmd = buf .c ;
671
+ cmd_len = buf .len ;
672
+
673
+ /* cleanup */
674
+ if (key_free )
675
+ for (i = 1 ; i < argc ; ++ i ) {
676
+ efree (keys [i ]);
677
+ }
678
+ efree (keys );
679
+ efree (keys_len );
680
+ efree (z_args );
681
+
682
+ /* send */
683
+ REDIS_PROCESS_REQUEST (redis_sock , cmd , cmd_len );
684
+ IF_ATOMIC () {
685
+ redis_long_response (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
686
+ }
687
+ REDIS_PROCESS_RESPONSE (redis_long_response );
688
+ }
689
+ /* }}} */
690
+
691
+ /* {{{ proto boolean Redis::bitcount(string key, [int start], [int end])
692
+ */
693
+ PHP_METHOD (Redis , bitcount )
694
+ {
695
+ zval * object ;
696
+ RedisSock * redis_sock ;
697
+ char * key = NULL , * cmd ;
698
+ int key_len , cmd_len , key_free ;
699
+ long start = 0 , end = -1 ;
700
+
701
+ if (zend_parse_method_parameters (ZEND_NUM_ARGS () TSRMLS_CC , getThis (), "Os|ll" ,
702
+ & object , redis_ce ,
703
+ & key , & key_len , & start , & end ) == FAILURE ) {
704
+ RETURN_FALSE ;
705
+ }
706
+
707
+ if (redis_sock_get (object , & redis_sock TSRMLS_CC , 0 ) < 0 ) {
708
+ RETURN_FALSE ;
709
+ }
710
+
711
+ /* BITCOUNT key start end */
712
+ key_free = redis_key_prefix (redis_sock , & key , & key_len TSRMLS_CC );
713
+ cmd_len = redis_cmd_format_static (& cmd , "BITCOUNT" , "sdd" , key , key_len , (int )start , (int )end );
714
+ if (key_free ) efree (key );
715
+
716
+ REDIS_PROCESS_REQUEST (redis_sock , cmd , cmd_len );
717
+ IF_ATOMIC () {
718
+ redis_long_response (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
719
+ }
720
+ REDIS_PROCESS_RESPONSE (redis_long_response );
721
+
722
+ }
723
+ /* }}} */
724
+
602
725
/* {{{ proto boolean Redis::close()
603
726
*/
604
727
PHP_METHOD (Redis , close )
@@ -2889,22 +3012,27 @@ PHP_METHOD(Redis, sortDescAlpha)
2889
3012
PHPAPI void generic_expire_cmd (INTERNAL_FUNCTION_PARAMETERS , char * keyword , int keyword_len ) {
2890
3013
zval * object ;
2891
3014
RedisSock * redis_sock ;
2892
- char * key = NULL , * cmd ;
2893
- int key_len , cmd_len , key_free ;
2894
- long t ;
3015
+ char * key = NULL , * cmd , * t ;
3016
+ int key_len , cmd_len , key_free , t_len ;
3017
+ int i ;
2895
3018
2896
- if (zend_parse_method_parameters (ZEND_NUM_ARGS () TSRMLS_CC , getThis (), "Osl " ,
3019
+ if (zend_parse_method_parameters (ZEND_NUM_ARGS () TSRMLS_CC , getThis (), "Oss " ,
2897
3020
& object , redis_ce , & key , & key_len ,
2898
- & t ) == FAILURE ) {
3021
+ & t , & t_len ) == FAILURE ) {
2899
3022
RETURN_FALSE ;
2900
3023
}
2901
3024
2902
3025
if (redis_sock_get (object , & redis_sock TSRMLS_CC , 0 ) < 0 ) {
2903
3026
RETURN_FALSE ;
2904
3027
}
2905
3028
3029
+ /* check that we have a number */
3030
+ for (i = 0 ; i < t_len ; ++ i )
3031
+ if (t [i ] < '0' || t [i ] > '9' )
3032
+ RETURN_FALSE ;
3033
+
2906
3034
key_free = redis_key_prefix (redis_sock , & key , & key_len TSRMLS_CC );
2907
- cmd_len = redis_cmd_format_static (& cmd , keyword , "sl " , key , key_len , t );
3035
+ cmd_len = redis_cmd_format_static (& cmd , keyword , "ss " , key , key_len , t , t_len );
2908
3036
if (key_free ) efree (key );
2909
3037
2910
3038
REDIS_PROCESS_REQUEST (redis_sock , cmd , cmd_len );
0 commit comments