Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
hiredis
Commits
ff4fa454
Unverified
Commit
ff4fa454
authored
Aug 27, 2019
by
Mark Nunberg
Committed by
GitHub
Aug 27, 2019
Browse files
Merge pull request #697 from yossigo/resp3
Port RESP3 support from Redis.
parents
ce7cb7bc
91de9c97
Changes
5
Hide whitespace changes
Inline
Side-by-side
.travis.yml
View file @
ff4fa454
...
@@ -8,6 +8,12 @@ os:
...
@@ -8,6 +8,12 @@ os:
-
linux
-
linux
-
osx
-
osx
branches
:
only
:
-
staging
-
trying
-
master
before_script
:
before_script
:
-
if [ "$TRAVIS_OS_NAME" == "osx" ] ; then brew update; brew install redis; fi
-
if [ "$TRAVIS_OS_NAME" == "osx" ] ; then brew update; brew install redis; fi
...
...
hiredis.c
View file @
ff4fa454
...
@@ -48,7 +48,9 @@ static redisReply *createReplyObject(int type);
...
@@ -48,7 +48,9 @@ static redisReply *createReplyObject(int type);
static
void
*
createStringObject
(
const
redisReadTask
*
task
,
char
*
str
,
size_t
len
);
static
void
*
createStringObject
(
const
redisReadTask
*
task
,
char
*
str
,
size_t
len
);
static
void
*
createArrayObject
(
const
redisReadTask
*
task
,
size_t
elements
);
static
void
*
createArrayObject
(
const
redisReadTask
*
task
,
size_t
elements
);
static
void
*
createIntegerObject
(
const
redisReadTask
*
task
,
long
long
value
);
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
*
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
/* Default set of functions to build the reply. Keep in mind that such a
* function returning NULL is interpreted as OOM. */
* function returning NULL is interpreted as OOM. */
...
@@ -56,7 +58,9 @@ static redisReplyObjectFunctions defaultFunctions = {
...
@@ -56,7 +58,9 @@ static redisReplyObjectFunctions defaultFunctions = {
createStringObject
,
createStringObject
,
createArrayObject
,
createArrayObject
,
createIntegerObject
,
createIntegerObject
,
createDoubleObject
,
createNilObject
,
createNilObject
,
createBoolObject
,
freeReplyObject
freeReplyObject
};
};
...
@@ -83,6 +87,8 @@ void freeReplyObject(void *reply) {
...
@@ -83,6 +87,8 @@ void freeReplyObject(void *reply) {
case
REDIS_REPLY_INTEGER
:
case
REDIS_REPLY_INTEGER
:
break
;
/* Nothing to free */
break
;
/* Nothing to free */
case
REDIS_REPLY_ARRAY
:
case
REDIS_REPLY_ARRAY
:
case
REDIS_REPLY_MAP
:
case
REDIS_REPLY_SET
:
if
(
r
->
element
!=
NULL
)
{
if
(
r
->
element
!=
NULL
)
{
for
(
j
=
0
;
j
<
r
->
elements
;
j
++
)
for
(
j
=
0
;
j
<
r
->
elements
;
j
++
)
freeReplyObject
(
r
->
element
[
j
]);
freeReplyObject
(
r
->
element
[
j
]);
...
@@ -92,6 +98,7 @@ void freeReplyObject(void *reply) {
...
@@ -92,6 +98,7 @@ void freeReplyObject(void *reply) {
case
REDIS_REPLY_ERROR
:
case
REDIS_REPLY_ERROR
:
case
REDIS_REPLY_STATUS
:
case
REDIS_REPLY_STATUS
:
case
REDIS_REPLY_STRING
:
case
REDIS_REPLY_STRING
:
case
REDIS_REPLY_DOUBLE
:
free
(
r
->
str
);
free
(
r
->
str
);
break
;
break
;
}
}
...
@@ -124,7 +131,9 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
...
@@ -124,7 +131,9 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
if
(
task
->
parent
)
{
if
(
task
->
parent
)
{
parent
=
task
->
parent
->
obj
;
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
;
parent
->
element
[
task
->
idx
]
=
r
;
}
}
return
r
;
return
r
;
...
@@ -133,7 +142,7 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
...
@@ -133,7 +142,7 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
static
void
*
createArrayObject
(
const
redisReadTask
*
task
,
size_t
elements
)
{
static
void
*
createArrayObject
(
const
redisReadTask
*
task
,
size_t
elements
)
{
redisReply
*
r
,
*
parent
;
redisReply
*
r
,
*
parent
;
r
=
createReplyObject
(
REDIS_REPLY_ARRAY
);
r
=
createReplyObject
(
task
->
type
);
if
(
r
==
NULL
)
if
(
r
==
NULL
)
return
NULL
;
return
NULL
;
...
@@ -149,7 +158,9 @@ static void *createArrayObject(const redisReadTask *task, size_t elements) {
...
@@ -149,7 +158,9 @@ static void *createArrayObject(const redisReadTask *task, size_t elements) {
if
(
task
->
parent
)
{
if
(
task
->
parent
)
{
parent
=
task
->
parent
->
obj
;
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
;
parent
->
element
[
task
->
idx
]
=
r
;
}
}
return
r
;
return
r
;
...
@@ -166,7 +177,41 @@ static void *createIntegerObject(const redisReadTask *task, long long value) {
...
@@ -166,7 +177,41 @@ static void *createIntegerObject(const redisReadTask *task, long long value) {
if
(
task
->
parent
)
{
if
(
task
->
parent
)
{
parent
=
task
->
parent
->
obj
;
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
;
parent
->
element
[
task
->
idx
]
=
r
;
}
}
return
r
;
return
r
;
...
@@ -181,7 +226,28 @@ static void *createNilObject(const redisReadTask *task) {
...
@@ -181,7 +226,28 @@ static void *createNilObject(const redisReadTask *task) {
if
(
task
->
parent
)
{
if
(
task
->
parent
)
{
parent
=
task
->
parent
->
obj
;
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
;
parent
->
element
[
task
->
idx
]
=
r
;
}
}
return
r
;
return
r
;
...
...
hiredis.h
View file @
ff4fa454
...
@@ -101,8 +101,10 @@ extern "C" {
...
@@ -101,8 +101,10 @@ extern "C" {
typedef
struct
redisReply
{
typedef
struct
redisReply
{
int
type
;
/* REDIS_REPLY_* */
int
type
;
/* REDIS_REPLY_* */
long
long
integer
;
/* The integer when type is REDIS_REPLY_INTEGER */
long
long
integer
;
/* The integer when type is REDIS_REPLY_INTEGER */
double
dval
;
/* The double when type is REDIS_REPLY_DOUBLE */
size_t
len
;
/* Length of string */
size_t
len
;
/* Length of string */
char
*
str
;
/* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */
char
*
str
;
/* Used for REDIS_REPLY_ERROR, REDIS_REPLY_STRING
and REDIS_REPLY_DOUBLE (in additionl to dval). */
size_t
elements
;
/* number of elements, for REDIS_REPLY_ARRAY */
size_t
elements
;
/* number of elements, for REDIS_REPLY_ARRAY */
struct
redisReply
**
element
;
/* elements vector for REDIS_REPLY_ARRAY */
struct
redisReply
**
element
;
/* elements vector for REDIS_REPLY_ARRAY */
}
redisReply
;
}
redisReply
;
...
...
read.c
View file @
ff4fa454
...
@@ -29,9 +29,9 @@
...
@@ -29,9 +29,9 @@
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#include "fmacros.h"
#include "fmacros.h"
#include <string.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdlib.h>
#ifndef _MSC_VER
#ifndef _MSC_VER
#include <unistd.h>
#include <unistd.h>
...
@@ -40,6 +40,7 @@
...
@@ -40,6 +40,7 @@
#include <errno.h>
#include <errno.h>
#include <ctype.h>
#include <ctype.h>
#include <limits.h>
#include <limits.h>
#include <math.h>
#include "read.h"
#include "read.h"
#include "sds.h"
#include "sds.h"
...
@@ -243,7 +244,9 @@ static void moveToNextTask(redisReader *r) {
...
@@ -243,7 +244,9 @@ static void moveToNextTask(redisReader *r) {
cur
=
&
(
r
->
rstack
[
r
->
ridx
]);
cur
=
&
(
r
->
rstack
[
r
->
ridx
]);
prv
=
&
(
r
->
rstack
[
r
->
ridx
-
1
]);
prv
=
&
(
r
->
rstack
[
r
->
ridx
-
1
]);
assert
(
prv
->
type
==
REDIS_REPLY_ARRAY
);
assert
(
prv
->
type
==
REDIS_REPLY_ARRAY
||
prv
->
type
==
REDIS_REPLY_MAP
||
prv
->
type
==
REDIS_REPLY_SET
);
if
(
cur
->
idx
==
prv
->
elements
-
1
)
{
if
(
cur
->
idx
==
prv
->
elements
-
1
)
{
r
->
ridx
--
;
r
->
ridx
--
;
}
else
{
}
else
{
...
@@ -276,6 +279,47 @@ static int processLineItem(redisReader *r) {
...
@@ -276,6 +279,47 @@ static int processLineItem(redisReader *r) {
}
else
{
}
else
{
obj
=
(
void
*
)
REDIS_REPLY_INTEGER
;
obj
=
(
void
*
)
REDIS_REPLY_INTEGER
;
}
}
}
else
if
(
cur
->
type
==
REDIS_REPLY_DOUBLE
)
{
if
(
r
->
fn
&&
r
->
fn
->
createDouble
)
{
char
buf
[
326
],
*
eptr
;
double
d
;
if
((
size_t
)
len
>=
sizeof
(
buf
))
{
__redisReaderSetError
(
r
,
REDIS_ERR_PROTOCOL
,
"Double value is too large"
);
return
REDIS_ERR
;
}
memcpy
(
buf
,
p
,
len
);
buf
[
len
]
=
'\0'
;
if
(
strcasecmp
(
buf
,
",inf"
)
==
0
)
{
d
=
1
.
0
/
0
.
0
;
/* Positive infinite. */
}
else
if
(
strcasecmp
(
buf
,
",-inf"
)
==
0
)
{
d
=
-
1
.
0
/
0
.
0
;
/* Nevative infinite. */
}
else
{
d
=
strtod
((
char
*
)
buf
,
&
eptr
);
if
(
buf
[
0
]
==
'\0'
||
eptr
[
0
]
!=
'\0'
||
isnan
(
d
))
{
__redisReaderSetError
(
r
,
REDIS_ERR_PROTOCOL
,
"Bad double value"
);
return
REDIS_ERR
;
}
}
obj
=
r
->
fn
->
createDouble
(
cur
,
d
,
buf
,
len
);
}
else
{
obj
=
(
void
*
)
REDIS_REPLY_DOUBLE
;
}
}
else
if
(
cur
->
type
==
REDIS_REPLY_NIL
)
{
if
(
r
->
fn
&&
r
->
fn
->
createNil
)
obj
=
r
->
fn
->
createNil
(
cur
);
else
obj
=
(
void
*
)
REDIS_REPLY_NIL
;
}
else
if
(
cur
->
type
==
REDIS_REPLY_BOOL
)
{
int
bval
=
p
[
0
]
==
't'
||
p
[
0
]
==
'T'
;
if
(
r
->
fn
&&
r
->
fn
->
createBool
)
obj
=
r
->
fn
->
createBool
(
cur
,
bval
);
else
obj
=
(
void
*
)
REDIS_REPLY_BOOL
;
}
else
{
}
else
{
/* Type will be error or status. */
/* Type will be error or status. */
if
(
r
->
fn
&&
r
->
fn
->
createString
)
if
(
r
->
fn
&&
r
->
fn
->
createString
)
...
@@ -362,7 +406,8 @@ static int processBulkItem(redisReader *r) {
...
@@ -362,7 +406,8 @@ static int processBulkItem(redisReader *r) {
return
REDIS_ERR
;
return
REDIS_ERR
;
}
}
static
int
processMultiBulkItem
(
redisReader
*
r
)
{
/* Process the array, map and set types. */
static
int
processAggregateItem
(
redisReader
*
r
)
{
redisReadTask
*
cur
=
&
(
r
->
rstack
[
r
->
ridx
]);
redisReadTask
*
cur
=
&
(
r
->
rstack
[
r
->
ridx
]);
void
*
obj
;
void
*
obj
;
char
*
p
;
char
*
p
;
...
@@ -404,10 +449,12 @@ static int processMultiBulkItem(redisReader *r) {
...
@@ -404,10 +449,12 @@ static int processMultiBulkItem(redisReader *r) {
moveToNextTask
(
r
);
moveToNextTask
(
r
);
}
else
{
}
else
{
if
(
cur
->
type
==
REDIS_REPLY_MAP
)
elements
*=
2
;
if
(
r
->
fn
&&
r
->
fn
->
createArray
)
if
(
r
->
fn
&&
r
->
fn
->
createArray
)
obj
=
r
->
fn
->
createArray
(
cur
,
elements
);
obj
=
r
->
fn
->
createArray
(
cur
,
elements
);
else
else
obj
=
(
void
*
)
REDIS_REPLY_ARRAY
;
obj
=
(
void
*
)
(
long
)
cur
->
type
;
if
(
obj
==
NULL
)
{
if
(
obj
==
NULL
)
{
__redisReaderSetErrorOOM
(
r
);
__redisReaderSetErrorOOM
(
r
);
...
@@ -455,12 +502,27 @@ static int processItem(redisReader *r) {
...
@@ -455,12 +502,27 @@ static int processItem(redisReader *r) {
case
':'
:
case
':'
:
cur
->
type
=
REDIS_REPLY_INTEGER
;
cur
->
type
=
REDIS_REPLY_INTEGER
;
break
;
break
;
case
','
:
cur
->
type
=
REDIS_REPLY_DOUBLE
;
break
;
case
'_'
:
cur
->
type
=
REDIS_REPLY_NIL
;
break
;
case
'$'
:
case
'$'
:
cur
->
type
=
REDIS_REPLY_STRING
;
cur
->
type
=
REDIS_REPLY_STRING
;
break
;
break
;
case
'*'
:
case
'*'
:
cur
->
type
=
REDIS_REPLY_ARRAY
;
cur
->
type
=
REDIS_REPLY_ARRAY
;
break
;
break
;
case
'%'
:
cur
->
type
=
REDIS_REPLY_MAP
;
break
;
case
'~'
:
cur
->
type
=
REDIS_REPLY_SET
;
break
;
case
'#'
:
cur
->
type
=
REDIS_REPLY_BOOL
;
break
;
default:
default:
__redisReaderSetErrorProtocolByte
(
r
,
*
p
);
__redisReaderSetErrorProtocolByte
(
r
,
*
p
);
return
REDIS_ERR
;
return
REDIS_ERR
;
...
@@ -476,11 +538,16 @@ static int processItem(redisReader *r) {
...
@@ -476,11 +538,16 @@ static int processItem(redisReader *r) {
case
REDIS_REPLY_ERROR
:
case
REDIS_REPLY_ERROR
:
case
REDIS_REPLY_STATUS
:
case
REDIS_REPLY_STATUS
:
case
REDIS_REPLY_INTEGER
:
case
REDIS_REPLY_INTEGER
:
case
REDIS_REPLY_DOUBLE
:
case
REDIS_REPLY_NIL
:
case
REDIS_REPLY_BOOL
:
return
processLineItem
(
r
);
return
processLineItem
(
r
);
case
REDIS_REPLY_STRING
:
case
REDIS_REPLY_STRING
:
return
processBulkItem
(
r
);
return
processBulkItem
(
r
);
case
REDIS_REPLY_ARRAY
:
case
REDIS_REPLY_ARRAY
:
return
processMultiBulkItem
(
r
);
case
REDIS_REPLY_MAP
:
case
REDIS_REPLY_SET
:
return
processAggregateItem
(
r
);
default:
default:
assert
(
NULL
);
assert
(
NULL
);
return
REDIS_ERR
;
/* Avoid warning. */
return
REDIS_ERR
;
/* Avoid warning. */
...
...
read.h
View file @
ff4fa454
...
@@ -54,6 +54,14 @@
...
@@ -54,6 +54,14 @@
#define REDIS_REPLY_NIL 4
#define REDIS_REPLY_NIL 4
#define REDIS_REPLY_STATUS 5
#define REDIS_REPLY_STATUS 5
#define REDIS_REPLY_ERROR 6
#define REDIS_REPLY_ERROR 6
#define REDIS_REPLY_DOUBLE 7
#define REDIS_REPLY_BOOL 8
#define REDIS_REPLY_VERB 9
#define REDIS_REPLY_MAP 9
#define REDIS_REPLY_SET 10
#define REDIS_REPLY_ATTR 11
#define REDIS_REPLY_PUSH 12
#define REDIS_REPLY_BIGNUM 13
#define REDIS_READER_MAX_BUF (1024*16)
/* Default max unused reader buffer. */
#define REDIS_READER_MAX_BUF (1024*16)
/* Default max unused reader buffer. */
...
@@ -74,7 +82,9 @@ typedef struct redisReplyObjectFunctions {
...
@@ -74,7 +82,9 @@ typedef struct redisReplyObjectFunctions {
void
*
(
*
createString
)(
const
redisReadTask
*
,
char
*
,
size_t
);
void
*
(
*
createString
)(
const
redisReadTask
*
,
char
*
,
size_t
);
void
*
(
*
createArray
)(
const
redisReadTask
*
,
size_t
);
void
*
(
*
createArray
)(
const
redisReadTask
*
,
size_t
);
void
*
(
*
createInteger
)(
const
redisReadTask
*
,
long
long
);
void
*
(
*
createInteger
)(
const
redisReadTask
*
,
long
long
);
void
*
(
*
createDouble
)(
const
redisReadTask
*
,
double
,
char
*
,
size_t
);
void
*
(
*
createNil
)(
const
redisReadTask
*
);
void
*
(
*
createNil
)(
const
redisReadTask
*
);
void
*
(
*
createBool
)(
const
redisReadTask
*
,
int
);
void
(
*
freeObject
)(
void
*
);
void
(
*
freeObject
)(
void
*
);
}
redisReplyObjectFunctions
;
}
redisReplyObjectFunctions
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment