]> git.saurik.com Git - redis.git/commitdiff
change delete function to accept a direction argument, so "p" can be properly updated
authorPieter Noordhuis <pcnoordhuis@gmail.com>
Sat, 29 May 2010 23:39:41 +0000 (01:39 +0200)
committerPieter Noordhuis <pcnoordhuis@gmail.com>
Sat, 29 May 2010 23:39:41 +0000 (01:39 +0200)
ziplist.c
ziplist.h

index 4bc4f75cbe0baf4f203e38c2242ca4752f8a9015..71d965a89221a76f0672955b1a1d58b1b0f366d1 100644 (file)
--- a/ziplist.c
+++ b/ziplist.c
@@ -469,13 +469,19 @@ unsigned char *ziplistInsert(unsigned char *zl, unsigned char *p, char *s, unsig
 /* 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;
 }
 
@@ -755,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();
@@ -797,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) {
index 8d37a8f54002e1e84b1e2109d36393d4e9c82947..08035dd5e317f931b5025808212869e30e1273f2 100644 (file)
--- a/ziplist.h
+++ b/ziplist.h
@@ -8,8 +8,8 @@ unsigned char *ziplistIndex(unsigned char *zl, int index);
 unsigned char *ziplistNext(unsigned char *p);
 unsigned char *ziplistPrev(unsigned char *p);
 unsigned int ziplistGet(unsigned char *p, char **sstr, unsigned int *slen, long long *sval);
-unsigned char *ziplistDelete(unsigned char *zl, unsigned char **p);
 unsigned char *ziplistInsert(unsigned char *zl, unsigned char *p, char *s, unsigned int slen);
+unsigned char *ziplistDelete(unsigned char *zl, unsigned char **p, int direction);
 unsigned char *ziplistDeleteRange(unsigned char *zl, unsigned int index, unsigned int num);
 unsigned int ziplistCompare(unsigned char *p, char *entry, unsigned int elen);
 unsigned int ziplistLen(unsigned char *zl);