* |11111111| - End of ziplist.
*
* All the integers are represented in little endian byte order.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Redis nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
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. */
+ /* Storing `prevrawlen` in this entry may increase or decrease the
+ * number of bytes required compare to the current `prevrawlen`.
+ * There always is room to store this, because it was previously
+ * stored by an entry that is now being deleted. */
nextdiff = zipPrevLenByteDiff(p,first.prevrawlen);
- zipPrevEncodeLength(p-nextdiff,first.prevrawlen);
+ p -= nextdiff;
+ zipPrevEncodeLength(p,first.prevrawlen);
/* Update offset for tail */
ZIPLIST_TAIL_OFFSET(zl) =
}
/* Move tail to the front of the ziplist */
- memmove(first.p,p-nextdiff,
- intrev32ifbe(ZIPLIST_BYTES(zl))-(p-zl)-1+nextdiff);
+ memmove(first.p,p,
+ intrev32ifbe(ZIPLIST_BYTES(zl))-(p-zl)-1);
} else {
/* The entire tail was deleted. No need to move memory. */
ZIPLIST_TAIL_OFFSET(zl) =
return len;
}
+void verify(unsigned char *zl, zlentry *e) {
+ int i;
+ int len = ziplistLen(zl);
+ zlentry _e;
+
+ for (i = 0; i < len; i++) {
+ memset(&e[i], 0, sizeof(zlentry));
+ e[i] = zipEntry(ziplistIndex(zl, i));
+
+ memset(&_e, 0, sizeof(zlentry));
+ _e = zipEntry(ziplistIndex(zl, -len+i));
+
+ assert(memcmp(&e[i], &_e, sizeof(zlentry)) == 0);
+ }
+}
+
int main(int argc, char **argv) {
unsigned char *zl, *p;
unsigned char *entry;
printf("SUCCESS\n\n");
}
+ printf("Regression test deleting next to last entries:\n");
+ {
+ char v[3][257];
+ zlentry e[3];
+ int i;
+
+ for (i = 0; i < (sizeof(v)/sizeof(v[0])); i++) {
+ memset(v[i], 'a' + i, sizeof(v[0]));
+ }
+
+ v[0][256] = '\0';
+ v[1][ 1] = '\0';
+ v[2][256] = '\0';
+
+ zl = ziplistNew();
+ for (i = 0; i < (sizeof(v)/sizeof(v[0])); i++) {
+ zl = ziplistPush(zl, (unsigned char *) v[i], strlen(v[i]), ZIPLIST_TAIL);
+ }
+
+ verify(zl, e);
+
+ assert(e[0].prevrawlensize == 1);
+ assert(e[1].prevrawlensize == 5);
+ assert(e[2].prevrawlensize == 1);
+
+ /* Deleting entry 1 will increase `prevrawlensize` for entry 2 */
+ unsigned char *p = e[1].p;
+ zl = ziplistDelete(zl, &p);
+
+ verify(zl, e);
+
+ assert(e[0].prevrawlensize == 1);
+ assert(e[1].prevrawlensize == 5);
+
+ printf("SUCCESS\n\n");
+ }
+
printf("Create long list and check indices:\n");
{
zl = ziplistNew();