Fix formatCommand to work with all empty interpolations

This commit is contained in:
Pieter Noordhuis 2011-03-06 11:38:07 +01:00
parent bf544ce81c
commit 8e2c39200d
2 changed files with 12 additions and 7 deletions

View File

@ -596,7 +596,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
char *cmd = NULL; /* final command */ char *cmd = NULL; /* final command */
int pos; /* position in final command */ int pos; /* position in final command */
sds current; /* current argument */ sds current; /* current argument */
int interpolated = 0; /* did we do interpolation on an argument? */ int touched = 0; /* was the current argument touched? */
char **argv = NULL; char **argv = NULL;
int argc = 0, j; int argc = 0, j;
int totlen = 0; int totlen = 0;
@ -610,13 +610,14 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
while(*c != '\0') { while(*c != '\0') {
if (*c != '%' || c[1] == '\0') { if (*c != '%' || c[1] == '\0') {
if (*c == ' ') { if (*c == ' ') {
if (sdslen(current) != 0) { if (touched) {
addArgument(current, &argv, &argc, &totlen); addArgument(current, &argv, &argc, &totlen);
current = sdsempty(); current = sdsempty();
interpolated = 0; touched = 0;
} }
} else { } else {
current = sdscatlen(current,c,1); current = sdscatlen(current,c,1);
touched = 1;
} }
} else { } else {
switch(c[1]) { switch(c[1]) {
@ -625,14 +626,12 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
size = strlen(arg); size = strlen(arg);
if (size > 0) if (size > 0)
current = sdscatlen(current,arg,size); current = sdscatlen(current,arg,size);
interpolated = 1;
break; break;
case 'b': case 'b':
arg = va_arg(ap,char*); arg = va_arg(ap,char*);
size = va_arg(ap,size_t); size = va_arg(ap,size_t);
if (size > 0) if (size > 0)
current = sdscatlen(current,arg,size); current = sdscatlen(current,arg,size);
interpolated = 1;
break; break;
case '%': case '%':
current = sdscat(current,"%"); current = sdscat(current,"%");
@ -678,7 +677,6 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
_format[_l] = '\0'; _format[_l] = '\0';
va_copy(_cpy,ap); va_copy(_cpy,ap);
current = sdscatvprintf(current,_format,_cpy); current = sdscatvprintf(current,_format,_cpy);
interpolated = 1;
va_end(_cpy); va_end(_cpy);
/* Update current position (note: outer blocks /* Update current position (note: outer blocks
@ -691,13 +689,14 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
va_arg(ap,void); va_arg(ap,void);
} }
} }
touched = 1;
c++; c++;
} }
c++; c++;
} }
/* Add the last argument if needed */ /* Add the last argument if needed */
if (interpolated || sdslen(current) != 0) { if (touched) {
addArgument(current, &argv, &argc, &totlen); addArgument(current, &argv, &argc, &totlen);
} else { } else {
sdsfree(current); sdsfree(current);

6
test.c
View File

@ -54,6 +54,12 @@ static void test_format_commands(void) {
len == 4+4+(3+2)+4+(3+2)+4+(0+2)); len == 4+4+(3+2)+4+(3+2)+4+(0+2));
free(cmd); free(cmd);
test("Format command with an empty string in between proper interpolations: ");
len = redisFormatCommand(&cmd,"SET %s %s","","foo");
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$0\r\n\r\n$3\r\nfoo\r\n",len) == 0 &&
len == 4+4+(3+2)+4+(0+2)+4+(3+2));
free(cmd);
test("Format command with %%b string interpolation: "); test("Format command with %%b string interpolation: ");
len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"b\0r",3); len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"b\0r",3);
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nb\0r\r\n",len) == 0 && test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nb\0r\r\n",len) == 0 &&