From 260f7f41e764e5c81a2e97e8826430f6e3ae6fa7 Mon Sep 17 00:00:00 2001 From: Julien Pauli Date: Mon, 2 Nov 2015 18:03:05 +0100 Subject: [PATCH] Many PHP5 improvements --- jsonreader.c | 262 +++++++++++++---------------------------------- php_jsonreader.h | 72 ++++++++++--- tests/011.phpt | 2 +- tests/012.phpt | 2 +- 4 files changed, 134 insertions(+), 204 deletions(-) diff --git a/jsonreader.c b/jsonreader.c index 77b402b..0eafb53 100644 --- a/jsonreader.c +++ b/jsonreader.c @@ -33,45 +33,9 @@ ZEND_DECLARE_MODULE_GLOBALS(jsonreader) static zend_object_handlers jsonreader_obj_handlers; -static zend_class_entry *jsonreader_ce; +zend_class_entry *jsonreader_ce; static zend_class_entry *jsonreader_exception_ce; - -const HashTable jsonreader_prop_handlers; - -typedef struct _jsonreader_object { - zend_object std; - php_stream *stream; - vktor_parser *parser; - zend_bool close_stream; - long max_depth; - long read_buffer; - int errmode; -} jsonreader_object; - -#define JSONREADER_REG_CLASS_CONST_L(name, value) \ - zend_declare_class_constant_long(jsonreader_ce, name, sizeof(name) - 1, \ - (long) value TSRMLS_CC) - -#define JSONREADER_VALUE_TOKEN VKTOR_T_NULL | \ - VKTOR_T_TRUE | \ - VKTOR_T_FALSE | \ - VKTOR_T_INT | \ - VKTOR_T_FLOAT | \ - VKTOR_T_STRING - -/* {{{ attribute keys and possible values */ -enum { - ATTR_MAX_DEPTH = 1, - ATTR_READ_BUFF, - ATTR_ERRMODE, - - ERRMODE_PHPERR, - ERRMODE_EXCEPT, - ERRMODE_INTERN -}; -/* }}} */ - -/* }}} */ +static HashTable jsonreader_prop_handlers; /* {{{ Memory management functions wrapping emalloc etc. */ @@ -108,18 +72,15 @@ static void jsonreader_handle_error(vktor_error *err, jsonreader_object *obj TSR { switch(obj->errmode) { case ERRMODE_PHPERR: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "parser error [#%d]: %s", - err->code, err->message); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "parser error [#%d]: %s", err->code, err->message); break; case ERRMODE_EXCEPT: - zend_throw_exception_ex(jsonreader_exception_ce, err->code TSRMLS_CC, - err->message); + zend_throw_exception_ex(jsonreader_exception_ce, err->code TSRMLS_CC, err->message); break; default: // For now emit a PHP WARNING - php_error_docref(NULL TSRMLS_CC, E_WARNING, "parser error [#%d]: %s", - err->code, err->message); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "parser error [#%d]: %s", err->code, err->message); break; } @@ -127,16 +88,6 @@ static void jsonreader_handle_error(vktor_error *err, jsonreader_object *obj TSR } /* }}} */ -/* {{{ Property access related functions and type definitions */ - -typedef int (*jsonreader_read_t) (jsonreader_object *obj, zval **retval TSRMLS_DC); -typedef int (*jsonreader_write_t) (jsonreader_object *obj, zval *newval TSRMLS_DC); - -typedef struct _jsonreader_prop_handler { - jsonreader_read_t read_func; - jsonreader_write_t write_func; -} jsonreader_prop_handler; - /* {{{ jsonreader_read_na Called when a user tries to read a write-only property of a JSONReader object */ static int jsonreader_read_na(jsonreader_object *obj, zval **retval TSRMLS_DC) @@ -162,57 +113,45 @@ static void jsonreader_register_prop_handler(char *name, jsonreader_read_t read_ { jsonreader_prop_handler jph; - jph.read_func = read_func ? read_func : jsonreader_read_na; + jph.read_func = read_func ? read_func : jsonreader_read_na; jph.write_func = write_func ? write_func : jsonreader_write_na; - zend_hash_add((HashTable *) &jsonreader_prop_handlers, name, strlen(name) + 1, &jph, - sizeof(jsonreader_prop_handler), NULL); + zend_hash_add(&jsonreader_prop_handlers, name, strlen(name) + 1, &jph, sizeof(jsonreader_prop_handler), NULL); } /* }}} */ /* {{{ jsonreader_read_property Property read handler */ -zval* jsonreader_read_property(zval *object, zval *member, int type TSRMLS_DC) +#if PHP_VERSION_ID < 50400 +static zval* jsonreader_read_property(zval *object, zval *member, int type TSRMLS_DC) +#else +static zval* jsonreader_read_property(zval *object, zval *member, int type, const struct _zend_literal *key TSRMLS_DC) +#endif { jsonreader_object *intern; - zval tmp_member; zval *retval; jsonreader_prop_handler *jph; - zend_object_handlers *std_hnd; - int ret; if (Z_TYPE_P(member) != IS_STRING) { - tmp_member = *member; - zval_copy_ctor(&tmp_member); - convert_to_string(&tmp_member); - member = &tmp_member; + goto std_h; } - ret = FAILURE; intern = (jsonreader_object *) zend_objects_get_address(object TSRMLS_CC); - ret = zend_hash_find(&jsonreader_prop_handlers, Z_STRVAL_P(member), - Z_STRLEN_P(member) + 1, (void **) &jph); - - if (ret == SUCCESS) { - ret = jph->read_func(intern, &retval TSRMLS_CC); - if (ret == SUCCESS) { + if (zend_hash_find(&jsonreader_prop_handlers, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **) &jph) == SUCCESS) { + if (jph->read_func(intern, &retval TSRMLS_CC) == SUCCESS) { Z_SET_REFCOUNT_P(retval, 0); + Z_UNSET_ISREF_P(retval); } else { retval = EG(uninitialized_zval_ptr); } } else { - std_hnd = zend_get_std_object_handlers(); -#if PHP_VERSION_ID < 50399 - retval = std_hnd->read_property(object, member, type TSRMLS_CC); +std_h: +#if PHP_VERSION_ID < 50400 + retval = std_object_handlers.read_property(object, member, type TSRMLS_CC); #else - retval = std_hnd->read_property(object, member, type TSRMLS_CC, NULL); + retval = std_object_handlers.read_property(object, member, type, key TSRMLS_CC); #endif - - } - - if (member == &tmp_member) { - zval_dtor(member); } return retval; @@ -220,41 +159,32 @@ zval* jsonreader_read_property(zval *object, zval *member, int type TSRMLS_DC) /* }}} */ /* {{{ jsonreader_write_property */ -void jsonreader_write_property(zval *object, zval *member, zval *value TSRMLS_DC) +#if PHP_VERSION_ID < 50400 +static void jsonreader_write_property(zval *object, zval *member, zval *value TSRMLS_DC) +#else +static void jsonreader_write_property(zval *object, zval *member, zval *value, const struct _zend_literal *key TSRMLS_DC) +#endif { jsonreader_object *intern; - zval tmp_member; jsonreader_prop_handler *jph; - zend_object_handlers *std_hnd; - int ret; if (Z_TYPE_P(member) != IS_STRING) { - tmp_member = *member; - zval_copy_ctor(&tmp_member); - convert_to_string(&tmp_member); - member = &tmp_member; + goto std_h; } - ret = FAILURE; intern = (jsonreader_object *) zend_objects_get_address(object TSRMLS_CC); - ret = zend_hash_find(&jsonreader_prop_handlers, Z_STRVAL_P(member), - Z_STRLEN_P(member) + 1, (void **) &jph); - - if (ret == SUCCESS) { + if (zend_hash_find(&jsonreader_prop_handlers, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **) &jph) == SUCCESS) { jph->write_func(intern, value TSRMLS_CC); } else { - std_hnd = zend_get_std_object_handlers(); -#if PHP_VERSION_ID < 50399 - std_hnd->write_property(object, member, value TSRMLS_CC); +std_h: +#if PHP_VERSION_ID < 50400 + std_object_handlers.write_property(object, member, value TSRMLS_CC); #else - std_hnd->write_property(object, member, value TSRMLS_CC, NULL); + std_object_handlers.write_property(object, member, value, key TSRMLS_CC); #endif } - if (member == &tmp_member) { - zval_dtor(member); - } } /* }}} */ @@ -268,7 +198,6 @@ static int jsonreader_get_token_type(jsonreader_object *obj, zval **retval TSRML if (! obj->parser) { ZVAL_NULL(*retval); - } else { token = vktor_get_token_type(obj->parser); if (token == VKTOR_T_NONE) { @@ -293,7 +222,6 @@ static int jsonreader_get_token_value(jsonreader_object *obj, zval **retval TSRM if (! obj->parser) { ZVAL_NULL(*retval); - } else { t_type = vktor_get_token_type(obj->parser); switch(t_type) { @@ -346,8 +274,7 @@ static int jsonreader_get_token_value(jsonreader_object *obj, zval **retval TSRM break; default: /* should not happen */ - php_error_docref(NULL TSRMLS_CC, E_ERROR, - "internal error: unkown token type %d", t_type); + php_error_docref(NULL TSRMLS_CC, E_ERROR, "internal error: unkown token type %d", t_type); return FAILURE; break; } @@ -367,7 +294,6 @@ static int jsonreader_get_current_struct(jsonreader_object *obj, zval **retval T if (! obj->parser) { ZVAL_NULL(*retval); - } else { cs = vktor_get_current_struct(obj->parser); if (cs == VKTOR_STRUCT_NONE) { @@ -391,7 +317,6 @@ static int jsonreader_get_current_depth(jsonreader_object *obj, zval **retval TS if (! obj->parser) { ZVAL_NULL(*retval); - } else { depth = vktor_get_depth(obj->parser); ZVAL_LONG(*retval, depth); @@ -401,8 +326,6 @@ static int jsonreader_get_current_depth(jsonreader_object *obj, zval **retval TS } /* }}} */ -/* }}} */ - /* {{{ jsonreader_object_free_storage C-level object destructor for JSONReader objects */ static void jsonreader_object_free_storage(void *object TSRMLS_DC) @@ -415,7 +338,7 @@ static void jsonreader_object_free_storage(void *object TSRMLS_DC) vktor_parser_free(intern->parser); } - if (intern->stream && intern->close_stream) { + if (intern->stream && !intern->internal_stream) { php_stream_close(intern->stream); } @@ -432,17 +355,16 @@ static zend_object_value jsonreader_object_new(zend_class_entry *ce TSRMLS_DC) jsonreader_object *intern; intern = ecalloc(1, sizeof(jsonreader_object)); - intern->max_depth = JSONREADER_G(max_depth); + intern->max_depth = JSONREADER_G(max_depth); intern->read_buffer = JSONREADER_G(read_buffer); - intern->errmode = ERRMODE_PHPERR; + intern->errmode = ERRMODE_PHPERR; zend_object_std_init(&(intern->std), ce TSRMLS_CC); - + #if PHP_VERSION_ID < 50399 - zend_hash_copy(intern->std.properties, &ce->default_properties, - (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); + zend_hash_copy(intern->std.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); #else - object_properties_init(&(intern->std), ce); + object_properties_init(&(intern->std), ce); #endif retval.handle = zend_objects_store_put(intern, @@ -456,23 +378,6 @@ static zend_object_value jsonreader_object_new(zend_class_entry *ce TSRMLS_DC) } /* }}} */ -/* {{{ jsonreader_init - Initialize or reset an internal jsonreader object struct. Will close & free - any stream opened by the reader, and initialize the associated vktor parser - (and free the old parser, if exists) */ -static void jsonreader_init(jsonreader_object *obj TSRMLS_DC) -{ - if (obj->parser) { - vktor_parser_free(obj->parser); - } - obj->parser = vktor_parser_init(obj->max_depth); - - if (obj->stream) { - php_stream_close(obj->stream); - } -} -/* }}} */ - /* {{{ jsonreader_read_more_data Read more data from the stream and pass it to the parser */ static int jsonreader_read_more_data(jsonreader_object *obj TSRMLS_DC) @@ -482,16 +387,18 @@ static int jsonreader_read_more_data(jsonreader_object *obj TSRMLS_DC) vktor_status status; vktor_error *err; - buffer = emalloc(sizeof(char) * obj->read_buffer); + buffer = ecalloc(1, obj->read_buffer); read = php_stream_read(obj->stream, buffer, obj->read_buffer); if (read <= 0) { /* done reading or error */ php_error_docref(NULL TSRMLS_CC, E_WARNING, "JSON stream ended while expecting more data"); + efree(buffer); return FAILURE; } status = vktor_feed(obj->parser, buffer, read, 1, &err); + if (status == VKTOR_ERROR) { jsonreader_handle_error(err, obj TSRMLS_CC); return FAILURE; @@ -523,8 +430,7 @@ static int jsonreader_read(jsonreader_object *obj TSRMLS_DC) case VKTOR_ERROR: jsonreader_handle_error(err, obj TSRMLS_CC); - retval = FAILURE; - break; + return FAILURE; case VKTOR_MORE_DATA: if (jsonreader_read_more_data(obj TSRMLS_CC) == FAILURE) { @@ -578,8 +484,7 @@ static void jsonreader_set_attribute(jsonreader_object *obj, ulong attr_key, zva break; default: - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "invalid error handler attribute value: %ld", lval); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid error handler attribute value: %ld", lval); break; } break; @@ -599,19 +504,21 @@ PHP_METHOD(jsonreader, __construct) } /* got attributes - set them */ - if (options != NULL) { + if (options) { jsonreader_object *intern; zval **attr_value; char *str_key; ulong long_key; + HashPosition pos; intern = (jsonreader_object *) zend_object_store_get_object(object TSRMLS_CC); - zend_hash_internal_pointer_reset(Z_ARRVAL_P(options)); - while (zend_hash_get_current_data(Z_ARRVAL_P(options), (void **) &attr_value) == SUCCESS && - zend_hash_get_current_key(Z_ARRVAL_P(options), &str_key, &long_key, 0) == HASH_KEY_IS_LONG) { - jsonreader_set_attribute(intern, long_key, *attr_value TSRMLS_CC); - zend_hash_move_forward(Z_ARRVAL_P(options)); + for(zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(options), &pos); + (zend_hash_get_current_data_ex(Z_ARRVAL_P(options), (void **)&attr_value, &pos) == SUCCESS) && + (zend_hash_get_current_key_ex(Z_ARRVAL_P(options), &str_key, NULL, &long_key, 0, &pos) == HASH_KEY_IS_LONG) && + (Z_TYPE_PP(attr_value) == IS_LONG); + zend_hash_move_forward_ex(Z_ARRVAL_P(options), &pos)) { + jsonreader_set_attribute(intern, long_key, *attr_value TSRMLS_CC); } } } @@ -626,7 +533,6 @@ PHP_METHOD(jsonreader, open) zval *object, *arg; jsonreader_object *intern; php_stream *tmp_stream; - int options = ENFORCE_SAFE_MODE | REPORT_ERRORS; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) { return; @@ -637,26 +543,24 @@ PHP_METHOD(jsonreader, open) switch(Z_TYPE_P(arg)) { case IS_STRING: - tmp_stream = php_stream_open_wrapper(Z_STRVAL_P(arg), "r", options, NULL); - intern->close_stream = 1; + tmp_stream = php_stream_open_wrapper(Z_STRVAL_P(arg), "r", REPORT_ERRORS, NULL); + if (tmp_stream) { + intern->stream = tmp_stream; + } break; case IS_RESOURCE: php_stream_from_zval(tmp_stream, &arg); - intern->close_stream = 0; + intern->internal_stream = tmp_stream->abstract; + intern->stream = tmp_stream; break; default: - php_error_docref(NULL TSRMLS_CC, E_ERROR, - "argument is expected to be a resource of type stream or a string, %s given", - zend_zval_type_name(arg)); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "argument is expected to be a resource of type stream or a string, %s given", zend_zval_type_name(arg)); RETURN_FALSE; - break; - } - jsonreader_init(intern TSRMLS_CC); - intern->stream = tmp_stream; + intern->parser = vktor_parser_init(intern->max_depth); RETURN_TRUE; } @@ -673,9 +577,9 @@ PHP_METHOD(jsonreader, close) intern = (jsonreader_object *) zend_object_store_get_object(object TSRMLS_CC); /* Close stream, if open */ - if (intern->stream) { + if (intern->stream && !intern->stream->abstract) { php_stream_close(intern->stream); - intern->stream = NULL; + intern->stream = NULL; } /* Free parser, if created */ @@ -701,15 +605,11 @@ PHP_METHOD(jsonreader, read) object = getThis(); intern = (jsonreader_object *) zend_object_store_get_object(object TSRMLS_CC); - if (! intern->stream) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "trying to read but no stream was opened"); + if (!intern->stream || (intern->internal_stream && intern->stream->abstract != intern->internal_stream)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "trying to read but no stream was opened or stream was closed"); RETURN_FALSE; } - /* TODO: replace assertion with an if(!) and init parser (?) */ - assert(intern->parser != NULL); - if (jsonreader_read(intern TSRMLS_CC) != SUCCESS) { RETVAL_FALSE; } @@ -738,7 +638,7 @@ static const zend_function_entry jsonreader_class_methods[] = { PHP_ME(jsonreader, open, arginfo_jsonreader_open, ZEND_ACC_PUBLIC) PHP_ME(jsonreader, close, arginfo_jsonreader_close, ZEND_ACC_PUBLIC) PHP_ME(jsonreader, read, arginfo_jsonreader_read, ZEND_ACC_PUBLIC) - {NULL, NULL, NULL} + {NULL, NULL, NULL, 0, 0} }; /* }}} */ @@ -748,16 +648,16 @@ ZEND_GET_MODULE(jsonreader) /* {{{ PHP_INI */ PHP_INI_BEGIN() - STD_PHP_INI_ENTRY("jsonreader.max_depth", "64", PHP_INI_ALL, OnUpdateLong, max_depth, zend_jsonreader_globals, jsonreader_globals) - STD_PHP_INI_ENTRY("jsonreader.read_buffer", "4096", PHP_INI_ALL, OnUpdateLong, read_buffer, zend_jsonreader_globals, jsonreader_globals) + STD_PHP_INI_ENTRY("jsonreader.max_depth", XSTRINGIFY(JSONREADER_DEFAULT_MAX_DEPTH), PHP_INI_ALL, OnUpdateLongGEZero, max_depth, zend_jsonreader_globals, jsonreader_globals) + STD_PHP_INI_ENTRY("jsonreader.read_buffer", XSTRINGIFY(JSONREADER_DEFAULT_MAX_READ_BUFFER), PHP_INI_ALL, OnUpdateLongGEZero, read_buffer, zend_jsonreader_globals, jsonreader_globals) PHP_INI_END() /* }}} */ /* {{{ PHP_GINIT_FUNCTION */ PHP_GINIT_FUNCTION(jsonreader) { - jsonreader_globals->max_depth = 64; - jsonreader_globals->read_buffer = 4096; + jsonreader_globals->max_depth = JSONREADER_DEFAULT_MAX_DEPTH; + jsonreader_globals->read_buffer= JSONREADER_DEFAULT_MAX_READ_BUFFER; } /* }}} */ @@ -767,25 +667,17 @@ PHP_MINIT_FUNCTION(jsonreader) zend_class_entry ce; REGISTER_INI_ENTRIES(); + zend_hash_init(&jsonreader_prop_handlers, 8, NULL, NULL, 1); - /** - * Declare the JSONReader class - */ - - /* Set object handlers */ - zend_hash_init((HashTable *) &jsonreader_prop_handlers, 0, NULL, NULL, 1); - memcpy(&jsonreader_obj_handlers, zend_get_std_object_handlers(), - sizeof(zend_object_handlers)); - jsonreader_obj_handlers.read_property = jsonreader_read_property; + memcpy(&jsonreader_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + jsonreader_obj_handlers.read_property = jsonreader_read_property; jsonreader_obj_handlers.write_property = jsonreader_write_property; - /* Initalize the class entry */ INIT_CLASS_ENTRY(ce, "JSONReader", jsonreader_class_methods); ce.create_object = jsonreader_object_new; jsonreader_ce = zend_register_internal_class(&ce TSRMLS_CC); - /* Register class constants */ JSONREADER_REG_CLASS_CONST_L("ATTR_MAX_DEPTH", ATTR_MAX_DEPTH); JSONREADER_REG_CLASS_CONST_L("ATTR_READ_BUFF", ATTR_READ_BUFF); JSONREADER_REG_CLASS_CONST_L("ATTR_ERRMODE", ATTR_ERRMODE); @@ -811,22 +703,14 @@ PHP_MINIT_FUNCTION(jsonreader) JSONREADER_REG_CLASS_CONST_L("ARRAY", VKTOR_STRUCT_ARRAY); JSONREADER_REG_CLASS_CONST_L("OBJECT", VKTOR_STRUCT_OBJECT); - /* Register property handlers */ jsonreader_register_prop_handler("tokenType", jsonreader_get_token_type, NULL TSRMLS_CC); jsonreader_register_prop_handler("value", jsonreader_get_token_value, NULL TSRMLS_CC); jsonreader_register_prop_handler("currentStruct", jsonreader_get_current_struct, NULL TSRMLS_CC); jsonreader_register_prop_handler("currentDepth", jsonreader_get_current_depth, NULL TSRMLS_CC); - /** - * Declare the JSONReaderException class - */ INIT_CLASS_ENTRY(ce, "JSONReaderException", NULL); - jsonreader_exception_ce = zend_register_internal_class_ex(&ce, - zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC); + jsonreader_exception_ce = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC); - /** - * Set libvktor to use PHP memory allocation functions - */ vktor_set_memory_handlers(jsr_malloc, jsr_realloc, jsr_free); return SUCCESS; @@ -837,7 +721,7 @@ PHP_MINIT_FUNCTION(jsonreader) PHP_MSHUTDOWN_FUNCTION(jsonreader) { UNREGISTER_INI_ENTRIES(); - zend_hash_destroy((HashTable *) &jsonreader_prop_handlers); + zend_hash_destroy(&jsonreader_prop_handlers); return SUCCESS; } /* }}} */ diff --git a/php_jsonreader.h b/php_jsonreader.h index e5705b4..aca26b7 100644 --- a/php_jsonreader.h +++ b/php_jsonreader.h @@ -21,6 +21,8 @@ #ifndef PHP_JSONREADER_H #define PHP_JSONREADER_H +#include "libvktor/vktor.h" + extern zend_module_entry jsonreader_module_entry; #define phpext_jsonreader_ptr &jsonreader_module_entry @@ -29,31 +31,75 @@ extern zend_module_entry jsonreader_module_entry; #elif defined(__GNUC__) && __GNUC__ >= 4 # define PHP_JSONREADER_API __attribute__ ((visibility("default"))) #else -# define PHP_JSONREADER_API +#define PHP_JSONREADER_API +zend_module_entry *get_module(void); #endif #ifdef ZTS #include "TSRM.h" #endif -PHP_MINIT_FUNCTION(jsonreader); -PHP_MSHUTDOWN_FUNCTION(jsonreader); -PHP_MINFO_FUNCTION(jsonreader); +#define JSONREADER_DEFAULT_MAX_DEPTH 64 +#define JSONREADER_DEFAULT_MAX_READ_BUFFER 4096 +#define STRINGIFY(x) #x +#define XSTRINGIFY(a) STRINGIFY(a) ZEND_BEGIN_MODULE_GLOBALS(jsonreader) long max_depth; long read_buffer; ZEND_END_MODULE_GLOBALS(jsonreader) -/* In every utility function you add that needs to use variables - in php_jsonreader_globals, call TSRMLS_FETCH(); after declaring other - variables used by that function, or better yet, pass in TSRMLS_CC - after the last function argument and declare your utility function - with TSRMLS_DC after the last declared argument. Always refer to - the globals in your function as JSONREADER_G(variable). You are - encouraged to rename these macros something shorter, see - examples in any other php module directory. -*/ +PHP_MINIT_FUNCTION(jsonreader); +PHP_GINIT_FUNCTION(jsonreader); +PHP_MSHUTDOWN_FUNCTION(jsonreader); +PHP_MINFO_FUNCTION(jsonreader); + +extern zend_class_entry *jsonreader_ce; + +PHP_METHOD(jsonreader, read); +PHP_METHOD(jsonreader, close); +PHP_METHOD(jsonreader, open); +PHP_METHOD(jsonreader, __construct); + +typedef struct _jsonreader_object { + zend_object std; + php_stream *stream; + void *internal_stream; + vktor_parser *parser; + long max_depth; + long read_buffer; + int errmode; +} jsonreader_object; + +#define JSONREADER_REG_CLASS_CONST_L(name, value) \ + zend_declare_class_constant_long(jsonreader_ce, name, sizeof(name) - 1, \ + (long) value TSRMLS_CC) + +#define JSONREADER_VALUE_TOKEN VKTOR_T_NULL | \ + VKTOR_T_TRUE | \ + VKTOR_T_FALSE | \ + VKTOR_T_INT | \ + VKTOR_T_FLOAT | \ + VKTOR_T_STRING + +/* {{{ attribute keys and possible values */ +enum { + ATTR_MAX_DEPTH = 1, + ATTR_READ_BUFF, + ATTR_ERRMODE, + + ERRMODE_PHPERR, + ERRMODE_EXCEPT, + ERRMODE_INTERN +}; + +typedef int (*jsonreader_read_t) (jsonreader_object *obj, zval **retval TSRMLS_DC); +typedef int (*jsonreader_write_t) (jsonreader_object *obj, zval *newval TSRMLS_DC); + +typedef struct _jsonreader_prop_handler { + jsonreader_read_t read_func; + jsonreader_write_t write_func; +} jsonreader_prop_handler; #ifdef ZTS #define JSONREADER_G(v) TSRMG(jsonreader_globals_id, zend_jsonreader_globals *, v) diff --git a/tests/011.phpt b/tests/011.phpt index 79a77ac..c14b1d9 100644 --- a/tests/011.phpt +++ b/tests/011.phpt @@ -16,5 +16,5 @@ $rdr->close(); --EXPECTF-- - %d -Warning: JSONReader::read(): parser error [#%d]: Unexpected character in input: '1' (0x31) in %s on line %d +Warning: JSONReader::read(): parser error [#%d]: [%s] Unexpected character in input: '1' (0x31) in %s on line %d diff --git a/tests/012.phpt b/tests/012.phpt index 569c9c6..f330a04 100644 --- a/tests/012.phpt +++ b/tests/012.phpt @@ -21,5 +21,5 @@ $rdr->close(); ?> --EXPECTF-- - %d -EX: %d Unexpected character in input: '1' (0x31) +EX: %d [%s] Unexpected character in input: '1' (0x31)