提交 7ffa248c 编写于 作者: A antirez

BITCOUNT refactoring.

The low level popualtion counting function is now separated from the
BITCOUNT command implementation, so that the low level function can be
further optimized and eventually used in other contexts if needed.
上级 84ec6706
#include "redis.h" #include "redis.h"
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Bits related string commands: GETBIT, SETBIT, BITCOUNT, BITOP. * Helpers and low level bit functions.
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
#define BITOP_AND 0
#define BITOP_OR 1
#define BITOP_XOR 2
#define BITOP_NOT 3
/* This helper function used by GETBIT / SETBIT parses the bit offset arguemnt /* This helper function used by GETBIT / SETBIT parses the bit offset arguemnt
* making sure an error is returned if it is negative or if it overflows * making sure an error is returned if it is negative or if it overflows
* Redis 512 MB limit for the string value. */ * Redis 512 MB limit for the string value. */
...@@ -30,6 +25,28 @@ static int getBitOffsetFromArgument(redisClient *c, robj *o, size_t *offset) { ...@@ -30,6 +25,28 @@ static int getBitOffsetFromArgument(redisClient *c, robj *o, size_t *offset) {
return REDIS_OK; return REDIS_OK;
} }
/* Count number of bits set in the binary array pointed by 's' and long
* 'count' bytes. The implementation of this function is required to
* work with a input string length up to 512 MB. */
long popcount(void *s, long count) {
long bits = 0;
unsigned char *p = s;
static const unsigned char bitsinbyte[256] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};
/* We can finally count bits. */
while(count--) bits += bitsinbyte[*p++];
return bits;
}
/* -----------------------------------------------------------------------------
* Bits related string commands: GETBIT, SETBIT, BITCOUNT, BITOP.
* -------------------------------------------------------------------------- */
#define BITOP_AND 0
#define BITOP_OR 1
#define BITOP_XOR 2
#define BITOP_NOT 3
/* SETBIT key offset bitvalue */ /* SETBIT key offset bitvalue */
void setbitCommand(redisClient *c) { void setbitCommand(redisClient *c) {
robj *o; robj *o;
...@@ -201,7 +218,6 @@ void bitopCommand(redisClient *c) { ...@@ -201,7 +218,6 @@ void bitopCommand(redisClient *c) {
/* BITCOUNT key [start end] */ /* BITCOUNT key [start end] */
void bitcountCommand(redisClient *c) { void bitcountCommand(redisClient *c) {
static const unsigned char bitsinbyte[256] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};
robj *o; robj *o;
long start, end; long start, end;
unsigned char *p; unsigned char *p;
...@@ -249,11 +265,8 @@ void bitcountCommand(redisClient *c) { ...@@ -249,11 +265,8 @@ void bitcountCommand(redisClient *c) {
if (start > end) { if (start > end) {
addReply(c,shared.czero); addReply(c,shared.czero);
} else { } else {
long bits = 0, bytes = end-start+1; long bytes = end-start+1;
/* We can finally count bits. */ addReplyLongLong(c,popcount(p+start,bytes));
p += start;
while(bytes--) bits += bitsinbyte[*p++];
addReplyLongLong(c,bits);
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册