#define ZIPLIST_INCR_LENGTH(zl,incr) { \
if (ZIPLIST_LENGTH(zl) < ZIP_BIGLEN) ZIPLIST_LENGTH(zl)+=incr; }
+typedef struct zlentry {
+ unsigned int prevrawlensize, prevrawlen;
+ unsigned int lensize, len;
+ unsigned int headersize;
+ unsigned char encoding;
+} zlentry;
+
/* Return bytes needed to store integer encoded by 'encoding' */
static unsigned int zipEncodingSize(char encoding) {
if (encoding == ZIP_ENC_SHORT) {
return ret;
}
+/* Return a struct with all information about an entry. */
+static zlentry zipEntry(unsigned char *p) {
+ zlentry e;
+ e.prevrawlen = zipDecodeLength(p,&e.prevrawlensize);
+ e.len = zipDecodeLength(p+e.prevrawlensize,&e.lensize);
+ e.headersize = e.prevrawlensize+e.lensize;
+ e.encoding = ZIP_ENCODING(p+e.prevrawlensize);
+ return e;
+}
+
/* Return the total amount used by an entry (encoded length + payload). */
static unsigned int zipRawEntryLength(unsigned char *p) {
unsigned int prevlensize, lensize, len;
unsigned char *ziplistPop(unsigned char *zl, sds *target, int where) {
unsigned int curlen = ZIPLIST_BYTES(zl), rawlen;
- unsigned int prevrawlensize, prevrawlen, lensize, len, headerlen;
+ zlentry entry;
int nextdiff = 0;
- unsigned char encoding;
unsigned char *p;
long long value;
if (target) *target = NULL;
p = (where == ZIPLIST_HEAD) ? ziplistHead(zl) : ziplistTail(zl);
if (*p == ZIP_END) return zl;
- prevrawlen = zipDecodeLength(p,&prevrawlensize);
- len = zipDecodeLength(p+prevrawlensize,&lensize);
- headerlen = prevrawlensize+lensize;
- rawlen = headerlen+len;
+ entry = zipEntry(p);
+ rawlen = entry.headersize+entry.len;
if (target) {
- encoding = ZIP_ENCODING(p+prevrawlensize);
- if (encoding == ZIP_ENC_RAW) {
- *target = sdsnewlen(p+headerlen,len);
+ if (entry.encoding == ZIP_ENC_RAW) {
+ *target = sdsnewlen(p+entry.headersize,entry.len);
} else {
- value = zipLoadInteger(p+headerlen,encoding);
+ value = zipLoadInteger(p+entry.headersize,entry.encoding);
*target = sdscatprintf(sdsempty(), "%lld", value);
}
}
ZIPLIST_TAIL_OFFSET(zl) -= rawlen+nextdiff;
} else {
/* Subtract the length of the previous element from the tail offset. */
- ZIPLIST_TAIL_OFFSET(zl) -= prevrawlen;
+ ZIPLIST_TAIL_OFFSET(zl) -= entry.prevrawlen;
}
/* Resize and update length */
* to find out whether the string pointer or the integer value was set.
* Return 0 if 'p' points to the end of the zipmap, 1 otherwise. */
unsigned int ziplistGet(unsigned char *p, unsigned char **e, unsigned int *elen, long long *v) {
- unsigned int prevrawlensize, lensize, len, headerlen;
+ zlentry entry;
if (*p == ZIP_END) return 0;
if (e) *e = NULL;
- zipDecodeLength(p,&prevrawlensize);
- len = zipDecodeLength(p+prevrawlensize,&lensize);
- headerlen = prevrawlensize+lensize;
- if (ZIP_ENCODING(p+prevrawlensize) == ZIP_ENC_RAW) {
+ entry = zipEntry(p);
+ if (entry.encoding == ZIP_ENC_RAW) {
if (e) {
- *elen = len;
- *e = p+headerlen;
+ *elen = entry.len;
+ *e = p+entry.headersize;
}
} else {
if (v) {
- *v = zipLoadInteger(p+headerlen,ZIP_ENCODING(p+prevrawlensize));
+ *v = zipLoadInteger(p+entry.headersize,entry.encoding);
}
}
return 1;
}
/* Compare entry pointer to by 'p' with 'entry'. Return 1 if equal. */
-unsigned int ziplistCompare(unsigned char *p, unsigned char *entry, unsigned int elen) {
- unsigned int prevrawlensize, lensize, len, headerlen;
- char encoding;
- long long val, eval;
+unsigned int ziplistCompare(unsigned char *p, unsigned char *s, unsigned int slen) {
+ zlentry entry;
+ unsigned char sencoding;
+ long long val, sval;
if (*p == ZIP_END) return 0;
- zipDecodeLength(p,&prevrawlensize);
- len = zipDecodeLength(p+prevrawlensize,&lensize);
- headerlen = prevrawlensize+lensize;
- if (ZIP_ENCODING(p+prevrawlensize) == ZIP_ENC_RAW) {
+ entry = zipEntry(p);
+ if (entry.encoding == ZIP_ENC_RAW) {
/* Raw compare */
- if (len == elen) {
- return memcmp(p+headerlen,entry,elen) == 0;
+ if (entry.len == slen) {
+ return memcmp(p+entry.headersize,s,slen) == 0;
} else {
return 0;
}
} else {
- if (zipTryEncoding(entry,&eval,&encoding)) {
- /* Do integer compare */
- val = zipLoadInteger(p+headerlen,ZIP_ENCODING(p+prevrawlensize));
- return val == eval;
- } else {
- /* Ziplist entry is integer encoded, but given entry is not. */
+ /* Try to compare encoded values */
+ if (zipTryEncoding(s,&sval,&sencoding)) {
+ if (entry.encoding == sencoding) {
+ val = zipLoadInteger(p+entry.headersize,entry.encoding);
+ return val == sval;
+ }
}
}
return 0;
}
void ziplistRepr(unsigned char *zl) {
- unsigned char *p, encoding;
- unsigned int prevrawlensize, prevrawlen, lensize, len;
+ unsigned char *p;
+ zlentry entry;
printf("{total bytes %d} {length %u}\n",ZIPLIST_BYTES(zl), ZIPLIST_LENGTH(zl));
p = ziplistHead(zl);
while(*p != ZIP_END) {
- prevrawlen = zipDecodeLength(p,&prevrawlensize);
- len = zipDecodeLength(p+prevrawlensize,&lensize);
- printf("{offset %ld, header %u, payload %u} ",p-zl,prevrawlensize+lensize,len);
- encoding = ZIP_ENCODING(p+prevrawlensize);
- p += prevrawlensize+lensize;
- if (encoding == ZIP_ENC_RAW) {
- fwrite(p,len,1,stdout);
+ entry = zipEntry(p);
+ printf("{offset %ld, header %u, payload %u} ",p-zl,entry.headersize,entry.len);
+ p += entry.headersize;
+ if (entry.encoding == ZIP_ENC_RAW) {
+ fwrite(p,entry.len,1,stdout);
} else {
- printf("%lld", zipLoadInteger(p,encoding));
+ printf("%lld", zipLoadInteger(p,entry.encoding));
}
printf("\n");
- p += len;
+ p += entry.len;
}
printf("{end}\n\n");
}