use rank to find starting point for ZRANGE and ZREVRANGE

This commit is contained in:
Pieter Noordhuis 2010-03-04 14:16:07 +01:00
parent 27b0ccca71
commit e74825c24f

28
redis.c
View File

@ -5081,6 +5081,26 @@ static unsigned long zslGetRank(zskiplist *zsl, double score, robj *o) {
return 0; return 0;
} }
/* Finds an element by its rank. The rank argument needs to be 1-based. */
zskiplistNode* zslGetElementByRank(zskiplist *zsl, unsigned long rank) {
zskiplistNode *x;
unsigned long traversed = 0;
int i;
x = zsl->header;
for (i = zsl->level-1; i >= 0; i--) {
while (x->forward[i] && (traversed + x->span[i]) <= rank) {
traversed += x->span[i];
x = x->forward[i];
}
if (traversed == rank) {
return x;
}
}
return NULL;
}
/* The actual Z-commands implementations */ /* The actual Z-commands implementations */
/* This generic command implements both ZADD and ZINCRBY. /* This generic command implements both ZADD and ZINCRBY.
@ -5282,13 +5302,9 @@ static void zrangeGenericCommand(redisClient *c, int reverse) {
/* Return the result in form of a multi-bulk reply */ /* Return the result in form of a multi-bulk reply */
if (reverse) { if (reverse) {
ln = zsl->tail; ln = zslGetElementByRank(zsl, llen - start);
while (start--)
ln = ln->backward;
} else { } else {
ln = zsl->header->forward[0]; ln = zslGetElementByRank(zsl, start + 1);
while (start--)
ln = ln->forward[0];
} }
addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n", addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",