summaryrefslogtreecommitdiff
path: root/ext/json/json_parser.y
diff options
context:
space:
mode:
Diffstat (limited to 'ext/json/json_parser.y')
-rw-r--r--ext/json/json_parser.y158
1 files changed, 113 insertions, 45 deletions
diff --git a/ext/json/json_parser.y b/ext/json/json_parser.y
index 2f37641c0c..f359c608d2 100644
--- a/ext/json/json_parser.y
+++ b/ext/json/json_parser.y
@@ -70,20 +70,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);
-
-#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
+static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
+static void php_json_yyerror(php_json_parser *parser, char const *msg);
+
}
%% /* Rules */
@@ -102,10 +91,12 @@ start:
;
object:
- '{' { PHP_JSON_DEPTH_INC; } members object_end
+ '{' { if (FAILURE == parser->methods->object_start(parser)) YYERROR; } members object_end
{
- PHP_JSON_DEPTH_DEC;
$$ = $3;
+ if (FAILURE == parser->methods->object_end(parser, &$$)) {
+ YYERROR;
+ }
}
;
@@ -121,7 +112,7 @@ object_end:
members:
/* empty */
{
- php_json_parser_object_init(parser, &$$);
+ parser->methods->object_create(parser, &$$);
}
| member
;
@@ -129,13 +120,13 @@ 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);
}
@@ -158,10 +149,12 @@ pair:
;
array:
- '[' { PHP_JSON_DEPTH_INC; } elements array_end
+ '[' { if (FAILURE == parser->methods->array_start(parser)) YYERROR; } elements array_end
{
- PHP_JSON_DEPTH_DEC;
ZVAL_COPY_VALUE(&$$, &$3);
+ if (FAILURE == parser->methods->array_end(parser, &$$)) {
+ YYERROR;
+ }
}
;
@@ -177,7 +170,7 @@ array_end:
elements:
/* empty */
{
- php_json_parser_array_init(&$$);
+ parser->methods->array_create(parser, &$$);
}
| element
;
@@ -185,12 +178,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 +220,37 @@ 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_array_start(php_json_parser *parser)
+{
+ return parser->methods->depth_increase(parser);
+}
+
+static int php_json_parser_array_end(php_json_parser *parser, zval *object)
+{
+ return parser->methods->depth_decrease(parser);
+}
+
+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 +279,94 @@ int php_json_parser_object_update(php_json_parser *parser, zval *object, zend_st
return SUCCESS;
}
-void php_json_parser_array_init(zval *array)
+static int php_json_parser_object_start(php_json_parser *parser)
{
- array_init(array);
+ return parser->methods->depth_increase(parser);
}
-void php_json_parser_array_append(zval *array, zval *zvalue)
+static int php_json_parser_object_end(php_json_parser *parser, zval *object)
{
- zend_hash_next_index_insert(Z_ARRVAL_P(array), zvalue);
+ return parser->methods->depth_decrease(parser);
}
-
-int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
+
+static int php_json_parser_depth_increase(php_json_parser *parser)
+{
+ if (parser->max_depth && parser->depth >= parser->max_depth) {
+ parser->scanner.errcode = PHP_JSON_ERROR_DEPTH;
+ return FAILURE;
+ }
+ ++parser->depth;
+ return SUCCESS;
+}
+
+static int php_json_parser_depth_decrease(php_json_parser *parser)
+{
+ --parser->depth;
+ return SUCCESS;
+}
+
+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_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,
+ php_json_parser_array_start,
+ php_json_parser_array_end,
+ php_json_parser_object_create,
+ php_json_parser_object_update,
+ php_json_parser_object_start,
+ php_json_parser_object_end,
+ php_json_parser_depth_increase,
+ php_json_parser_depth_decrease
+};
+
+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;
+ parser->methods = parser_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_parser_init_ex(
+ parser,
+ return_value,
+ str,
+ str_len,
+ options,
+ max_depth,
+ &default_parser_methods);
+}