Skip to content

Commit d07bf91

Browse files
committed
Initial import of jsond
1 parent 12cf41c commit d07bf91

10 files changed

+693
-200
lines changed

ext/json/CREDITS

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
JSON
2-
Omar Kilani, Scott MacVicar
2+
Jakub Zelenka, Omar Kilani, Scott MacVicar

ext/json/Makefile.frag

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
$(srcdir)/json_scanner.c: $(srcdir)/json_scanner.re
2+
$(RE2C) -t php_json_scanner_defs.h --no-generation-date -bci -o $@ json_scanner.re
3+
4+
$(srcdir)/json_parser.tab.c: $(srcdir)/json_parser.y
5+
$(YACC) --defines -l $(srcdir)/json_parser.y -o $@

ext/json/config.m4

+6-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ if test "$PHP_JSON" != "no"; then
99
AC_DEFINE([HAVE_JSON],1 ,[whether to enable JavaScript Object Serialization support])
1010
AC_HEADER_STDC
1111

12-
PHP_NEW_EXTENSION(json, json.c utf8_decode.c JSON_parser.c, $ext_shared)
12+
PHP_NEW_EXTENSION(json,
13+
json.c \
14+
json_parser.tab.c \
15+
json_scanner.c,
16+
$ext_shared)
1317
PHP_INSTALL_HEADERS([ext/json], [php_json.h])
18+
PHP_ADD_MAKEFILE_FRAGMENT()
1419
PHP_SUBST(JSON_SHARED_LIBADD)
1520
fi

ext/json/config.w32

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ ARG_ENABLE("json", "JavaScript Object Serialization support", "yes");
55

66
if (PHP_JSON != "no") {
77
EXTENSION('json', 'json.c', PHP_JSON_SHARED, "");
8-
ADD_SOURCES(configure_module_dirname, "JSON_parser.c utf8_decode.c", "json");
8+
PHP_NEW_EXTENSION(json,
9+
json.c \
10+
json_parser.tab.c \
11+
json_scanner.c,
12+
$ext_shared)
913
PHP_INSTALL_HEADERS("ext/json/", "php_json.h");
1014
}
1115

ext/json/json_parser.y

