This commit is contained in:
Mingyi Kang 2026-02-04 04:53:57 +07:00 committed by GitHub
commit 4b0859dc7b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 41 additions and 2 deletions

View file

@ -1456,6 +1456,45 @@ unsigned char *lpBatchDelete(unsigned char *lp, unsigned char **ps, unsigned lon
return lpShrinkToFit(lp);
}
/* Trim a listpack, remove 'ltrim' elements from left and 'rtrim' elements from right. */
unsigned char *lpTrim(unsigned char *lp, unsigned long ltrim, unsigned long rtrim) {
if (ltrim == 0 && rtrim == 0) return lp;
size_t bytes = lpBytes(lp);
unsigned long llen = lpLength(lp);
if (ltrim + rtrim >= llen) {
/* Remove all elements */
lp[LP_HDR_SIZE] = LP_EOF;
lpSetTotalBytes(lp, LP_HDR_SIZE + 1);
lpSetNumElements(lp, 0);
return lpShrinkToFit(lp);
}
unsigned long rangelen = llen - ltrim - rtrim;
unsigned char *first, *tail; /* first points to the first byte we want to save,
and tail points to the byte after the last byte we want to save */
first = lpSeek(lp, ltrim);
assert(first != NULL);
tail = lp + bytes - 1; /* When rtrim is zero, tail points to the EOF char */
if (rtrim) {
if (rangelen < rtrim) {
tail = first;
unsigned long num = rangelen;
while (num--) {
tail = lpSkip(tail);
}
assert(tail[0] != LP_EOF);
lpAssertValidEntry(lp, bytes, tail);
} else {
tail = lpSeek(lp, llen - (int)rtrim);
}
}
size_t rangebytes = tail - first;
memmove(lp + LP_HDR_SIZE, first, rangebytes);
lp[LP_HDR_SIZE + rangebytes] = LP_EOF;
lpSetTotalBytes(lp, LP_HDR_SIZE + rangebytes + 1);
lpSetNumElements(lp, rangelen);
return lpShrinkToFit(lp);
}
/* Merge listpacks 'first' and 'second' by appending 'second' to 'first'.
*
* NOTE: The larger listpack is reallocated to contain the new merged listpack.

View file

@ -54,6 +54,7 @@ unsigned char *lpBatchAppend(unsigned char *lp, listpackEntry *entries, unsigned
unsigned char *lpBatchInsert(unsigned char *lp, unsigned char *p, int where,
listpackEntry *entries, unsigned int len, unsigned char **newp);
unsigned char *lpBatchDelete(unsigned char *lp, unsigned char **ps, unsigned long count);
unsigned char *lpTrim(unsigned char *lp, unsigned long ltrim, unsigned long rtrim);
unsigned char *lpMerge(unsigned char **first, unsigned char **second);
unsigned char *lpDup(unsigned char *lp);
unsigned long lpLength(unsigned char *lp);

View file

@ -961,8 +961,7 @@ void ltrimCommand(client *c) {
quicklistDelRange(o->ptr,0,ltrim);
quicklistDelRange(o->ptr,-rtrim,rtrim);
} else if (o->encoding == OBJ_ENCODING_LISTPACK) {
o->ptr = lpDeleteRange(o->ptr,0,ltrim);
o->ptr = lpDeleteRange(o->ptr,-rtrim,rtrim);
o->ptr = lpTrim(o->ptr, ltrim, rtrim);
} else {
serverPanic("Unknown list encoding");
}