ziplist.c fixes for bigendian
This commit is contained in:
parent
ac834d237a
commit
5653847714
17
src/endian.c
17
src/endian.c
@ -1,3 +1,5 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/* Toggle the 16 bit unsigned integer pointed by *p from little endian to
|
/* Toggle the 16 bit unsigned integer pointed by *p from little endian to
|
||||||
* big endian */
|
* big endian */
|
||||||
void memrev16(void *p) {
|
void memrev16(void *p) {
|
||||||
@ -40,6 +42,21 @@ void memrev64(void *p) {
|
|||||||
x[4] = t;
|
x[4] = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t intrev16(uint16_t v) {
|
||||||
|
memrev16(&v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t intrev32(uint32_t v) {
|
||||||
|
memrev32(&v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t intrev64(uint64_t v) {
|
||||||
|
memrev64(&v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TESTMAIN
|
#ifdef TESTMAIN
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
@ -11,10 +11,16 @@ void memrev64(void *p);
|
|||||||
#define memrev16ifbe(p)
|
#define memrev16ifbe(p)
|
||||||
#define memrev32ifbe(p)
|
#define memrev32ifbe(p)
|
||||||
#define memrev64ifbe(p)
|
#define memrev64ifbe(p)
|
||||||
|
#define intrev16ifbe(v) (v)
|
||||||
|
#define intrev32ifbe(v) (v)
|
||||||
|
#define intrev64ifbe(v) (v)
|
||||||
#else
|
#else
|
||||||
#define memrev16ifbe(p) memrev16(p)
|
#define memrev16ifbe(p) memrev16(p)
|
||||||
#define memrev32ifbe(p) memrev32(p)
|
#define memrev32ifbe(p) memrev32(p)
|
||||||
#define memrev64ifbe(p) memrev64(p)
|
#define memrev64ifbe(p) memrev64(p)
|
||||||
|
#define intrev16ifbe(v) intrev16(v)
|
||||||
|
#define intrev32ifbe(v) intrev32(v)
|
||||||
|
#define intrev64ifbe(v) intrev64(v)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -98,7 +98,9 @@
|
|||||||
/* We know a positive increment can only be 1 because entries can only be
|
/* We know a positive increment can only be 1 because entries can only be
|
||||||
* pushed one at a time. */
|
* pushed one at a time. */
|
||||||
#define ZIPLIST_INCR_LENGTH(zl,incr) { \
|
#define ZIPLIST_INCR_LENGTH(zl,incr) { \
|
||||||
if (ZIPLIST_LENGTH(zl) < UINT16_MAX) ZIPLIST_LENGTH(zl)+=incr; }
|
if (ZIPLIST_LENGTH(zl) < UINT16_MAX) \
|
||||||
|
ZIPLIST_LENGTH(zl) += intrev16ifbe(incr); \
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct zlentry {
|
typedef struct zlentry {
|
||||||
unsigned int prevrawlensize, prevrawlen;
|
unsigned int prevrawlensize, prevrawlen;
|
||||||
@ -335,8 +337,8 @@ static unsigned int zipRawEntryLength(unsigned char *p) {
|
|||||||
unsigned char *ziplistNew(void) {
|
unsigned char *ziplistNew(void) {
|
||||||
unsigned int bytes = ZIPLIST_HEADER_SIZE+1;
|
unsigned int bytes = ZIPLIST_HEADER_SIZE+1;
|
||||||
unsigned char *zl = zmalloc(bytes);
|
unsigned char *zl = zmalloc(bytes);
|
||||||
ZIPLIST_BYTES(zl) = bytes;
|
ZIPLIST_BYTES(zl) = intrev32ifbe(bytes);
|
||||||
ZIPLIST_TAIL_OFFSET(zl) = ZIPLIST_HEADER_SIZE;
|
ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(ZIPLIST_HEADER_SIZE);
|
||||||
ZIPLIST_LENGTH(zl) = 0;
|
ZIPLIST_LENGTH(zl) = 0;
|
||||||
zl[bytes-1] = ZIP_END;
|
zl[bytes-1] = ZIP_END;
|
||||||
return zl;
|
return zl;
|
||||||
@ -345,7 +347,7 @@ unsigned char *ziplistNew(void) {
|
|||||||
/* Resize the ziplist. */
|
/* Resize the ziplist. */
|
||||||
static unsigned char *ziplistResize(unsigned char *zl, unsigned int len) {
|
static unsigned char *ziplistResize(unsigned char *zl, unsigned int len) {
|
||||||
zl = zrealloc(zl,len);
|
zl = zrealloc(zl,len);
|
||||||
ZIPLIST_BYTES(zl) = len;
|
ZIPLIST_BYTES(zl) = intrev32ifbe(len);
|
||||||
zl[len-1] = ZIP_END;
|
zl[len-1] = ZIP_END;
|
||||||
return zl;
|
return zl;
|
||||||
}
|
}
|
||||||
@ -371,7 +373,7 @@ static unsigned char *ziplistResize(unsigned char *zl, unsigned int len) {
|
|||||||
* The pointer "p" points to the first entry that does NOT need to be
|
* The pointer "p" points to the first entry that does NOT need to be
|
||||||
* updated, i.e. consecutive fields MAY need an update. */
|
* updated, i.e. consecutive fields MAY need an update. */
|
||||||
static unsigned char *__ziplistCascadeUpdate(unsigned char *zl, unsigned char *p) {
|
static unsigned char *__ziplistCascadeUpdate(unsigned char *zl, unsigned char *p) {
|
||||||
size_t curlen = ZIPLIST_BYTES(zl), rawlen, rawlensize;
|
size_t curlen = intrev32ifbe(ZIPLIST_BYTES(zl)), rawlen, rawlensize;
|
||||||
size_t offset, noffset, extra;
|
size_t offset, noffset, extra;
|
||||||
unsigned char *np;
|
unsigned char *np;
|
||||||
zlentry cur, next;
|
zlentry cur, next;
|
||||||
@ -401,8 +403,8 @@ static unsigned char *__ziplistCascadeUpdate(unsigned char *zl, unsigned char *p
|
|||||||
noffset = np-zl;
|
noffset = np-zl;
|
||||||
|
|
||||||
/* Update tail offset when next element is not the tail element. */
|
/* Update tail offset when next element is not the tail element. */
|
||||||
if ((zl+ZIPLIST_TAIL_OFFSET(zl)) != np)
|
if ((zl+intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl))) != np)
|
||||||
ZIPLIST_TAIL_OFFSET(zl) += extra;
|
ZIPLIST_TAIL_OFFSET(zl) += intrev32ifbe(extra);
|
||||||
|
|
||||||
/* Move the tail to the back. */
|
/* Move the tail to the back. */
|
||||||
memmove(np+rawlensize,
|
memmove(np+rawlensize,
|
||||||
@ -453,25 +455,27 @@ static unsigned char *__ziplistDelete(unsigned char *zl, unsigned char *p, unsig
|
|||||||
zipPrevEncodeLength(p-nextdiff,first.prevrawlen);
|
zipPrevEncodeLength(p-nextdiff,first.prevrawlen);
|
||||||
|
|
||||||
/* Update offset for tail */
|
/* Update offset for tail */
|
||||||
ZIPLIST_TAIL_OFFSET(zl) -= totlen;
|
ZIPLIST_TAIL_OFFSET(zl) -= intrev32ifbe(totlen);
|
||||||
|
|
||||||
/* When the tail contains more than one entry, we need to take
|
/* When the tail contains more than one entry, we need to take
|
||||||
* "nextdiff" in account as well. Otherwise, a change in the
|
* "nextdiff" in account as well. Otherwise, a change in the
|
||||||
* size of prevlen doesn't have an effect on the *tail* offset. */
|
* size of prevlen doesn't have an effect on the *tail* offset. */
|
||||||
tail = zipEntry(p);
|
tail = zipEntry(p);
|
||||||
if (p[tail.headersize+tail.len] != ZIP_END)
|
if (p[tail.headersize+tail.len] != ZIP_END)
|
||||||
ZIPLIST_TAIL_OFFSET(zl) += nextdiff;
|
ZIPLIST_TAIL_OFFSET(zl) += intrev32ifbe(nextdiff);
|
||||||
|
|
||||||
/* Move tail to the front of the ziplist */
|
/* Move tail to the front of the ziplist */
|
||||||
memmove(first.p,p-nextdiff,ZIPLIST_BYTES(zl)-(p-zl)-1+nextdiff);
|
memmove(first.p,p-nextdiff,
|
||||||
|
intrev32ifbe(ZIPLIST_BYTES(zl))-(p-zl)-1+nextdiff);
|
||||||
} else {
|
} else {
|
||||||
/* The entire tail was deleted. No need to move memory. */
|
/* The entire tail was deleted. No need to move memory. */
|
||||||
ZIPLIST_TAIL_OFFSET(zl) = (first.p-zl)-first.prevrawlen;
|
ZIPLIST_TAIL_OFFSET(zl) =
|
||||||
|
intrev32ifbe((first.p-zl)-first.prevrawlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resize and update length */
|
/* Resize and update length */
|
||||||
offset = first.p-zl;
|
offset = first.p-zl;
|
||||||
zl = ziplistResize(zl, ZIPLIST_BYTES(zl)-totlen+nextdiff);
|
zl = ziplistResize(zl, intrev32ifbe(ZIPLIST_BYTES(zl))-totlen+nextdiff);
|
||||||
ZIPLIST_INCR_LENGTH(zl,-deleted);
|
ZIPLIST_INCR_LENGTH(zl,-deleted);
|
||||||
p = zl+offset;
|
p = zl+offset;
|
||||||
|
|
||||||
@ -485,7 +489,7 @@ static unsigned char *__ziplistDelete(unsigned char *zl, unsigned char *p, unsig
|
|||||||
|
|
||||||
/* Insert item at "p". */
|
/* Insert item at "p". */
|
||||||
static unsigned char *__ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char *s, unsigned int slen) {
|
static unsigned char *__ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char *s, unsigned int slen) {
|
||||||
size_t curlen = ZIPLIST_BYTES(zl), reqlen, prevlen = 0;
|
size_t curlen = intrev32ifbe(ZIPLIST_BYTES(zl)), reqlen, prevlen = 0;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
int nextdiff = 0;
|
int nextdiff = 0;
|
||||||
unsigned char encoding = 0;
|
unsigned char encoding = 0;
|
||||||
@ -538,17 +542,17 @@ static unsigned char *__ziplistInsert(unsigned char *zl, unsigned char *p, unsig
|
|||||||
zipPrevEncodeLength(p+reqlen,reqlen);
|
zipPrevEncodeLength(p+reqlen,reqlen);
|
||||||
|
|
||||||
/* Update offset for tail */
|
/* Update offset for tail */
|
||||||
ZIPLIST_TAIL_OFFSET(zl) += reqlen;
|
ZIPLIST_TAIL_OFFSET(zl) += intrev32ifbe(reqlen);
|
||||||
|
|
||||||
/* When the tail contains more than one entry, we need to take
|
/* When the tail contains more than one entry, we need to take
|
||||||
* "nextdiff" in account as well. Otherwise, a change in the
|
* "nextdiff" in account as well. Otherwise, a change in the
|
||||||
* size of prevlen doesn't have an effect on the *tail* offset. */
|
* size of prevlen doesn't have an effect on the *tail* offset. */
|
||||||
tail = zipEntry(p+reqlen);
|
tail = zipEntry(p+reqlen);
|
||||||
if (p[reqlen+tail.headersize+tail.len] != ZIP_END)
|
if (p[reqlen+tail.headersize+tail.len] != ZIP_END)
|
||||||
ZIPLIST_TAIL_OFFSET(zl) += nextdiff;
|
ZIPLIST_TAIL_OFFSET(zl) += intrev32ifbe(nextdiff);
|
||||||
} else {
|
} else {
|
||||||
/* This element will be the new tail. */
|
/* This element will be the new tail. */
|
||||||
ZIPLIST_TAIL_OFFSET(zl) = p-zl;
|
ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(p-zl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When nextdiff != 0, the raw length of the next entry has changed, so
|
/* When nextdiff != 0, the raw length of the next entry has changed, so
|
||||||
@ -720,8 +724,8 @@ unsigned int ziplistCompare(unsigned char *p, unsigned char *sstr, unsigned int
|
|||||||
/* Return length of ziplist. */
|
/* Return length of ziplist. */
|
||||||
unsigned int ziplistLen(unsigned char *zl) {
|
unsigned int ziplistLen(unsigned char *zl) {
|
||||||
unsigned int len = 0;
|
unsigned int len = 0;
|
||||||
if (ZIPLIST_LENGTH(zl) < UINT16_MAX) {
|
if (intrev16ifbe(ZIPLIST_LENGTH(zl)) < UINT16_MAX) {
|
||||||
len = ZIPLIST_LENGTH(zl);
|
len = intrev16ifbe(ZIPLIST_LENGTH(zl));
|
||||||
} else {
|
} else {
|
||||||
unsigned char *p = zl+ZIPLIST_HEADER_SIZE;
|
unsigned char *p = zl+ZIPLIST_HEADER_SIZE;
|
||||||
while (*p != ZIP_END) {
|
while (*p != ZIP_END) {
|
||||||
@ -730,14 +734,14 @@ unsigned int ziplistLen(unsigned char *zl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Re-store length if small enough */
|
/* Re-store length if small enough */
|
||||||
if (len < UINT16_MAX) ZIPLIST_LENGTH(zl) = len;
|
if (len < UINT16_MAX) ZIPLIST_LENGTH(zl) = intrev16ifbe(len);
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return ziplist blob size in bytes. */
|
/* Return ziplist blob size in bytes. */
|
||||||
size_t ziplistBlobLen(unsigned char *zl) {
|
size_t ziplistBlobLen(unsigned char *zl) {
|
||||||
return ZIPLIST_BYTES(zl);
|
return intrev32ifbe(ZIPLIST_BYTES(zl));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ziplistRepr(unsigned char *zl) {
|
void ziplistRepr(unsigned char *zl) {
|
||||||
@ -749,9 +753,9 @@ void ziplistRepr(unsigned char *zl) {
|
|||||||
"{total bytes %d} "
|
"{total bytes %d} "
|
||||||
"{length %u}\n"
|
"{length %u}\n"
|
||||||
"{tail offset %u}\n",
|
"{tail offset %u}\n",
|
||||||
ZIPLIST_BYTES(zl),
|
intrev32ifbe(ZIPLIST_BYTES(zl)),
|
||||||
ZIPLIST_LENGTH(zl),
|
intrev16ifbe(ZIPLIST_LENGTH(zl)),
|
||||||
ZIPLIST_TAIL_OFFSET(zl));
|
intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl)));
|
||||||
p = ZIPLIST_ENTRY_HEAD(zl);
|
p = ZIPLIST_ENTRY_HEAD(zl);
|
||||||
while(*p != ZIP_END) {
|
while(*p != ZIP_END) {
|
||||||
entry = zipEntry(p);
|
entry = zipEntry(p);
|
||||||
@ -852,7 +856,7 @@ void stress(int pos, int num, int maxsize, int dnum) {
|
|||||||
zl = ziplistDeleteRange(zl,0,1);
|
zl = ziplistDeleteRange(zl,0,1);
|
||||||
}
|
}
|
||||||
printf("List size: %8d, bytes: %8d, %dx push+pop (%s): %6lld usec\n",
|
printf("List size: %8d, bytes: %8d, %dx push+pop (%s): %6lld usec\n",
|
||||||
i,ZIPLIST_BYTES(zl),num,posstr[pos],usec()-start);
|
i,intrev32ifbe(ZIPLIST_BYTES(zl)),num,posstr[pos],usec()-start);
|
||||||
zfree(zl);
|
zfree(zl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user