mirror of
https://github.com/fluencelabs/redis
synced 2025-04-09 10:46:06 +00:00
More consistent BITPOS behavior with bit=0 and ranges.
With the new behavior it is possible to specify just the start in the range (the end will be assumed to be the first byte), or it is possible to specify both start and end. This is useful to change the behavior of the command when looking for zeros inside a string. 1) If the user specifies both start and end, and no 0 is found inside the range, the command returns -1. 2) If instead no range is specified, or just the start is given, even if in the actual string no 0 bit is found, the command returns the first bit on the right after the end of the string. So for example if the string stored at key foo is "\xff\xff": BITPOS foo (returns 16) BITPOS foo 0 -1 (returns -1) BITPOS foo 0 (returns 16) The idea is that when no end is given the user is just looking for the first bit that is zero and can be set to 1 with SETBIT, as it is "available". Instead when a specific range is given, we just look for a zero within the boundaries of the range.
This commit is contained in:
parent
38c620b3b5
commit
0e31eaa27f
24
src/bitops.c
24
src/bitops.c
@ -505,12 +505,13 @@ void bitcountCommand(redisClient *c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BITPOS key bit [start end] */
|
/* BITPOS key bit [start [end]] */
|
||||||
void bitposCommand(redisClient *c) {
|
void bitposCommand(redisClient *c) {
|
||||||
robj *o;
|
robj *o;
|
||||||
long bit, start, end, strlen;
|
long bit, start, end, strlen;
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
char llbuf[32];
|
char llbuf[32];
|
||||||
|
int end_given = 0;
|
||||||
|
|
||||||
/* Parse the bit argument to understand what we are looking for, set
|
/* Parse the bit argument to understand what we are looking for, set
|
||||||
* or clear bits. */
|
* or clear bits. */
|
||||||
@ -541,11 +542,16 @@ void bitposCommand(redisClient *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parse start/end range if any. */
|
/* Parse start/end range if any. */
|
||||||
if (c->argc == 5) {
|
if (c->argc == 4 || c->argc == 5) {
|
||||||
if (getLongFromObjectOrReply(c,c->argv[3],&start,NULL) != REDIS_OK)
|
if (getLongFromObjectOrReply(c,c->argv[3],&start,NULL) != REDIS_OK)
|
||||||
return;
|
return;
|
||||||
if (getLongFromObjectOrReply(c,c->argv[4],&end,NULL) != REDIS_OK)
|
if (c->argc == 5) {
|
||||||
return;
|
if (getLongFromObjectOrReply(c,c->argv[4],&end,NULL) != REDIS_OK)
|
||||||
|
return;
|
||||||
|
end_given = 1;
|
||||||
|
} else {
|
||||||
|
end = strlen-1;
|
||||||
|
}
|
||||||
/* Convert negative indexes */
|
/* Convert negative indexes */
|
||||||
if (start < 0) start = strlen+start;
|
if (start < 0) start = strlen+start;
|
||||||
if (end < 0) end = strlen+end;
|
if (end < 0) end = strlen+end;
|
||||||
@ -570,14 +576,14 @@ void bitposCommand(redisClient *c) {
|
|||||||
long bytes = end-start+1;
|
long bytes = end-start+1;
|
||||||
long pos = redisBitpos(p+start,bytes,bit);
|
long pos = redisBitpos(p+start,bytes,bit);
|
||||||
|
|
||||||
/* If we are looking for clear bits, and our range does not includes
|
/* If we are looking for clear bits, and the user specified an exact
|
||||||
* the end of the string, but terminates before, we can't consider the
|
* range with start-end, we can't consider the right of the range as
|
||||||
* right of the range as zero padded.
|
* zero padded (as we do when no explicit end is given).
|
||||||
*
|
*
|
||||||
* so if redisBitpos() returns the first bit outside the string,
|
* So if redisBitpos() returns the first bit outside the range,
|
||||||
* we return -1 to the caller, to mean, in the specified range there
|
* we return -1 to the caller, to mean, in the specified range there
|
||||||
* is not a single "0" bit. */
|
* is not a single "0" bit. */
|
||||||
if (end != strlen-1 && bit == 0 && pos == bytes*8) {
|
if (end_given && bit == 0 && pos == bytes*8) {
|
||||||
addReplyLongLong(c,-1);
|
addReplyLongLong(c,-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user