diff options
author | michael-grunder <michael.grunder@gmail.com> | 2014-03-03 18:23:38 +0400 |
---|---|---|
committer | michael-grunder <michael.grunder@gmail.com> | 2014-03-03 18:23:38 +0400 |
commit | e74ffe036643265b18e864a9a4139cdb3d072d65 (patch) | |
tree | ceaf4e25dac1bce1f4382447be7d0ee358d6a812 | |
parent | 8f006cba2d20479a3b15741fc1a0c801aec4c246 (diff) |
Implemented BITPOS command
This commit introduces the new BITPOS redis command
http://redis.io/commands/bitpos
-rw-r--r-- | php_redis.h | 1 | ||||
-rw-r--r-- | redis.c | 54 | ||||
-rw-r--r-- | tests/TestRedis.php | 19 |
3 files changed, 74 insertions, 0 deletions
diff --git a/php_redis.h b/php_redis.h index 176ba2b6..12eb7462 100644 --- a/php_redis.h +++ b/php_redis.h @@ -129,6 +129,7 @@ PHP_METHOD(Redis, slaveof); PHP_METHOD(Redis, object); PHP_METHOD(Redis, bitop); PHP_METHOD(Redis, bitcount); +PHP_METHOD(Redis, bitpos); PHP_METHOD(Redis, eval); PHP_METHOD(Redis, evalsha); @@ -177,6 +177,7 @@ static zend_function_entry redis_functions[] = { PHP_ME(Redis, object, NULL, ZEND_ACC_PUBLIC) PHP_ME(Redis, bitop, NULL, ZEND_ACC_PUBLIC) PHP_ME(Redis, bitcount, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Redis, bitpos, NULL, ZEND_ACC_PUBLIC) /* 1.1 */ PHP_ME(Redis, mset, NULL, ZEND_ACC_PUBLIC) @@ -820,6 +821,59 @@ PHP_METHOD(Redis, bitcount) } /* }}} */ +/* {{{ proto integer Redis::bitpos(string key, int bit, [int start], [int end]) */ +PHP_METHOD(Redis, bitpos) +{ + zval *object; + RedisSock *redis_sock; + char *key, *cmd; + int key_len, cmd_len, argc, key_free=0; + long bit, start, end; + + argc = ZEND_NUM_ARGS(); + + if(zend_parse_method_parameters(argc TSRMLS_CC, getThis(), "Osl|ll", + &object, redis_ce, &key, &key_len, &bit, + &start, &end)==FAILURE) + { + RETURN_FALSE; + } + + if(redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) { + RETURN_FALSE; + } + + // We can prevalidate the first argument + if(bit != 0 && bit != 1) { + RETURN_FALSE; + } + + // Prefix our key + key_free = redis_key_prefix(redis_sock, &key, &key_len TSRMLS_CC); + + // Various command semantics + if(argc == 2) { + cmd_len = redis_cmd_format_static(&cmd, "BITPOS", "sd", key, key_len, + bit); + } else if(argc == 3) { + cmd_len = redis_cmd_format_static(&cmd, "BITPOS", "sdd", key, key_len, + bit, start); + } else { + cmd_len = redis_cmd_format_static(&cmd, "BITPOS", "sddd", key, key_len, + bit, start, end); + } + + // Free our key if it was prefixed + if(key_free) efree(key); + + REDIS_PROCESS_REQUEST(redis_sock, cmd, cmd_len); + IF_ATOMIC() { + redis_long_response(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, NULL, NULL); + } + REDIS_PROCESS_RESPONSE(redis_long_response); +} +/* }}} */ + /* {{{ proto boolean Redis::close() */ PHP_METHOD(Redis, close) diff --git a/tests/TestRedis.php b/tests/TestRedis.php index 94ebfc9d..9fa220ae 100644 --- a/tests/TestRedis.php +++ b/tests/TestRedis.php @@ -118,6 +118,25 @@ class Redis_Test extends TestSuite $this->assertFalse($this->redis->setBit('key', 4294967296, 1)); } + public function testBitPos() { + if(version_compare($this->version, "2.8.7", "lt")) { + $this->MarkTestSkipped(); + return; + } + + $this->redis->del('bpkey'); + + $this->redis->set('bpkey', "\xff\xf0\x00"); + $this->assertEquals($this->redis->bitpos('bpkey', 0), 12); + + $this->redis->set('bpkey', "\x00\xff\xf0"); + $this->assertEquals($this->redis->bitpos('bpkey', 1, 0), 8); + $this->assertEquals($this->redis->bitpos('bpkey', 1, 1), 8); + + $this->redis->set('bpkey', "\x00\x00\x00"); + $this->assertEquals($this->redis->bitpos('bpkey', 1), -1); + } + public function test1000() { $s = str_repeat('A', 1000); |