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_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. */
int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
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);
static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
static void php_json_yyerror(php_json_parser *parser, char const *msg);
#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. */
static const yytype_uint8 yyrline[] =
{
0, 92, 92, 98, 105, 105, 113, 114, 123, 126,
130, 136, 142, 149, 154, 161, 161, 169, 170, 179,
182, 186, 191, 196, 203, 204, 208, 209, 210, 211,
212, 213, 214, 215, 216, 217, 221
0, 89, 89, 95, 103, 102, 120, 121, 130, 133,
137, 144, 151, 158, 163, 171, 170, 188, 189, 198,
201, 205, 210, 215, 222, 223, 227, 228, 229, 230,
231, 232, 233, 234, 235, 236, 240
};
#endif
@ -1465,15 +1462,23 @@ yyreduce:
case 4:
{ PHP_JSON_DEPTH_INC; }
{
PHP_JSON_DEPTH_INC;
if (parser->methods.object_start && FAILURE == parser->methods.object_start(parser)) {
YYERROR;
}
}
break;
case 5:
{
ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-1].value));
PHP_JSON_DEPTH_DEC;
(yyval.value) = (yyvsp[-1].value);
if (parser->methods.object_end && FAILURE == parser->methods.object_end(parser, &(yyval.value))) {
YYERROR;
}
}
break;
@ -1490,7 +1495,7 @@ yyreduce:
case 8:
{
php_json_parser_object_init(parser, &(yyval.value));
parser->methods.object_create(parser, &(yyval.value));
}
break;
@ -1498,18 +1503,20 @@ yyreduce:
case 10:
{
php_json_parser_object_init(parser, &(yyval.value));
if (php_json_parser_object_update(parser, &(yyval.value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val) == FAILURE)
parser->methods.object_create(parser, &(yyval.value));
if (parser->methods.object_update(parser, &(yyval.value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val) == FAILURE) {
YYERROR;
}
}
break;
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;
}
ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-2].value));
}
@ -1542,15 +1549,23 @@ yyreduce:
case 15:
{ PHP_JSON_DEPTH_INC; }
{
PHP_JSON_DEPTH_INC;
if (parser->methods.array_start && FAILURE == parser->methods.array_start(parser)) {
YYERROR;
}
}
break;
case 16:
{
PHP_JSON_DEPTH_DEC;
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;
@ -1567,7 +1582,7 @@ yyreduce:
case 19:
{
php_json_parser_array_init(&(yyval.value));
parser->methods.array_create(parser, &(yyval.value));
}
break;
@ -1575,8 +1590,8 @@ yyreduce:
case 21:
{
php_json_parser_array_init(&(yyval.value));
php_json_parser_array_append(&(yyval.value), &(yyvsp[0].value));
parser->methods.array_create(parser, &(yyval.value));
parser->methods.array_append(parser, &(yyval.value), &(yyvsp[0].value));
}
break;
@ -1584,7 +1599,7 @@ yyreduce:
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));
}
@ -1839,30 +1854,27 @@ yyreturn:
/* 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));
php_json_scanner_init(&parser->scanner, str, str_len, options);
parser->depth = 1;
parser->max_depth = max_depth;
parser->return_value = return_value;
return array_init(array);
}
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) {
array_init(object);
return array_init(object);
} 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 (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;
}
void php_json_parser_array_init(zval *array)
{
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)
static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
{
int token = php_json_scan(&parser->scanner);
value->value = parser->scanner.value;
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) {
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_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
@ -70,20 +78,9 @@ int json_yydebug = 1;
%destructor { zend_string_release($$.key); zval_dtor(&$$.val); } <pair>
%code {
int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
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);
static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
static void php_json_yyerror(php_json_parser *parser, char const *msg);
#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 */
@ -102,10 +99,20 @@ start:
;
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;
$$ = $3;
if (parser->methods.object_end && FAILURE == parser->methods.object_end(parser, &$$)) {
YYERROR;
}
}
;
@ -121,7 +128,7 @@ object_end:
members:
/* empty */
{
php_json_parser_object_init(parser, &$$);
parser->methods.object_create(parser, &$$);
}
| member
;
@ -129,14 +136,16 @@ members:
member:
pair
{
php_json_parser_object_init(parser, &$$);
if (php_json_parser_object_update(parser, &$$, $1.key, &$1.val) == FAILURE)
parser->methods.object_create(parser, &$$);
if (parser->methods.object_update(parser, &$$, $1.key, &$1.val) == FAILURE) {
YYERROR;
}
}
| 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;
}
ZVAL_COPY_VALUE(&$$, &$1);
}
| member errlex
@ -158,10 +167,20 @@ pair:
;
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);
PHP_JSON_DEPTH_DEC;
if (parser->methods.array_end && FAILURE == parser->methods.array_end(parser, &$$)) {
YYERROR;
}
}
;
@ -177,7 +196,7 @@ array_end:
elements:
/* empty */
{
php_json_parser_array_init(&$$);
parser->methods.array_create(parser, &$$);
}
| element
;
@ -185,12 +204,12 @@ elements:
element:
value
{
php_json_parser_array_init(&$$);
php_json_parser_array_append(&$$, &$1);
parser->methods.array_create(parser, &$$);
parser->methods.array_append(parser, &$$, &$1);
}
| element ',' value
{
php_json_parser_array_append(&$1, &$3);
parser->methods.array_append(parser, &$1, &$3);
ZVAL_COPY_VALUE(&$$, &$1);
}
| element errlex
@ -227,30 +246,27 @@ errlex:
%% /* 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));
php_json_scanner_init(&parser->scanner, str, str_len, options);
parser->depth = 1;
parser->max_depth = max_depth;
parser->return_value = return_value;
return array_init(array);
}
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) {
array_init(object);
return array_init(object);
} 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 (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;
}
void php_json_parser_array_init(zval *array)
{
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)
static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
{
int token = php_json_scan(&parser->scanner);
value->value = parser->scanner.value;
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) {
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_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;
zval *return_value;
int depth;
unsigned int 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);