diff --git a/hiredis.c b/hiredis.c index 30e5838..084561c 100644 --- a/hiredis.c +++ b/hiredis.c @@ -374,7 +374,7 @@ static int processItem(redisReader *r) { #define READ_BUFFER_SIZE 2048 static redisReply *redisReadReply(int fd) { - void *reader = redisCreateReplyReader(&defaultFunctions); + void *reader = redisReplyReaderCreate(&defaultFunctions); redisReply *reply; char buf[1024]; int nread; @@ -384,15 +384,16 @@ static redisReply *redisReadReply(int fd) { reply = createErrorObject(reader,"I/O error"); break; } else { - reply = redisFeedReplyReader(reader,buf,nread); + redisReplyReaderFeed(reader,buf,nread); + reply = redisReplyReaderGetReply(reader); } } while (reply == NULL); - redisFreeReplyReader(reader); + redisReplyReaderFree(reader); return reply; } -void *redisCreateReplyReader(redisReplyFunctions *fn) { +void *redisReplyReaderCreate(redisReplyFunctions *fn) { redisReader *r = calloc(sizeof(redisReader),1); r->fn = fn == NULL ? &defaultFunctions : fn; r->buf = sdsempty(); @@ -404,12 +405,12 @@ void *redisCreateReplyReader(redisReplyFunctions *fn) { * variable while the reply is built up. When the reader contains an * object in between receiving some bytes to parse, this object might * otherwise be free'd by garbage collection. */ -void *redisGetReplyObjectFromReplyReader(void *reader) { +void *redisReplyReaderGetObject(void *reader) { redisReader *r = reader; return r->reply; } -void redisFreeReplyReader(void *reader) { +void redisReplyReaderFree(void *reader) { redisReader *r = reader; if (r->reply != NULL) r->fn->freeObject(r->reply); @@ -420,13 +421,6 @@ void redisFreeReplyReader(void *reader) { free(r); } -int redisIsReplyReaderEmpty(void *reader) { - redisReader *r = reader; - if ((r->buf != NULL && sdslen(r->buf) > 0) || - (r->rpos < r->rlen)) return 0; - return 1; -} - static void redisSetReplyReaderError(redisReader *r, void *obj) { if (r->reply != NULL) r->fn->freeObject(r->reply); @@ -441,16 +435,20 @@ static void redisSetReplyReaderError(redisReader *r, void *obj) { r->reply = obj; } -void *redisFeedReplyReader(void *reader, char *buf, int len) { +void redisReplyReaderFeed(void *reader, char *buf, int len) { redisReader *r = reader; - /* Check if we are able to do *something*. */ - if (sdslen(r->buf) == 0 && (buf == NULL || len <= 0)) - return NULL; - /* Copy the provided buffer. */ if (buf != NULL && len >= 1) r->buf = sdscatlen(r->buf,buf,len); +} + +void *redisReplyReaderGetReply(void *reader) { + redisReader *r = reader; + + /* When the buffer is empty, there will never be a reply. */ + if (sdslen(r->buf) == 0) + return NULL; /* Create first item to process when the item list is empty. */ if (r->rlen == 0) { diff --git a/hiredis.h b/hiredis.h index c354935..ea01dee 100644 --- a/hiredis.h +++ b/hiredis.h @@ -66,10 +66,10 @@ typedef struct redisReplyObjectFunctions { redisReply *redisConnect(int *fd, const char *ip, int port); void freeReplyObject(void *reply); redisReply *redisCommand(int fd, const char *format, ...); -void *redisCreateReplyReader(redisReplyFunctions *fn); -void *redisGetReplyObjectFromReplyReader(void *reader); -void redisFreeReplyReader(void *ptr); -int redisIsReplyReaderEmpty(void *ptr); -void *redisFeedReplyReader(void *reader, char *buf, int len); +void *redisReplyReaderCreate(redisReplyFunctions *fn); +void *redisReplyReaderGetObject(void *reader); +void redisReplyReaderFree(void *ptr); +void redisReplyReaderFeed(void *reader, char *buf, int len); +void *redisReplyReaderGetReply(void *reader); #endif diff --git a/test.c b/test.c index 020d125..640cabd 100644 --- a/test.c +++ b/test.c @@ -124,24 +124,26 @@ int main(void) { freeReplyObject(reply); test("Error handling in reply parser: "); - reader = redisCreateReplyReader(NULL); - reply = redisFeedReplyReader(reader,(char*)"@foo\r\n",6); + reader = redisReplyReaderCreate(NULL); + redisReplyReaderFeed(reader,(char*)"@foo\r\n",6); + reply = redisReplyReaderGetReply(reader); test_cond(reply->type == REDIS_PROTOCOL_ERROR && strcasecmp(reply->reply,"protocol error, got \"@\" as reply type byte") == 0); freeReplyObject(reply); - redisFreeReplyReader(reader); + redisReplyReaderFree(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 = redisCreateReplyReader(NULL); - redisFeedReplyReader(reader,(char*)"*2\r\n",4); - redisFeedReplyReader(reader,(char*)"$5\r\nhello\r\n",11); - reply = redisFeedReplyReader(reader,(char*)"@foo\r\n",6); + reader = redisReplyReaderCreate(NULL); + redisReplyReaderFeed(reader,(char*)"*2\r\n",4); + redisReplyReaderFeed(reader,(char*)"$5\r\nhello\r\n",11); + redisReplyReaderFeed(reader,(char*)"@foo\r\n",6); + reply = redisReplyReaderGetReply(reader); test_cond(reply->type == REDIS_PROTOCOL_ERROR && strcasecmp(reply->reply,"protocol error, got \"@\" as reply type byte") == 0); freeReplyObject(reply); - redisFreeReplyReader(reader); + redisReplyReaderFree(reader); test("Throughput:\n"); for (i = 0; i < 500; i++)