8000 Merge remote-tracking branch 'upstream/master' · jrtkcoder/phpredis@0ca8a1d · GitHub
[go: up one dir, main page]

Skip to content

Commit 0ca8a1d

Browse files
Merge remote-tracking branch 'upstream/master'
2 parents ca7868d + f8f552e commit 0ca8a1d

File tree

4 files changed

+162
-9
lines changed

4 files changed

+162
-9
lines changed

README.markdown

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,6 +1579,29 @@ $redis->setBit('key', 7, 1); /* returns 0 */
15791579
$redis->get('key'); /* chr(0x2f) = "/" = b("0010 1111") */
15801580
</pre>
15811581

1582+
## bitop
1583+
##### *Description*
1584+
Bitwise operation on multiple keys.
1585+
1586+
##### *Parameters*
1587+
*operation*: either "AND", "OR", "NOT", "XOR"
1588+
*ret_key*: return key
1589+
*key1*
1590+
*key2...*
1591+
1592+
##### *Return value*
1593+
*LONG*: The size of the string stored in the destination key.
1594+
1595+
## bitcount
1596+
##### *Description*
1597+
Count bits in a string.
1598+
1599+
##### *Parameters*
1600+
*key*
1601+
1602+
##### *Return value*
1603+
*LONG*: The number of bits set to 1 in the value behind the input key.
1604+
15821605
## flushDB
15831606

15841607
##### *Description*

library.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -614,16 +614,16 @@ PHPAPI void redis_long_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
614614
}
615615

616616
if(response[0] == ':') {
617-
long ret = atol(response + 1);
617+
long long ret = atoll(response + 1);
618618
IF_MULTI_OR_PIPELINE() {
619-
if(ret > (long)LONG_MAX) { /* overflow */
619+
if(ret > LONG_MAX) { /* overflow */
620620
add_next_index_stringl(z_tab, response+1, response_len-1, 1);
621621
} else {
622622
efree(response);
623623
add_next_index_long(z_tab, (long)ret);
624624
}
625625
} else {
626-
if(ret > (long)LONG_MAX) { /* overflow */
626+
if(ret > LONG_MAX) { /* overflow */
627627
RETURN_STRINGL(response+1, response_len-1, 1);
628628
} else {
629629
efree(response);

php_redis.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ PHP_METHOD(Redis, pexpireAt);
126126
PHP_METHOD(Redis, bgrewriteaof);
127127
PHP_METHOD(Redis, slaveof);
128128
PHP_METHOD(Redis, object);
129+
PHP_METHOD(Redis, bitop);
130+
PHP_METHOD(Redis, bitcount);
129131

130132
PHP_METHOD(Redis, eval);
131133
PHP_METHOD(Redis, evalsha);

redis.c

Lines changed: 134 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ 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)
158+
PHP_ME(Redis, bitcount, NULL, ZEND_ACC_PUBLIC)
157159

158160
PHP_ME(Redis, eval, NULL, ZEND_ACC_PUBLIC)
159161
PHP_ME(Redis, evalsha, NULL, ZEND_ACC_PUBLIC)
@@ -599,6 +601,127 @@ PHPAPI int redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
599601
return SUCCESS;
600602
}
601603

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+
602725
/* {{{ proto boolean Redis::close()
603726
*/
604727
PHP_METHOD(Redis, close)
@@ -2889,22 +3012,27 @@ PHP_METHOD(Redis, sortDescAlpha)
28893012
PHPAPI void generic_expire_cmd(INTERNAL_FUNCTION_PARAMETERS, char *keyword, int keyword_len) {
28903013
zval *object;
28913014
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;
28953018

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",
28973020
&object, redis_ce, &key, &key_len,
2898-
&t) == FAILURE) {
3021+
&t, &t_len) == FAILURE) {
28993022
RETURN_FALSE;
29003023
}
29013024

29023025
if (redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) {
29033026
RETURN_FALSE;
29043027
}
29053028

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+
29063034
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);
29083036
if(key_free) efree(key);
29093037

29103038
REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len);

0 commit comments

Comments
 (0)
0