Merge branch 'json_parser_method'

This commit is contained in:
Jakub Zelenka 2016-05-15 13:50:23 +01:00
commit 89d02e0019
3 changed files with 276 additions and 110 deletions

View file

@ -98,6 +98,14 @@ int json_yydebug = 1;
#define PHP_JSON_USE_1(uvr, uv1) PHP_JSON_USE(uvr); PHP_JSON_USE(uv1) #define PHP_JSON_USE_1(uvr, uv1) PHP_JSON_USE(uvr); PHP_JSON_USE(uv1)
#define PHP_JSON_USE_2(uvr, uv1, uv2) PHP_JSON_USE(uvr); PHP_JSON_USE(uv1); PHP_JSON_USE(uv2) #define PHP_JSON_USE_2(uvr, uv1, uv2) PHP_JSON_USE(uvr); PHP_JSON_USE(uv1); PHP_JSON_USE(uv2)
#define PHP_JSON_DEPTH_DEC --parser->depth
#define PHP_JSON_DEPTH_INC \
if (parser->max_depth && parser->depth >= parser->max_depth) { \
parser->scanner.errcode = PHP_JSON_ERROR_DEPTH; \
YYERROR; \
} \
++parser->depth
@ -201,20 +209,9 @@ int php_json_yyparse (php_json_parser *parser);
/* Unqualified %code blocks. */ /* Unqualified %code blocks. */
int php_json_yylex(union YYSTYPE *value, php_json_parser *parser); static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
void php_json_yyerror(php_json_parser *parser, char const *msg); static void php_json_yyerror(php_json_parser *parser, char const *msg);
void php_json_parser_object_init(php_json_parser *parser, zval *object);
int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue);
void php_json_parser_array_init(zval *object);
void php_json_parser_array_append(zval *array, zval *zvalue);
#define PHP_JSON_DEPTH_DEC --parser->depth
#define PHP_JSON_DEPTH_INC \
if (parser->max_depth && parser->depth >= parser->max_depth) { \
parser->scanner.errcode = PHP_JSON_ERROR_DEPTH; \
YYERROR; \
} \
++parser->depth
@ -514,10 +511,10 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] = static const yytype_uint8 yyrline[] =
{ {
0, 92, 92, 98, 105, 105, 113, 114, 123, 126, 0, 89, 89, 95, 103, 102, 120, 121, 130, 133,
130, 136, 142, 149, 154, 161, 161, 169, 170, 179, 137, 144, 151, 158, 163, 171, 170, 188, 189, 198,
182, 186, 191, 196, 203, 204, 208, 209, 210, 211, 201, 205, 210, 215, 222, 223, 227, 228, 229, 230,
212, 213, 214, 215, 216, 217, 221 231, 232, 233, 234, 235, 236, 240
}; };
#endif #endif
@ -1465,15 +1462,23 @@ yyreduce:
case 4: case 4:
{ PHP_JSON_DEPTH_INC; } {
PHP_JSON_DEPTH_INC;
if (parser->methods.object_start && FAILURE == parser->methods.object_start(parser)) {
YYERROR;
}
}
break; break;
case 5: case 5:
{ {
ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-1].value));
PHP_JSON_DEPTH_DEC; PHP_JSON_DEPTH_DEC;
(yyval.value) = (yyvsp[-1].value); if (parser->methods.object_end && FAILURE == parser->methods.object_end(parser, &(yyval.value))) {
YYERROR;
}
} }
break; break;
@ -1490,7 +1495,7 @@ yyreduce:
case 8: case 8:
{ {
php_json_parser_object_init(parser, &(yyval.value)); parser->methods.object_create(parser, &(yyval.value));
} }
break; break;
@ -1498,9 +1503,10 @@ yyreduce:
case 10: case 10:
{ {
php_json_parser_object_init(parser, &(yyval.value)); parser->methods.object_create(parser, &(yyval.value));
if (php_json_parser_object_update(parser, &(yyval.value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val) == FAILURE) if (parser->methods.object_update(parser, &(yyval.value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val) == FAILURE) {
YYERROR; YYERROR;
}
} }
break; break;
@ -1508,8 +1514,9 @@ yyreduce:
case 11: case 11:
{ {
if (php_json_parser_object_update(parser, &(yyvsp[-2].value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val) == FAILURE) if (parser->methods.object_update(parser, &(yyvsp[-2].value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val) == FAILURE) {
YYERROR; YYERROR;
}
ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-2].value)); ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-2].value));
} }
@ -1542,15 +1549,23 @@ yyreduce:
case 15: case 15:
{ PHP_JSON_DEPTH_INC; } {
PHP_JSON_DEPTH_INC;
if (parser->methods.array_start && FAILURE == parser->methods.array_start(parser)) {
YYERROR;
}
}
break; break;
case 16: case 16:
{ {
PHP_JSON_DEPTH_DEC;
ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-1].value)); ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-1].value));
PHP_JSON_DEPTH_DEC;
if (parser->methods.array_end && FAILURE == parser->methods.array_end(parser, &(yyval.value))) {
YYERROR;
}
} }
break; break;
@ -1567,7 +1582,7 @@ yyreduce:
case 19: case 19:
{ {
php_json_parser_array_init(&(yyval.value)); parser->methods.array_create(parser, &(yyval.value));
} }
break; break;
@ -1575,8 +1590,8 @@ yyreduce:
case 21: case 21:
{ {
php_json_parser_array_init(&(yyval.value)); parser->methods.array_create(parser, &(yyval.value));
php_json_parser_array_append(&(yyval.value), &(yyvsp[0].value)); parser->methods.array_append(parser, &(yyval.value), &(yyvsp[0].value));
} }
break; break;
@ -1584,7 +1599,7 @@ yyreduce:
case 22: case 22:
{ {
php_json_parser_array_append(&(yyvsp[-2].value), &(yyvsp[0].value)); parser->methods.array_append(parser, &(yyvsp[-2].value), &(yyvsp[0].value));
ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-2].value)); ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-2].value));
} }
@ -1839,30 +1854,27 @@ yyreturn:
/* Functions */ /* Functions */
void php_json_parser_init(php_json_parser *parser, zval *return_value, char *str, size_t str_len, int options, int max_depth) static int php_json_parser_array_create(php_json_parser *parser, zval *array)
{ {
memset(parser, 0, sizeof(php_json_parser)); return array_init(array);
php_json_scanner_init(&parser->scanner, str, str_len, options);
parser->depth = 1;
parser->max_depth = max_depth;
parser->return_value = return_value;
} }
php_json_error_code php_json_parser_error_code(php_json_parser *parser) static int php_json_parser_array_append(php_json_parser *parser, zval *array, zval *zvalue)
{ {
return parser->scanner.errcode; zend_hash_next_index_insert(Z_ARRVAL_P(array), zvalue);
return SUCCESS;
} }
void php_json_parser_object_init(php_json_parser *parser, zval *object) static int php_json_parser_object_create(php_json_parser *parser, zval *object)
{ {
if (parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) { if (parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) {
array_init(object); return array_init(object);
} else { } else {
object_init(object); return object_init(object);
} }
} }
int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue) static int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue)
{ {
/* if JSON_OBJECT_AS_ARRAY is set */ /* if JSON_OBJECT_AS_ARRAY is set */
if (Z_TYPE_P(object) == IS_ARRAY) { if (Z_TYPE_P(object) == IS_ARRAY) {
@ -1891,26 +1903,71 @@ int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_st
return SUCCESS; return SUCCESS;
} }
void php_json_parser_array_init(zval *array) static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
{
array_init(array);
}
void php_json_parser_array_append(zval *array, zval *zvalue)
{
zend_hash_next_index_insert(Z_ARRVAL_P(array), zvalue);
}
int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
{ {
int token = php_json_scan(&parser->scanner); int token = php_json_scan(&parser->scanner);
value->value = parser->scanner.value; value->value = parser->scanner.value;
return token; return token;
} }
void php_json_yyerror(php_json_parser *parser, char const *msg) static void php_json_yyerror(php_json_parser *parser, char const *msg)
{ {
if (!parser->scanner.errcode) { if (!parser->scanner.errcode) {
parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX; parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX;
} }
} }
PHP_JSON_API php_json_error_code php_json_parser_error_code(const php_json_parser *parser)
{
return parser->scanner.errcode;
}
static const php_json_parser_methods default_parser_methods =
{
php_json_parser_array_create,
php_json_parser_array_append,
NULL,
NULL,
php_json_parser_object_create,
php_json_parser_object_update,
NULL,
NULL,
};
PHP_JSON_API void php_json_parser_init_ex(php_json_parser *parser,
zval *return_value,
char *str,
size_t str_len,
int options,
int max_depth,
const php_json_parser_methods *parser_methods)
{
memset(parser, 0, sizeof(php_json_parser));
php_json_scanner_init(&parser->scanner, str, str_len, options);
parser->depth = 1;
parser->max_depth = max_depth;
parser->return_value = return_value;
memcpy(&parser->methods, parser_methods, sizeof(php_json_parser_methods));
}
PHP_JSON_API void php_json_parser_init(php_json_parser *parser,
zval *return_value,
char *str,
size_t str_len,
int options,
int max_depth)
{
php_json_parser_init_ex(
parser,
return_value,
str,
str_len,
options,
max_depth,
&default_parser_methods);
}
PHP_JSON_API int php_json_parse(php_json_parser *parser)
{
return php_json_yyparse(parser);
}

View file

@ -36,6 +36,14 @@ int json_yydebug = 1;
#define PHP_JSON_USE_1(uvr, uv1) PHP_JSON_USE(uvr); PHP_JSON_USE(uv1) #define PHP_JSON_USE_1(uvr, uv1) PHP_JSON_USE(uvr); PHP_JSON_USE(uv1)
#define PHP_JSON_USE_2(uvr, uv1, uv2) PHP_JSON_USE(uvr); PHP_JSON_USE(uv1); PHP_JSON_USE(uv2) #define PHP_JSON_USE_2(uvr, uv1, uv2) PHP_JSON_USE(uvr); PHP_JSON_USE(uv1); PHP_JSON_USE(uv2)
#define PHP_JSON_DEPTH_DEC --parser->depth
#define PHP_JSON_DEPTH_INC \
if (parser->max_depth && parser->depth >= parser->max_depth) { \
parser->scanner.errcode = PHP_JSON_ERROR_DEPTH; \
YYERROR; \
} \
++parser->depth
} }
%pure-parser %pure-parser
@ -70,20 +78,9 @@ int json_yydebug = 1;
%destructor { zend_string_release($$.key); zval_dtor(&$$.val); } <pair> %destructor { zend_string_release($$.key); zval_dtor(&$$.val); } <pair>
%code { %code {
int php_json_yylex(union YYSTYPE *value, php_json_parser *parser); static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
void php_json_yyerror(php_json_parser *parser, char const *msg); static void php_json_yyerror(php_json_parser *parser, char const *msg);
void php_json_parser_object_init(php_json_parser *parser, zval *object);
int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue);
void php_json_parser_array_init(zval *object);
void php_json_parser_array_append(zval *array, zval *zvalue);
#define PHP_JSON_DEPTH_DEC --parser->depth
#define PHP_JSON_DEPTH_INC \
if (parser->max_depth && parser->depth >= parser->max_depth) { \
parser->scanner.errcode = PHP_JSON_ERROR_DEPTH; \
YYERROR; \
} \
++parser->depth
} }
%% /* Rules */ %% /* Rules */
@ -102,10 +99,20 @@ start:
; ;
object: object:
'{' { PHP_JSON_DEPTH_INC; } members object_end '{'
{ {
PHP_JSON_DEPTH_INC;
if (parser->methods.object_start && FAILURE == parser->methods.object_start(parser)) {
YYERROR;
}
}
members object_end
{
ZVAL_COPY_VALUE(&$$, &$3);
PHP_JSON_DEPTH_DEC; PHP_JSON_DEPTH_DEC;
$$ = $3; if (parser->methods.object_end && FAILURE == parser->methods.object_end(parser, &$$)) {
YYERROR;
}
} }
; ;
@ -121,7 +128,7 @@ object_end:
members: members:
/* empty */ /* empty */
{ {
php_json_parser_object_init(parser, &$$); parser->methods.object_create(parser, &$$);
} }
| member | member
; ;
@ -129,14 +136,16 @@ members:
member: member:
pair pair
{ {
php_json_parser_object_init(parser, &$$); parser->methods.object_create(parser, &$$);
if (php_json_parser_object_update(parser, &$$, $1.key, &$1.val) == FAILURE) if (parser->methods.object_update(parser, &$$, $1.key, &$1.val) == FAILURE) {
YYERROR; YYERROR;
}
} }
| member ',' pair | member ',' pair
{ {
if (php_json_parser_object_update(parser, &$1, $3.key, &$3.val) == FAILURE) if (parser->methods.object_update(parser, &$1, $3.key, &$3.val) == FAILURE) {
YYERROR; YYERROR;
}
ZVAL_COPY_VALUE(&$$, &$1); ZVAL_COPY_VALUE(&$$, &$1);
} }
| member errlex | member errlex
@ -158,10 +167,20 @@ pair:
; ;
array: array:
'[' { PHP_JSON_DEPTH_INC; } elements array_end '['
{
PHP_JSON_DEPTH_INC;
if (parser->methods.array_start && FAILURE == parser->methods.array_start(parser)) {
YYERROR;
}
}
elements array_end
{ {
PHP_JSON_DEPTH_DEC;
ZVAL_COPY_VALUE(&$$, &$3); ZVAL_COPY_VALUE(&$$, &$3);
PHP_JSON_DEPTH_DEC;
if (parser->methods.array_end && FAILURE == parser->methods.array_end(parser, &$$)) {
YYERROR;
}
} }
; ;
@ -177,7 +196,7 @@ array_end:
elements: elements:
/* empty */ /* empty */
{ {
php_json_parser_array_init(&$$); parser->methods.array_create(parser, &$$);
} }
| element | element
; ;
@ -185,12 +204,12 @@ elements:
element: element:
value value
{ {
php_json_parser_array_init(&$$); parser->methods.array_create(parser, &$$);
php_json_parser_array_append(&$$, &$1); parser->methods.array_append(parser, &$$, &$1);
} }
| element ',' value | element ',' value
{ {
php_json_parser_array_append(&$1, &$3); parser->methods.array_append(parser, &$1, &$3);
ZVAL_COPY_VALUE(&$$, &$1); ZVAL_COPY_VALUE(&$$, &$1);
} }
| element errlex | element errlex
@ -227,30 +246,27 @@ errlex:
%% /* Functions */ %% /* Functions */
void php_json_parser_init(php_json_parser *parser, zval *return_value, char *str, size_t str_len, int options, int max_depth) static int php_json_parser_array_create(php_json_parser *parser, zval *array)
{ {
memset(parser, 0, sizeof(php_json_parser)); return array_init(array);
php_json_scanner_init(&parser->scanner, str, str_len, options);
parser->depth = 1;
parser->max_depth = max_depth;
parser->return_value = return_value;
} }
php_json_error_code php_json_parser_error_code(php_json_parser *parser) static int php_json_parser_array_append(php_json_parser *parser, zval *array, zval *zvalue)
{ {
return parser->scanner.errcode; zend_hash_next_index_insert(Z_ARRVAL_P(array), zvalue);
return SUCCESS;
} }
void php_json_parser_object_init(php_json_parser *parser, zval *object) static int php_json_parser_object_create(php_json_parser *parser, zval *object)
{ {
if (parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) { if (parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) {
array_init(object); return array_init(object);
} else { } else {
object_init(object); return object_init(object);
} }
} }
int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue) static int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_string *key, zval *zvalue)
{ {
/* if JSON_OBJECT_AS_ARRAY is set */ /* if JSON_OBJECT_AS_ARRAY is set */
if (Z_TYPE_P(object) == IS_ARRAY) { if (Z_TYPE_P(object) == IS_ARRAY) {
@ -279,26 +295,71 @@ int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_st
return SUCCESS; return SUCCESS;
} }
void php_json_parser_array_init(zval *array) static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
{
array_init(array);
}
void php_json_parser_array_append(zval *array, zval *zvalue)
{
zend_hash_next_index_insert(Z_ARRVAL_P(array), zvalue);
}
int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
{ {
int token = php_json_scan(&parser->scanner); int token = php_json_scan(&parser->scanner);
value->value = parser->scanner.value; value->value = parser->scanner.value;
return token; return token;
} }
void php_json_yyerror(php_json_parser *parser, char const *msg) static void php_json_yyerror(php_json_parser *parser, char const *msg)
{ {
if (!parser->scanner.errcode) { if (!parser->scanner.errcode) {
parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX; parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX;
} }
} }
PHP_JSON_API php_json_error_code php_json_parser_error_code(const php_json_parser *parser)
{
return parser->scanner.errcode;
}
static const php_json_parser_methods default_parser_methods =
{
php_json_parser_array_create,
php_json_parser_array_append,
NULL,
NULL,
php_json_parser_object_create,
php_json_parser_object_update,
NULL,
NULL,
};
PHP_JSON_API void php_json_parser_init_ex(php_json_parser *parser,
zval *return_value,
char *str,
size_t str_len,
int options,
int max_depth,
const php_json_parser_methods *parser_methods)
{
memset(parser, 0, sizeof(php_json_parser));
php_json_scanner_init(&parser->scanner, str, str_len, options);
parser->depth = 1;
parser->max_depth = max_depth;
parser->return_value = return_value;
memcpy(&parser->methods, parser_methods, sizeof(php_json_parser_methods));
}
PHP_JSON_API void php_json_parser_init(php_json_parser *parser,
zval *return_value,
char *str,
size_t str_len,
int options,
int max_depth)
{
php_json_parser_init_ex(
parser,
return_value,
str,
str_len,
options,
max_depth,
&default_parser_methods);
}
PHP_JSON_API int php_json_parse(php_json_parser *parser)
{
return php_json_yyparse(parser);
}

View file

@ -22,16 +22,64 @@
#include "php.h" #include "php.h"
#include "php_json_scanner.h" #include "php_json_scanner.h"
typedef struct _php_json_parser { typedef struct _php_json_parser php_json_parser;
typedef int (*php_json_parser_func_array_create_t)(
php_json_parser *parser, zval *array);
typedef int (*php_json_parser_func_array_append_t)(
php_json_parser *parser, zval *array, zval *zvalue);
typedef int (*php_json_parser_func_array_start_t)(
php_json_parser *parser);
typedef int (*php_json_parser_func_array_end_t)(
php_json_parser *parser, zval *object);
typedef int (*php_json_parser_func_object_create_t)(
php_json_parser *parser, zval *object);
typedef int (*php_json_parser_func_object_update_t)(
php_json_parser *parser, zval *object, zend_string *key, zval *zvalue);
typedef int (*php_json_parser_func_object_start_t)(
php_json_parser *parser);
typedef int (*php_json_parser_func_object_end_t)(
php_json_parser *parser, zval *object);
typedef struct _php_json_parser_methods {
php_json_parser_func_array_create_t array_create;
php_json_parser_func_array_append_t array_append;
php_json_parser_func_array_start_t array_start;
php_json_parser_func_array_end_t array_end;
php_json_parser_func_object_create_t object_create;
php_json_parser_func_object_update_t object_update;
php_json_parser_func_object_start_t object_start;
php_json_parser_func_object_end_t object_end;
} php_json_parser_methods;
struct _php_json_parser {
php_json_scanner scanner; php_json_scanner scanner;
zval *return_value; zval *return_value;
int depth; unsigned int depth;
int max_depth; int max_depth;
} php_json_parser; php_json_parser_methods methods;
};
void php_json_parser_init(php_json_parser *parser, zval *return_value, char *str, size_t str_len, int options, int max_depth); PHP_JSON_API void php_json_parser_init_ex(
php_json_parser *parser,
zval *return_value,
char *str,
size_t str_len,
int options,
int max_depth,
const php_json_parser_methods *methods);
php_json_error_code php_json_parser_error_code(php_json_parser *parser); PHP_JSON_API void php_json_parser_init(
php_json_parser *parser,
zval *return_value,
char *str,
size_t str_len,
int options,
int max_depth);
PHP_JSON_API php_json_error_code php_json_parser_error_code(const php_json_parser *parser);
PHP_JSON_API int php_json_parse(php_json_parser *parser);
int php_json_yyparse(php_json_parser *parser); int php_json_yyparse(php_json_parser *parser);