in src/commands/cmd_zset.cc [734:816]
Status Parse(const std::vector<std::string> &args) override {
key_ = args[1];
int64_t offset = 0;
int64_t count = -1;
// skip the <CMD> <src> <min> <max> args and parse remaining optional arguments
CommandParser parser(args, 4);
while (parser.Good()) {
if (parser.EatEqICase("withscores")) {
with_scores_ = true;
} else if (parser.EatEqICase("limit")) {
auto parse_offset = parser.TakeInt<int64_t>();
auto parse_count = parser.TakeInt<int64_t>();
if (!parse_offset || !parse_count) {
return {Status::RedisParseErr, errValueNotInteger};
}
offset = *parse_offset;
count = *parse_count;
} else if (range_type_ == kZRangeAuto && parser.EatEqICase("bylex")) {
range_type_ = kZRangeLex;
} else if (range_type_ == kZRangeAuto && parser.EatEqICase("byscore")) {
range_type_ = kZRangeScore;
} else if (direction_ == kZRangeDirectionAuto && parser.EatEqICase("rev")) {
direction_ = kZRangeDirectionReverse;
} else {
return parser.InvalidSyntax();
}
}
// use defaults if not overridden by arguments
if (range_type_ == kZRangeAuto) {
range_type_ = kZRangeRank;
}
if (direction_ == kZRangeDirectionAuto) {
direction_ = kZRangeDirectionForward;
}
// check for conflicting arguments
if (with_scores_ && range_type_ == kZRangeLex) {
return {Status::RedisParseErr, "syntax error, WITHSCORES not supported in combination with BYLEX"};
}
if (count != -1 && range_type_ == kZRangeRank) {
return {Status::RedisParseErr,
"syntax error, LIMIT is only supported in combination with either BYSCORE or BYLEX"};
}
// resolve index of <min> <max>
int min_idx = 2;
int max_idx = 3;
if (direction_ == kZRangeDirectionReverse && (range_type_ == kZRangeLex || range_type_ == kZRangeScore)) {
min_idx = 3;
max_idx = 2;
}
// parse range spec
switch (range_type_) {
case kZRangeAuto:
case kZRangeRank:
GET_OR_RET(ParseRangeRankSpec(args[min_idx], args[max_idx], &rank_spec_));
if (direction_ == kZRangeDirectionReverse) {
rank_spec_.reversed = true;
}
break;
case kZRangeLex:
GET_OR_RET(ParseRangeLexSpec(args[min_idx], args[max_idx], &lex_spec_));
lex_spec_.offset = offset;
lex_spec_.count = count;
if (direction_ == kZRangeDirectionReverse) {
lex_spec_.reversed = true;
}
break;
case kZRangeScore:
GET_OR_RET(ParseRangeScoreSpec(args[min_idx], args[max_idx], &score_spec_));
score_spec_.offset = offset;
score_spec_.count = count;
if (direction_ == kZRangeDirectionReverse) {
score_spec_.reversed = true;
}
break;
}
return Status::OK();
}