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
a3a405bc
Commit
a3a405bc
authored
Oct 31, 2010
by
Pieter Noordhuis
Browse files
Format a command using an argument vector
parent
e95c9d4c
Changes
3
Hide whitespace changes
Inline
Side-by-side
hiredis.c
View file @
a3a405bc
...
...
@@ -578,6 +578,42 @@ int redisFormatCommand(char **target, const char *format, ...) {
return
len
;
}
/* Format a command according to the Redis protocol. This function takes the
* number of arguments, an array with arguments and an array with their
* lengths. If the latter is set to NULL, strlen will be used to compute the
* argument lengths.
*/
int
redisFormatCommandArgv
(
char
**
target
,
int
argc
,
const
char
**
argv
,
const
size_t
*
argvlen
)
{
char
*
cmd
=
NULL
;
/* final command */
int
pos
;
/* position in final command */
size_t
len
;
int
totlen
,
j
;
/* Calculate number of bytes needed for the command */
totlen
=
1
+
intlen
(
argc
)
+
2
;
for
(
j
=
0
;
j
<
argc
;
j
++
)
{
len
=
argvlen
?
argvlen
[
j
]
:
strlen
(
argv
[
j
]);
totlen
+=
1
+
intlen
(
len
)
+
2
+
len
+
2
;
}
/* Build the command at protocol level */
cmd
=
malloc
(
totlen
+
1
);
if
(
!
cmd
)
redisOOM
();
pos
=
sprintf
(
cmd
,
"*%d
\r\n
"
,
argc
);
for
(
j
=
0
;
j
<
argc
;
j
++
)
{
len
=
argvlen
?
argvlen
[
j
]
:
strlen
(
argv
[
j
]);
pos
+=
sprintf
(
cmd
+
pos
,
"$%zu
\r\n
"
,
len
);
memcpy
(
cmd
+
pos
,
argv
[
j
],
len
);
pos
+=
len
;
cmd
[
pos
++
]
=
'\r'
;
cmd
[
pos
++
]
=
'\n'
;
}
assert
(
pos
==
totlen
);
cmd
[
totlen
]
=
'\0'
;
*
target
=
cmd
;
return
totlen
;
}
static
int
redisContextConnect
(
redisContext
*
c
,
const
char
*
ip
,
int
port
)
{
char
err
[
ANET_ERR_LEN
];
if
(
c
->
flags
&
REDIS_BLOCK
)
{
...
...
hiredis.h
View file @
a3a405bc
...
...
@@ -125,6 +125,7 @@ int redisReplyReaderGetReply(void *reader, void **reply);
/* Functions to format a command according to the protocol. */
int
redisvFormatCommand
(
char
**
target
,
const
char
*
format
,
va_list
ap
);
int
redisFormatCommand
(
char
**
target
,
const
char
*
format
,
...);
int
redisFormatCommandArgv
(
char
**
target
,
int
argc
,
const
char
**
argv
,
const
size_t
*
argvlen
);
redisContext
*
redisConnect
(
const
char
*
ip
,
int
port
,
redisReplyObjectFunctions
*
fn
);
redisContext
*
redisConnectNonBlock
(
const
char
*
ip
,
int
port
,
redisReplyObjectFunctions
*
fn
);
...
...
test.c
View file @
a3a405bc
...
...
@@ -28,6 +28,48 @@ static void __connect(redisContext **target) {
}
}
static
void
test_format_commands
()
{
char
*
cmd
;
int
len
;
test
(
"Format command without interpolation: "
);
len
=
redisFormatCommand
(
&
cmd
,
"SET foo bar"
);
test_cond
(
strncmp
(
cmd
,
"*3
\r\n
$3
\r\n
SET
\r\n
$3
\r\n
foo
\r\n
$3
\r\n
bar
\r\n
"
,
len
)
==
0
&&
len
==
4
+
4
+
(
3
+
2
)
+
4
+
(
3
+
2
)
+
4
+
(
3
+
2
));
free
(
cmd
);
test
(
"Format command with %%s string interpolation: "
);
len
=
redisFormatCommand
(
&
cmd
,
"SET %s %s"
,
"foo"
,
"bar"
);
test_cond
(
strncmp
(
cmd
,
"*3
\r\n
$3
\r\n
SET
\r\n
$3
\r\n
foo
\r\n
$3
\r\n
bar
\r\n
"
,
len
)
==
0
&&
len
==
4
+
4
+
(
3
+
2
)
+
4
+
(
3
+
2
)
+
4
+
(
3
+
2
));
free
(
cmd
);
test
(
"Format command with %%b string interpolation: "
);
len
=
redisFormatCommand
(
&
cmd
,
"SET %b %b"
,
"foo"
,
3
,
"b
\0
r"
,
3
);
test_cond
(
strncmp
(
cmd
,
"*3
\r\n
$3
\r\n
SET
\r\n
$3
\r\n
foo
\r\n
$3
\r\n
b
\0
r
\r\n
"
,
len
)
==
0
&&
len
==
4
+
4
+
(
3
+
2
)
+
4
+
(
3
+
2
)
+
4
+
(
3
+
2
));
free
(
cmd
);
const
char
*
argv
[
3
];
argv
[
0
]
=
"SET"
;
argv
[
1
]
=
"foo"
;
argv
[
2
]
=
"bar"
;
size_t
lens
[
3
]
=
{
3
,
3
,
3
};
int
argc
=
3
;
test
(
"Format command by passing argc/argv without lengths: "
);
len
=
redisFormatCommandArgv
(
&
cmd
,
argc
,
argv
,
NULL
);
test_cond
(
strncmp
(
cmd
,
"*3
\r\n
$3
\r\n
SET
\r\n
$3
\r\n
foo
\r\n
$3
\r\n
bar
\r\n
"
,
len
)
==
0
&&
len
==
4
+
4
+
(
3
+
2
)
+
4
+
(
3
+
2
)
+
4
+
(
3
+
2
));
free
(
cmd
);
test
(
"Format command by passing argc/argv with lengths: "
);
len
=
redisFormatCommandArgv
(
&
cmd
,
argc
,
argv
,
lens
);
test_cond
(
strncmp
(
cmd
,
"*3
\r\n
$3
\r\n
SET
\r\n
$3
\r\n
foo
\r\n
$3
\r\n
bar
\r\n
"
,
len
)
==
0
&&
len
==
4
+
4
+
(
3
+
2
)
+
4
+
(
3
+
2
)
+
4
+
(
3
+
2
));
free
(
cmd
);
}
static
void
test_blocking_connection
()
{
redisContext
*
c
;
redisReply
*
reply
;
...
...
@@ -294,6 +336,7 @@ static void test_nonblocking_connection() {
}
int
main
(
void
)
{
test_format_commands
();
test_blocking_connection
();
test_reply_reader
();
test_nonblocking_connection
();
...
...
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