summaryrefslogtreecommitdiff
path: root/hiredis.c
diff options
context:
space:
mode:
authorMark Nunberg <mnunberg@users.noreply.github.com>2019-08-27 06:59:32 -0400
committerGitHub <noreply@github.com>2019-08-27 06:59:32 -0400
commitff4fa45422dc104f3377cdc3bc88d2d24ac2fcf3 (patch)
treee78792fdfe41d39c887e5ca0f325e46865ad74aa /hiredis.c
parentce7cb7bcc4ca53291aca8ab8dc0f31e27c032dcc (diff)
parent91de9c975ac66b6eaddb6de96440a282e4227447 (diff)
Merge pull request #697 from yossigo/resp3
Port RESP3 support from Redis.
Diffstat (limited to 'hiredis.c')
-rw-r--r--hiredis.c76
1 files changed, 71 insertions, 5 deletions
diff --git a/hiredis.c b/hiredis.c
index 5a6fcf8..9627832 100644
--- a/hiredis.c
+++ b/hiredis.c
@@ -48,7 +48,9 @@ static redisReply *createReplyObject(int type);
static void *createStringObject(const redisReadTask *task, char *str, size_t len);
static void *createArrayObject(const redisReadTask *task, size_t elements);
static void *createIntegerObject(const redisReadTask *task, long long value);
+static void *createDoubleObject(const redisReadTask *task, double value, char *str, size_t len);
static void *createNilObject(const redisReadTask *task);
+static void *createBoolObject(const redisReadTask *task, int bval);
/* Default set of functions to build the reply. Keep in mind that such a
* function returning NULL is interpreted as OOM. */
@@ -56,7 +58,9 @@ static redisReplyObjectFunctions defaultFunctions = {
createStringObject,
createArrayObject,
createIntegerObject,
+ createDoubleObject,
createNilObject,
+ createBoolObject,
freeReplyObject
};
@@ -83,6 +87,8 @@ void freeReplyObject(void *reply) {
case REDIS_REPLY_INTEGER:
break; /* Nothing to free */
case REDIS_REPLY_ARRAY:
+ case REDIS_REPLY_MAP:
+ case REDIS_REPLY_SET:
if (r->element != NULL) {
for (j = 0; j < r->elements; j++)
freeReplyObject(r->element[j]);
@@ -92,6 +98,7 @@ void freeReplyObject(void *reply) {
case REDIS_REPLY_ERROR:
case REDIS_REPLY_STATUS:
case REDIS_REPLY_STRING:
+ case REDIS_REPLY_DOUBLE:
free(r->str);
break;
}
@@ -124,7 +131,9 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
if (task->parent) {
parent = task->parent->obj;
- assert(parent->type == REDIS_REPLY_ARRAY);
+ assert(parent->type == REDIS_REPLY_ARRAY ||
+ parent->type == REDIS_REPLY_MAP ||
+ parent->type == REDIS_REPLY_SET);
parent->element[task->idx] = r;
}
return r;
@@ -133,7 +142,7 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
static void *createArrayObject(const redisReadTask *task, size_t elements) {
redisReply *r, *parent;
- r = createReplyObject(REDIS_REPLY_ARRAY);
+ r = createReplyObject(task->type);
if (r == NULL)
return NULL;
@@ -149,7 +158,9 @@ static void *createArrayObject(const redisReadTask *task, size_t elements) {
if (task->parent) {
parent = task->parent->obj;
- assert(parent->type == REDIS_REPLY_ARRAY);
+ assert(parent->type == REDIS_REPLY_ARRAY ||
+ parent->type == REDIS_REPLY_MAP ||
+ parent->type == REDIS_REPLY_SET);
parent->element[task->idx] = r;
}
return r;
@@ -166,7 +177,41 @@ static void *createIntegerObject(const redisReadTask *task, long long value) {
if (task->parent) {
parent = task->parent->obj;
- assert(parent->type == REDIS_REPLY_ARRAY);
+ assert(parent->type == REDIS_REPLY_ARRAY ||
+ parent->type == REDIS_REPLY_MAP ||
+ parent->type == REDIS_REPLY_SET);
+ parent->element[task->idx] = r;
+ }
+ return r;
+}
+
+static void *createDoubleObject(const redisReadTask *task, double value, char *str, size_t len) {
+ redisReply *r, *parent;
+
+ r = createReplyObject(REDIS_REPLY_DOUBLE);
+ if (r == NULL)
+ return NULL;
+
+ r->dval = value;
+ r->str = malloc(len+1);
+ if (r->str == NULL) {
+ freeReplyObject(r);
+ return NULL;
+ }
+
+ /* The double reply also has the original protocol string representing a
+ * double as a null terminated string. This way the caller does not need
+ * to format back for string conversion, especially since Redis does efforts
+ * to make the string more human readable avoiding the calssical double
+ * decimal string conversion artifacts. */
+ memcpy(r->str, str, len);
+ r->str[len] = '\0';
+
+ if (task->parent) {
+ parent = task->parent->obj;
+ assert(parent->type == REDIS_REPLY_ARRAY ||
+ parent->type == REDIS_REPLY_MAP ||
+ parent->type == REDIS_REPLY_SET);
parent->element[task->idx] = r;
}
return r;
@@ -181,7 +226,28 @@ static void *createNilObject(const redisReadTask *task) {
if (task->parent) {
parent = task->parent->obj;
- assert(parent->type == REDIS_REPLY_ARRAY);
+ assert(parent->type == REDIS_REPLY_ARRAY ||
+ parent->type == REDIS_REPLY_MAP ||
+ parent->type == REDIS_REPLY_SET);
+ parent->element[task->idx] = r;
+ }
+ return r;
+}
+
+static void *createBoolObject(const redisReadTask *task, int bval) {
+ redisReply *r, *parent;
+
+ r = createReplyObject(REDIS_REPLY_BOOL);
+ if (r == NULL)
+ return NULL;
+
+ r->integer = bval != 0;
+
+ if (task->parent) {
+ parent = task->parent->obj;
+ assert(parent->type == REDIS_REPLY_ARRAY ||
+ parent->type == REDIS_REPLY_MAP ||
+ parent->type == REDIS_REPLY_SET);
parent->element[task->idx] = r;
}
return r;