X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/c03206fdf1dc0241d97204aba813c13b82f40d6e..a6dd455b09cb67e18799c0b2ed720d213608e13d:/ziplist.c diff --git a/ziplist.c b/ziplist.c index b29c630b..71d965a8 100644 --- a/ziplist.c +++ b/ziplist.c @@ -340,7 +340,7 @@ static unsigned char *__ziplistInsert(unsigned char *zl, unsigned char *p, char /* When the insert position is not equal to the tail, we need to * make sure that the next entry can hold this entry's length in * its prevlen field. */ - nextdiff = p[0] != ZIP_END ? zipPrevLenByteDiff(p,reqlen) : 0; + nextdiff = (p[0] != ZIP_END) ? zipPrevLenByteDiff(p,reqlen) : 0; /* Store offset because a realloc may change the address of zl. */ offset = p-zl; @@ -424,12 +424,18 @@ unsigned char *ziplistIndex(unsigned char *zl, int index) { p += zipRawEntryLength(p); } } - return p[0] == ZIP_END || index > 0 ? NULL : p; + return (p[0] == ZIP_END || index > 0) ? NULL : p; } /* Return pointer to next entry in ziplist. */ unsigned char *ziplistNext(unsigned char *p) { - return *p == ZIP_END ? p : p+zipRawEntryLength(p); + return (p[0] == ZIP_END) ? NULL : p+zipRawEntryLength(p); +} + +/* Return pointer to previous entry in ziplist. */ +unsigned char *ziplistPrev(unsigned char *p) { + zlentry entry = zipEntry(p); + return (entry.prevrawlen == 0) ? NULL : p-entry.prevrawlen; } /* Get entry pointer to by 'p' and store in either 'e' or 'v' depending @@ -455,31 +461,42 @@ unsigned int ziplistGet(unsigned char *p, char **sstr, unsigned int *slen, long return 1; } -/* Delete a range of entries from the ziplist. */ -unsigned char *ziplistDeleteRange(unsigned char *zl, unsigned int index, unsigned int num) { - unsigned char *p = ziplistIndex(zl,index); - return p == NULL ? zl : __ziplistDelete(zl,p,num); +/* Insert an entry at "p". */ +unsigned char *ziplistInsert(unsigned char *zl, unsigned char *p, char *s, unsigned int slen) { + return __ziplistInsert(zl,p,s,slen); } /* Delete a single entry from the ziplist, pointed to by *p. * Also update *p in place, to be able to iterate over the * ziplist, while deleting entries. */ -unsigned char *ziplistDelete(unsigned char *zl, unsigned char **p) { +unsigned char *ziplistDelete(unsigned char *zl, unsigned char **p, int direction) { unsigned int offset = *p-zl; zl = __ziplistDelete(zl,*p,1); /* Store pointer to current element in p, because ziplistDelete will - * do a realloc which might result in a different "zl"-pointer. */ - *p = zl+offset; + * do a realloc which might result in a different "zl"-pointer. + * When the delete direction is back to front, we might delete the last + * entry and end up with "p" pointing to ZIP_END, so check this. */ + if (*(zl+offset) == ZIP_END && direction == ZIPLIST_HEAD) { + *p = ZIPLIST_ENTRY_TAIL(zl); + } else { + *p = zl+offset; + } return zl; } +/* Delete a range of entries from the ziplist. */ +unsigned char *ziplistDeleteRange(unsigned char *zl, unsigned int index, unsigned int num) { + unsigned char *p = ziplistIndex(zl,index); + return (p == NULL) ? zl : __ziplistDelete(zl,p,num); +} + /* Compare entry pointer to by 'p' with 'entry'. Return 1 if equal. */ unsigned int ziplistCompare(unsigned char *p, char *sstr, unsigned int slen) { zlentry entry; char sencoding; long long val, sval; - if (*p == ZIP_END) return 0; + if (p[0] == ZIP_END) return 0; entry = zipEntry(p); if (entry.encoding == ZIP_ENC_RAW) { @@ -744,6 +761,40 @@ int main(int argc, char **argv) { printf("\n"); } + printf("Iterate from back to front:\n"); + { + zl = createList(); + p = ziplistIndex(zl, -1); + while (ziplistGet(p, &entry, &elen, &value)) { + printf("Entry: "); + if (entry) { + fwrite(entry,elen,1,stdout); + } else { + printf("%lld", value); + } + p = ziplistPrev(p); + printf("\n"); + } + printf("\n"); + } + + printf("Iterate from back to front, deleting all items:\n"); + { + zl = createList(); + p = ziplistIndex(zl, -1); + while (ziplistGet(p, &entry, &elen, &value)) { + printf("Entry: "); + if (entry) { + fwrite(entry,elen,1,stdout); + } else { + printf("%lld", value); + } + zl = ziplistDelete(zl, &p, ZIPLIST_HEAD); + printf("\n"); + } + printf("\n"); + } + printf("Delete inclusive range 0,0:\n"); { zl = createList(); @@ -786,7 +837,7 @@ int main(int argc, char **argv) { while (ziplistGet(p, &entry, &elen, &value)) { if (entry && strncmp("foo", entry, elen) == 0) { printf("Delete foo\n"); - zl = ziplistDelete(zl, &p); + zl = ziplistDelete(zl, &p, ZIPLIST_TAIL); } else { printf("Entry: "); if (entry) {