+
+ /* Ok, lookup the key and get the range */
+ emptyreply = justcount ? shared.czero : shared.emptymultibulk;
+ if ((o = lookupKeyReadOrReply(c,c->argv[1],emptyreply)) == NULL ||
+ checkType(c,o,REDIS_ZSET)) return;
+ zsetobj = o->ptr;
+ zsl = zsetobj->zsl;
+
+ /* If reversed, assume the elements are sorted from high to low score. */
+ ln = zslFirstWithScore(zsl,range.min);
+ if (reverse) {
+ /* If range.min is out of range, ln will be NULL and we need to use
+ * the tail of the skiplist as first node of the range. */
+ if (ln == NULL) ln = zsl->tail;
+
+ /* zslFirstWithScore returns the first element with where with
+ * score >= range.min, so backtrack to make sure the element we use
+ * here has score <= range.min. */
+ while (ln && ln->score > range.min) ln = ln->backward;
+
+ /* Move to the right element according to the range spec. */
+ if (range.minex) {
+ /* Find last element with score < range.min */
+ while (ln && ln->score == range.min) ln = ln->backward;
+ } else {
+ /* Find last element with score <= range.min */
+ while (ln && ln->level[0].forward &&
+ ln->level[0].forward->score == range.min)
+ ln = ln->level[0].forward;
+ }
+ } else {
+ if (range.minex) {
+ /* Find first element with score > range.min */
+ while (ln && ln->score == range.min) ln = ln->level[0].forward;
+ }