Update hiredis
This commit is contained in:
parent
8df3dcada5
commit
afc156c2d8
98
deps/hiredis/hiredis.c
vendored
98
deps/hiredis/hiredis.c
vendored
@ -162,11 +162,20 @@ static char *readBytes(redisReader *r, unsigned int bytes) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *seekNewline(char *s) {
|
||||||
|
/* Find pointer to \r\n without strstr */
|
||||||
|
while(s != NULL && s[0] != '\r' && s[1] != '\n')
|
||||||
|
s = strchr(s,'\r');
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
static char *readLine(redisReader *r, int *_len) {
|
static char *readLine(redisReader *r, int *_len) {
|
||||||
char *p, *s = strstr(r->buf+r->pos,"\r\n");
|
char *p, *s;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
p = r->buf+r->pos;
|
||||||
|
s = seekNewline(p);
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
p = r->buf+r->pos;
|
|
||||||
len = s-(r->buf+r->pos);
|
len = s-(r->buf+r->pos);
|
||||||
r->pos += len+2; /* skip \r\n */
|
r->pos += len+2; /* skip \r\n */
|
||||||
if (_len) *_len = len;
|
if (_len) *_len = len;
|
||||||
@ -177,26 +186,26 @@ static char *readLine(redisReader *r, int *_len) {
|
|||||||
|
|
||||||
static void moveToNextTask(redisReader *r) {
|
static void moveToNextTask(redisReader *r) {
|
||||||
redisReadTask *cur, *prv;
|
redisReadTask *cur, *prv;
|
||||||
assert(r->ridx >= 0);
|
while (r->ridx >= 0) {
|
||||||
|
/* Return a.s.a.p. when the stack is now empty. */
|
||||||
|
if (r->ridx == 0) {
|
||||||
|
r->ridx--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return a.s.a.p. when the stack is now empty. */
|
cur = &(r->rstack[r->ridx]);
|
||||||
if (r->ridx == 0) {
|
prv = &(r->rstack[r->ridx-1]);
|
||||||
r->ridx--;
|
assert(prv->type == REDIS_REPLY_ARRAY);
|
||||||
return;
|
if (cur->idx == prv->elements-1) {
|
||||||
}
|
r->ridx--;
|
||||||
|
} else {
|
||||||
cur = &(r->rstack[r->ridx]);
|
/* Reset the type because the next item can be anything */
|
||||||
prv = &(r->rstack[r->ridx-1]);
|
assert(cur->idx < prv->elements);
|
||||||
assert(prv->type == REDIS_REPLY_ARRAY);
|
cur->type = -1;
|
||||||
if (cur->idx == prv->elements-1) {
|
cur->elements = -1;
|
||||||
r->ridx--;
|
cur->idx++;
|
||||||
moveToNextTask(r);
|
return;
|
||||||
} else {
|
}
|
||||||
/* Reset the type because the next item can be anything */
|
|
||||||
assert(cur->idx < prv->elements);
|
|
||||||
cur->type = -1;
|
|
||||||
cur->elements = -1;
|
|
||||||
cur->idx++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,10 +216,14 @@ static int processLineItem(redisReader *r) {
|
|||||||
int len;
|
int len;
|
||||||
|
|
||||||
if ((p = readLine(r,&len)) != NULL) {
|
if ((p = readLine(r,&len)) != NULL) {
|
||||||
if (cur->type == REDIS_REPLY_INTEGER) {
|
if (r->fn) {
|
||||||
obj = r->fn->createInteger(cur,strtoll(p,NULL,10));
|
if (cur->type == REDIS_REPLY_INTEGER) {
|
||||||
|
obj = r->fn->createInteger(cur,strtoll(p,NULL,10));
|
||||||
|
} else {
|
||||||
|
obj = r->fn->createString(cur,p,len);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
obj = r->fn->createString(cur,p,len);
|
obj = (void*)(size_t)(cur->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there is no root yet, register this object as root. */
|
/* If there is no root yet, register this object as root. */
|
||||||
@ -230,7 +243,7 @@ static int processBulkItem(redisReader *r) {
|
|||||||
unsigned long bytelen;
|
unsigned long bytelen;
|
||||||
|
|
||||||
p = r->buf+r->pos;
|
p = r->buf+r->pos;
|
||||||
s = strstr(p,"\r\n");
|
s = seekNewline(p);
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
p = r->buf+r->pos;
|
p = r->buf+r->pos;
|
||||||
bytelen = s-(r->buf+r->pos)+2; /* include \r\n */
|
bytelen = s-(r->buf+r->pos)+2; /* include \r\n */
|
||||||
@ -238,12 +251,14 @@ static int processBulkItem(redisReader *r) {
|
|||||||
|
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
/* The nil object can always be created. */
|
/* The nil object can always be created. */
|
||||||
obj = r->fn->createNil(cur);
|
obj = r->fn ? r->fn->createNil(cur) :
|
||||||
|
(void*)REDIS_REPLY_NIL;
|
||||||
} else {
|
} else {
|
||||||
/* Only continue when the buffer contains the entire bulk item. */
|
/* Only continue when the buffer contains the entire bulk item. */
|
||||||
bytelen += len+2; /* include \r\n */
|
bytelen += len+2; /* include \r\n */
|
||||||
if (r->pos+bytelen <= sdslen(r->buf)) {
|
if (r->pos+bytelen <= sdslen(r->buf)) {
|
||||||
obj = r->fn->createString(cur,s+2,len);
|
obj = r->fn ? r->fn->createString(cur,s+2,len) :
|
||||||
|
(void*)REDIS_REPLY_STRING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,10 +283,12 @@ static int processMultiBulkItem(redisReader *r) {
|
|||||||
if ((p = readLine(r,NULL)) != NULL) {
|
if ((p = readLine(r,NULL)) != NULL) {
|
||||||
elements = strtol(p,NULL,10);
|
elements = strtol(p,NULL,10);
|
||||||
if (elements == -1) {
|
if (elements == -1) {
|
||||||
obj = r->fn->createNil(cur);
|
obj = r->fn ? r->fn->createNil(cur) :
|
||||||
|
(void*)REDIS_REPLY_NIL;
|
||||||
moveToNextTask(r);
|
moveToNextTask(r);
|
||||||
} else {
|
} else {
|
||||||
obj = r->fn->createArray(cur,elements);
|
obj = r->fn ? r->fn->createArray(cur,elements) :
|
||||||
|
(void*)REDIS_REPLY_ARRAY;
|
||||||
|
|
||||||
/* Modify task stack when there are more than 0 elements. */
|
/* Modify task stack when there are more than 0 elements. */
|
||||||
if (elements > 0) {
|
if (elements > 0) {
|
||||||
@ -348,15 +365,26 @@ static int processItem(redisReader *r) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *redisReplyReaderCreate(redisReplyObjectFunctions *fn) {
|
void *redisReplyReaderCreate() {
|
||||||
redisReader *r = calloc(sizeof(redisReader),1);
|
redisReader *r = calloc(sizeof(redisReader),1);
|
||||||
r->error = NULL;
|
r->error = NULL;
|
||||||
r->fn = fn == NULL ? &defaultFunctions : fn;
|
r->fn = &defaultFunctions;
|
||||||
r->buf = sdsempty();
|
r->buf = sdsempty();
|
||||||
r->ridx = -1;
|
r->ridx = -1;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the function set to build the reply. Returns REDIS_OK when there
|
||||||
|
* is no temporary object and it can be set, REDIS_ERR otherwise. */
|
||||||
|
int redisReplyReaderSetReplyObjectFunctions(void *reader, redisReplyObjectFunctions *fn) {
|
||||||
|
redisReader *r = reader;
|
||||||
|
if (r->reply == NULL) {
|
||||||
|
r->fn = fn;
|
||||||
|
return REDIS_OK;
|
||||||
|
}
|
||||||
|
return REDIS_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
/* External libraries wrapping hiredis might need access to the temporary
|
/* External libraries wrapping hiredis might need access to the temporary
|
||||||
* variable while the reply is built up. When the reader contains an
|
* variable while the reply is built up. When the reader contains an
|
||||||
* object in between receiving some bytes to parse, this object might
|
* object in between receiving some bytes to parse, this object might
|
||||||
@ -370,7 +398,7 @@ void redisReplyReaderFree(void *reader) {
|
|||||||
redisReader *r = reader;
|
redisReader *r = reader;
|
||||||
if (r->error != NULL)
|
if (r->error != NULL)
|
||||||
sdsfree(r->error);
|
sdsfree(r->error);
|
||||||
if (r->reply != NULL)
|
if (r->reply != NULL && r->fn)
|
||||||
r->fn->freeObject(r->reply);
|
r->fn->freeObject(r->reply);
|
||||||
if (r->buf != NULL)
|
if (r->buf != NULL)
|
||||||
sdsfree(r->buf);
|
sdsfree(r->buf);
|
||||||
@ -695,8 +723,10 @@ int redisSetReplyObjectFunctions(redisContext *c, redisReplyObjectFunctions *fn)
|
|||||||
|
|
||||||
/* Helper function to lazily create a reply reader. */
|
/* Helper function to lazily create a reply reader. */
|
||||||
static void __redisCreateReplyReader(redisContext *c) {
|
static void __redisCreateReplyReader(redisContext *c) {
|
||||||
if (c->reader == NULL)
|
if (c->reader == NULL) {
|
||||||
c->reader = redisReplyReaderCreate(c->fn);
|
c->reader = redisReplyReaderCreate();
|
||||||
|
assert(redisReplyReaderSetReplyObjectFunctions(c->reader,c->fn) == REDIS_OK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use this function to handle a read event on the descriptor. It will try
|
/* Use this function to handle a read event on the descriptor. It will try
|
||||||
|
3
deps/hiredis/hiredis.h
vendored
3
deps/hiredis/hiredis.h
vendored
@ -110,7 +110,8 @@ typedef struct redisContext {
|
|||||||
} redisContext;
|
} redisContext;
|
||||||
|
|
||||||
void freeReplyObject(void *reply);
|
void freeReplyObject(void *reply);
|
||||||
void *redisReplyReaderCreate(redisReplyObjectFunctions *fn);
|
void *redisReplyReaderCreate();
|
||||||
|
int redisReplyReaderSetReplyObjectFunctions(void *reader, redisReplyObjectFunctions *fn);
|
||||||
void *redisReplyReaderGetObject(void *reader);
|
void *redisReplyReaderGetObject(void *reader);
|
||||||
char *redisReplyReaderGetError(void *reader);
|
char *redisReplyReaderGetError(void *reader);
|
||||||
void redisReplyReaderFree(void *ptr);
|
void redisReplyReaderFree(void *ptr);
|
||||||
|
13
deps/hiredis/test.c
vendored
13
deps/hiredis/test.c
vendored
@ -186,11 +186,12 @@ static void test_blocking_connection() {
|
|||||||
|
|
||||||
static void test_reply_reader() {
|
static void test_reply_reader() {
|
||||||
void *reader;
|
void *reader;
|
||||||
|
void *reply;
|
||||||
char *err;
|
char *err;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
test("Error handling in reply parser: ");
|
test("Error handling in reply parser: ");
|
||||||
reader = redisReplyReaderCreate(NULL);
|
reader = redisReplyReaderCreate();
|
||||||
redisReplyReaderFeed(reader,(char*)"@foo\r\n",6);
|
redisReplyReaderFeed(reader,(char*)"@foo\r\n",6);
|
||||||
ret = redisReplyReaderGetReply(reader,NULL);
|
ret = redisReplyReaderGetReply(reader,NULL);
|
||||||
err = redisReplyReaderGetError(reader);
|
err = redisReplyReaderGetError(reader);
|
||||||
@ -201,7 +202,7 @@ static void test_reply_reader() {
|
|||||||
/* when the reply already contains multiple items, they must be free'd
|
/* when the reply already contains multiple items, they must be free'd
|
||||||
* on an error. valgrind will bark when this doesn't happen. */
|
* on an error. valgrind will bark when this doesn't happen. */
|
||||||
test("Memory cleanup in reply parser: ");
|
test("Memory cleanup in reply parser: ");
|
||||||
reader = redisReplyReaderCreate(NULL);
|
reader = redisReplyReaderCreate();
|
||||||
redisReplyReaderFeed(reader,(char*)"*2\r\n",4);
|
redisReplyReaderFeed(reader,(char*)"*2\r\n",4);
|
||||||
redisReplyReaderFeed(reader,(char*)"$5\r\nhello\r\n",11);
|
redisReplyReaderFeed(reader,(char*)"$5\r\nhello\r\n",11);
|
||||||
redisReplyReaderFeed(reader,(char*)"@foo\r\n",6);
|
redisReplyReaderFeed(reader,(char*)"@foo\r\n",6);
|
||||||
@ -210,6 +211,14 @@ static void test_reply_reader() {
|
|||||||
test_cond(ret == REDIS_ERR &&
|
test_cond(ret == REDIS_ERR &&
|
||||||
strcasecmp(err,"protocol error, got \"@\" as reply type byte") == 0);
|
strcasecmp(err,"protocol error, got \"@\" as reply type byte") == 0);
|
||||||
redisReplyReaderFree(reader);
|
redisReplyReaderFree(reader);
|
||||||
|
|
||||||
|
test("Works with NULL functions for reply: ");
|
||||||
|
reader = redisReplyReaderCreate();
|
||||||
|
redisReplyReaderSetReplyObjectFunctions(reader,NULL);
|
||||||
|
redisReplyReaderFeed(reader,(char*)"+OK\r\n",5);
|
||||||
|
ret = redisReplyReaderGetReply(reader,&reply);
|
||||||
|
test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);
|
||||||
|
redisReplyReaderFree(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_throughput() {
|
static void test_throughput() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user