Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
hiredis
Commits
b919612b
Commit
b919612b
authored
Jul 02, 2011
by
Pieter Noordhuis
Browse files
Cut down on conditional jumps
parent
dcb783ab
Changes
1
Hide whitespace changes
Inline
Side-by-side
parser.c
View file @
b919612b
...
@@ -48,6 +48,18 @@ static const char * strstate[] = {
...
@@ -48,6 +48,18 @@ static const char * strstate[] = {
};
};
#undef _ENUM_GEN
#undef _ENUM_GEN
#define TRANSITION(st) do { \
state = s_##st; \
pos++; nread++; \
if (pos < end) { \
ch = *pos; \
goto l_##st; \
} \
\
/* No more data */
\
goto finalize; \
} while(0)
#ifdef DEBUG
#ifdef DEBUG
#define LOG(fmt, args...) do { \
#define LOG(fmt, args...) do { \
fprintf(stderr, fmt "\n" , ## args); \
fprintf(stderr, fmt "\n" , ## args); \
...
@@ -147,24 +159,19 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
...
@@ -147,24 +159,19 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
switch
(
ch
)
{
switch
(
ch
)
{
case
'$'
:
case
'$'
:
cur
->
type
=
REDIS_STRING_T
;
cur
->
type
=
REDIS_STRING_T
;
state
=
s_integer_sign
;
TRANSITION
(
integer_sign
);
break
;
case
'*'
:
case
'*'
:
cur
->
type
=
REDIS_ARRAY_T
;
cur
->
type
=
REDIS_ARRAY_T
;
state
=
s_integer_sign
;
TRANSITION
(
integer_sign
);
break
;
case
':'
:
case
':'
:
cur
->
type
=
REDIS_INTEGER_T
;
cur
->
type
=
REDIS_INTEGER_T
;
state
=
s_integer_sign
;
TRANSITION
(
integer_sign
);
break
;
case
'+'
:
case
'+'
:
cur
->
type
=
REDIS_STATUS_T
;
cur
->
type
=
REDIS_STATUS_T
;
state
=
s_line
;
assert
(
NULL
);
break
;
case
'-'
:
case
'-'
:
cur
->
type
=
REDIS_ERROR_T
;
cur
->
type
=
REDIS_ERROR_T
;
state
=
s_line
;
assert
(
NULL
);
break
;
default:
default:
goto
error
;
goto
error
;
}
}
...
@@ -172,17 +179,23 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
...
@@ -172,17 +179,23 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
}
}
case
s_integer_sign
:
case
s_integer_sign
:
l_integer_sign:
{
{
i64
.
neg
=
(
ch
==
'-'
);
i64
.
neg
=
(
ch
==
'-'
);
i64
.
ui64
=
0
;
i64
.
ui64
=
0
;
state
=
s_integer_start
;
/* Break when char was consumed */
/* Break when char was consumed */
if
(
ch
==
'-'
||
ch
==
'+'
)
if
(
ch
==
'-'
||
ch
==
'+'
)
{
break
;
TRANSITION
(
integer_start
);
}
/* First integer character */
if
(
ch
>=
'1'
&&
ch
<=
'9'
)
{
i64
.
ui64
=
ch
-
'0'
;
TRANSITION
(
integer_body
);
}
/* Char was not consumed, jump to s_integer_start */
goto
error
;
goto
l_integer_start
;
}
}
case
s_integer_start
:
case
s_integer_start
:
...
@@ -190,14 +203,14 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
...
@@ -190,14 +203,14 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
{
{
if
(
ch
>=
'1'
&&
ch
<=
'9'
)
{
if
(
ch
>=
'1'
&&
ch
<=
'9'
)
{
i64
.
ui64
=
ch
-
'0'
;
i64
.
ui64
=
ch
-
'0'
;
state
=
s_integer_body
;
TRANSITION
(
integer_body
);
}
else
{
goto
error
;
}
}
break
;
goto
error
;
}
}
case
s_integer_body
:
case
s_integer_body
:
l_integer_body:
{
{
if
(
ch
>=
'0'
&&
ch
<=
'9'
)
{
if
(
ch
>=
'0'
&&
ch
<=
'9'
)
{
if
(
i64
.
ui64
>
(
UINT64_MAX
/
10
))
/* Overflow */
if
(
i64
.
ui64
>
(
UINT64_MAX
/
10
))
/* Overflow */
...
@@ -206,6 +219,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
...
@@ -206,6 +219,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
if
(
i64
.
ui64
>
(
UINT64_MAX
-
(
ch
-
'0'
)))
/* Overflow */
if
(
i64
.
ui64
>
(
UINT64_MAX
-
(
ch
-
'0'
)))
/* Overflow */
goto
error
;
goto
error
;
i64
.
ui64
+=
ch
-
'0'
;
i64
.
ui64
+=
ch
-
'0'
;
TRANSITION
(
integer_body
);
}
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
(
i64
.
neg
)
{
if
(
i64
.
neg
)
{
...
@@ -217,15 +231,14 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
...
@@ -217,15 +231,14 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
goto
error
;
goto
error
;
i64
.
i64
=
i64
.
ui64
;
i64
.
i64
=
i64
.
ui64
;
}
}
TRANSITION
(
integer_lf
);
state
=
s_integer_lf
;
}
else
{
goto
error
;
}
}
break
;
goto
error
;
}
}
case
s_integer_lf
:
case
s_integer_lf
:
l_integer_lf:
{
{
if
(
ch
!=
'\n'
)
{
if
(
ch
!=
'\n'
)
{
goto
error
;
goto
error
;
...
@@ -241,7 +254,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
...
@@ -241,7 +254,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
case
REDIS_ARRAY_T
:
goto
l_integer_lf_array_t
;
case
REDIS_ARRAY_T
:
goto
l_integer_lf_array_t
;
case
REDIS_INTEGER_T
:
goto
l_integer_lf_integer_t
;
case
REDIS_INTEGER_T
:
goto
l_integer_lf_integer_t
;
default:
default:
assert
(
NULL
);
assert
(
NULL
&&
"unexpected object type in s_integer_lf"
);
goto
error
;
goto
error
;
}
}
...
@@ -284,6 +297,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
...
@@ -284,6 +297,7 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
}
}
case
s_bulk
:
case
s_bulk
:
l_bulk:
{
{
size_t
len
=
cur
->
remaining
;
size_t
len
=
cur
->
remaining
;
...
@@ -300,11 +314,11 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
...
@@ -300,11 +314,11 @@ size_t redis_parser_execute(redis_parser_t *parser, redis_protocol_t **dst, cons
goto
error
;
goto
error
;
}
}
state
=
s_bulk_lf
;
TRANSITION
(
bulk_lf
);
break
;
}
}
case
s_bulk_lf
:
case
s_bulk_lf
:
l_bulk_lf:
{
{
if
(
ch
!=
'\n'
)
{
if
(
ch
!=
'\n'
)
{
goto
error
;
goto
error
;
...
...
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