diff --git a/parser.c b/parser.c index be8dd56..b6fbd3b 100644 --- a/parser.c +++ b/parser.c @@ -190,10 +190,10 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons ADVANCE_AND_MOVE(integer_start); case '+': cur->type = REDIS_STATUS_T; - assert(NULL); + ADVANCE_AND_MOVE(line); case '-': cur->type = REDIS_ERROR_T; - assert(NULL); + ADVANCE_AND_MOVE(line); } SET_ERRNO(ERR_INVALID_TYPE); @@ -395,6 +395,36 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons SET_ERRNO(ERR_EXPECTED_LF); goto error; } + + STATE(line) { + const char *mark = pos; + + /* Remove tight loop and add function-wide "line mark" once + * limits on line length are added. */ + while(pos < end) { + if (*pos == '\r') { + cur->coff = cur->poff + 1; + cur->clen = nread - cur->coff; + CALLBACK(string, cur, mark, pos-mark); + ADVANCE_AND_MOVE(line_lf); + } + + ADVANCE(1); + } + + /* No more data */ + CALLBACK(string, cur, mark, pos-mark); + } + + STATE(line_lf) { + if (*pos == '\n') { + cur->plen = nread - cur->poff + 1; /* include \n */ + goto done; + } + + SET_ERRNO(ERR_EXPECTED_LF); + goto error; + } } /* Transitions should be made from within the switch */ diff --git a/test/parser.c b/test/parser.c index 6ea0e96..8fe3e4e 100644 --- a/test/parser.c +++ b/test/parser.c @@ -363,6 +363,38 @@ void test_nil(redis_parser_t *p) { test_char_by_char(p, res, buf, len); } +void test_status(redis_parser_t *p) { + const char *buf = "+status\r\n"; + size_t len = 9; + redis_protocol_t *res; + + /* Parse and check resulting protocol_t */ + RESET_PARSER_T(p); + assert_equal_size_t(redis_parser_execute(p, &res, buf, len), len); + assert(res != NULL); + assert(res->type == REDIS_STATUS_T); + assert(res->poff == 0); + assert(res->plen == 9); + assert(res->coff == 1); + assert(res->clen == 6); +} + +void test_error(redis_parser_t *p) { + const char *buf = "-error\r\n"; + size_t len = 8; + redis_protocol_t *res; + + /* Parse and check resulting protocol_t */ + RESET_PARSER_T(p); + assert_equal_size_t(redis_parser_execute(p, &res, buf, len), len); + assert(res != NULL); + assert(res->type == REDIS_ERROR_T); + assert(res->poff == 0); + assert(res->plen == 8); + assert(res->coff == 1); + assert(res->clen == 5); +} + int main(int argc, char **argv) { redis_parser_t *parser = malloc(sizeof(redis_parser_t)); redis_parser_init(parser, &callbacks); @@ -375,6 +407,8 @@ int main(int argc, char **argv) { test_array(parser); test_empty_array(parser); test_integer(parser); + test_status(parser); + test_error(parser); free(parser); return 0;