X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/dcb9cf4e8213744e431f38722d04b841f78b316c..bb57b965c4252a48472d99a1b2e7a30d66d65796:/ziplist.c diff --git a/ziplist.c b/ziplist.c index adb7d054..16e9dbc1 100644 --- a/ziplist.c +++ b/ziplist.c @@ -51,6 +51,13 @@ #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) { @@ -192,14 +199,20 @@ static long long zipLoadInteger(unsigned char *p, char encoding) { return ret; } -/* Return the total amount used by an entry (encoded length + payload). */ +/* 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 number of bytes used by the entry at "p". */ static unsigned int zipRawEntryLength(unsigned char *p) { - unsigned int prevlensize, lensize, len; - /* Byte-size of encoded length of previous entry */ - zipDecodeLength(p,&prevlensize); - /* Encoded length of this entry's payload */ - len = zipDecodeLength(p+prevlensize, &lensize); - return prevlensize+lensize+len; + zlentry e = zipEntry(p); + return e.headersize + e.len; } /* Create a new empty ziplist. */ @@ -297,9 +310,8 @@ unsigned char *ziplistPush(unsigned char *zl, unsigned char *entry, unsigned int 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; @@ -308,16 +320,13 @@ unsigned char *ziplistPop(unsigned char *zl, sds *target, int where) { 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); } } @@ -342,7 +351,7 @@ unsigned char *ziplistPop(unsigned char *zl, sds *target, int where) { 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 */ @@ -371,22 +380,20 @@ unsigned char *ziplistNext(unsigned char *p) { * on the encoding of the entry. 'e' is always set to NULL to be able * 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; +unsigned int ziplistGet(unsigned char *p, unsigned char **sstr, unsigned int *slen, long long *sval) { + 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) { - if (e) { - *elen = len; - *e = p+headerlen; + if (sstr) *sstr = NULL; + + entry = zipEntry(p); + if (entry.encoding == ZIP_ENC_RAW) { + if (sstr) { + *slen = entry.len; + *sstr = p+entry.headersize; } } else { - if (v) { - *v = zipLoadInteger(p+headerlen,ZIP_ENCODING(p+prevrawlensize)); + if (sval) { + *sval = zipLoadInteger(p+entry.headersize,entry.encoding); } } return 1; @@ -435,29 +442,27 @@ unsigned char *ziplistDelete(unsigned char *zl, unsigned char **p) { } /* 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 *sstr, 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,sstr,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(sstr,&sval,&sencoding)) { + if (entry.encoding == sencoding) { + val = zipLoadInteger(p+entry.headersize,entry.encoding); + return val == sval; + } } } return 0; @@ -487,24 +492,22 @@ unsigned int ziplistSize(unsigned char *zl) { } 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"); }