Commit dcb783ab authored by Pieter Noordhuis's avatar Pieter Noordhuis
Browse files

Move temporary integer to the stack

parent 96a5c166
...@@ -109,6 +109,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons ...@@ -109,6 +109,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
size_t nread; size_t nread;
int stackidx; int stackidx;
unsigned char state; unsigned char state;
struct redis_parser_int64_s i64;
/* Reset destination */ /* Reset destination */
if (dst) *dst = NULL; if (dst) *dst = NULL;
...@@ -127,6 +128,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons ...@@ -127,6 +128,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
nread = parser->nread; nread = parser->nread;
stackidx = parser->stackidx; stackidx = parser->stackidx;
state = parser->state; state = parser->state;
i64 = parser->i64;
while (pos < end && stackidx >= 0) { while (pos < end && stackidx >= 0) {
redis_protocol_t *cur = &stack[stackidx]; redis_protocol_t *cur = &stack[stackidx];
...@@ -171,8 +173,8 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons ...@@ -171,8 +173,8 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
case s_integer_sign: case s_integer_sign:
{ {
parser->i64.neg = (ch == '-'); i64.neg = (ch == '-');
parser->i64.ui64 = 0; i64.ui64 = 0;
state = s_integer_start; state = s_integer_start;
/* Break when char was consumed */ /* Break when char was consumed */
...@@ -187,7 +189,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons ...@@ -187,7 +189,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
l_integer_start: l_integer_start:
{ {
if (ch >= '1' && ch <= '9') { if (ch >= '1' && ch <= '9') {
parser->i64.ui64 = ch - '0'; i64.ui64 = ch - '0';
state = s_integer_body; state = s_integer_body;
} else { } else {
goto error; goto error;
...@@ -198,22 +200,22 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons ...@@ -198,22 +200,22 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
case s_integer_body: case s_integer_body:
{ {
if (ch >= '0' && ch <= '9') { if (ch >= '0' && ch <= '9') {
if (parser->i64.ui64 > (UINT64_MAX / 10)) /* Overflow */ if (i64.ui64 > (UINT64_MAX / 10)) /* Overflow */
goto error; goto error;
parser->i64.ui64 *= 10; i64.ui64 *= 10;
if (parser->i64.ui64 > (UINT64_MAX - (ch-'0'))) /* Overflow */ if (i64.ui64 > (UINT64_MAX - (ch-'0'))) /* Overflow */
goto error; goto error;
parser->i64.ui64 += ch - '0'; i64.ui64 += ch - '0';
} else if (ch == '\r') { } else if (ch == '\r') {
/* Check if the uint64_t can be safely casted to int64_t */ /* Check if the uint64_t can be safely casted to int64_t */
if (parser->i64.neg) { if (i64.neg) {
if (parser->i64.ui64 > ((uint64_t)(-(INT64_MIN+1))+1)) /* Overflow */ if (i64.ui64 > ((uint64_t)(-(INT64_MIN+1))+1)) /* Overflow */
goto error; goto error;
parser->i64.i64 = -parser->i64.ui64; i64.i64 = -i64.ui64;
} else { } else {
if (parser->i64.ui64 > INT64_MAX) /* Overflow */ if (i64.ui64 > INT64_MAX) /* Overflow */
goto error; goto error;
parser->i64.i64 = parser->i64.ui64; i64.i64 = i64.ui64;
} }
state = s_integer_lf; state = s_integer_lf;
...@@ -245,7 +247,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons ...@@ -245,7 +247,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
l_integer_lf_string_t: l_integer_lf_string_t:
/* Trap the nil bulk */ /* Trap the nil bulk */
if (parser->i64.i64 < 0) { if (i64.i64 < 0) {
CALLBACK(nil); CALLBACK(nil);
goto done; goto done;
} }
...@@ -254,22 +256,22 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons ...@@ -254,22 +256,22 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
* known upfront, but not necessarily valid (we may see EOF * known upfront, but not necessarily valid (we may see EOF
* before seeing the last content byte). */ * before seeing the last content byte). */
cur->coff = nread + 1; /* include \n */ cur->coff = nread + 1; /* include \n */
cur->clen = (unsigned)parser->i64.i64; cur->clen = (unsigned)i64.i64;
cur->plen += cur->clen + 2; /* include \r\n */ cur->plen += cur->clen + 2; /* include \r\n */
/* Store remaining bytes for a complete bulk */ /* Store remaining bytes for a complete bulk */
cur->remaining = (unsigned)parser->i64.i64; cur->remaining = (unsigned)i64.i64;
state = s_bulk; state = s_bulk;
break; break;
l_integer_lf_array_t: l_integer_lf_array_t:
/* Trap the nil multi bulk */ /* Trap the nil multi bulk */
if (parser->i64.i64 < 0) { if (i64.i64 < 0) {
CALLBACK(nil); CALLBACK(nil);
goto done; goto done;
} }
cur->remaining = (unsigned)parser->i64.i64; cur->remaining = (unsigned)i64.i64;
CALLBACK(array, cur->remaining); CALLBACK(array, cur->remaining);
goto done; goto done;
...@@ -277,7 +279,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons ...@@ -277,7 +279,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
/* Setup content offset and length */ /* Setup content offset and length */
cur->coff = cur->poff + 1; cur->coff = cur->poff + 1;
cur->clen = nread - cur->coff - 1; /* remove \r */ cur->clen = nread - cur->coff - 1; /* remove \r */
CALLBACK(integer, parser->i64.i64); CALLBACK(integer, i64.i64);
goto done; goto done;
} }
...@@ -354,6 +356,7 @@ finalize: ...@@ -354,6 +356,7 @@ finalize:
parser->nread = nread; parser->nread = nread;
parser->stackidx = stackidx; parser->stackidx = stackidx;
parser->state = state; parser->state = state;
parser->i64 = i64;
return pos-buf; return pos-buf;
error: error:
......
...@@ -54,7 +54,7 @@ struct redis_parser_s { ...@@ -54,7 +54,7 @@ struct redis_parser_s {
unsigned char state; unsigned char state;
/* private: temporary integer (integer reply, bulk length) */ /* private: temporary integer (integer reply, bulk length) */
struct { struct redis_parser_int64_s {
int neg; /* sign */ int neg; /* sign */
uint64_t ui64; /* accumulator */ uint64_t ui64; /* accumulator */
int64_t i64; /* result */ int64_t i64; /* result */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment