Implements the generic list pop operation for LPOP/RPOP. * The where argument specifies which end of the list is operated on. An * optional count may be provided as the third argument of the client's * command. */
| 456 | * optional count may be provided as the third argument of the client's |
| 457 | * command. */ |
| 458 | void popGenericCommand(client *c, int where) { |
| 459 | long count = 0; |
| 460 | robj *value; |
| 461 | |
| 462 | if (c->argc > 3) { |
| 463 | addReplyErrorFormat(c,"wrong number of arguments for '%s' command", |
| 464 | c->cmd->name); |
| 465 | return; |
| 466 | } else if (c->argc == 3) { |
| 467 | /* Parse the optional count argument. */ |
| 468 | if (getPositiveLongFromObjectOrReply(c,c->argv[2],&count,NULL) != C_OK) |
| 469 | return; |
| 470 | if (count == 0) { |
| 471 | /* Fast exit path. */ |
| 472 | addReplyNullArray(c); |
| 473 | return; |
| 474 | } |
| 475 | } |
| 476 | |
| 477 | robj *o = lookupKeyWriteOrReply(c, c->argv[1], shared.null[c->resp]); |
| 478 | if (o == NULL || checkType(c, o, OBJ_LIST)) |
| 479 | return; |
| 480 | |
| 481 | if (!count) { |
| 482 | /* Pop a single element. This is POP's original behavior that replies |
| 483 | * with a bulk string. */ |
| 484 | value = listTypePop(o,where); |
| 485 | serverAssert(value != NULL); |
| 486 | addReplyBulk(c,value); |
| 487 | decrRefCount(value); |
| 488 | listElementsRemoved(c,c->argv[1],where,o,1); |
| 489 | } else { |
| 490 | /* Pop a range of elements. An addition to the original POP command, |
| 491 | * which replies with a multi-bulk. */ |
| 492 | long llen = listTypeLength(o); |
| 493 | long rangelen = (count > llen) ? llen : count; |
| 494 | long rangestart = (where == LIST_HEAD) ? 0 : -rangelen; |
| 495 | long rangeend = (where == LIST_HEAD) ? rangelen - 1 : -1; |
| 496 | int reverse = (where == LIST_HEAD) ? 0 : 1; |
| 497 | |
| 498 | addListRangeReply(c,o,rangestart,rangeend,reverse); |
| 499 | quicklistDelRange((quicklist*)ptrFromObj(o),rangestart,rangelen); |
| 500 | listElementsRemoved(c,c->argv[1],where,o,rangelen); |
| 501 | } |
| 502 | } |
| 503 | |
| 504 | /* LPOP <key> [count] */ |
| 505 | void lpopCommand(client *c) { |
no test coverage detected