mirror of
https://github.com/fluencelabs/redis
synced 2025-03-19 17:10:50 +00:00
function to insert an element at an arbitrary position in the list
This commit is contained in:
parent
0c0d056412
commit
6435c76772
77
ziplist.c
77
ziplist.c
@ -286,66 +286,79 @@ static unsigned char *__ziplistDelete(unsigned char *zl, unsigned char *p, int n
|
|||||||
return zl;
|
return zl;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *ziplistPush(unsigned char *zl, unsigned char *entry, unsigned int elen, int where) {
|
/* Insert item at "p". */
|
||||||
unsigned int curlen = ZIPLIST_BYTES(zl), reqlen, prevlen;
|
static unsigned char *__ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char *s, unsigned int slen) {
|
||||||
unsigned char *p, *curtail;
|
unsigned int curlen = ZIPLIST_BYTES(zl), reqlen, prevlen = 0;
|
||||||
|
unsigned int offset, nextdiff = 0;
|
||||||
|
unsigned char *tail;
|
||||||
char encoding = ZIP_ENC_RAW;
|
char encoding = ZIP_ENC_RAW;
|
||||||
long long value;
|
long long value;
|
||||||
|
zlentry entry;
|
||||||
|
|
||||||
/* We need to store the length of the current tail when the list
|
/* Find out prevlen for the entry that is inserted. */
|
||||||
* is non-empty and we push at the tail. */
|
if (p[0] != ZIP_END) {
|
||||||
curtail = zl+ZIPLIST_TAIL_OFFSET(zl);
|
entry = zipEntry(p);
|
||||||
if (where == ZIPLIST_TAIL && curtail[0] != ZIP_END) {
|
prevlen = entry.prevrawlen;
|
||||||
prevlen = zipRawEntryLength(curtail);
|
|
||||||
} else {
|
} else {
|
||||||
prevlen = 0;
|
tail = ziplistTail(zl);
|
||||||
|
if (tail[0] != ZIP_END) {
|
||||||
|
prevlen = zipRawEntryLength(tail);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See if the entry can be encoded */
|
/* See if the entry can be encoded */
|
||||||
if (zipTryEncoding(entry,&value,&encoding)) {
|
if (zipTryEncoding(s,&value,&encoding)) {
|
||||||
reqlen = zipEncodingSize(encoding);
|
reqlen = zipEncodingSize(encoding);
|
||||||
} else {
|
} else {
|
||||||
reqlen = elen;
|
reqlen = slen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need space for both the length of the previous entry and
|
/* We need space for both the length of the previous entry and
|
||||||
* the length of the payload. */
|
* the length of the payload. */
|
||||||
reqlen += zipEncodeLength(NULL,ZIP_ENC_RAW,prevlen);
|
reqlen += zipEncodeLength(NULL,ZIP_ENC_RAW,prevlen);
|
||||||
reqlen += zipEncodeLength(NULL,encoding,elen);
|
reqlen += zipEncodeLength(NULL,encoding,slen);
|
||||||
|
|
||||||
/* Resize the ziplist and move if needed */
|
/* When the insert position is not equal to the tail, we need to
|
||||||
zl = ziplistResize(zl,curlen+reqlen);
|
* make sure that the next entry can hold this entry's length in
|
||||||
if (where == ZIPLIST_HEAD) {
|
* its prevlen field. */
|
||||||
p = zl+ZIPLIST_HEADER_SIZE;
|
nextdiff = p[0] != ZIP_END ? zipPrevLenByteDiff(p,reqlen) : 0;
|
||||||
if (*p != ZIP_END) {
|
|
||||||
/* Subtract one because of the ZIP_END bytes */
|
/* Store offset because a realloc may change the address of zl. */
|
||||||
memmove(p+reqlen,p,curlen-ZIPLIST_HEADER_SIZE-1);
|
offset = p-zl;
|
||||||
}
|
zl = ziplistResize(zl,curlen+reqlen+nextdiff);
|
||||||
|
p = zl+offset;
|
||||||
|
|
||||||
|
/* Apply memory move when necessary and update tail offset. */
|
||||||
|
if (p[0] != ZIP_END) {
|
||||||
|
/* Subtract one because of the ZIP_END bytes */
|
||||||
|
memmove(p+reqlen,p-nextdiff,curlen-offset-1+nextdiff);
|
||||||
|
/* Encode this entry's raw length in the next entry. */
|
||||||
|
zipEncodeLength(p+reqlen,ZIP_ENC_RAW,reqlen);
|
||||||
|
/* Update offset for tail */
|
||||||
|
ZIPLIST_TAIL_OFFSET(zl) += reqlen+nextdiff;
|
||||||
} else {
|
} else {
|
||||||
p = zl+curlen-1;
|
/* This element will be the new tail. */
|
||||||
}
|
ZIPLIST_TAIL_OFFSET(zl) = p-zl;
|
||||||
|
|
||||||
/* Update tail offset if this is not the first element */
|
|
||||||
if (curtail[0] != ZIP_END) {
|
|
||||||
if (where == ZIPLIST_HEAD) {
|
|
||||||
ZIPLIST_TAIL_OFFSET(zl) += reqlen;
|
|
||||||
} else {
|
|
||||||
ZIPLIST_TAIL_OFFSET(zl) += prevlen;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the entry */
|
/* Write the entry */
|
||||||
p += zipEncodeLength(p,ZIP_ENC_RAW,prevlen);
|
p += zipEncodeLength(p,ZIP_ENC_RAW,prevlen);
|
||||||
p += zipEncodeLength(p,encoding,elen);
|
p += zipEncodeLength(p,encoding,slen);
|
||||||
if (encoding != ZIP_ENC_RAW) {
|
if (encoding != ZIP_ENC_RAW) {
|
||||||
zipSaveInteger(p,value,encoding);
|
zipSaveInteger(p,value,encoding);
|
||||||
} else {
|
} else {
|
||||||
memcpy(p,entry,elen);
|
memcpy(p,s,slen);
|
||||||
}
|
}
|
||||||
ZIPLIST_INCR_LENGTH(zl,1);
|
ZIPLIST_INCR_LENGTH(zl,1);
|
||||||
return zl;
|
return zl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned char *ziplistPush(unsigned char *zl, unsigned char *s, unsigned int slen, int where) {
|
||||||
|
unsigned char *p;
|
||||||
|
p = (where == ZIPLIST_HEAD) ? ziplistHead(zl) : (zl+ZIPLIST_BYTES(zl)-1);
|
||||||
|
return __ziplistInsert(zl,p,s,slen);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char *ziplistPop(unsigned char *zl, sds *target, int where) {
|
unsigned char *ziplistPop(unsigned char *zl, sds *target, int where) {
|
||||||
zlentry entry;
|
zlentry entry;
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user