@@ -154,6 +154,7 @@ static zend_function_entry redis_functions[] = {
154154 PHP_ME (Redis , bgrewriteaof , NULL , ZEND_ACC_PUBLIC )
155155 PHP_ME (Redis , slaveof , NULL , ZEND_ACC_PUBLIC )
156156 PHP_ME (Redis , object , NULL , ZEND_ACC_PUBLIC )
157+ PHP_ME (Redis , bitop , NULL , ZEND_ACC_PUBLIC )
157158
158159 /* 1.1 */
159160 PHP_ME (Redis , mset , NULL , ZEND_ACC_PUBLIC )
@@ -588,6 +589,93 @@ PHPAPI int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
588589 return SUCCESS ;
589590}
590591
592+ /* {{{ proto boolean Redis::bitop(string op, string key, ...)
593+ */
594+ PHP_METHOD (Redis , bitop )
595+ {
596+ char * cmd ;
597+ int cmd_len ;
598+
599+ zval * * z_args ;
600+ char * * keys ;
601+ int * keys_len ;
602+ int argc = ZEND_NUM_ARGS (), i ;
603+ RedisSock * redis_sock = NULL ;
604+ smart_str buf = {0 };
605+ int key_free = 0 ;
606+
607+ /* get redis socket */
608+ if (redis_sock_get (getThis (), & redis_sock TSRMLS_CC , 0 ) < 0 ) {
609+ RETURN_FALSE ;
610+ }
611+
612+ /* fetch args */
613+ z_args = emalloc (argc * sizeof (zval * ));
614+ if (zend_get_parameters_array (ht , argc , z_args ) == FAILURE
615+ || argc < 3 /* 3 args min. */
616+ || Z_TYPE_P (z_args [0 ]) != IS_STRING /* operation must be a string. */
617+ ) {
618+ efree (z_args );
619+ RETURN_FALSE ;
620+ }
621+
622+
623+ keys = emalloc (argc * sizeof (char * ));
624+ keys_len = emalloc (argc * sizeof (int ));
625+
626+ /* prefix keys */
627+ for (i = 0 ; i < argc ; ++ i ) {
628+ convert_to_string (z_args [i ]);
629+
630+ keys [i ] = Z_STRVAL_P (z_args [i ]);
631+ keys_len [i ] = Z_STRLEN_P (z_args [i ]);
632+ if (i != 0 )
633+ key_free = redis_key_prefix (redis_sock , & keys [i ], & keys_len [i ] TSRMLS_CC );
634+ }
635+
636+ /* start building the command */
637+ smart_str_appendc (& buf , '*' );
638+ smart_str_append_long (& buf , argc + 1 ); /* +1 for BITOP command */
639+ smart_str_appendl (& buf , _NL , sizeof (_NL ) - 1 );
640+
641+ /* add command name */
642+ smart_str_appendc (& buf , '$' );
643+ smart_str_append_long (& buf , 5 );
644+ smart_str_appendl (& buf , _NL , sizeof (_NL ) - 1 );
645+ smart_str_appendl (& buf , "BITOP" , 5 );
646+ smart_str_appendl (& buf , _NL , sizeof (_NL ) - 1 );
647+
648+ /* add keys */
649+ for (i = 0 ; i < argc ; ++ i ) {
650+ smart_str_appendc (& buf , '$' );
651+ smart_str_append_long (& buf , keys_len [i ]);
652+ smart_str_appendl (& buf , _NL , sizeof (_NL ) - 1 );
653+ smart_str_appendl (& buf , keys [i ], keys_len [i ]);
654+ smart_str_appendl (& buf , _NL , sizeof (_NL ) - 1 );
655+ }
656+ /* end string */
657+ smart_str_0 (& buf );
658+ cmd = buf .c ;
659+ cmd_len = buf .len ;
660+
661+ /* cleanup */
662+ if (key_free )
663+ for (i = 1 ; i < argc ; ++ i ) {
664+ efree (keys [i ]);
665+ }
666+ efree (keys );
667+ efree (keys_len );
668+ efree (z_args );
669+
670+ /* send */
671+ REDIS_PROCESS_REQUEST (redis_sock , cmd , cmd_len );
672+ IF_ATOMIC () {
673+ redis_long_response (INTERNAL_FUNCTION_PARAM_PASSTHRU , redis_sock , NULL , NULL );
674+ }
675+ REDIS_PROCESS_RESPONSE (redis_long_response );
676+ }
677+ /* }}} */
678+
591679/* {{{ proto boolean Redis::close()
592680 */
593681PHP_METHOD (Redis , close )
0 commit comments