diff options
author | Pieter Noordhuis <pcnoordhuis@gmail.com> | 2010-11-04 10:54:01 +0100 |
---|---|---|
committer | Pieter Noordhuis <pcnoordhuis@gmail.com> | 2010-11-04 13:15:44 +0100 |
commit | 2e5e9a49fd1941296a6c94ca117e33bf2934bcfd (patch) | |
tree | d50d1d155a133a7917225cfc545a1106181b9028 | |
parent | e5a8228946611fea64707a32ecc218ff5e89b497 (diff) |
Return the reply type when the reply object function set is NULL
-rw-r--r-- | hiredis.c | 45 | ||||
-rw-r--r-- | hiredis.h | 3 | ||||
-rw-r--r-- | test.c | 13 |
3 files changed, 46 insertions, 15 deletions
@@ -207,10 +207,14 @@ static int processLineItem(redisReader *r) { int len; if ((p = readLine(r,&len)) != NULL) { - if (cur->type == REDIS_REPLY_INTEGER) { - obj = r->fn->createInteger(cur,strtoll(p,NULL,10)); + if (r->fn) { + if (cur->type == REDIS_REPLY_INTEGER) { + obj = r->fn->createInteger(cur,strtoll(p,NULL,10)); + } else { + obj = r->fn->createString(cur,p,len); + } } 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. */ @@ -238,12 +242,14 @@ static int processBulkItem(redisReader *r) { if (len < 0) { /* The nil object can always be created. */ - obj = r->fn->createNil(cur); + obj = r->fn ? r->fn->createNil(cur) : + (void*)REDIS_REPLY_NIL; } else { /* Only continue when the buffer contains the entire bulk item. */ bytelen += len+2; /* include \r\n */ 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 +274,12 @@ static int processMultiBulkItem(redisReader *r) { if ((p = readLine(r,NULL)) != NULL) { elements = strtol(p,NULL,10); if (elements == -1) { - obj = r->fn->createNil(cur); + obj = r->fn ? r->fn->createNil(cur) : + (void*)REDIS_REPLY_NIL; moveToNextTask(r); } 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. */ if (elements > 0) { @@ -348,15 +356,26 @@ static int processItem(redisReader *r) { } } -void *redisReplyReaderCreate(redisReplyObjectFunctions *fn) { +void *redisReplyReaderCreate() { redisReader *r = calloc(sizeof(redisReader),1); r->error = NULL; - r->fn = fn == NULL ? &defaultFunctions : fn; + r->fn = &defaultFunctions; r->buf = sdsempty(); r->ridx = -1; 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 * variable while the reply is built up. When the reader contains an * object in between receiving some bytes to parse, this object might @@ -370,7 +389,7 @@ void redisReplyReaderFree(void *reader) { redisReader *r = reader; if (r->error != NULL) sdsfree(r->error); - if (r->reply != NULL) + if (r->reply != NULL && r->fn) r->fn->freeObject(r->reply); if (r->buf != NULL) sdsfree(r->buf); @@ -695,8 +714,10 @@ int redisSetReplyObjectFunctions(redisContext *c, redisReplyObjectFunctions *fn) /* Helper function to lazily create a reply reader. */ static void __redisCreateReplyReader(redisContext *c) { - if (c->reader == NULL) - c->reader = redisReplyReaderCreate(c->fn); + if (c->reader == NULL) { + 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 @@ -110,7 +110,8 @@ typedef struct redisContext { } redisContext; void freeReplyObject(void *reply); -void *redisReplyReaderCreate(redisReplyObjectFunctions *fn); +void *redisReplyReaderCreate(); +int redisReplyReaderSetReplyObjectFunctions(void *reader, redisReplyObjectFunctions *fn); void *redisReplyReaderGetObject(void *reader); char *redisReplyReaderGetError(void *reader); void redisReplyReaderFree(void *ptr); @@ -186,11 +186,12 @@ static void test_blocking_connection() { static void test_reply_reader() { void *reader; + void *reply; char *err; int ret; test("Error handling in reply parser: "); - reader = redisReplyReaderCreate(NULL); + reader = redisReplyReaderCreate(); redisReplyReaderFeed(reader,(char*)"@foo\r\n",6); ret = redisReplyReaderGetReply(reader,NULL); err = redisReplyReaderGetError(reader); @@ -201,7 +202,7 @@ static void test_reply_reader() { /* when the reply already contains multiple items, they must be free'd * on an error. valgrind will bark when this doesn't happen. */ test("Memory cleanup in reply parser: "); - reader = redisReplyReaderCreate(NULL); + reader = redisReplyReaderCreate(); redisReplyReaderFeed(reader,(char*)"*2\r\n",4); redisReplyReaderFeed(reader,(char*)"$5\r\nhello\r\n",11); redisReplyReaderFeed(reader,(char*)"@foo\r\n",6); @@ -210,6 +211,14 @@ static void test_reply_reader() { test_cond(ret == REDIS_ERR && strcasecmp(err,"protocol error, got \"@\" as reply type byte") == 0); 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() { |