+
+/* Delete "num" entries, starting at "p". Returns pointer to the ziplist. */
+static unsigned char *__ziplistDelete(unsigned char *zl, unsigned char *p, int num) {
+ unsigned int i, totlen, deleted = 0;
+ int nextdiff = 0;
+ zlentry first = zipEntry(p);
+ for (i = 0; p[0] != ZIP_END && i < num; i++) {
+ p += zipRawEntryLength(p);
+ deleted++;
+ }
+
+ totlen = p-first.p;
+ if (totlen > 0) {
+ if (p[0] != ZIP_END) {
+ /* Tricky: storing the prevlen in this entry might reduce or
+ * increase the number of bytes needed, compared to the current
+ * prevlen. Note that we can always store this length because
+ * it was previously stored by an entry that is being deleted. */
+ nextdiff = zipPrevLenByteDiff(p,first.prevrawlen);
+ zipEncodeLength(p-nextdiff,ZIP_ENC_RAW,first.prevrawlen);
+
+ /* Update offset for tail */
+ ZIPLIST_TAIL_OFFSET(zl) -= totlen+nextdiff;
+
+ /* Move tail to the front of the ziplist */
+ memmove(first.p,p-nextdiff,ZIPLIST_BYTES(zl)-(p-zl)-1+nextdiff);
+ } else {
+ /* The entire tail was deleted. No need to move memory. */
+ ZIPLIST_TAIL_OFFSET(zl) = (first.p-zl)-first.prevrawlen;
+ }
+
+ /* Resize and update length */
+ zl = ziplistResize(zl, ZIPLIST_BYTES(zl)-totlen+nextdiff);
+ ZIPLIST_INCR_LENGTH(zl,-deleted);
+ }
+ return zl;