Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/redis.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ struct redisCommand redisCommandTable[] = {
{"setex",setexCommand,4,"wm",0,NULL,1,1,1,0,0},
{"psetex",psetexCommand,4,"wm",0,NULL,1,1,1,0,0},
{"append",appendCommand,3,"wm",0,NULL,1,1,1,0,0},
{"prepend",prependCommand,3,"wm",0,NULL,1,1,1,0,0},
{"prependfe",prependfeCommand,3,"wm",0,NULL,1,1,1,0,0},
{"strlen",strlenCommand,2,"rF",0,NULL,1,1,1,0,0},
{"del",delCommand,-2,"w",0,NULL,1,-1,1,0,0},
{"exists",existsCommand,2,"rF",0,NULL,1,1,1,0,0},
Expand Down
2 changes: 2 additions & 0 deletions src/redis.h
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,8 @@ void blpopCommand(redisClient *c);
void brpopCommand(redisClient *c);
void brpoplpushCommand(redisClient *c);
void appendCommand(redisClient *c);
void prependCommand(redisClient *c);
void prependfeCommand(redisClient *c);
void strlenCommand(redisClient *c);
void zrankCommand(redisClient *c);
void zrevrankCommand(redisClient *c);
Expand Down
20 changes: 20 additions & 0 deletions src/sds.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,26 @@ sds sdscatlen(sds s, const void *t, size_t len) {
return s;
}

/* Prepend the specified binary-safe string pointed by 't' of 'len' bytes to the
* beginning of the specified sds string 's'.
*
* After the call, the passed sds string is no longer valid and all the
* references must be substituted with the new pointer returned by the call. */
sds sdsprecatlen(sds s, const void *t, size_t len) {
struct sdshdr *sh;
size_t curlen = sdslen(s);

s = sdsMakeRoomFor(s,len);
if (s == NULL) return NULL;
sh = (void*) (s-(sizeof(struct sdshdr)));
memmove(s+len, s, curlen);
memcpy(s, t, len);
sh->len = curlen+len;
sh->free = sh->free-len;
s[curlen+len] = '\0';
return s;
}

/* Append the specified null termianted C string to the sds string 's'.
*
* After the call, the passed sds string is no longer valid and all the
Expand Down
1 change: 1 addition & 0 deletions src/sds.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ void sdsfree(sds s);
size_t sdsavail(const sds s);
sds sdsgrowzero(sds s, size_t len);
sds sdscatlen(sds s, const void *t, size_t len);
sds sdsprecatlen(sds s, const void *t, size_t len);
sds sdscat(sds s, const char *t);
sds sdscatsds(sds s, const sds t);
sds sdscpylen(sds s, const char *t, size_t len);
Expand Down
75 changes: 75 additions & 0 deletions src/t_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,81 @@ void appendCommand(redisClient *c) {
addReplyLongLong(c,totlen);
}

void prependCommand(redisClient *c) {
size_t totlen;
robj *o, *prepend;

o = lookupKeyWrite(c->db,c->argv[1]);
if (o == NULL) {
/* Create the key */
c->argv[2] = tryObjectEncoding(c->argv[2]);
dbAdd(c->db,c->argv[1],c->argv[2]);
incrRefCount(c->argv[2]);
totlen = stringObjectLen(c->argv[2]);
} else {
/* Key exists, check type */
if (checkType(c,o,REDIS_STRING))
return;

/* "prepend" is an argument, so always an sds */
prepend = c->argv[2];
totlen = stringObjectLen(o)+sdslen(prepend->ptr);
if (checkStringLength(c,totlen) != REDIS_OK)
return;

/* Prepend the value */
o = dbUnshareStringValue(c->db,c->argv[1],o);
o->ptr = sdsprecatlen(o->ptr,prepend->ptr,sdslen(prepend->ptr));
totlen = sdslen(o->ptr);
}
signalModifiedKey(c->db,c->argv[1]);
notifyKeyspaceEvent(REDIS_NOTIFY_STRING,"prepend",c->argv[1],c->db->id);
server.dirty++;
addReplyLongLong(c,totlen);
}

void prependfeCommand(redisClient *c) {
size_t totlen;
robj *o, *prepend;

o = lookupKeyWrite(c->db,c->argv[1]);
if (o == NULL) {
/* Create the key */
c->argv[2] = tryObjectEncoding(c->argv[2]);
dbAdd(c->db,c->argv[1],c->argv[2]);
incrRefCount(c->argv[2]);
totlen = stringObjectLen(c->argv[2]);
} else {
/* Key exists, check type */
if (checkType(c,o,REDIS_STRING))
return;

/* "prepend" is an argument, so always an sds */
prepend = c->argv[2];
totlen = stringObjectLen(o)+sdslen(prepend->ptr);
if (checkStringLength(c,totlen) != REDIS_OK)
return;

/* Check to see if the first bytes match */
/* if they do, no change is needed */
if(((char*)o->ptr)[0] == ((char*)prepend->ptr)[0]){
addReplyLongLong(c,stringObjectLen(o));
return;
}

/* Prepend the value */
else {
o = dbUnshareStringValue(c->db,c->argv[1],o);
o->ptr = sdsprecatlen(o->ptr,prepend->ptr,sdslen(prepend->ptr));
totlen = sdslen(o->ptr);
}
}
signalModifiedKey(c->db,c->argv[1]);
notifyKeyspaceEvent(REDIS_NOTIFY_STRING,"prepend",c->argv[1],c->db->id);
server.dirty++;
addReplyLongLong(c,totlen);
}

void strlenCommand(redisClient *c) {
robj *o;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||
Expand Down