Permalink
Browse files

add BITCOUNT and BITOP commands

  • Loading branch information...
1 parent acb008e commit 70eca8f2cb7199f6d9d458bd7d3baaeae766818e @wg committed Jun 24, 2012
@@ -84,6 +84,41 @@ public String auth(String password) {
return dispatch(BGSAVE, new StatusOutput<K, V>(codec));
}
+ public Future<Long> bitcount(K key) {
+ CommandArgs<K, V> args = new CommandArgs<K, V>(codec).addKey(key);
+ return dispatch(BITCOUNT, new IntegerOutput<K, V>(codec), args);
+ }
+
+ public Future<Long> bitcount(K key, long start, long end) {
+ CommandArgs<K, V> args = new CommandArgs<K, V>(codec);
+ args.addKey(key).add(start).add(end);
+ return dispatch(BITCOUNT, new IntegerOutput<K, V>(codec), args);
+ }
+
+ public Future<Long> bitopAnd(K destination, K... keys) {
+ CommandArgs<K, V> args = new CommandArgs<K, V>(codec);
+ args.add(AND).addKey(destination).addKeys(keys);
+ return dispatch(BITOP, new IntegerOutput<K, V>(codec), args);
+ }
+
+ public Future<Long> bitopNot(K destination, K source) {
+ CommandArgs<K, V> args = new CommandArgs<K, V>(codec);
+ args.add(NOT).addKey(destination).addKey(source);
+ return dispatch(BITOP, new IntegerOutput<K, V>(codec), args);
+ }
+
+ public Future<Long> bitopOr(K destination, K... keys) {
+ CommandArgs<K, V> args = new CommandArgs<K, V>(codec);
+ args.add(OR).addKey(destination).addKeys(keys);
+ return dispatch(BITOP, new IntegerOutput<K, V>(codec), args);
+ }
+
+ public Future<Long> bitopXor(K destination, K... keys) {
+ CommandArgs<K, V> args = new CommandArgs<K, V>(codec);
+ args.add(XOR).addKey(destination).addKeys(keys);
+ return dispatch(BITOP, new IntegerOutput<K, V>(codec), args);
+ }
+
public Future<KeyValue<K, V>> blpop(long timeout, K... keys) {
CommandArgs<K, V> args = new CommandArgs<K, V>(codec).addKeys(keys).add(timeout);
return dispatch(BLPOP, new KeyValueOutput<K, V>(codec), args);
@@ -68,6 +68,29 @@ public String bgsave() {
return await(c.bgsave());
}
+ public Long bitcount(K key) {
+ return await(c.bitcount(key));
+ }
+
+ public Long bitcount(K key, long start, long end) {
+ return await(c.bitcount(key, start, end));
+ }
+
+ public Long bitopAnd(K destination, K... keys) {
+ return await(c.bitopAnd(destination, keys));
+ }
+
+ public Long bitopNot(K destination, K source) {
+ return await(c.bitopNot(destination, source));
+ }
+
+ public Long bitopOr(K destination, K... keys) {
+ return await(c.bitopOr(destination, keys));
+ }
+ public Long bitopXor(K destination, K... keys) {
+ return await(c.bitopXor(destination, keys));
+ }
+
public KeyValue<K, V> blpop(long timeout, K... keys) {
long timeout2 = (timeout == 0 ? Long.MAX_VALUE : max(timeout, unit.toSeconds(this.timeout)));
return await(c.blpop(timeout, keys), timeout2, SECONDS);
@@ -8,9 +8,9 @@
* @author Will Glozer
*/
public enum CommandKeyword {
- AFTER, AGGREGATE, ALPHA, ASC, BEFORE, BY, COUNT, DESC, ENCODING, FLUSH,
- IDLETIME, KILL, LEN, LIMIT, LIST, LOAD, MAX, MIN, NO, NOSAVE, ONE, REFCOUNT,
- RESET, RESETSTAT, STORE, SUM, WEIGHTS, WITHSCORES;
+ AFTER, AGGREGATE, ALPHA, AND, ASC, BEFORE, BY, COUNT, DESC, ENCODING, FLUSH,
+ IDLETIME, KILL, LEN, LIMIT, LIST, LOAD, MAX, MIN, NO, NOSAVE, NOT, ONE, OR,
+ REFCOUNT, RESET, RESETSTAT, STORE, SUM, WEIGHTS, WITHSCORES, XOR;
public byte[] bytes;
@@ -25,8 +25,8 @@
// String
- APPEND, GET, GETBIT, GETRANGE, GETSET, MGET, MSET, MSETNX,
- SET, SETEX, SETNX, SETBIT, SETRANGE, STRLEN,
+ APPEND, GET, GETRANGE, GETSET, MGET, MSET, MSETNX, SET, SETEX, SETNX,
+ SETRANGE, STRLEN,
// Numeric
@@ -64,7 +64,11 @@
// Scripting
- EVAL, EVALSHA, SCRIPT;
+ EVAL, EVALSHA, SCRIPT,
+
+ // Bits
+
+ BITCOUNT, BITOP, GETBIT, SETBIT;
public byte[] bytes;
@@ -0,0 +1,99 @@
+// Copyright (C) 2012 - Will Glozer. All rights reserved.
+
+package com.lambdaworks.redis;
+
+import com.lambdaworks.redis.codec.Utf8StringCodec;
+import org.junit.*;
+
+import java.nio.ByteBuffer;
+
+import static org.junit.Assert.assertEquals;
+
+public class BitCommandTest extends AbstractCommandTest {
+ protected RedisConnection<String, String> bitstring;
+
+ @Before
+ public final void openBitStringConnection() throws Exception {
+ bitstring = client.connect(new BitStringCodec());
+ }
+
+ @After
+ public final void closeBitStringConnection() throws Exception {
+ bitstring.close();
+ }
+
+ @Test
+ public void bitcount() throws Exception {
+ assertEquals(0, (long) redis.bitcount(key));
+ redis.setbit(key, 0, 1);
+ redis.setbit(key, 1, 1);
+ redis.setbit(key, 2, 1);
+ assertEquals(3, (long) redis.bitcount(key));
+ //assertEquals(2, (long) redis.bitcount(key, 1, 3));
+ assertEquals(0, (long) redis.bitcount(key, 3, -1));
+ }
+
+ @Test
+ public void bitopAnd() throws Exception {
+ redis.setbit("foo", 0, 1);
+ redis.setbit("bar", 1, 1);
+ redis.setbit("baz", 2, 1);
+ assertEquals(1, (long) redis.bitopAnd(key, "foo", "bar", "baz"));
+ assertEquals(0, (long) redis.bitcount(key));
+ assertEquals("00000000", bitstring.get(key));
+ }
+
+ @Test
+ public void bitopNot() throws Exception {
+ redis.setbit("foo", 0, 1);
+ redis.setbit("foo", 2, 1);
+ assertEquals(1, (long) redis.bitopNot(key, "foo"));
+ assertEquals(6, (long) redis.bitcount(key));
+ assertEquals("11111010", bitstring.get(key));
+ }
+
+ @Test
+ public void bitopOr() throws Exception {
+ redis.setbit("foo", 0, 1);
+ redis.setbit("bar", 1, 1);
+ redis.setbit("baz", 2, 1);
+ assertEquals(1, (long) redis.bitopOr(key, "foo", "bar", "baz"));
+ assertEquals("00000111", bitstring.get(key));
+ }
+
+ @Test
+ public void bitopXor() throws Exception {
+ redis.setbit("foo", 0, 1);
+ redis.setbit("bar", 0, 1);
+ redis.setbit("baz", 2, 1);
+ assertEquals(1, (long) redis.bitopXor(key, "foo", "bar", "baz"));
+ assertEquals("00000100", bitstring.get(key));
+ }
+
+ @Test
+ public void getbit() throws Exception {
+ assertEquals(0, (long) redis.getbit(key, 0));
+ redis.setbit(key, 0, 1);
+ assertEquals(1, (long) redis.getbit(key, 0));
+ }
+
+ @Test
+ public void setbit() throws Exception {
+ assertEquals(0, (long) redis.setbit(key, 0, 1));
+ assertEquals(1, (long) redis.setbit(key, 0, 0));
+ }
+
+ static class BitStringCodec extends Utf8StringCodec {
+ @Override
+ public String decodeValue(ByteBuffer bytes) {
+ StringBuilder bits = new StringBuilder(bytes.remaining() * 8);
+ while (bytes.remaining() > 0) {
+ byte b = bytes.get();
+ for (int i = 0; i < 8; i++) {
+ bits.append(Integer.valueOf(b >>> i & 1));
+ }
+ }
+ return bits.toString();
+ }
+ }
+}

0 comments on commit 70eca8f

Please sign in to comment.