+242
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
%code top {
2+
/*
3+
+----------------------------------------------------------------------+
4+
| PHP Version 5 |
5+
+----------------------------------------------------------------------+
6+
| Copyright (c) 1997-2014 The PHP Group |
7+
+----------------------------------------------------------------------+
8+
| This source file is subject to version 3.01 of the PHP license, |
9+
| that is bundled with this package in the file LICENSE, and is |
10+
| available through the world-wide-web at the following url: |
11+
| http://www.php.net/license/3_01.txt |
12+
| If you did not receive a copy of the PHP license and are unable to |
13+
| obtain it through the world-wide-web, please send a note to |
14+
| [email protected] so we can mail you a copy immediately. |
15+
+----------------------------------------------------------------------+
16+
| Author: Jakub Zelenka <[email protected]> |
17+
+----------------------------------------------------------------------+
18+
*/
19+
20+
#include "php.h"
21+
#include "php_json.h"
22+
#include "php_json_parser.h"
23+
24+
#define YYDEBUG 0
25+
26+
#if YYDEBUG
27+
int json_yydebug = 1;
28+
#endif
29+
30+
#define PHP_JSON_USE(uv) ((void) (uv))
31+
#define PHP_JSON_USE_1(uvr, uv1) PHP_JSON_USE(uvr); PHP_JSON_USE(uv1)
32+
#define PHP_JSON_USE_2(uvr, uv1, uv2) PHP_JSON_USE(uvr); PHP_JSON_USE(uv1); PHP_JSON_USE(uv2)
33+
34+
}
35+
36+
%pure-parser
37+
%name-prefix "php_json_yy"
38+
%lex-param { php_json_parser *parser }
39+
%parse-param { php_json_parser *parser }
40+
41+
%union {
42+
zval value;
43+
struct {
44+
zval key;
45+
zval val;
46+
} pair;
47+
HashTable *ht;
48+
}
49+
50+
51+
%token <value> PHP_JSON_T_NUL
52+
%token <value> PHP_JSON_T_TRUE
53+
%token <value> PHP_JSON_T_FALSE
54+
%token <value> PHP_JSON_T_INT
55+
%token <value> PHP_JSON_T_DOUBLE
56+
%token <value> PHP_JSON_T_STRING
57+
%token <value> PHP_JSON_T_ESTRING
58+
%token <value> PHP_JSON_T_EOI
59+
%token <value> PHP_JSON_T_ERROR
60+
61+
%type <value> start object key value array errlex
62+
%type <ht> members member elements element
63+
%type <pair> pair
64+
65+
%destructor { zval_dtor(&$$); } <value>
66+
%destructor { zend_hash_destroy($$); FREE_HASHTABLE($$); } <ht>
67+
%destructor { zval_dtor(&$$.key); zval_dtor(&$$.val); } <pair>
68+
69+
%code {
70+
int php_json_yylex(union YYSTYPE *value, php_json_parser *parser);
71+
void php_json_yyerror(php_json_parser *parser, char const *msg);
72+
void php_json_parser_object_to_zval(php_json_parser *parser, zval *zv, HashTable *ht);
73+
void php_json_parser_array_to_zval(zval *zv, HashTable *ht);
74+
void php_json_parser_ht_init(HashTable **ht, uint nSize);
75+
void php_json_parser_ht_update(php_json_parser *parser, HashTable *ht, zval *zkey, zval *zvalue);
76+
void php_json_parser_ht_append(HashTable *ht, zval *zvalue);
77+
78+
#define PHP_JSON_DEPTH_DEC --parser->depth
79+
#define PHP_JSON_DEPTH_INC \
80+
if (parser->max_depth && parser->depth >= parser->max_depth) { \
81+
parser->scanner.errcode = PHP_JSON_ERROR_DEPTH; \
82+
YYERROR; \
83+
} \
84+
++parser->depth
85+
}
86+
87+
%% /* Rules */
88+
89+
start:
90+
value PHP_JSON_T_EOI { $$ = $1; INIT_PZVAL_COPY(parser->return_value, &$1); PHP_JSON_USE($2); YYACCEPT; }
91+
| value errlex { PHP_JSON_USE_2($$, $1, $2); }
92+
;
93+
94+
object:
95+
'{' { PHP_JSON_DEPTH_INC; } members object_end { PHP_JSON_DEPTH_DEC; php_json_parser_object_to_zval(parser, &$$, $3); }
96+
;
97+
98+
object_end:
99+
'}'
100+
| ']' { parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH; YYERROR; }
101+
;
102+
103+
members:
104+
/* empty */ { php_json_parser_ht_init(&$$, 0); }
105+
| member
106+
;
107+
108+
member:
109+
pair { php_json_parser_ht_init(&$$, 4); php_json_parser_ht_update(parser, $$, &$1.key, &$1.val); }
110+
| member ',' pair { php_json_parser_ht_update(parser, $1, &$3.key, &$3.val); $$ = $1; }
111+
| member errlex { PHP_JSON_USE_2($$, $1, $2); }
112+
;
113+
114+
pair:
115+
key ':' value { $$.key = $1; $$.val = $3; }
116+
| key errlex { PHP_JSON_USE_2($$, $1, $2); }
117+
;
118+
119+
array:
120+
'[' { PHP_JSON_DEPTH_INC; } elements array_end { PHP_JSON_DEPTH_DEC; php_json_parser_array_to_zval(&$$, $3); }
121+
;
122+
123+
array_end:
124+
']'
125+
| '}' { parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH; YYERROR; }
126+
;
127+
128+
elements:
129+
/* empty */ { php_json_parser_ht_init(&$$, 0); }
130+
| element
131+
;
132+
133+
element:
134+
value { php_json_parser_ht_init(&$$, 4); php_json_parser_ht_append($$, &$1); }
135+
| element ',' value { php_json_parser_ht_append($1, &$3); $$ = $1; }
136+
| element errlex { PHP_JSON_USE_2($$, $1, $2); }
137+
;
138+
139+
key:
140+
PHP_JSON_T_STRING
141+
| PHP_JSON_T_ESTRING
142+
;
143+
144+
value:
145+
object
146+
| array
147+
| PHP_JSON_T_STRING
148+
| PHP_JSON_T_ESTRING
149+
| PHP_JSON_T_INT
150+
| PHP_JSON_T_DOUBLE
151+
| PHP_JSON_T_NUL
152+
| PHP_JSON_T_TRUE
153+
| PHP_JSON_T_FALSE
154+
| errlex
155+
;
156+
157+
errlex:
158+
PHP_JSON_T_ERROR { PHP_JSON_USE_1($$, $1); YYERROR; }
159+
;
160+
161+
%% /* Functions */
162+
163+
void php_json_parser_init(php_json_parser *parser, zval *return_value, char *str, int str_len, long options, long max_depth TSRMLS_DC)
164+
{
165+
memset(parser, 0, sizeof(php_json_parser));
166+
php_json_scanner_init(&parser->scanner, str, str_len, options);
167+
parser->depth = 1;
168+
parser->max_depth = max_depth;
169+
parser->return_value = return_value;
170+
TSRMLS_SET_CTX(parser->zts_ctx);
171+
}
172+
173+
php_json_error_code php_json_parser_error_code(php_json_parser *parser)
174+
{
175+
return parser->scanner.errcode;
176+
}
177+
178+
void php_json_parser_object_to_zval(php_json_parser *parser, zval *zv, HashTable *ht)
179+
{
180+
TSRMLS_FETCH_FROM_CTX(parser->zts_ctx);
181+
182+
if (parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) {
183+
php_json_parser_array_to_zval(zv, ht);
184+
} else {
185+
object_and_properties_init(zv, zend_standard_class_def, ht);
186+
}
187+
}
188+
189+
void php_json_parser_array_to_zval(zval *zv, HashTable *ht)
190+
{
191+
Z_TYPE_P(zv) = IS_ARRAY;
192+
Z_ARRVAL_P(zv) = ht;
193+
}
194+
195+
void php_json_parser_ht_init(HashTable **ht, uint nSize)
196+
{
197+
ALLOC_HASHTABLE(*ht);
198+
zend_hash_init(*ht, nSize, NULL, ZVAL_PTR_DTOR, 0);
199+
}
200+
201+
void php_json_parser_ht_update(php_json_parser *parser, HashTable *ht, zval *zkey, zval *zvalue)
202+
{
203+
zval *data;
204+
char *key = Z_STRVAL_P(zkey);
205+
int key_len = Z_STRLEN_P(zkey)+1;
206+
MAKE_STD_ZVAL(data);
207+
ZVAL_ZVAL(data, zvalue, 0, 0);
208+
209+
if (parser->scanner.options & PHP_JSON_OBJECT_AS_ARRAY) {
210+
zend_symtable_update(ht, key, key_len, &data, sizeof(zval *), NULL);
211+
} else {
212+
if (key_len == 1) {
213+
key = "_empty_";
214+
key_len = sizeof("_empty_");
215+
}
216+
zend_hash_update(ht, key, key_len, &data, sizeof(zval *), NULL);
217+
}
218+
219+
zval_dtor(zkey);
220+
}
221+
222+
void php_json_parser_ht_append(HashTable *ht, zval *zvalue)
223+
{
224+
zval *data;
225+
MAKE_STD_ZVAL(data);
226+
ZVAL_ZVAL(data, zvalue, 0, 0);
227+
zend_hash_next_index_insert(ht, &data, sizeof(zval *), NULL);
228+
}
229+
230+
int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)
231+
{
232+
int token = php_json_scan(&parser->scanner);
233+
value->value = parser->scanner.value;
234+
return token;
235+
}
236+
237+
void php_json_yyerror(php_json_parser *parser, char const *msg)
238+
{
239+
if (!parser->scanner.errcode) {
240+
parser->scanner.errcode = PHP_JSON_ERROR_SYNTAX;
241+
}
242+
}

0 commit comments

Comments
 (0)