29
29
#include "ext/standard/html.h"
30
30
#include "zend_smart_str.h"
31
31
#include "php_json.h"
32
+ #include "php_json_encoder.h"
32
33
#include <zend_exceptions.h>
33
34
34
35
static const char digits [] = "0123456789abcdef" ;
35
36
36
- static int php_json_escape_string (smart_str * buf , char * s , size_t len , int options );
37
+ static int php_json_escape_string (
38
+ smart_str * buf , char * s , size_t len ,
39
+ int options , php_json_encoder * encoder );
37
40
38
41
static int php_json_determine_array_type (zval * val ) /* {{{ */
39
42
{
@@ -76,12 +79,12 @@ static inline void php_json_pretty_print_char(smart_str *buf, int options, char
76
79
}
77
80
/* }}} */
78
81
79
- static inline void php_json_pretty_print_indent (smart_str * buf , int options ) /* {{{ */
82
+ static inline void php_json_pretty_print_indent (smart_str * buf , int options , php_json_encoder * encoder ) /* {{{ */
80
83
{
81
84
int i ;
82
85
83
86
if (options & PHP_JSON_PRETTY_PRINT ) {
84
- for (i = 0 ; i < JSON_G ( encoder_depth ) ; ++ i ) {
87
+ for (i = 0 ; i < encoder -> depth ; ++ i ) {
85
88
smart_str_appendl (buf , " " , 4 );
86
89
}
87
90
}
@@ -126,7 +129,7 @@ static inline void php_json_encode_double(smart_str *buf, double d, int options)
126
129
} \
127
130
} while (0)
128
131
129
- static int php_json_encode_array (smart_str * buf , zval * val , int options ) /* {{{ */
132
+ static int php_json_encode_array (smart_str * buf , zval * val , int options , php_json_encoder * encoder ) /* {{{ */
130
133
{
131
134
int i , r , need_comma = 0 ;
132
135
HashTable * myht ;
@@ -140,7 +143,7 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
140
143
}
141
144
142
145
if (myht && ZEND_HASH_GET_APPLY_COUNT (myht ) > 1 ) {
143
- JSON_G ( error_code ) = PHP_JSON_ERROR_RECURSION ;
146
+ encoder -> error_code = PHP_JSON_ERROR_RECURSION ;
144
147
smart_str_appendl (buf , "null" , 4 );
145
148
return FAILURE ;
146
149
}
@@ -151,7 +154,7 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
151
154
smart_str_appendc (buf , '{' );
152
155
}
153
156
154
- ++ JSON_G ( encoder_depth ) ;
157
+ ++ encoder -> depth ;
155
158
156
159
i = myht ? zend_hash_num_elements (myht ) : 0 ;
157
160
@@ -174,7 +177,7 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
174
177
}
175
178
176
179
php_json_pretty_print_char (buf , options , '\n' );
177
- php_json_pretty_print_indent (buf , options );
180
+ php_json_pretty_print_indent (buf , options , encoder );
178
181
} else if (r == PHP_JSON_OUTPUT_OBJECT ) {
179
182
if (key ) {
180
183
if (ZSTR_VAL (key )[0 ] == '\0' && ZSTR_LEN (key ) > 0 && Z_TYPE_P (val ) == IS_OBJECT ) {
@@ -190,9 +193,10 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
190
193
}
191
194
192
195
php_json_pretty_print_char (buf , options , '\n' );
193
- php_json_pretty_print_indent (buf , options );
196
+ php_json_pretty_print_indent (buf , options , encoder );
194
197
195
- php_json_escape_string (buf , ZSTR_VAL (key ), ZSTR_LEN (key ), options & ~PHP_JSON_NUMERIC_CHECK );
198
+ php_json_escape_string (buf , ZSTR_VAL (key ), ZSTR_LEN (key ),
199
+ options & ~PHP_JSON_NUMERIC_CHECK , encoder );
196
200
} else {
197
201
if (need_comma ) {
198
202
smart_str_appendc (buf , ',' );
@@ -201,7 +205,7 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
201
205
}
202
206
203
207
php_json_pretty_print_char (buf , options , '\n' );
204
- php_json_pretty_print_indent (buf , options );
208
+ php_json_pretty_print_indent (buf , options , encoder );
205
209
206
210
smart_str_appendc (buf , '"' );
207
211
smart_str_append_long (buf , (zend_long ) index );
@@ -212,7 +216,8 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
212
216
php_json_pretty_print_char (buf , options , ' ' );
213
217
}
214
218
215
- if (php_json_encode (buf , data , options ) == FAILURE && !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR )) {
219
+ if (php_json_encode_zval (buf , data , options , encoder ) == FAILURE &&
220
+ !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR )) {
216
221
PHP_JSON_HASH_APPLY_PROTECTION_DEC (tmp_ht );
217
222
return FAILURE ;
218
223
}
@@ -221,18 +226,18 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
221
226
} ZEND_HASH_FOREACH_END ();
222
227
}
223
228
224
- if (JSON_G ( encoder_depth ) > JSON_G ( encode_max_depth ) ) {
225
- JSON_G ( error_code ) = PHP_JSON_ERROR_DEPTH ;
229
+ if (encoder -> depth > encoder -> max_depth ) {
230
+ encoder -> error_code = PHP_JSON_ERROR_DEPTH ;
226
231
if (!(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR )) {
227
232
return FAILURE ;
228
233
}
229
234
}
230
- -- JSON_G ( encoder_depth ) ;
235
+ -- encoder -> depth ;
231
236
232
237
/* Only keep closing bracket on same line for empty arrays/objects */
233
238
if (need_comma ) {
234
239
php_json_pretty_print_char (buf , options , '\n' );
235
- php_json_pretty_print_indent (buf , options );
240
+ php_json_pretty_print_indent (buf , options , encoder );
236
241
}
237
242
238
243
if (r == PHP_JSON_OUTPUT_ARRAY ) {
@@ -282,7 +287,9 @@ static int php_json_utf8_to_utf16(unsigned short *utf16, char utf8[], size_t len
282
287
}
283
288
/* }}} */
284
289
285
- static int php_json_escape_string (smart_str * buf , char * s , size_t len , int options ) /* {{{ */
290
+ static int php_json_escape_string (
291
+ smart_str * buf , char * s , size_t len ,
292
+ int options , php_json_encoder * encoder ) /* {{{ */
286
293
{
287
294
int status ;
288
295
unsigned int us ;
@@ -313,7 +320,7 @@ static int php_json_escape_string(smart_str *buf, char *s, size_t len, int optio
313
320
if (options & PHP_JSON_UNESCAPED_UNICODE ) {
314
321
/* validate UTF-8 string first */
315
322
if (php_json_utf8_to_utf16 (NULL , s , len ) < 0 ) {
316
- JSON_G ( error_code ) = PHP_JSON_ERROR_UTF8 ;
323
+ encoder -> error_code = PHP_JSON_ERROR_UTF8 ;
317
324
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR ) {
318
325
smart_str_appendl (buf , "null" , 4 );
319
326
}
@@ -337,7 +344,7 @@ static int php_json_escape_string(smart_str *buf, char *s, size_t len, int optio
337
344
if (buf -> s ) {
338
345
ZSTR_LEN (buf -> s ) = checkpoint ;
339
346
}
340
- JSON_G ( error_code ) = PHP_JSON_ERROR_UTF8 ;
347
+ encoder -> error_code = PHP_JSON_ERROR_UTF8 ;
341
348
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR ) {
342
349
smart_str_appendl (buf , "null" , 4 );
343
350
}
@@ -465,12 +472,12 @@ static int php_json_escape_string(smart_str *buf, char *s, size_t len, int optio
465
472
}
466
473
/* }}} */
467
474
468
- static int php_json_encode_serializable_object (smart_str * buf , zval * val , int options ) /* {{{ */
475
+ static int php_json_encode_serializable_object (smart_str * buf , zval * val , int options , php_json_encoder * encoder ) /* {{{ */
469
476
{
470
477
zend_class_entry * ce = Z_OBJCE_P (val );
471
478
zval retval , fname ;
472
479
HashTable * myht ;
473
- int origin_error_code ;
480
+ int return_code ;
474
481
475
482
if (Z_TYPE_P (val ) == IS_ARRAY ) {
476
483
myht = Z_ARRVAL_P (val );
@@ -479,7 +486,7 @@ static int php_json_encode_serializable_object(smart_str *buf, zval *val, int op
479
486
}
480
487
481
488
if (myht && ZEND_HASH_GET_APPLY_COUNT (myht ) > 1 ) {
482
- JSON_G ( error_code ) = PHP_JSON_ERROR_RECURSION ;
489
+ encoder -> error_code = PHP_JSON_ERROR_RECURSION ;
483
490
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR ) {
484
491
smart_str_appendl (buf , "null" , 4 );
485
492
}
@@ -489,7 +496,6 @@ static int php_json_encode_serializable_object(smart_str *buf, zval *val, int op
489
496
490
497
ZVAL_STRING (& fname , "jsonSerialize" );
491
498
492
- origin_error_code = JSON_G (error_code );
493
499
if (FAILURE == call_user_function_ex (EG (function_table ), val , & fname , & retval , 0 , NULL , 1 , NULL ) || Z_TYPE (retval ) == IS_UNDEF ) {
494
500
if (!EG (exception )) {
495
501
zend_throw_exception_ex (NULL , 0 , "Failed calling %s::jsonSerialize()" , ZSTR_VAL (ce -> name ));
@@ -502,7 +508,6 @@ static int php_json_encode_serializable_object(smart_str *buf, zval *val, int op
502
508
return FAILURE ;
503
509
}
504
510
505
- JSON_G (error_code ) = origin_error_code ;
506
511
if (EG (exception )) {
507
512
/* Error already raised */
508
513
zval_ptr_dtor (& retval );
@@ -517,20 +522,20 @@ static int php_json_encode_serializable_object(smart_str *buf, zval *val, int op
517
522
if ((Z_TYPE (retval ) == IS_OBJECT ) &&
518
523
(Z_OBJ (retval ) == Z_OBJ_P (val ))) {
519
524
/* Handle the case where jsonSerialize does: return $this; by going straight to encode array */
520
- php_json_encode_array (buf , & retval , options );
525
+ return_code = php_json_encode_array (buf , & retval , options , encoder );
521
526
} else {
522
527
/* All other types, encode as normal */
523
- php_json_encode (buf , & retval , options );
528
+ return_code = php_json_encode_zval (buf , & retval , options , encoder );
524
529
}
525
530
526
531
zval_ptr_dtor (& retval );
527
532
zval_ptr_dtor (& fname );
528
533
529
- return SUCCESS ;
534
+ return return_code ;
530
535
}
531
536
/* }}} */
532
537
533
- int php_json_encode_zval (smart_str * buf , zval * val , int options ) /* {{{ */
538
+ int php_json_encode_zval (smart_str * buf , zval * val , int options , php_json_encoder * encoder ) /* {{{ */
534
539
{
535
540
again :
536
541
switch (Z_TYPE_P (val ))
@@ -554,28 +559,28 @@ int php_json_encode_zval(smart_str *buf, zval *val, int options) /* {{{ */
554
559
if (php_json_is_valid_double (Z_DVAL_P (val ))) {
555
560
php_json_encode_double (buf , Z_DVAL_P (val ), options );
556
561
} else {
557
- JSON_G ( error_code ) = PHP_JSON_ERROR_INF_OR_NAN ;
562
+ encoder -> error_code = PHP_JSON_ERROR_INF_OR_NAN ;
558
563
smart_str_appendc (buf , '0' );
559
564
}
560
565
break ;
561
566
562
567
case IS_STRING :
563
- return php_json_escape_string (buf , Z_STRVAL_P (val ), Z_STRLEN_P (val ), options );
568
+ return php_json_escape_string (buf , Z_STRVAL_P (val ), Z_STRLEN_P (val ), options , encoder );
564
569
565
570
case IS_OBJECT :
566
571
if (instanceof_function (Z_OBJCE_P (val ), php_json_serializable_ce )) {
567
- return php_json_encode_serializable_object (buf , val , options );
572
+ return php_json_encode_serializable_object (buf , val , options , encoder );
568
573
}
569
574
/* fallthrough -- Non-serializable object */
570
575
case IS_ARRAY :
571
- return php_json_encode_array (buf , val , options );
576
+ return php_json_encode_array (buf , val , options , encoder );
572
577
573
578
case IS_REFERENCE :
574
579
val = Z_REFVAL_P (val );
575
580
goto again ;
576
581
577
582
default :
578
- JSON_G ( error_code ) = PHP_JSON_ERROR_UNSUPPORTED_TYPE ;
583
+ encoder -> error_code = PHP_JSON_ERROR_UNSUPPORTED_TYPE ;
579
584
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR ) {
580
585
smart_str_appendl (buf , "null" , 4 );
581
586
}
0 commit comments