/* 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;
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
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) {
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();
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) {