From cb69b6218d9d6e789527b3bd62c3cc37686547a3 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 17 Aug 2015 16:57:23 +0200 Subject: [PATCH] finish port --- .travis.yml | 36 +-- gen_travis_yml.php | 6 +- src/php_pq_callback.c | 21 +- src/php_pq_callback.h | 1 + src/php_pq_misc.c | 31 ++- src/php_pq_misc.h | 3 + src/php_pq_object.c | 106 ++++++- src/php_pq_object.h | 15 +- src/php_pq_params.c | 15 +- src/php_pqcancel.c | 37 ++- src/php_pqcancel.h | 4 +- src/php_pqconn.c | 163 ++++++++--- src/php_pqconn.h | 5 +- src/php_pqconn_event.c | 26 +- src/php_pqconn_event.h | 2 + src/php_pqcopy.c | 36 ++- src/php_pqcopy.h | 4 +- src/php_pqcur.c | 36 ++- src/php_pqcur.h | 4 +- src/php_pqexc.c | 7 +- src/php_pqexc.h | 2 +- src/php_pqlob.c | 43 ++- src/php_pqlob.h | 4 +- src/php_pqres.c | 540 ++++++++++++++++-------------------- src/php_pqres.h | 8 +- src/php_pqstm.c | 248 ++++++++--------- src/php_pqstm.h | 4 +- src/php_pqtxn.c | 426 ++++++++++++++-------------- src/php_pqtxn.h | 4 +- src/php_pqtypes.c | 256 +++++++---------- src/php_pqtypes.h | 4 +- tests/async001.phpt | 3 +- tests/async002.phpt | 5 +- tests/async003.phpt | 2 +- tests/basic002.phpt | 7 +- tests/bound002.phpt | 12 +- tests/lob002.phpt | 2 +- travis/pecl | 2 +- travis/raphf-phpng.ext.phar | Bin 0 -> 166778 bytes 39 files changed, 1098 insertions(+), 1032 deletions(-) create mode 100755 travis/raphf-phpng.ext.phar diff --git a/.travis.yml b/.travis.yml index afeaa5c..1ed1390 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,38 +12,22 @@ env: global: - PQ_DSN="postgres://postgres@localhost/test" matrix: - - PHP=5.4 enable_debug=no enable_maintainer_zts=no enable_json=no enable_hash=yes - - PHP=5.5 enable_debug=no enable_maintainer_zts=no enable_json=no enable_hash=yes - - PHP=5.6 enable_debug=no enable_maintainer_zts=no enable_json=no enable_hash=yes - - PHP=5.4 enable_debug=yes enable_maintainer_zts=no enable_json=no enable_hash=yes - - PHP=5.5 enable_debug=yes enable_maintainer_zts=no enable_json=no enable_hash=yes - - PHP=5.6 enable_debug=yes enable_maintainer_zts=no enable_json=no enable_hash=yes - - PHP=5.4 enable_debug=no enable_maintainer_zts=yes enable_json=no enable_hash=yes - - PHP=5.5 enable_debug=no enable_maintainer_zts=yes enable_json=no enable_hash=yes - - PHP=5.6 enable_debug=no enable_maintainer_zts=yes enable_json=no enable_hash=yes - - PHP=5.4 enable_debug=yes enable_maintainer_zts=yes enable_json=no enable_hash=yes - - PHP=5.5 enable_debug=yes enable_maintainer_zts=yes enable_json=no enable_hash=yes - - PHP=5.6 enable_debug=yes enable_maintainer_zts=yes enable_json=no enable_hash=yes - - PHP=5.4 enable_debug=no enable_maintainer_zts=no enable_json=yes enable_hash=yes - - PHP=5.5 enable_debug=no enable_maintainer_zts=no enable_json=yes enable_hash=yes - - PHP=5.6 enable_debug=no enable_maintainer_zts=no enable_json=yes enable_hash=yes - - PHP=5.4 enable_debug=yes enable_maintainer_zts=no enable_json=yes enable_hash=yes - - PHP=5.5 enable_debug=yes enable_maintainer_zts=no enable_json=yes enable_hash=yes - - PHP=5.6 enable_debug=yes enable_maintainer_zts=no enable_json=yes enable_hash=yes - - PHP=5.4 enable_debug=no enable_maintainer_zts=yes enable_json=yes enable_hash=yes - - PHP=5.5 enable_debug=no enable_maintainer_zts=yes enable_json=yes enable_hash=yes - - PHP=5.6 enable_debug=no enable_maintainer_zts=yes enable_json=yes enable_hash=yes - - PHP=5.4 enable_debug=yes enable_maintainer_zts=yes enable_json=yes enable_hash=yes - - PHP=5.5 enable_debug=yes enable_maintainer_zts=yes enable_json=yes enable_hash=yes - - PHP=5.6 enable_debug=yes enable_maintainer_zts=yes enable_json=yes enable_hash=yes + - PHP=master enable_debug=no enable_maintainer_zts=no enable_json=no enable_hash=yes enable_phar=yes enable_posix=yes + - PHP=master enable_debug=yes enable_maintainer_zts=no enable_json=no enable_hash=yes enable_phar=yes enable_posix=yes + - PHP=master enable_debug=no enable_maintainer_zts=yes enable_json=no enable_hash=yes enable_phar=yes enable_posix=yes + - PHP=master enable_debug=yes enable_maintainer_zts=yes enable_json=no enable_hash=yes enable_phar=yes enable_posix=yes + - PHP=master enable_debug=no enable_maintainer_zts=no enable_json=yes enable_hash=yes enable_phar=yes enable_posix=yes + - PHP=master enable_debug=yes enable_maintainer_zts=no enable_json=yes enable_hash=yes enable_phar=yes enable_posix=yes + - PHP=master enable_debug=no enable_maintainer_zts=yes enable_json=yes enable_hash=yes enable_phar=yes enable_posix=yes + - PHP=master enable_debug=yes enable_maintainer_zts=yes enable_json=yes enable_hash=yes enable_phar=yes enable_posix=yes before_script: - make -f travis/pecl/Makefile php - - make -f travis/pecl/Makefile pecl PECL=raphf + - make -f travis/pecl/Makefile pharext/raphf-phpng + - make -f travis/pecl/Makefile ext PECL=pq - psql -U postgres -c "CREATE DATABASE test" script: - - make -f travis/pecl/Makefile ext PECL=pq - make -f travis/pecl/Makefile test sudo: false diff --git a/gen_travis_yml.php b/gen_travis_yml.php index 804dad0..19240be 100755 --- a/gen_travis_yml.php +++ b/gen_travis_yml.php @@ -22,6 +22,8 @@ $env = $gen([ "enable_maintainer_zts", "enable_json", "enable_hash" => ["yes"], + "enable_phar" => ["yes"], + "enable_posix" => ["yes"] ]); foreach ($env as $e) { printf(" - %s\n", $e); @@ -31,11 +33,11 @@ foreach ($env as $e) { before_script: - make -f travis/pecl/Makefile php - - make -f travis/pecl/Makefile pecl PECL=raphf + - make -f travis/pecl/Makefile pharext/raphf-phpng + - make -f travis/pecl/Makefile ext PECL=pq - psql -U postgres -c "CREATE DATABASE test" script: - - make -f travis/pecl/Makefile ext PECL=pq - make -f travis/pecl/Makefile test sudo: false diff --git a/src/php_pq_callback.c b/src/php_pq_callback.c index 6b0213f..695d592 100644 --- a/src/php_pq_callback.c +++ b/src/php_pq_callback.c @@ -30,7 +30,10 @@ void php_pq_callback_dtor(php_pq_callback_t *cb) zend_fcall_info_args_clear(&cb->fci, 1); zval_ptr_dtor(&cb->fci.function_name); if (cb->fci.object) { - zend_objects_store_del(cb->fci.object); + zval tmp; + + ZVAL_OBJ(&tmp, cb->fci.object); + zval_ptr_dtor(&tmp); } cb->fci.size = 0; } @@ -62,6 +65,22 @@ zval *php_pq_callback_to_zval(php_pq_callback_t *cb, zval *tmp) return &cb->fci.function_name; } +zval *php_pq_callback_to_zval_no_addref(php_pq_callback_t *cb, zval *tmp) +{ + if (cb->fci.object) { + zval zo; + + array_init_size(tmp, 2); + ZVAL_OBJ(&zo, cb->fci.object); + add_next_index_zval(tmp, &zo); + add_next_index_zval(tmp, &cb->fci.function_name); + + return tmp; + } + + return &cb->fci.function_name; +} + zend_bool php_pq_callback_is_locked(php_pq_callback_t *cb) { /* TODO: fixed in php7? diff --git a/src/php_pq_callback.h b/src/php_pq_callback.h index 23521a8..da71143 100644 --- a/src/php_pq_callback.h +++ b/src/php_pq_callback.h @@ -24,6 +24,7 @@ typedef struct php_pq_callback { extern void php_pq_callback_dtor(php_pq_callback_t *cb); extern void php_pq_callback_addref(php_pq_callback_t *cb); extern zval *php_pq_callback_to_zval(php_pq_callback_t *cb, zval *tmp); +extern zval *php_pq_callback_to_zval_no_addref(php_pq_callback_t *cb, zval *tmp); extern zend_bool php_pq_callback_is_locked(php_pq_callback_t *cb); extern void php_pq_callback_recurse(php_pq_callback_t *old, php_pq_callback_t *new); diff --git a/src/php_pq_misc.c b/src/php_pq_misc.c index 484d760..10defed 100644 --- a/src/php_pq_misc.c +++ b/src/php_pq_misc.c @@ -54,18 +54,23 @@ const char *php_pq_strmode(long mode) int php_pq_compare_index(const void *lptr, const void *rptr) { - const Bucket *l = *(const Bucket **) lptr; - const Bucket *r = *(const Bucket **) rptr; + zend_ulong l = ((const Bucket *) lptr)->h; + zend_ulong r = ((const Bucket *) rptr)->h; - if (l->h < r->h) { + if (l < r) { return -1; } - if (l->h > r->h) { + if (l > r) { return 1; } return 0; } +void php_pq_hash_ptr_dtor(zval *p) +{ + efree(Z_PTR_P(p)); +} + zend_class_entry *php_pqdt_class_entry; ZEND_BEGIN_ARG_INFO_EX(ai_pqdt_to_string, 0, 0, 0) @@ -89,7 +94,7 @@ static PHP_METHOD(pqdt, createFromFormat) { zend_error_handling zeh; char *fmt_str, *dt_str; - int fmt_len, dt_len; + size_t fmt_len, dt_len; zval *ztz = NULL; ZEND_RESULT_CODE rv; @@ -338,7 +343,7 @@ static ZEND_RESULT_CODE parse_array(ArrayParserState *a) } list = ecalloc(1, sizeof(*list)); - ZVAL_NEW_ARR(&list->arr); + array_init(&list->arr); if (a->list) { add_next_index_zval(&a->list->arr, &list->arr); @@ -354,8 +359,12 @@ static ZEND_RESULT_CODE parse_array(ArrayParserState *a) return FAILURE; } + /* step one level back up */ if (a->list->parent) { - a->list = a->list->parent; + HashTableList *l = a->list->parent; + + efree(a->list); + a->list = l; } return SUCCESS; @@ -386,9 +395,13 @@ HashTable *php_pq_parse_array(php_pqres_t *res, const char *val_str, size_t val_ php_error_docref(NULL, E_NOTICE, "Trailing input: '%s'", a.ptr); } - do { + while (a.list) { + HashTableList *l = a.list->parent; + ht = Z_ARRVAL(a.list->arr); - } while ((a.list = a.list->parent)); + efree(a.list); + a.list = l; + } return ht; } diff --git a/src/php_pq_misc.h b/src/php_pq_misc.h index 937d7ad..b25f871 100644 --- a/src/php_pq_misc.h +++ b/src/php_pq_misc.h @@ -41,6 +41,9 @@ extern const char *php_pq_strmode(long mode); /* compare array index */ extern int php_pq_compare_index(const void *lptr, const void *rptr); +/* free zval ptr values (as hash dtor) */ +extern void php_pq_hash_ptr_dtor(zval *p); + #define PHP_PQerrorMessage(c) php_pq_rtrim(PQerrorMessage((c))) #define PHP_PQresultErrorMessage(r) php_pq_rtrim(PQresultErrorMessage((r))) diff --git a/src/php_pq_object.c b/src/php_pq_object.c index bfab410..c7e04d6 100644 --- a/src/php_pq_object.c +++ b/src/php_pq_object.c @@ -18,6 +18,29 @@ #include "php_pq_object.h" +void *php_pq_object_create(zend_class_entry *ce, void *intern, size_t obj_size, zend_object_handlers *oh, HashTable *ph) +{ + php_pq_object_t *o = ecalloc(1, obj_size + zend_object_properties_size(ce)); + + zend_object_std_init(&o->zo, ce); + object_properties_init(&o->zo, ce); + o->zo.handlers = oh; + o->intern = intern; + o->prophandler = ph; + + zend_hash_init(&o->gc, 0, NULL, NULL, 0); + + return o; +} + +void php_pq_object_dtor(zend_object *o) +{ + php_pq_object_t *obj = PHP_PQ_OBJ(NULL, o); + + zend_hash_destroy(&obj->gc); + zend_object_std_dtor(o); +} + void php_pq_object_to_zval(void *o, zval *zv) { php_pq_object_t *obj = o; @@ -39,29 +62,44 @@ void php_pq_object_addref(void *o) ++GC_REFCOUNT(&obj->zo); } -void php_pq_object_delref(void *o TSRMLS_DC) +void php_pq_object_delref(void *o) { php_pq_object_t *obj = o; - zend_objects_store_del(&obj->zo); + zval tmp; + + /* this should gc immediately */ + ZVAL_OBJ(&tmp, &obj->zo); + zval_ptr_dtor(&tmp); } struct apply_pi_to_ht_arg { HashTable *ht; zval *object; php_pq_object_t *pq_obj; - unsigned addref:1; + unsigned gc:1; }; static int apply_pi_to_ht(zval *p, void *a) { zend_property_info *pi = Z_PTR_P(p); struct apply_pi_to_ht_arg *arg = a; - zval tmp_prop, *property = zend_read_property(arg->pq_obj->zo.ce, arg->object, pi->name->val, pi->name->len, 0, &tmp_prop); - if (arg->addref) { - Z_TRY_ADDREF_P(property); + if (arg->gc) { + php_pq_object_prophandler_t *handler; + + if ((handler = zend_hash_find_ptr(arg->pq_obj->prophandler, pi->name)) && handler->gc) { + zval member, return_value; + + ZVAL_STR(&member, pi->name); + ZVAL_ARR(&return_value, arg->ht); + handler->gc(arg->object, arg->pq_obj, &return_value); + } + } else { + zval tmp_prop, *property = NULL; + + property = zend_read_property(arg->pq_obj->zo.ce, arg->object, pi->name->val, pi->name->len, 0, &tmp_prop); + zend_hash_update(arg->ht, pi->name, property); } - zend_hash_update(arg->ht, pi->name, property); return ZEND_HASH_APPLY_KEEP; } @@ -76,7 +114,7 @@ HashTable *php_pq_object_debug_info(zval *object, int *temp) arg.object = object; arg.pq_obj = PHP_PQ_OBJ(object, NULL); - arg.addref = 1; + arg.gc = 0; zend_hash_apply_with_argument(&arg.pq_obj->zo.ce->properties_info, apply_pi_to_ht, &arg); @@ -90,10 +128,29 @@ HashTable *php_pq_object_properties(zval *object) arg.ht = zend_get_std_object_handlers()->get_properties(object); arg.object = object; arg.pq_obj = PHP_PQ_OBJ(object, NULL); - arg.addref = 1; + arg.gc = 0; + + zend_hash_apply_with_argument(&arg.pq_obj->zo.ce->properties_info, apply_pi_to_ht, &arg); + + return arg.ht; +} + +HashTable *php_pq_object_get_gc(zval *object, zval **table, int *n) +{ + struct apply_pi_to_ht_arg arg = {NULL}; + + arg.object = object; + arg.pq_obj = PHP_PQ_OBJ(object, NULL); + arg.ht = &arg.pq_obj->gc; + arg.gc = 1; + zend_hash_clean(arg.ht); + zend_hash_copy(arg.ht, zend_std_get_properties(object), NULL); zend_hash_apply_with_argument(&arg.pq_obj->zo.ce->properties_info, apply_pi_to_ht, &arg); + *table = NULL; + *n = 0; + return arg.ht; } @@ -111,17 +168,32 @@ zval *php_pq_object_read_prop(zval *object, zval *member, int type, void **cache php_pq_object_prophandler_t *handler; zval *return_value = NULL; + return_value = zend_get_std_object_handlers()->read_property(object, member, type, cache_slot, tmp); + if (!obj->intern) { - php_error(E_RECOVERABLE_ERROR, "%s not initialized", ancestor(obj->zo.ce)->name); - return_value = zend_get_std_object_handlers()->read_property(object, member, type, cache_slot, tmp); - } else if (!(handler= zend_hash_find_ptr(obj->prophandler, Z_STR_P(member))) || !handler->read) { - return_value = zend_get_std_object_handlers()->read_property(object, member, type, cache_slot, tmp); + php_error(E_RECOVERABLE_ERROR, "%s not initialized", ancestor(obj->zo.ce)->name->val); + } else if (!(handler = zend_hash_find_ptr(obj->prophandler, Z_STR_P(member))) || !handler->read) { + /* default handler */ } else if (type != BP_VAR_R) { php_error(E_WARNING, "Cannot access %s properties by reference or array key/index", ancestor(obj->zo.ce)->name->val); - return_value = zend_get_std_object_handlers()->read_property(object, member, type, cache_slot, tmp); } else { + handler->read(object, obj, tmp); + zend_get_std_object_handlers()->write_property(object, member, tmp, cache_slot); return_value = tmp; - handler->read(object, obj, return_value); + + /* + zval dtor; + + ZVAL_COPY_VALUE(&dtor, return_value); + + ZVAL_ZVAL(return_value, tmp, 0, 0); + zval_ptr_dtor(&dtor); + + */ + + if (cache_slot) { + *cache_slot = NULL; + } } return return_value; @@ -144,3 +216,7 @@ void php_pq_object_write_prop(zval *object, zval *member, zval *value, void **ca } } +void php_pq_object_prophandler_dtor(zval *zv) { + pefree(Z_PTR_P(zv), 1); +} + diff --git a/src/php_pq_object.h b/src/php_pq_object.h index 47ccbbf..2c7417a 100644 --- a/src/php_pq_object.h +++ b/src/php_pq_object.h @@ -13,10 +13,14 @@ #ifndef PHP_PQ_OBJECT_H #define PHP_PQ_OBJECT_H -typedef struct php_pq_object { - void *intern; - HashTable *prophandler; +#define PHP_PQ_OBJ_DECL(_intern_type) \ + _intern_type intern; \ + HashTable *prophandler; \ + HashTable gc; \ zend_object zo; + +typedef struct php_pq_object { + PHP_PQ_OBJ_DECL(void *) } php_pq_object_t; static inline void *PHP_PQ_OBJ(zval *zv, zend_object *zo) { @@ -31,17 +35,22 @@ typedef void (*php_pq_object_prophandler_func_t)(zval *object, void *o, zval *re typedef struct php_pq_object_prophandler { php_pq_object_prophandler_func_t read; php_pq_object_prophandler_func_t write; + php_pq_object_prophandler_func_t gc; } php_pq_object_prophandler_t; +extern void *php_pq_object_create(zend_class_entry *ce, void *intern, size_t obj_size, zend_object_handlers *oh, HashTable *ph); +extern void php_pq_object_dtor(zend_object *obj); extern void php_pq_object_to_zval(void *o, zval *zv); extern void php_pq_object_to_zval_no_addref(void *o, zval *zv); extern void php_pq_object_addref(void *o); extern void php_pq_object_delref(void *o); extern HashTable *php_pq_object_debug_info(zval *object, int *temp); extern HashTable *php_pq_object_properties(zval *object); +HashTable *php_pq_object_get_gc(zval *object, zval **table, int *n); extern zend_class_entry *ancestor(zend_class_entry *ce); extern zval *php_pq_object_read_prop(zval *object, zval *member, int type, void **cache_slot, zval *tmp); extern void php_pq_object_write_prop(zval *object, zval *member, zval *value, void **cache_slot); +extern void php_pq_object_prophandler_dtor(zval *zv); #endif diff --git a/src/php_pq_params.c b/src/php_pq_params.c index ead7fac..0f7ba50 100644 --- a/src/php_pq_params.c +++ b/src/php_pq_params.c @@ -130,10 +130,16 @@ static int apply_to_param_from_array(zval *zparam, void *arg_ptr) ZVAL_LONG(&ztype, arg->type); zend_call_method_with_2_params(arg->zconv, NULL, NULL, "converttostring", &rv, zparam, &ztype); str = zval_get_string(&rv); + zval_ptr_dtor(&rv); goto append_string; } else { + again: switch (Z_TYPE_P(zparam)) { + case IS_REFERENCE: + ZVAL_DEREF(zparam); + goto again; + case IS_NULL: smart_str_appends(arg->buffer, "NULL"); break; @@ -209,7 +215,6 @@ static zend_string *array_param_to_string(php_pq_params_t *p, zval *zarr, Oid ty smart_str_appendc(arg.buffer, '{'); SEPARATE_ZVAL(zarr); zend_hash_apply_with_argument(Z_ARRVAL_P(zarr), apply_to_param_from_array, &arg); - zval_ptr_dtor(zarr); smart_str_appendc(arg.buffer, '}'); break; } @@ -238,7 +243,12 @@ static void php_pq_params_set_param(php_pq_params_t *p, unsigned index, zval *zp char tmp_str[64]; size_t tmp_len = 0; + again: switch (Z_TYPE_P(zpp)) { + case IS_REFERENCE: + ZVAL_DEREF(zpp); + goto again; + case IS_NULL: p->param.strings[index] = NULL; return; @@ -257,7 +267,7 @@ static void php_pq_params_set_param(php_pq_params_t *p, unsigned index, zval *zp break; case IS_ARRAY: - str = array_param_to_string(p, &tmp, type); + str = array_param_to_string(p, zpp, type); break; case IS_OBJECT: @@ -265,7 +275,6 @@ static void php_pq_params_set_param(php_pq_params_t *p, unsigned index, zval *zp break; } /* no break */ - default: str = zval_get_string(zpp); break; diff --git a/src/php_pqcancel.c b/src/php_pqcancel.c index 7105363..4d5d339 100644 --- a/src/php_pqcancel.c +++ b/src/php_pqcancel.c @@ -32,7 +32,7 @@ static void php_pqcancel_object_free(zend_object *o) { php_pqcancel_object_t *obj = PHP_PQ_OBJ(NULL, o); #if DBG_GC - fprintf(stderr, "FREE cancel(#%d) %p (conn(#%d): %p)\n", obj->zv.handle, obj, obj->intern->conn->zv.handle, obj->intern->conn); + fprintf(stderr, "FREE cancel(#%d) %p (conn(#%d): %p)\n", obj->zo.handle, obj, obj->intern->conn->zo.handle, obj->intern->conn); #endif if (obj->intern) { PQfreeCancel(obj->intern->cancel); @@ -40,26 +40,13 @@ static void php_pqcancel_object_free(zend_object *o) efree(obj->intern); obj->intern = NULL; } - zend_object_std_dtor(o); - efree(obj); + php_pq_object_dtor(o); } php_pqcancel_object_t *php_pqcancel_create_object_ex(zend_class_entry *ce, php_pqcancel_t *intern) { - php_pqcancel_object_t *o; - - o = ecalloc(1, sizeof(*o) + zend_object_properties_size(ce)); - zend_object_std_init(&o->zo, ce); - object_properties_init(&o->zo, ce); - o->prophandler = &php_pqcancel_object_prophandlers; - - if (intern) { - o->intern = intern; - } - - o->zo.handlers = &php_pqcancel_object_handlers; - - return o; + return php_pq_object_create(ce, intern, sizeof(php_pqcancel_object_t), + &php_pqcancel_object_handlers, &php_pqcancel_object_prophandlers); } static zend_object *php_pqcancel_create_object(zend_class_entry *class_type TSRMLS_DC) @@ -74,6 +61,15 @@ static void php_pqcancel_object_read_connection(zval *object, void *o, zval *ret php_pq_object_to_zval(obj->intern->conn, return_value); } +static void php_pqcancel_object_gc_connection(zval *object, void *o, zval *return_value) +{ + php_pqcancel_object_t *obj = o; + zval zconn; + + php_pq_object_to_zval_no_addref(obj->intern->conn, &zconn); + add_next_index_zval(return_value, &zconn); +} + ZEND_BEGIN_ARG_INFO_EX(ai_pqcancel_construct, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, connection, pq\\Connection, 0) ZEND_END_ARG_INFO(); @@ -161,14 +157,15 @@ PHP_MINIT_FUNCTION(pqcancel) php_pqcancel_object_handlers.write_property = php_pq_object_write_prop; php_pqcancel_object_handlers.clone_obj = NULL; php_pqcancel_object_handlers.get_property_ptr_ptr = NULL; - php_pqcancel_object_handlers.get_gc = NULL; + php_pqcancel_object_handlers.get_gc = php_pq_object_get_gc; php_pqcancel_object_handlers.get_properties = php_pq_object_properties; php_pqcancel_object_handlers.get_debug_info = php_pq_object_debug_info; - zend_hash_init(&php_pqcancel_object_prophandlers, 1, NULL, NULL, 1); + zend_hash_init(&php_pqcancel_object_prophandlers, 1, NULL, php_pq_object_prophandler_dtor, 1); - zend_declare_property_null(php_pqcancel_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(php_pqcancel_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC); ph.read = php_pqcancel_object_read_connection; + ph.gc = php_pqcancel_object_gc_connection; zend_hash_str_add_mem(&php_pqcancel_object_prophandlers, ZEND_STRL("connection"), (void *) &ph, sizeof(ph)); return SUCCESS; diff --git a/src/php_pqcancel.h b/src/php_pqcancel.h index 8bbd7a9..fb0a69e 100644 --- a/src/php_pqcancel.h +++ b/src/php_pqcancel.h @@ -22,9 +22,7 @@ typedef struct php_pqcancel { } php_pqcancel_t; typedef struct php_pqcancel_object { - php_pqcancel_t *intern; - HashTable *prophandler; - zend_object zo; + PHP_PQ_OBJ_DECL(php_pqcancel_t *) } php_pqcancel_object_t; extern zend_class_entry *php_pqcancel_class_entry; diff --git a/src/php_pqconn.c b/src/php_pqconn.c index 3e4aed8..a7fca0e 100644 --- a/src/php_pqconn.c +++ b/src/php_pqconn.c @@ -35,8 +35,14 @@ zend_class_entry *php_pqconn_class_entry; static zend_object_handlers php_pqconn_object_handlers; static HashTable php_pqconn_object_prophandlers; +static void php_pq_callback_hash_dtor(zval *p) +{ + php_pq_callback_dtor(Z_PTR_P(p)); + efree(Z_PTR_P(p)); +} + /* -static void php_pqconn_del_eventhandler(php_pqconn_object_t *obj, const char *type_str, size_t type_len, ulong id TSRMLS_DC) +static void php_pqconn_del_eventhandler(php_pqconn_object_t *obj, const char *type_str, size_t type_len, ulong id) { zval **evhs; @@ -46,21 +52,25 @@ static void php_pqconn_del_eventhandler(php_pqconn_object_t *obj, const char *ty } */ -static ulong php_pqconn_add_eventhandler(php_pqconn_object_t *obj, const char *type_str, size_t type_len, php_pq_callback_t *cb TSRMLS_DC) +static zend_long php_pqconn_add_eventhandler(php_pqconn_object_t *obj, const char *type_str, size_t type_len, php_pq_callback_t *cb) { - ulong h; - HashTable *evhs; + zend_long h; + zval *zevhs; - if (!(evhs = zend_hash_str_find_ptr(&obj->intern->eventhandlers, type_str, type_len))) { - HashTable evh; + if (!(zevhs = zend_hash_str_find(&obj->intern->eventhandlers, type_str, type_len))) { + HashTable *evhs; + zval tmp; - zend_hash_init(&evh, 1, NULL, (dtor_func_t) php_pq_callback_dtor, 0); - evhs = zend_hash_str_add_mem(&obj->intern->eventhandlers, type_str, type_len, (void *) &evh, sizeof(evh)); + ALLOC_HASHTABLE(evhs); + zend_hash_init(evhs, 1, NULL, php_pq_callback_hash_dtor, 0); + + ZVAL_ARR(&tmp, evhs); + zevhs = zend_hash_str_add(&obj->intern->eventhandlers, type_str, type_len, &tmp); } php_pq_callback_addref(cb); - h = zend_hash_next_free_element(evhs); - zend_hash_index_update_ptr(evhs, h, (void *) cb); + h = zend_hash_next_free_element(Z_ARRVAL_P(zevhs)); + zend_hash_index_update_mem(Z_ARRVAL_P(zevhs), h, (void *) cb, sizeof(*cb)); return h; } @@ -69,7 +79,7 @@ static void php_pqconn_object_free(zend_object *o) { php_pqconn_object_t *obj = PHP_PQ_OBJ(NULL, o); #if DBG_GC - fprintf(stderr, "FREE conn(#%d) %p\n", obj->zv.handle, obj); + fprintf(stderr, "FREE conn(#%d) %p\n", obj->zo.handle, obj); #endif if (obj->intern) { php_pq_callback_dtor(&obj->intern->onevent); @@ -81,27 +91,14 @@ static void php_pqconn_object_free(zend_object *o) efree(obj->intern); obj->intern = NULL; } - zend_object_std_dtor(o); - efree(obj); + php_pq_object_dtor(o); } php_pqconn_object_t *php_pqconn_create_object_ex(zend_class_entry *ce, php_pqconn_t *intern) { - php_pqconn_object_t *o; - - o = ecalloc(1, sizeof(*o) + zend_object_properties_size(ce)); - zend_object_std_init(&o->zo, ce); - object_properties_init(&o->zo, ce); - o->prophandler = &php_pqconn_object_prophandlers; - - if (intern) { - o->intern = intern; - } - - o->zo.handlers = &php_pqconn_object_handlers; - - return o; + return php_pq_object_create(ce, intern, sizeof(php_pqconn_object_t), + &php_pqconn_object_handlers, &php_pqconn_object_prophandlers); } static zend_object *php_pqconn_create_object(zend_class_entry *class_type) @@ -147,6 +144,7 @@ static int apply_notify_listener(zval *p, void *arg) zend_fcall_info_argn(&listener->fci, 3, &zchannel, &zmessage, &zpid); zend_fcall_info_call(&listener->fci, &listener->fcc, NULL, NULL); + zend_fcall_info_args_clear(&listener->fci, 0); zval_ptr_dtor(&zchannel); zval_ptr_dtor(&zmessage); @@ -310,7 +308,7 @@ static void php_pqconn_object_read_options(zval *object, void *o, zval *return_v } } -static int apply_read_event_handler_ex(zval *p, void *arg) +static int apply_read_callback_ex(zval *p, void *arg) { HashTable *rv = arg; zval zcb; @@ -320,9 +318,9 @@ static int apply_read_event_handler_ex(zval *p, void *arg) return ZEND_HASH_APPLY_KEEP; } -static int apply_read_event_handlers(zval *p, int argc, va_list argv, zend_hash_key *key) +static int apply_read_callbacks(zval *p, int argc, va_list argv, zend_hash_key *key) { - HashTable *evhs = Z_PTR_P(p), *rv = va_arg(argv, HashTable *); + HashTable *evhs = Z_ARRVAL_P(p), *rv = va_arg(argv, HashTable *); zval entry, *entry_ptr; array_init_size(&entry, zend_hash_num_elements(evhs)); @@ -333,7 +331,7 @@ static int apply_read_event_handlers(zval *p, int argc, va_list argv, zend_hash_ entry_ptr = zend_hash_index_update(rv, key->h, &entry); } - zend_hash_apply_with_argument(evhs, apply_read_event_handler_ex, Z_ARRVAL_P(entry_ptr)); + zend_hash_apply_with_argument(evhs, apply_read_callback_ex, Z_ARRVAL_P(entry_ptr)); return ZEND_HASH_APPLY_KEEP; } @@ -342,7 +340,75 @@ static void php_pqconn_object_read_event_handlers(zval *object, void *o, zval *r php_pqconn_object_t *obj = o; array_init(return_value); - zend_hash_apply_with_arguments(&obj->intern->eventhandlers, apply_read_event_handlers, 1, Z_ARRVAL_P(return_value) TSRMLS_CC); + zend_hash_apply_with_arguments(&obj->intern->eventhandlers, apply_read_callbacks, 1, Z_ARRVAL_P(return_value)); +} + +static void php_pqconn_object_gc_event_handlers(zval *object, void *o, zval *return_value) +{ + php_pqconn_object_t *obj = o; + zval *evhs; + + ZEND_HASH_FOREACH_VAL(&obj->intern->eventhandlers, evhs) + { + zval *evh; + + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(evhs), evh) + { + zval zcb; + + add_next_index_zval(return_value, php_pq_callback_to_zval_no_addref(Z_PTR_P(evh), &zcb)); + } + ZEND_HASH_FOREACH_END(); + } + ZEND_HASH_FOREACH_END(); +} + +static void php_pqconn_object_read_listeners(zval *object, void *o, zval *return_value) +{ + php_pqconn_object_t *obj = o; + + array_init(return_value); + zend_hash_apply_with_arguments(&obj->intern->listeners, apply_read_callbacks, 1, Z_ARRVAL_P(return_value)); +} + +static void php_pqconn_object_gc_listeners(zval *object, void *o, zval *return_value) +{ + php_pqconn_object_t *obj = o; + zval *listeners; + + ZEND_HASH_FOREACH_VAL(&obj->intern->listeners, listeners) + { + zval *listener; + + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(listeners), listener) + { + zval zcb; + + add_next_index_zval(return_value, php_pq_callback_to_zval_no_addref(Z_PTR_P(listener), &zcb)); + } + ZEND_HASH_FOREACH_END(); + } + ZEND_HASH_FOREACH_END(); +} + +static void php_pqconn_object_read_converters(zval *object, void *o, zval *return_value) +{ + php_pqconn_object_t *obj = o; + + array_init(return_value); + zend_hash_copy(Z_ARRVAL_P(return_value), &obj->intern->converters, zval_add_ref); +} + +static void php_pqconn_object_gc_converters(zval *object, void *o, zval *return_value) +{ + php_pqconn_object_t *obj = o; + zval *converter; + + ZEND_HASH_FOREACH_VAL(&obj->intern->converters, converter) + { + add_next_index_zval(return_value, converter); + } + ZEND_HASH_FOREACH_END(); } static void php_pqconn_object_read_def_fetch_type(zval *object, void *o, zval *return_value) @@ -435,6 +501,7 @@ static ZEND_RESULT_CODE php_pqconn_update_socket(zval *zobj, php_pqconn_object_t } zend_get_std_object_handlers()->write_property(zobj, &zmember, &zsocket, NULL); zval_ptr_dtor(&zsocket); + zval_ptr_dtor(&zmember); return retval; } @@ -602,7 +669,7 @@ static PHP_METHOD(pqconn, __construct) { zend_hash_init(&obj->intern->listeners, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_init(&obj->intern->converters, 0, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_init(&obj->intern->eventhandlers, 0, NULL, (dtor_func_t) zend_hash_destroy, 0); + zend_hash_init(&obj->intern->eventhandlers, 0, NULL, ZVAL_PTR_DTOR, 0); if (flags & PHP_PQCONN_PERSISTENT) { zend_string *dsn = zend_string_init(dsn_str, dsn_len, 0); @@ -760,15 +827,21 @@ static PHP_METHOD(pqconn, unlistenAsync) { static void php_pqconn_add_listener(php_pqconn_object_t *obj, const char *channel_str, size_t channel_len, php_pq_callback_t *listener) { - zval *existing, tmp; + zval *existing; php_pq_callback_addref(listener); if ((existing = zend_hash_str_find(&obj->intern->listeners, channel_str, channel_len))) { zend_hash_next_index_insert_mem(Z_ARRVAL_P(existing), (void *) listener, sizeof(*listener)); } else { - ZVAL_NEW_ARR(&tmp); - zend_hash_next_index_insert_mem(Z_ARRVAL(tmp), (void *) listener, sizeof(*listener)); + zval tmp; + HashTable *ht; + + ALLOC_HASHTABLE(ht); + zend_hash_init(ht, 0, NULL, php_pq_callback_hash_dtor, 0); + zend_hash_next_index_insert_mem(ht, (void *) listener, sizeof(*listener)); + + ZVAL_ARR(&tmp, ht); zend_hash_str_add(&obj->intern->listeners, channel_str, channel_len, &tmp); } } @@ -1880,11 +1953,11 @@ PHP_MINIT_FUNCTION(pqconn) php_pqconn_object_handlers.write_property = php_pq_object_write_prop; php_pqconn_object_handlers.clone_obj = NULL; php_pqconn_object_handlers.get_property_ptr_ptr = NULL; - php_pqconn_object_handlers.get_gc = NULL; + php_pqconn_object_handlers.get_gc = php_pq_object_get_gc; php_pqconn_object_handlers.get_properties = php_pq_object_properties; php_pqconn_object_handlers.get_debug_info = php_pq_object_debug_info; - zend_hash_init(&php_pqconn_object_prophandlers, 20, NULL, NULL, 1); + zend_hash_init(&php_pqconn_object_prophandlers, 22, NULL, php_pq_object_prophandler_dtor, 1); zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("status"), CONNECTION_BAD, ZEND_ACC_PUBLIC); ph.read = php_pqconn_object_read_status; @@ -1950,7 +2023,21 @@ PHP_MINIT_FUNCTION(pqconn) zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("eventHandlers"), ZEND_ACC_PUBLIC); ph.read = php_pqconn_object_read_event_handlers; + ph.gc = php_pqconn_object_gc_event_handlers; zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "eventHandlers", sizeof("eventHandlers")-1, (void *) &ph, sizeof(ph)); + ph.gc = NULL; + + zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("listeners"), ZEND_ACC_PUBLIC); + ph.read = php_pqconn_object_read_listeners; + ph.gc = php_pqconn_object_gc_listeners; + zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "listeners", sizeof("listeners")-1, (void *) &ph, sizeof(ph)); + ph.gc = NULL; + + zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("converters"), ZEND_ACC_PUBLIC); + ph.read = php_pqconn_object_read_converters; + ph.gc = php_pqconn_object_gc_converters; + zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "converters", sizeof("converters")-1, (void *) &ph, sizeof(ph)); + ph.gc = NULL; zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("defaultFetchType"), 0, ZEND_ACC_PUBLIC); ph.read = php_pqconn_object_read_def_fetch_type; diff --git a/src/php_pqconn.h b/src/php_pqconn.h index 0514e0a..65c1278 100644 --- a/src/php_pqconn.h +++ b/src/php_pqconn.h @@ -18,6 +18,7 @@ #define PHP_PQCONN_PERSISTENT 0x02 #include +#include "php_pq_object.h" #include "php_pq_callback.h" #include "php_pq_params.h" @@ -38,9 +39,7 @@ typedef struct php_pqconn { } php_pqconn_t; typedef struct php_pqconn_object { - php_pqconn_t *intern; - HashTable *prophandler; - zend_object zo; + PHP_PQ_OBJ_DECL(php_pqconn_t *) } php_pqconn_object_t; typedef struct php_pqconn_resource_factory_data { diff --git a/src/php_pqconn_event.c b/src/php_pqconn_event.c index 07fb173..2b94dee 100644 --- a/src/php_pqconn_event.c +++ b/src/php_pqconn_event.c @@ -33,6 +33,7 @@ static int apply_event(zval *p, void *a) ZVAL_NULL(&rv); zend_fcall_info_args(&cb->fci, args); zend_fcall_info_call(&cb->fci, &cb->fcc, &rv, NULL); + zend_fcall_info_args_clear(&cb->fci, 0); zval_ptr_dtor(&rv); return ZEND_HASH_APPLY_KEEP; @@ -43,15 +44,15 @@ static void php_pqconn_event_connreset(PGEventConnReset *event) php_pqconn_event_data_t *data = PQinstanceData(event->conn, php_pqconn_event); if (data) { - HashTable *evhs; + zval *zevhs; - if ((evhs = zend_hash_str_find_ptr(&data->obj->intern->eventhandlers, ZEND_STRS("reset")))) { + if ((zevhs = zend_hash_str_find(&data->obj->intern->eventhandlers, ZEND_STRL("reset")))) { zval args, connection; array_init(&args); php_pq_object_to_zval(data->obj, &connection); add_next_index_zval(&args, &connection); - zend_hash_apply_with_argument(evhs, apply_event, &args); + zend_hash_apply_with_argument(Z_ARRVAL_P(zevhs), apply_event, &args); zval_ptr_dtor(&args); } } @@ -62,13 +63,11 @@ static void php_pqconn_event_resultcreate(PGEventResultCreate *event) php_pqconn_event_data_t *data = PQinstanceData(event->conn, php_pqconn_event); if (data) { - php_pqres_object_t *obj; - HashTable *evhs; - - php_pqres_init_instance_data(event->result, data->obj, &obj); + php_pqres_object_t *obj = php_pqres_init_instance_data(event->result, data->obj); + zval *zevhs; /* event listener */ - if ((evhs = zend_hash_str_find_ptr(&data->obj->intern->eventhandlers, ZEND_STRL("result")))) { + if ((zevhs = zend_hash_str_find(&data->obj->intern->eventhandlers, ZEND_STRL("result")))) { zval args, connection, res; array_init(&args); @@ -76,7 +75,7 @@ static void php_pqconn_event_resultcreate(PGEventResultCreate *event) add_next_index_zval(&args, &connection); php_pq_object_to_zval(obj, &res); add_next_index_zval(&args, &res); - zend_hash_apply_with_argument(evhs, apply_event, &args); + zend_hash_apply_with_argument(Z_ARRVAL_P(zevhs), apply_event, &args); zval_ptr_dtor(&args); } @@ -99,6 +98,8 @@ static void php_pqconn_event_resultdestroy(PGEventResultDestroy *event) if (obj) { obj->intern->res = NULL; + assert(GC_REFCOUNT(&obj->zo)); + php_pq_object_delref(obj); } } @@ -126,6 +127,7 @@ php_pqconn_event_data_t *php_pqconn_event_data_init(php_pqconn_object_t *obj) php_pqconn_event_data_t *data = emalloc(sizeof(*data)); data->obj = obj; + data->res = NULL; return data; } @@ -135,16 +137,16 @@ void php_pqconn_notice_recv(void *p, const PGresult *res) php_pqconn_event_data_t *data = p; if (data) { - HashTable *evhs; + zval *zevhs; - if ((evhs = zend_hash_str_find_ptr(&data->obj->intern->eventhandlers, ZEND_STRL("notice")))) { + if ((zevhs = zend_hash_str_find(&data->obj->intern->eventhandlers, ZEND_STRL("notice")))) { zval args, connection; array_init(&args); php_pq_object_to_zval(data->obj, &connection); add_next_index_zval(&args, &connection); add_next_index_string(&args, PHP_PQresultErrorMessage(res)); - zend_hash_apply_with_argument(evhs, apply_event, &args); + zend_hash_apply_with_argument(Z_ARRVAL_P(zevhs), apply_event, &args); zval_ptr_dtor(&args); } } diff --git a/src/php_pqconn_event.h b/src/php_pqconn_event.h index f8aa4ab..b7513a6 100644 --- a/src/php_pqconn_event.h +++ b/src/php_pqconn_event.h @@ -17,9 +17,11 @@ #include #include "php_pqconn.h" +#include "php_pqres.h" typedef struct php_pqconn_event_data { php_pqconn_object_t *obj; + php_pqres_object_t *res; } php_pqconn_event_data_t; extern php_pqconn_event_data_t *php_pqconn_event_data_init(php_pqconn_object_t *obj); diff --git a/src/php_pqcopy.c b/src/php_pqcopy.c index 2c4b626..2413268 100644 --- a/src/php_pqcopy.c +++ b/src/php_pqcopy.c @@ -35,7 +35,7 @@ static void php_pqcopy_object_free(zend_object *o) { php_pqcopy_object_t *obj = PHP_PQ_OBJ(NULL, o); #if DBG_GC - fprintf(stderr, "FREE copy(#%d) %p (conn(#%d): %p)\n", obj->zv.handle, obj, obj->intern->conn->zv.handle, obj->intern->conn); + fprintf(stderr, "FREE copy(#%d) %p (conn(#%d): %p)\n", obj->zo.handle, obj, obj->intern->conn->zo.handle, obj->intern->conn); #endif if (obj->intern) { efree(obj->intern->expression); @@ -44,26 +44,13 @@ static void php_pqcopy_object_free(zend_object *o) efree(obj->intern); obj->intern = NULL; } - zend_object_std_dtor(o); - efree(obj); + php_pq_object_dtor(o); } php_pqcopy_object_t *php_pqcopy_create_object_ex(zend_class_entry *ce, php_pqcopy_t *intern) { - php_pqcopy_object_t *o; - - o = ecalloc(1, sizeof(*o) + zend_object_properties_size(ce)); - zend_object_std_init(&o->zo, ce); - object_properties_init(&o->zo, ce); - o->prophandler = &php_pqcopy_object_prophandlers; - - if (intern) { - o->intern = intern; - } - - o->zo.handlers = &php_pqcopy_object_handlers; - - return o; + return php_pq_object_create(ce, intern, sizeof(php_pqcopy_object_t), + &php_pqcopy_object_handlers, &php_pqcopy_object_prophandlers); } static zend_object *php_pqcopy_create_object(zend_class_entry *class_type) @@ -78,6 +65,15 @@ static void php_pqcopy_object_read_connection(zval *object, void *o, zval *retur php_pq_object_to_zval(obj->intern->conn, return_value); } +static void php_pqcopy_object_gc_connection(zval *object, void *o, zval *return_value) +{ + php_pqcopy_object_t *obj = o; + zval zconn; + + php_pq_object_to_zval_no_addref(obj->intern->conn, &zconn); + add_next_index_zval(return_value, &zconn); +} + static void php_pqcopy_object_read_direction(zval *object, void *o, zval *return_value) { php_pqcopy_object_t *obj = o; @@ -326,15 +322,17 @@ PHP_MINIT_FUNCTION(pqcopy) php_pqcopy_object_handlers.write_property = php_pq_object_write_prop; php_pqcopy_object_handlers.clone_obj = NULL; php_pqcopy_object_handlers.get_property_ptr_ptr = NULL; - php_pqcopy_object_handlers.get_gc = NULL; + php_pqcopy_object_handlers.get_gc = php_pq_object_get_gc; php_pqcopy_object_handlers.get_properties = php_pq_object_properties; php_pqcopy_object_handlers.get_debug_info = php_pq_object_debug_info; - zend_hash_init(&php_pqcopy_object_prophandlers, 4, NULL, NULL, 1); + zend_hash_init(&php_pqcopy_object_prophandlers, 4, NULL, php_pq_object_prophandler_dtor, 1); zend_declare_property_null(php_pqcopy_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC); ph.read = php_pqcopy_object_read_connection; + ph.gc = php_pqcopy_object_gc_connection; zend_hash_str_add_mem(&php_pqcopy_object_prophandlers, "connection", sizeof("connection")-1, (void *) &ph, sizeof(ph)); + ph.gc = NULL; zend_declare_property_null(php_pqcopy_class_entry, ZEND_STRL("expression"), ZEND_ACC_PUBLIC); ph.read = php_pqcopy_object_read_expression; diff --git a/src/php_pqcopy.h b/src/php_pqcopy.h index dbac9a3..decc817 100644 --- a/src/php_pqcopy.h +++ b/src/php_pqcopy.h @@ -35,9 +35,7 @@ typedef struct php_pqcopy { } php_pqcopy_t; typedef struct php_pqcopy_object { - php_pqcopy_t *intern; - HashTable *prophandler; - zend_object zo; + PHP_PQ_OBJ_DECL(php_pqcopy_t *) } php_pqcopy_object_t; extern zend_class_entry *php_pqcopy_class_entry; diff --git a/src/php_pqcur.c b/src/php_pqcur.c index be6443d..7a96994 100644 --- a/src/php_pqcur.c +++ b/src/php_pqcur.c @@ -152,7 +152,7 @@ static void php_pqcur_object_free(zend_object *o) { php_pqcur_object_t *obj = PHP_PQ_OBJ(NULL, o); #if DBG_GC - fprintf(stderr, "FREE cur(#%d) %p (conn: %p)\n", obj->zv.handle, obj, obj->intern->conn); + fprintf(stderr, "FREE cur(#%d) %p (conn: %p)\n", obj->zo.handle, obj, obj->intern->conn); #endif if (obj->intern) { cur_close(obj, 0, 1); @@ -162,26 +162,13 @@ static void php_pqcur_object_free(zend_object *o) efree(obj->intern); obj->intern = NULL; } - zend_object_std_dtor(o); - efree(obj); + php_pq_object_dtor(o); } php_pqcur_object_t *php_pqcur_create_object_ex(zend_class_entry *ce, php_pqcur_t *intern) { - php_pqcur_object_t *o; - - o = ecalloc(1, sizeof(*o) + zend_object_properties_size(ce)); - zend_object_std_init(&o->zo, ce); - object_properties_init(&o->zo, ce); - o->prophandler = &php_pqcur_object_prophandlers; - - if (intern) { - o->intern = intern; - } - - o->zo.handlers = &php_pqcur_object_handlers; - - return o; + return php_pq_object_create(ce, intern, sizeof(php_pqcur_object_t), + &php_pqcur_object_handlers, &php_pqcur_object_prophandlers); } static zend_object *php_pqcur_create_object(zend_class_entry *class_type) @@ -203,6 +190,15 @@ static void php_pqcur_object_read_connection(zval *object, void *o, zval *return php_pq_object_to_zval(obj->intern->conn, return_value); } +static void php_pqcur_object_gc_connection(zval *object, void *o, zval *return_value) +{ + php_pqcur_object_t *obj = o; + zval zconn; + + php_pq_object_to_zval_no_addref(obj->intern->conn, &zconn); + add_next_index_zval(return_value, &zconn); +} + static void php_pqcur_object_read_query(zval *object, void *o, zval *return_value) { php_pqcur_object_t *obj = o; @@ -438,11 +434,11 @@ PHP_MINIT_FUNCTION(pqcur) php_pqcur_object_handlers.write_property = php_pq_object_write_prop; php_pqcur_object_handlers.clone_obj = NULL; php_pqcur_object_handlers.get_property_ptr_ptr = NULL; - php_pqcur_object_handlers.get_gc = NULL; + php_pqcur_object_handlers.get_gc = php_pq_object_get_gc; php_pqcur_object_handlers.get_properties = php_pq_object_properties; php_pqcur_object_handlers.get_debug_info = php_pq_object_debug_info; - zend_hash_init(&php_pqcur_object_prophandlers, 4, NULL, NULL, 1); + zend_hash_init(&php_pqcur_object_prophandlers, 4, NULL, php_pq_object_prophandler_dtor, 1); zend_declare_class_constant_long(php_pqcur_class_entry, ZEND_STRL("BINARY"), PHP_PQ_DECLARE_BINARY); zend_declare_class_constant_long(php_pqcur_class_entry, ZEND_STRL("INSENSITIVE"), PHP_PQ_DECLARE_INSENSITIVE); @@ -456,7 +452,9 @@ PHP_MINIT_FUNCTION(pqcur) zend_declare_property_null(php_pqcur_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC); ph.read = php_pqcur_object_read_connection; + ph.gc = php_pqcur_object_gc_connection; zend_hash_str_add_mem(&php_pqcur_object_prophandlers, "connection", sizeof("connection")-1, (void *) &ph, sizeof(ph)); + ph.gc = NULL; zend_declare_property_null(php_pqcur_class_entry, ZEND_STRL("query"), ZEND_ACC_PUBLIC); ph.read = php_pqcur_object_read_query; diff --git a/src/php_pqcur.h b/src/php_pqcur.h index ea4353a..ab74e8d 100644 --- a/src/php_pqcur.h +++ b/src/php_pqcur.h @@ -32,9 +32,7 @@ typedef struct php_pqcur { } php_pqcur_t; typedef struct php_pqcur_object { - php_pqcur_t *intern; - HashTable *prophandler; - zend_object zo; + PHP_PQ_OBJ_DECL(php_pqcur_t *) } php_pqcur_object_t; extern zend_class_entry *php_pqcur_class_entry; diff --git a/src/php_pqexc.c b/src/php_pqexc.c index 63aa9d3..1f96662 100644 --- a/src/php_pqexc.c +++ b/src/php_pqexc.c @@ -53,10 +53,10 @@ zend_class_entry *exce(php_pqexc_type_t type) } } -zval *throw_exce(php_pqexc_type_t type, const char *fmt, ...) +zend_object *throw_exce(php_pqexc_type_t type, const char *fmt, ...) { char *msg; - zval *zexc; + zend_object *zexc; va_list argv; va_start(argv, fmt); @@ -75,6 +75,7 @@ PHP_MINIT_FUNCTION(pqexc) INIT_NS_CLASS_ENTRY(ce, "pq", "Exception", php_pqexc_methods); php_pqexc_interface_class_entry = zend_register_internal_interface(&ce); + zend_class_implements(php_pqexc_interface_class_entry, 1, zend_ce_throwable); zend_declare_class_constant_long(php_pqexc_interface_class_entry, ZEND_STRL("INVALID_ARGUMENT"), EX_INVALID_ARGUMENT); zend_declare_class_constant_long(php_pqexc_interface_class_entry, ZEND_STRL("RUNTIME"), EX_RUNTIME); @@ -104,7 +105,7 @@ PHP_MINIT_FUNCTION(pqexc) memset(&ce, 0, sizeof(ce)); INIT_NS_CLASS_ENTRY(ce, "pq\\Exception", "DomainException", php_pqexc_methods); php_pqexc_domain_class_entry = zend_register_internal_class_ex(&ce, spl_ce_DomainException); - zend_class_implements(php_pqexc_domain_class_entry TSRMLS_CC, 1, php_pqexc_interface_class_entry); + zend_class_implements(php_pqexc_domain_class_entry, 1, php_pqexc_interface_class_entry); zend_declare_property_null(php_pqexc_domain_class_entry, ZEND_STRL("sqlstate"), ZEND_ACC_PUBLIC); return SUCCESS; diff --git a/src/php_pqexc.h b/src/php_pqexc.h index de1be0f..2666dcf 100644 --- a/src/php_pqexc.h +++ b/src/php_pqexc.h @@ -27,7 +27,7 @@ typedef enum php_pqexc_type { } php_pqexc_type_t; extern zend_class_entry *exce(php_pqexc_type_t type); -extern zval *throw_exce(php_pqexc_type_t type, const char *fmt, ...); +extern zend_object *throw_exce(php_pqexc_type_t type, const char *fmt, ...); extern PHP_MINIT_FUNCTION(pqexc); diff --git a/src/php_pqlob.c b/src/php_pqlob.c index 5149472..01c0ec2 100644 --- a/src/php_pqlob.c +++ b/src/php_pqlob.c @@ -32,7 +32,7 @@ static void php_pqlob_object_free(zend_object *o) { php_pqlob_object_t *obj = PHP_PQ_OBJ(NULL, o); #if DBG_GC - fprintf(stderr, "FREE lob(#%d) %p (txn(#%d): %p)\n", obj->zv.handle, obj, obj->intern->txn->zv.handle, obj->intern->txn); + fprintf(stderr, "FREE lob(#%d) %p (txn(#%d): %p)\n", obj->zo.handle, obj, obj->intern->txn->zo.handle, obj->intern->txn); #endif if (obj->intern) { if (obj->intern->lofd) { @@ -47,26 +47,13 @@ static void php_pqlob_object_free(zend_object *o) efree(obj->intern); obj->intern = NULL; } - zend_object_std_dtor(o); - efree(obj); + php_pq_object_dtor(o); } php_pqlob_object_t *php_pqlob_create_object_ex(zend_class_entry *ce, php_pqlob_t *intern) { - php_pqlob_object_t *o; - - o = ecalloc(1, sizeof(*o) + zend_object_properties_size(ce)); - zend_object_std_init(&o->zo, ce); - object_properties_init(&o->zo, ce); - o->prophandler = &php_pqlob_object_prophandlers; - - if (intern) { - o->intern = intern; - } - - o->zo.handlers = &php_pqlob_object_handlers; - - return o; + return php_pq_object_create(ce, intern, sizeof(php_pqlob_object_t), + &php_pqlob_object_handlers, &php_pqlob_object_prophandlers); } static zend_object *php_pqlob_create_object(zend_class_entry *class_type) @@ -81,6 +68,15 @@ static void php_pqlob_object_read_transaction(zval *object, void *o, zval *retur php_pq_object_to_zval(obj->intern->txn, return_value); } +static void php_pqlob_object_gc_transaction(zval *object, void *o, zval *return_value) +{ + php_pqlob_object_t *obj = o; + zval ztxn; + + php_pq_object_to_zval_no_addref(obj->intern->txn, &ztxn); + add_next_index_zval(return_value, &ztxn); +} + static void php_pqlob_object_read_oid(zval *object, void *o, zval *return_value) { php_pqlob_object_t *obj = o; @@ -101,7 +97,7 @@ static void php_pqlob_object_read_stream(zval *object, void *o, zval *return_val php_stream_to_zval(obj->intern->stream, &zstream); } - RETVAL_ZVAL(&zstream, 1, 1); + RETVAL_ZVAL(&zstream, 1, 0); } static size_t php_pqlob_stream_write(php_stream *stream, const char *buffer, size_t length TSRMLS_DC) @@ -209,6 +205,7 @@ static void php_pqlob_object_update_stream(zval *zpqlob, php_pqlob_object_t *obj php_stream_to_zval(obj->intern->stream, zstream); zend_get_std_object_handlers()->write_property(zpqlob, &zmember, zstream, NULL); + zval_ptr_dtor(&zmember); } ZEND_BEGIN_ARG_INFO_EX(ai_pqlob_construct, 0, 0, 1) @@ -457,23 +454,25 @@ PHP_MINIT_FUNCTION(pqlob) php_pqlob_object_handlers.write_property = php_pq_object_write_prop; php_pqlob_object_handlers.clone_obj = NULL; php_pqlob_object_handlers.get_property_ptr_ptr = NULL; - php_pqlob_object_handlers.get_gc = NULL; + php_pqlob_object_handlers.get_gc = php_pq_object_get_gc; php_pqlob_object_handlers.get_properties = php_pq_object_properties; php_pqlob_object_handlers.get_debug_info = php_pq_object_debug_info; - zend_hash_init(&php_pqlob_object_prophandlers, 3, NULL, NULL, 1); + zend_hash_init(&php_pqlob_object_prophandlers, 3, NULL, php_pq_object_prophandler_dtor, 1); zend_declare_property_null(php_pqlob_class_entry, ZEND_STRL("transaction"), ZEND_ACC_PUBLIC); ph.read = php_pqlob_object_read_transaction; + ph.gc = php_pqlob_object_gc_transaction; zend_hash_str_add_mem(&php_pqlob_object_prophandlers, "transaction", sizeof("transaction")-1, (void *) &ph, sizeof(ph)); + ph.gc = NULL; zend_declare_property_long(php_pqlob_class_entry, ZEND_STRL("oid"), InvalidOid, ZEND_ACC_PUBLIC); ph.read = php_pqlob_object_read_oid; - zend_hash_str_add_mem(&php_pqlob_object_prophandlers, "oid", sizeof("oid"), (void *) &ph, sizeof(ph)); + zend_hash_str_add_mem(&php_pqlob_object_prophandlers, "oid", sizeof("oid")-1, (void *) &ph, sizeof(ph)); zend_declare_property_null(php_pqlob_class_entry, ZEND_STRL("stream"), ZEND_ACC_PUBLIC); ph.read = php_pqlob_object_read_stream; - zend_hash_str_add_mem(&php_pqlob_object_prophandlers, "stream", sizeof("stream"), (void *) &ph, sizeof(ph)); + zend_hash_str_add_mem(&php_pqlob_object_prophandlers, "stream", sizeof("stream")-1, (void *) &ph, sizeof(ph)); zend_declare_class_constant_long(php_pqlob_class_entry, ZEND_STRL("INVALID_OID"), InvalidOid); zend_declare_class_constant_long(php_pqlob_class_entry, ZEND_STRL("R"), INV_READ); diff --git a/src/php_pqlob.h b/src/php_pqlob.h index c56049d..fc7fa13 100644 --- a/src/php_pqlob.h +++ b/src/php_pqlob.h @@ -24,9 +24,7 @@ typedef struct php_pqlob { } php_pqlob_t; typedef struct php_pqlob_object { - php_pqlob_t *intern; - HashTable *prophandler; - zend_object zo; + PHP_PQ_OBJ_DECL(php_pqlob_t *) } php_pqlob_object_t; extern zend_class_entry *php_pqlob_class_entry; diff --git a/src/php_pqres.c b/src/php_pqres.c index b83ee97..f2ddf98 100644 --- a/src/php_pqres.c +++ b/src/php_pqres.c @@ -43,31 +43,48 @@ static zend_object_iterator *php_pqres_iterator_init(zend_class_entry *ce, zval iter = ecalloc(1, sizeof(*iter)); iter->zi.funcs = &php_pqres_iterator_funcs; - iter->zi.data = PHP_PQ_OBJ(object, NULL); - php_pq_object_addref(iter->zi.data); + ZVAL_COPY(&iter->zi.data, object); + + zend_iterator_init(&iter->zi); zfetch_type = zend_read_property(ce, object, ZEND_STRL("fetchType"), 0, &tmp); iter->fetch_type = zval_get_long(zfetch_type); - +#if DBG_GC + fprintf(stderr, "INIT iter(#%d) %p res(#%d) %p\n", iter->zi.std.handle, iter, Z_OBJ_HANDLE_P(object), PHP_PQ_OBJ(object, NULL)); +#endif return (zend_object_iterator *) iter; } +static void php_pqres_internal_iterator_init(zval *zobj) +{ + php_pqres_object_t *obj = PHP_PQ_OBJ(zobj, NULL); + + obj->intern->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(zobj), zobj, 0); + /* prevent cyclic dep */ + Z_DELREF_P(zobj); + obj->intern->iter->zi.funcs->rewind((zend_object_iterator *) obj->intern->iter); + +} + static void php_pqres_iterator_dtor(zend_object_iterator *i) { php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i; - php_pqres_object_t *obj = i->data; - if (!Z_IS_UNDEF(&iter->current_val)) { +#if DBG_GC + fprintf(stderr, "FREE iter(#%d) %p\n", iter->zi.std.handle, iter); +#endif + if (!Z_ISUNDEF(iter->current_val)) { zval_ptr_dtor(&iter->current_val); + ZVAL_UNDEF(&iter->current_val); } - php_pq_object_delref(obj); - efree(iter); + zval_ptr_dtor(&i->data); + zend_iterator_dtor(i); } static ZEND_RESULT_CODE php_pqres_iterator_valid(zend_object_iterator *i) { php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i; - php_pqres_object_t *obj = i->data; + php_pqres_object_t *obj = PHP_PQ_OBJ(&i->data, NULL); switch (PQresultStatus(obj->intern->res)) { case PGRES_TUPLES_OK: @@ -101,7 +118,8 @@ zval *php_pqres_typed_zval(php_pqres_t *res, Oid typ, zval *zv) ZVAL_LONG(&ztype, typ); zend_call_method_with_2_params(zconv, NULL, NULL, "convertfromstring", &rv, zv, &ztype); - ZVAL_ZVAL(&rv, zv, 1, 1); + zval_ptr_dtor(zv); + ZVAL_ZVAL(zv, &rv, 0, 0); return zv; } @@ -203,7 +221,7 @@ zval *php_pqres_typed_zval(php_pqres_t *res, Oid typ, zval *zv) break; } - zend_sring_release(str); + zend_string_release(str); return zv; noconversion: @@ -264,19 +282,19 @@ static inline void php_pqres_add_col_to_zval(php_pqres_t *r, unsigned row, unsig zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch_type, zval *data) { - int c, cols; + int c, cols = PQnfields(res); php_pqres_object_t *res_obj = PQresultInstanceData(res, php_pqconn_event); if (Z_TYPE_P(data) != IS_OBJECT && Z_TYPE_P(data) != IS_ARRAY) { if (PHP_PQRES_FETCH_OBJECT == fetch_type) { object_init(data); } else { - array_init(data); + array_init_size(data, cols); } } if (PQntuples(res) > row) { - for (c = 0, cols = PQnfields(res); c < cols; ++c) { + for (c = 0; c < cols; ++c) { php_pqres_add_col_to_zval(res_obj->intern, row, c, fetch_type, data); } } @@ -284,58 +302,47 @@ zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch return data; } -static void php_pqres_iterator_current(zend_object_iterator *i, zval ***data_ptr TSRMLS_DC) +static zval *php_pqres_iterator_current(zend_object_iterator *i) { php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i; - php_pqres_object_t *obj = i->data; + php_pqres_object_t *obj = PHP_PQ_OBJ(&i->data, NULL); - if (!iter->current_val) { - iter->current_val = php_pqres_row_to_zval(obj->intern->res, iter->index, iter->fetch_type, NULL TSRMLS_CC); + if (Z_ISUNDEF(iter->current_val)) { + php_pqres_row_to_zval(obj->intern->res, iter->index, iter->fetch_type, &iter->current_val); } - *data_ptr = &iter->current_val; + return &iter->current_val; } -#if PHP_VERSION_ID >= 50500 -static void php_pqres_iterator_key(zend_object_iterator *i, zval *key TSRMLS_DC) +static void php_pqres_iterator_key(zend_object_iterator *i, zval *key) { php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i; ZVAL_LONG(key, iter->index); } -#else -static int php_pqres_iterator_key(zend_object_iterator *i, char **key_str, uint *key_len, ulong *key_num TSRMLS_DC) -{ - php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i; - - *key_num = (ulong) iter->index; - - return HASH_KEY_IS_LONG; -} -#endif -static void php_pqres_iterator_invalidate(zend_object_iterator *i TSRMLS_DC) +static void php_pqres_iterator_invalidate(zend_object_iterator *i) { php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i; - if (iter->current_val) { + if (!Z_ISUNDEF(iter->current_val)) { zval_ptr_dtor(&iter->current_val); - iter->current_val = NULL; + ZVAL_UNDEF(&iter->current_val); } } -static void php_pqres_iterator_next(zend_object_iterator *i TSRMLS_DC) +static void php_pqres_iterator_next(zend_object_iterator *i) { php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i; - php_pqres_iterator_invalidate(i TSRMLS_CC); + php_pqres_iterator_invalidate(i); ++iter->index; } -static void php_pqres_iterator_rewind(zend_object_iterator *i TSRMLS_DC) +static void php_pqres_iterator_rewind(zend_object_iterator *i) { php_pqres_iterator_t *iter = (php_pqres_iterator_t *) i; - php_pqres_iterator_invalidate(i TSRMLS_CC); + php_pqres_iterator_invalidate(i); iter->index = 0; } @@ -355,9 +362,9 @@ static zend_object_iterator_funcs php_pqres_iterator_funcs = { php_pqres_iterator_invalidate }; -static int php_pqres_count_elements(zval *object, long *count TSRMLS_DC) +static ZEND_RESULT_CODE php_pqres_count_elements(zval *object, long *count) { - php_pqres_object_t *obj = zend_object_store_get_object(object TSRMLS_CC); + php_pqres_object_t *obj = PHP_PQ_OBJ(object, NULL); if (!obj->intern) { return FAILURE; @@ -369,39 +376,37 @@ static int php_pqres_count_elements(zval *object, long *count TSRMLS_DC) ZEND_RESULT_CODE php_pqres_success(PGresult *res TSRMLS_DC) { - zval *zexc; + zval zexc; switch (PQresultStatus(res)) { case PGRES_BAD_RESPONSE: case PGRES_NONFATAL_ERROR: case PGRES_FATAL_ERROR: - zexc = throw_exce(EX_SQL TSRMLS_CC, "%s", PHP_PQresultErrorMessage(res)); - zend_update_property_string(Z_OBJCE_P(zexc), zexc, ZEND_STRL("sqlstate"), PQresultErrorField(res, PG_DIAG_SQLSTATE) TSRMLS_CC); + ZVAL_OBJ(&zexc, throw_exce(EX_SQL, "%s", PHP_PQresultErrorMessage(res))); + zend_update_property_string(Z_OBJCE(zexc), &zexc, ZEND_STRL("sqlstate"), PQresultErrorField(res, PG_DIAG_SQLSTATE)); return FAILURE; default: return SUCCESS; } } -void php_pqres_init_instance_data(PGresult *res, php_pqconn_object_t *conn_obj, php_pqres_object_t **ptr TSRMLS_DC) +php_pqres_object_t *php_pqres_init_instance_data(PGresult *res, php_pqconn_object_t *conn_obj) { php_pqres_object_t *obj; php_pqres_t *r = ecalloc(1, sizeof(*r)); r->res = res; zend_hash_init(&r->bound, 0, 0, ZVAL_PTR_DTOR, 0); - zend_hash_init(&r->converters, 0, 0, ZVAL_PTR_DTOR, 0); - zend_hash_copy(&r->converters, &conn_obj->intern->converters, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); + zend_hash_init(&r->converters, zend_hash_num_elements(&conn_obj->intern->converters), 0, ZVAL_PTR_DTOR, 0); + zend_hash_copy(&r->converters, &conn_obj->intern->converters, (copy_ctor_func_t) zval_add_ref); r->auto_convert = conn_obj->intern->default_auto_convert; r->default_fetch_type = conn_obj->intern->default_fetch_type; - php_pqres_create_object_ex(php_pqres_class_entry, r, &obj TSRMLS_CC); + obj = php_pqres_create_object_ex(php_pqres_class_entry, r); PQresultSetInstanceData(res, php_pqconn_event, obj); - if (ptr) { - *ptr = obj; - } + return obj; } php_pqres_fetch_t php_pqres_fetch_type(php_pqres_t *res) @@ -409,12 +414,10 @@ php_pqres_fetch_t php_pqres_fetch_type(php_pqres_t *res) return res->iter ? res->iter->fetch_type : res->default_fetch_type; } -static void php_pqres_object_free(void *o TSRMLS_DC) +static void php_pqres_object_free(zend_object *o) { - php_pqres_object_t *obj = o; -#if DBG_GC - fprintf(stderr, "FREE res(#%d) %p\n", obj->zv.handle, obj); -#endif + php_pqres_object_t *obj = PHP_PQ_OBJ(NULL, o); + if (obj->intern) { if (obj->intern->res) { PQresultSetInstanceData(obj->intern->res, php_pqconn_event, NULL); @@ -423,7 +426,8 @@ static void php_pqres_object_free(void *o TSRMLS_DC) } if (obj->intern->iter) { - php_pqres_iterator_dtor((zend_object_iterator *) obj->intern->iter TSRMLS_CC); + ZVAL_NULL(&obj->intern->iter->zi.data); + php_pqres_iterator_dtor((zend_object_iterator *) obj->intern->iter); obj->intern->iter = NULL; } @@ -433,170 +437,117 @@ static void php_pqres_object_free(void *o TSRMLS_DC) efree(obj->intern); obj->intern = NULL; } - zend_object_std_dtor((zend_object *) o TSRMLS_CC); - efree(obj); + php_pq_object_dtor(o); } -zend_object_value php_pqres_create_object_ex(zend_class_entry *ce, php_pqres_t *intern, php_pqres_object_t **ptr TSRMLS_DC) +php_pqres_object_t *php_pqres_create_object_ex(zend_class_entry *ce, php_pqres_t *intern) { - php_pqres_object_t *o; - - o = ecalloc(1, sizeof(*o)); - zend_object_std_init((zend_object *) o, ce TSRMLS_CC); - object_properties_init((zend_object *) o, ce); - o->prophandler = &php_pqres_object_prophandlers; - - if (ptr) { - *ptr = o; - } - - if (intern) { - o->intern = intern; - } - - o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqres_object_free, NULL TSRMLS_CC); - o->zv.handlers = &php_pqres_object_handlers; - - return o->zv; + return php_pq_object_create(ce, intern, sizeof(php_pqres_object_t), + &php_pqres_object_handlers, &php_pqres_object_prophandlers); } -static zend_object_value php_pqres_create_object(zend_class_entry *class_type TSRMLS_DC) +static zend_object *php_pqres_create_object(zend_class_entry *class_type) { - return php_pqres_create_object_ex(class_type, NULL, NULL TSRMLS_CC); + return &php_pqres_create_object_ex(class_type, NULL)->zo; } -static void php_pqres_object_read_status(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqres_object_read_status(zval *object, void *o, zval *return_value) { php_pqres_object_t *obj = o; RETVAL_LONG(PQresultStatus(obj->intern->res)); } -static void php_pqres_object_read_status_message(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqres_object_read_status_message(zval *object, void *o, zval *return_value) { php_pqres_object_t *obj = o; - RETVAL_STRING(PQresStatus(PQresultStatus(obj->intern->res))+sizeof("PGRES"), 1); + RETVAL_STRING(PQresStatus(PQresultStatus(obj->intern->res))+sizeof("PGRES")); } -static void php_pqres_object_read_error_message(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqres_object_read_error_message(zval *object, void *o, zval *return_value) { php_pqres_object_t *obj = o; char *error = PHP_PQresultErrorMessage(obj->intern->res); if (error) { - RETVAL_STRING(error, 1); + RETVAL_STRING(error); } else { RETVAL_NULL(); } } -static void php_pqres_object_read_num_rows(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqres_object_read_num_rows(zval *object, void *o, zval *return_value) { php_pqres_object_t *obj = o; RETVAL_LONG(PQntuples(obj->intern->res)); } -static void php_pqres_object_read_num_cols(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqres_object_read_num_cols(zval *object, void *o, zval *return_value) { php_pqres_object_t *obj = o; RETVAL_LONG(PQnfields(obj->intern->res)); } -static void php_pqres_object_read_affected_rows(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqres_object_read_affected_rows(zval *object, void *o, zval *return_value) { php_pqres_object_t *obj = o; RETVAL_LONG(atoi(PQcmdTuples(obj->intern->res))); } -static void php_pqres_object_read_fetch_type(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqres_object_read_fetch_type(zval *object, void *o, zval *return_value) { php_pqres_object_t *obj = o; RETVAL_LONG(php_pqres_fetch_type(obj->intern)); } -static void php_pqres_object_write_fetch_type(zval *object, void *o, zval *value TSRMLS_DC) +static void php_pqres_object_write_fetch_type(zval *object, void *o, zval *value) { php_pqres_object_t *obj = o; - zval *zfetch_type = value; - - if (Z_TYPE_P(value) != IS_LONG) { - if (Z_REFCOUNT_P(value) > 1) { - zval *tmp; - MAKE_STD_ZVAL(tmp); - ZVAL_ZVAL(tmp, zfetch_type, 1, 0); - convert_to_long(tmp); - zfetch_type = tmp; - } else { - convert_to_long_ex(&zfetch_type); - } - } if (!obj->intern->iter) { - obj->intern->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(object), object, 0 TSRMLS_CC); - obj->intern->iter->zi.funcs->rewind((zend_object_iterator *) obj->intern->iter TSRMLS_CC); - } - obj->intern->iter->fetch_type = Z_LVAL_P(zfetch_type); - - if (zfetch_type != value) { - zval_ptr_dtor(&zfetch_type); + php_pqres_internal_iterator_init(object); } + obj->intern->iter->fetch_type = zval_get_long(value); } -static void php_pqres_object_read_auto_conv(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqres_object_read_auto_conv(zval *object, void *o, zval *return_value) { php_pqres_object_t *obj = o; RETVAL_LONG(obj->intern->auto_convert); } -static void php_pqres_object_write_auto_conv(zval *object, void *o, zval *value TSRMLS_DC) +static void php_pqres_object_write_auto_conv(zval *object, void *o, zval *value) { php_pqres_object_t *obj = o; - zval *zauto_conv = value; - - if (Z_TYPE_P(value) != IS_LONG) { - if (Z_REFCOUNT_P(value) > 1) { - zval *tmp; - MAKE_STD_ZVAL(tmp); - ZVAL_ZVAL(tmp, zauto_conv, 1, 0); - convert_to_long(tmp); - zauto_conv = tmp; - } else { - convert_to_long_ex(&zauto_conv); - } - } - obj->intern->auto_convert = Z_LVAL_P(zauto_conv); - - if (zauto_conv != value) { - zval_ptr_dtor(&zauto_conv); - } + obj->intern->auto_convert = zval_get_long(value); } -static ZEND_RESULT_CODE php_pqres_iteration(zval *this_ptr, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type, zval ***row TSRMLS_DC) +static ZEND_RESULT_CODE php_pqres_iteration(zval *zobj, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type, zval *row TSRMLS_DC) { ZEND_RESULT_CODE rv; php_pqres_fetch_t orig_fetch; if (!obj) { - obj = zend_object_store_get_object(getThis() TSRMLS_CC); + obj = PHP_PQ_OBJ(zobj, NULL); } if (obj->intern->iter) { - obj->intern->iter->zi.funcs->move_forward((zend_object_iterator *) obj->intern->iter TSRMLS_CC); + obj->intern->iter->zi.funcs->move_forward((zend_object_iterator *) obj->intern->iter); } else { - obj->intern->iter = (php_pqres_iterator_t *) php_pqres_iterator_init(Z_OBJCE_P(getThis()), getThis(), 0 TSRMLS_CC); - obj->intern->iter->zi.funcs->rewind((zend_object_iterator *) obj->intern->iter TSRMLS_CC); + php_pqres_internal_iterator_init(zobj); } orig_fetch = obj->intern->iter->fetch_type; obj->intern->iter->fetch_type = fetch_type; - if (SUCCESS == (rv = obj->intern->iter->zi.funcs->valid((zend_object_iterator *) obj->intern->iter TSRMLS_CC))) { - obj->intern->iter->zi.funcs->get_current_data((zend_object_iterator *) obj->intern->iter, row TSRMLS_CC); + if (SUCCESS == (rv = obj->intern->iter->zi.funcs->valid((zend_object_iterator *) obj->intern->iter))) { + zval *tmp = obj->intern->iter->zi.funcs->get_current_data((zend_object_iterator *) obj->intern->iter); + ZVAL_COPY_VALUE(row, tmp); } obj->intern->iter->fetch_type = orig_fetch; @@ -608,7 +559,7 @@ typedef struct php_pqres_col { int num; } php_pqres_col_t; -static ZEND_RESULT_CODE column_nn(php_pqres_object_t *obj, zval *zcol, php_pqres_col_t *col TSRMLS_DC) +static ZEND_RESULT_CODE column_nn(php_pqres_object_t *obj, zval *zcol, php_pqres_col_t *col) { long index = -1; char *name = NULL; @@ -646,11 +597,11 @@ static ZEND_RESULT_CODE column_nn(php_pqres_object_t *obj, zval *zcol, php_pqres } if (!col->name) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to find column at index %ld", index); + php_error_docref(NULL, E_WARNING, "Failed to find column at index %ld", index); return FAILURE; } if (col->num == -1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to find column with name '%s'", name); + php_error_docref(NULL, E_WARNING, "Failed to find column with name '%s'", name); return FAILURE; } return SUCCESS; @@ -665,28 +616,28 @@ static PHP_METHOD(pqres, bind) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z", &zcol, &zref); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "z/z", &zcol, &zref); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized"); } else { php_pqres_col_t col; - if (SUCCESS != column_nn(obj, zcol, &col TSRMLS_CC)) { + if (SUCCESS != column_nn(obj, zcol, &col)) { RETVAL_FALSE; } else { - Z_ADDREF_P(zref); + Z_TRY_ADDREF_P(zref); - if (SUCCESS != zend_hash_index_update(&obj->intern->bound, col.num, (void *) &zref, sizeof(zval *), NULL)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to bind column %s@%d", col.name, col.num); + if (!zend_hash_index_update(&obj->intern->bound, col.num, zref)) { + php_error_docref(NULL, E_WARNING, "Failed to bind column %s@%d", col.name, col.num); RETVAL_FALSE; } else { - zend_hash_sort(&obj->intern->bound, zend_qsort, php_pq_compare_index, 0 TSRMLS_CC); + zend_hash_sort(&obj->intern->bound, php_pq_compare_index, 0); RETVAL_TRUE; } } @@ -694,23 +645,20 @@ static PHP_METHOD(pqres, bind) { } } -static int apply_bound(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key) +static int apply_bound(zval *zbound, int argc, va_list argv, zend_hash_key *key) { - zval **zvalue, **zbound = p; - zval **zrow = va_arg(argv, zval **); + zval *zvalue; + zval *zrow = va_arg(argv, zval *); ZEND_RESULT_CODE *rv = va_arg(argv, ZEND_RESULT_CODE *); - if (SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(zrow), key->h, (void *) &zvalue)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to find column ad index %lu", key->h); + if (!(zvalue = zend_hash_index_find(Z_ARRVAL_P(zrow), key->h))) { + php_error_docref(NULL, E_WARNING, "Failed to find column ad index %lu", key->h); *rv = FAILURE; return ZEND_HASH_APPLY_STOP; } else { - zval_dtor(*zbound); - ZVAL_COPY_VALUE(*zbound, *zvalue); - ZVAL_NULL(*zvalue); - zval_ptr_dtor(zvalue); - Z_ADDREF_P(*zbound); - *zvalue = *zbound; + ZVAL_DEREF(zbound); + zval_dtor(zbound); + ZVAL_COPY(zbound, zvalue); *rv = SUCCESS; return ZEND_HASH_APPLY_KEEP; } @@ -722,29 +670,27 @@ static PHP_METHOD(pqres, fetchBound) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized"); } else { - zval **row = NULL; + zval row; - if (SUCCESS == php_pqres_iteration(getThis(), obj, PHP_PQRES_FETCH_ARRAY, &row TSRMLS_CC) && row) { - zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC); - zend_hash_apply_with_arguments(&obj->intern->bound TSRMLS_CC, apply_bound, 2, row, &rv); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh); + if (SUCCESS == php_pqres_iteration(getThis(), obj, PHP_PQRES_FETCH_ARRAY, &row)) { + zend_hash_apply_with_arguments(&obj->intern->bound, apply_bound, 2, &row, &rv); - if (SUCCESS != rv) { - zval_ptr_dtor(row); - } else { - RETVAL_ZVAL(*row, 1, 0); + if (SUCCESS == rv) { + RETVAL_ZVAL(&row, 1, 0); } } + zend_restore_error_handling(&zeh); } } } @@ -754,49 +700,47 @@ ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_row, 0, 0, 0) ZEND_END_ARG_INFO(); static PHP_METHOD(pqres, fetchRow) { zend_error_handling zeh; - php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); - long fetch_type = -1; + php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); + zend_long fetch_type = -1; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_type); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &fetch_type); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized"); } else { - zval **row = NULL; + zval row; if (fetch_type == -1) { fetch_type = php_pqres_fetch_type(obj->intern); } - zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC); - php_pqres_iteration(getThis(), obj, fetch_type, &row TSRMLS_CC); - zend_restore_error_handling(&zeh TSRMLS_CC); - - if (row) { - RETVAL_ZVAL(*row, 1, 0); + zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh); + if (SUCCESS == php_pqres_iteration(getThis(), obj, fetch_type, &row)) { + RETVAL_ZVAL(&row, 1, 0); } + zend_restore_error_handling(&zeh); } } } -static zval **column_at(zval *row, int col TSRMLS_DC) +static zval *column_at(zval *row, int col) { - zval **data = NULL; + zval *data = NULL; HashTable *ht = HASH_OF(row); int count = zend_hash_num_elements(ht); if (col >= count) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column index %d exceeds column count %d", col, count); + php_error_docref(NULL, E_WARNING, "Column index %d exceeds column count %d", col, count); } else { zend_hash_internal_pointer_reset(ht); while (col-- > 0) { zend_hash_move_forward(ht); } - zend_hash_get_current_data(ht, (void *) &data); + data = zend_hash_get_current_data(ht); } return data; } @@ -810,38 +754,38 @@ static PHP_METHOD(pqres, fetchCol) { zval *zcol = NULL, *zref; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z/!", &zref, &zcol); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "z|z/!", &zref, &zcol); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized"); } else { - zval **row = NULL; + zval row; - zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC); - php_pqres_iteration(getThis(), obj, php_pqres_fetch_type(obj->intern), &row TSRMLS_CC); - if (row) { + zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh); + if (SUCCESS == php_pqres_iteration(getThis(), obj, php_pqres_fetch_type(obj->intern), &row)) { php_pqres_col_t col; - if (SUCCESS != column_nn(obj, zcol, &col TSRMLS_CC)) { + if (SUCCESS != column_nn(obj, zcol, &col)) { RETVAL_FALSE; } else { - zval **zres = column_at(*row, col.num TSRMLS_CC); + zval *zres = column_at(&row, col.num); if (!zres) { RETVAL_FALSE; } else { + ZVAL_DEREF(zref); zval_dtor(zref); - ZVAL_ZVAL(zref, *zres, 1, 0); + ZVAL_ZVAL(zref, zres, 1, 0); RETVAL_TRUE; } } } - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); } } } @@ -854,28 +798,29 @@ static PHP_METHOD(pqres, fetchAllCols) { zval *zcol = NULL; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!", &zcol); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|z!", &zcol); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized"); } else { php_pqres_col_t col; - zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh TSRMLS_CC); - if (SUCCESS == column_nn(obj, zcol, &col TSRMLS_CC)) { + zend_replace_error_handling(EH_THROW, exce(EX_RUNTIME), &zeh); + if (SUCCESS == column_nn(obj, zcol, &col)) { int r, rows = PQntuples(obj->intern->res); + zval tmp; array_init(return_value); for (r = 0; r < rows; ++r) { - add_next_index_zval(return_value, php_pqres_get_col(obj->intern, r, col.num TSRMLS_CC)); + add_next_index_zval(return_value, php_pqres_get_col(obj->intern, r, col.num, &tmp)); } } - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); } } } @@ -886,12 +831,11 @@ struct apply_to_col_arg { ZEND_RESULT_CODE status; }; -static int apply_to_col(void *p, void *a TSRMLS_DC) +static int apply_to_col(zval *c, void *a) { - zval **c = p; struct apply_to_col_arg *arg = a; - if (SUCCESS != column_nn(arg->obj, *c, arg->cols TSRMLS_CC)) { + if (SUCCESS != column_nn(arg->obj, c, arg->cols)) { arg->status = FAILURE; return ZEND_HASH_APPLY_STOP; } else { @@ -901,7 +845,7 @@ static int apply_to_col(void *p, void *a TSRMLS_DC) } } -static php_pqres_col_t *php_pqres_convert_to_cols(php_pqres_object_t *obj, HashTable *ht TSRMLS_DC) +static php_pqres_col_t *php_pqres_convert_to_cols(php_pqres_object_t *obj, HashTable *ht) { struct apply_to_col_arg arg = {NULL}; php_pqres_col_t *tmp; @@ -909,7 +853,7 @@ static php_pqres_col_t *php_pqres_convert_to_cols(php_pqres_object_t *obj, HashT arg.obj = obj; arg.cols = ecalloc(zend_hash_num_elements(ht), sizeof(*tmp)); tmp = arg.cols; - zend_hash_apply_with_argument(ht, apply_to_col, &arg TSRMLS_CC); + zend_hash_apply_with_argument(ht, apply_to_col, &arg); if (SUCCESS == arg.status) { return tmp; @@ -927,18 +871,18 @@ ZEND_END_ARG_INFO(); static PHP_METHOD(pqres, map) { zend_error_handling zeh; zval *zkeys = 0, *zvals = 0; - long fetch_type = -1; + zend_long fetch_type = -1; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z/!z/!l", &zkeys, &zvals, &fetch_type); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|z/!z/!l", &zkeys, &zvals, &fetch_type); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized"); } else { int ks = 0, vs = 0; php_pqres_col_t def = {PQfname(obj->intern->res, 0), 0}, *keys = NULL, *vals = NULL; @@ -947,7 +891,7 @@ static PHP_METHOD(pqres, map) { convert_to_array(zkeys); if ((ks = zend_hash_num_elements(Z_ARRVAL_P(zkeys)))) { - keys = php_pqres_convert_to_cols(obj, Z_ARRVAL_P(zkeys) TSRMLS_CC); + keys = php_pqres_convert_to_cols(obj, Z_ARRVAL_P(zkeys)); } else { ks = 1; keys = &def; @@ -960,7 +904,7 @@ static PHP_METHOD(pqres, map) { convert_to_array(zvals); if ((vs = zend_hash_num_elements(Z_ARRVAL_P(zvals)))) { - vals = php_pqres_convert_to_cols(obj, Z_ARRVAL_P(zvals) TSRMLS_CC); + vals = php_pqres_convert_to_cols(obj, Z_ARRVAL_P(zvals)); } } @@ -970,7 +914,7 @@ static PHP_METHOD(pqres, map) { if (keys) { int rows, r; - zval **cur; + zval *cur; switch (fetch_type) { case PHP_PQRES_FETCH_ARRAY: @@ -983,30 +927,32 @@ static PHP_METHOD(pqres, map) { } for (r = 0, rows = PQntuples(obj->intern->res); r < rows; ++r) { int k, v; + zval *ptr; - cur = &return_value; + cur = return_value; for (k = 0; k < ks; ++k) { char *key = PQgetvalue(obj->intern->res, r, keys[k].num); int len = PQgetlength(obj->intern->res, r, keys[k].num); - if (SUCCESS != zend_symtable_find(HASH_OF(*cur), key, len + 1, (void *) &cur)) { - zval *tmp; + if (!(ptr = zend_symtable_str_find(HASH_OF(cur), key, len))) { + zval tmp; - MAKE_STD_ZVAL(tmp); switch (fetch_type) { case PHP_PQRES_FETCH_ARRAY: case PHP_PQRES_FETCH_ASSOC: - array_init(tmp); + array_init(&tmp); break; case PHP_PQRES_FETCH_OBJECT: - object_init(tmp); + object_init(&tmp); break; } - if (SUCCESS != zend_symtable_update(HASH_OF(*cur), key, len + 1, (void *) &tmp, sizeof(zval *), (void *) &cur)) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to create map"); + if (!(ptr = zend_symtable_str_update(HASH_OF(cur), key, len, &tmp))) { + throw_exce(EX_RUNTIME, "Failed to create map"); goto err; } + cur = ptr; } + cur = ptr; } if (vals && vs) { for (v = 0; v < vs; ++v) { @@ -1015,18 +961,18 @@ static PHP_METHOD(pqres, map) { switch (fetch_type) { case PHP_PQRES_FETCH_ARRAY: - add_index_stringl(*cur, vals[v].num, val, len, 1); + add_index_stringl(cur, vals[v].num, val, len); break; case PHP_PQRES_FETCH_ASSOC: - add_assoc_stringl(*cur, vals[v].name, val, len, 1); + add_assoc_stringl(cur, vals[v].name, val, len); break; case PHP_PQRES_FETCH_OBJECT: - add_property_stringl(*cur, vals[v].name, val, len, 1); + add_property_stringl(cur, vals[v].name, val, len); break; } } } else { - php_pqres_row_to_zval(obj->intern->res, r, fetch_type, cur TSRMLS_CC); + php_pqres_row_to_zval(obj->intern->res, r, fetch_type, cur); } } } @@ -1047,19 +993,21 @@ ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_all, 0, 0, 0) ZEND_END_ARG_INFO(); static PHP_METHOD(pqres, fetchAll) { zend_error_handling zeh; - long fetch_type = -1; + zend_long fetch_type = -1; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &fetch_type); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &fetch_type); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); + if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized"); } else { int r, rows = PQntuples(obj->intern->res); + zval tmp; if (fetch_type == -1) { fetch_type = php_pqres_fetch_type(obj->intern); @@ -1067,7 +1015,8 @@ static PHP_METHOD(pqres, fetchAll) { array_init(return_value); for (r = 0; r < rows; ++r) { - add_next_index_zval(return_value, php_pqres_row_to_zval(obj->intern->res, r, fetch_type, NULL TSRMLS_CC)); + ZVAL_NULL(&tmp); + add_next_index_zval(return_value, php_pqres_row_to_zval(obj->intern->res, r, fetch_type, &tmp)); } } } @@ -1079,15 +1028,15 @@ static PHP_METHOD(pqres, count) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { long count; - if (SUCCESS != php_pqres_count_elements(getThis(), &count TSRMLS_CC)) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized"); + if (SUCCESS != php_pqres_count_elements(getThis(), &count)) { + throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized"); } else { RETVAL_LONG(count); } @@ -1100,15 +1049,15 @@ static PHP_METHOD(pqres, desc) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqres_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqres_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Result not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Result not initialized"); } else { int p, params; @@ -1145,89 +1094,90 @@ PHP_MINIT_FUNCTION(pqres) php_pq_object_prophandler_t ph = {0}; INIT_NS_CLASS_ENTRY(ce, "pq", "Result", php_pqres_methods); - php_pqres_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC); + php_pqres_class_entry = zend_register_internal_class_ex(&ce, NULL); php_pqres_class_entry->create_object = php_pqres_create_object; - php_pqres_class_entry->iterator_funcs.funcs = &php_pqres_iterator_funcs; php_pqres_class_entry->get_iterator = php_pqres_iterator_init; - zend_class_implements(php_pqres_class_entry TSRMLS_CC, 2, zend_ce_traversable, spl_ce_Countable); + zend_class_implements(php_pqres_class_entry, 2, zend_ce_traversable, spl_ce_Countable); memcpy(&php_pqres_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + php_pqres_object_handlers.offset = XtOffsetOf(php_pqres_object_t, zo); + php_pqres_object_handlers.free_obj = php_pqres_object_free; php_pqres_object_handlers.read_property = php_pq_object_read_prop; php_pqres_object_handlers.write_property = php_pq_object_write_prop; php_pqres_object_handlers.clone_obj = NULL; php_pqres_object_handlers.get_property_ptr_ptr = NULL; - php_pqres_object_handlers.get_gc = NULL; + php_pqres_object_handlers.get_gc = php_pq_object_get_gc; php_pqres_object_handlers.get_debug_info = php_pq_object_debug_info; php_pqres_object_handlers.get_properties = php_pq_object_properties; php_pqres_object_handlers.count_elements = php_pqres_count_elements; - zend_hash_init(&php_pqres_object_prophandlers, 8, NULL, NULL, 1); + zend_hash_init(&php_pqres_object_prophandlers, 8, NULL, php_pq_object_prophandler_dtor, 1); - zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("status"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("status"), ZEND_ACC_PUBLIC); ph.read = php_pqres_object_read_status; - zend_hash_add(&php_pqres_object_prophandlers, "status", sizeof("status"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqres_object_prophandlers, "status", sizeof("status")-1, (void *) &ph, sizeof(ph)); - zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("statusMessage"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("statusMessage"), ZEND_ACC_PUBLIC); ph.read = php_pqres_object_read_status_message; - zend_hash_add(&php_pqres_object_prophandlers, "statusMessage", sizeof("statusMessage"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqres_object_prophandlers, "statusMessage", sizeof("statusMessage")-1, (void *) &ph, sizeof(ph)); - zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(php_pqres_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC); ph.read = php_pqres_object_read_error_message; - zend_hash_add(&php_pqres_object_prophandlers, "errorMessage", sizeof("errorMessage"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqres_object_prophandlers, "errorMessage", sizeof("errorMessage")-1, (void *) &ph, sizeof(ph)); - zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numRows"), 0, ZEND_ACC_PUBLIC); ph.read = php_pqres_object_read_num_rows; - zend_hash_add(&php_pqres_object_prophandlers, "numRows", sizeof("numRows"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqres_object_prophandlers, "numRows", sizeof("numRows")-1, (void *) &ph, sizeof(ph)); - zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numCols"), 0, ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("numCols"), 0, ZEND_ACC_PUBLIC); ph.read = php_pqres_object_read_num_cols; - zend_hash_add(&php_pqres_object_prophandlers, "numCols", sizeof("numCols"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqres_object_prophandlers, "numCols", sizeof("numCols")-1, (void *) &ph, sizeof(ph)); - zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("affectedRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("affectedRows"), 0, ZEND_ACC_PUBLIC); ph.read = php_pqres_object_read_affected_rows; - zend_hash_add(&php_pqres_object_prophandlers, "affectedRows", sizeof("affectedRows"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqres_object_prophandlers, "affectedRows", sizeof("affectedRows")-1, (void *) &ph, sizeof(ph)); - zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("fetchType"), PHP_PQRES_FETCH_ARRAY, ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("fetchType"), PHP_PQRES_FETCH_ARRAY, ZEND_ACC_PUBLIC); ph.read = php_pqres_object_read_fetch_type; ph.write = php_pqres_object_write_fetch_type; - zend_hash_add(&php_pqres_object_prophandlers, "fetchType", sizeof("fetchType"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqres_object_prophandlers, "fetchType", sizeof("fetchType")-1, (void *) &ph, sizeof(ph)); ph.write = NULL; - zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("autoConvert"), PHP_PQRES_CONV_ALL, ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_long(php_pqres_class_entry, ZEND_STRL("autoConvert"), PHP_PQRES_CONV_ALL, ZEND_ACC_PUBLIC); ph.read = php_pqres_object_read_auto_conv; ph.write = php_pqres_object_write_auto_conv; - zend_hash_add(&php_pqres_object_prophandlers, "autoConvert", sizeof("autoConvert"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqres_object_prophandlers, "autoConvert", sizeof("autoConvert")-1, (void *) &ph, sizeof(ph)); ph.write = NULL; - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("EMPTY_QUERY"), PGRES_EMPTY_QUERY TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COMMAND_OK"), PGRES_COMMAND_OK TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("TUPLES_OK"), PGRES_TUPLES_OK TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_OUT"), PGRES_COPY_OUT TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_IN"), PGRES_COPY_IN TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("BAD_RESPONSE"), PGRES_BAD_RESPONSE TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("NONFATAL_ERROR"), PGRES_NONFATAL_ERROR TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FATAL_ERROR"), PGRES_FATAL_ERROR TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("EMPTY_QUERY"), PGRES_EMPTY_QUERY); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COMMAND_OK"), PGRES_COMMAND_OK); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("TUPLES_OK"), PGRES_TUPLES_OK); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_OUT"), PGRES_COPY_OUT); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_IN"), PGRES_COPY_IN); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("BAD_RESPONSE"), PGRES_BAD_RESPONSE); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("NONFATAL_ERROR"), PGRES_NONFATAL_ERROR); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FATAL_ERROR"), PGRES_FATAL_ERROR); #ifdef HAVE_PGRES_COPY_BOTH - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_BOTH"), PGRES_COPY_BOTH TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("COPY_BOTH"), PGRES_COPY_BOTH); #endif #ifdef HAVE_PGRES_SINGLE_TUPLE - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("SINGLE_TUPLE"), PGRES_SINGLE_TUPLE TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("SINGLE_TUPLE"), PGRES_SINGLE_TUPLE); #endif - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ARRAY"), PHP_PQRES_FETCH_ARRAY TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ASSOC"), PHP_PQRES_FETCH_ASSOC TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_OBJECT"), PHP_PQRES_FETCH_OBJECT TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ARRAY"), PHP_PQRES_FETCH_ARRAY); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_ASSOC"), PHP_PQRES_FETCH_ASSOC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("FETCH_OBJECT"), PHP_PQRES_FETCH_OBJECT); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_BOOL"), PHP_PQRES_CONV_BOOL TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_INT"), PHP_PQRES_CONV_INT TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_FLOAT"), PHP_PQRES_CONV_FLOAT TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_SCALAR"), PHP_PQRES_CONV_SCALAR TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ARRAY"), PHP_PQRES_CONV_ARRAY TSRMLS_CC); - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_DATETIME"), PHP_PQRES_CONV_DATETIME TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_BOOL"), PHP_PQRES_CONV_BOOL); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_INT"), PHP_PQRES_CONV_INT); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_FLOAT"), PHP_PQRES_CONV_FLOAT); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_SCALAR"), PHP_PQRES_CONV_SCALAR); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ARRAY"), PHP_PQRES_CONV_ARRAY); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_DATETIME"), PHP_PQRES_CONV_DATETIME); #if PHP_PQ_HAVE_PHP_JSON_H - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_JSON"), PHP_PQRES_CONV_JSON TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_JSON"), PHP_PQRES_CONV_JSON); #endif - zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ALL"), PHP_PQRES_CONV_ALL TSRMLS_CC); + zend_declare_class_constant_long(php_pqres_class_entry, ZEND_STRL("CONV_ALL"), PHP_PQRES_CONV_ALL); return SUCCESS; } diff --git a/src/php_pqres.h b/src/php_pqres.h index e0ed25e..acc03cc 100644 --- a/src/php_pqres.h +++ b/src/php_pqres.h @@ -48,14 +48,12 @@ typedef struct php_pqres { } php_pqres_t; typedef struct php_pqres_object { - php_pqres_t *intern; - HashTable *prophandler; - zend_object zo; + PHP_PQ_OBJ_DECL(php_pqres_t *) } php_pqres_object_t; extern ZEND_RESULT_CODE php_pqres_success(PGresult *res); -extern void php_pqres_init_instance_data(PGresult *res, php_pqconn_object_t *obj, php_pqres_object_t **ptr); -extern zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch_type, zval **data_ptr); +extern php_pqres_object_t *php_pqres_init_instance_data(PGresult *res, php_pqconn_object_t *obj); +extern zval *php_pqres_row_to_zval(PGresult *res, unsigned row, php_pqres_fetch_t fetch_type, zval *data); extern zval *php_pqres_typed_zval(php_pqres_t *res, Oid typ, zval *zv); extern php_pqres_fetch_t php_pqres_fetch_type(php_pqres_t *res); diff --git a/src/php_pqstm.c b/src/php_pqstm.c index 6d61a19..dff5375 100644 --- a/src/php_pqstm.c +++ b/src/php_pqstm.c @@ -15,7 +15,7 @@ #endif #include -#include +#include #include "php_pq.h" #include "php_pq_misc.h" @@ -29,7 +29,7 @@ zend_class_entry *php_pqstm_class_entry; static zend_object_handlers php_pqstm_object_handlers; static HashTable php_pqstm_object_prophandlers; -static void php_pqstm_deallocate(php_pqstm_object_t *obj, zend_bool async, zend_bool silent TSRMLS_DC) +static void php_pqstm_deallocate(php_pqstm_object_t *obj, zend_bool async, zend_bool silent) { if (obj->intern->allocated) { char *quoted_name = PQescapeIdentifier(obj->intern->conn->intern->conn, obj->intern->name, strlen(obj->intern->name)); @@ -42,19 +42,19 @@ static void php_pqstm_deallocate(php_pqstm_object_t *obj, zend_bool async, zend_ smart_str_0(&cmd); if (async) { - if (PQsendQuery(obj->intern->conn->intern->conn, cmd.c)) { + if (PQsendQuery(obj->intern->conn->intern->conn, smart_str_v(&cmd))) { obj->intern->conn->intern->poller = PQconsumeInput; - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } else if (!silent) { - throw_exce(EX_IO TSRMLS_CC, "Failed to deallocate statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_IO, "Failed to deallocate statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } } else { PGresult *res; - if ((res = PQexec(obj->intern->conn->intern->conn, cmd.c))) { + if ((res = PQexec(obj->intern->conn->intern->conn, smart_str_v(&cmd)))) { PHP_PQclear(res); } else if (!silent) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to deallocate statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to deallocate statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } } @@ -66,17 +66,17 @@ static void php_pqstm_deallocate(php_pqstm_object_t *obj, zend_bool async, zend_ } } -static void php_pqstm_object_free(void *o TSRMLS_DC) +static void php_pqstm_object_free(zend_object *o) { - php_pqstm_object_t *obj = o; + php_pqstm_object_t *obj = PHP_PQ_OBJ(NULL, o); #if DBG_GC - fprintf(stderr, "FREE stm(#%d) %p (conn(#%d): %p)\n", obj->zv.handle, obj, obj->intern->conn->zv.handle, obj->intern->conn); + fprintf(stderr, "FREE stm(#%d) %p (conn(#%d): %p)\n", obj->zo.handle, obj, obj->intern->conn->zo.handle, obj->intern->conn); #endif if (obj->intern) { if (obj->intern->conn->intern) { php_pq_callback_dtor(&obj->intern->conn->intern->onevent); - php_pqstm_deallocate(obj, 0, 1 TSRMLS_CC); - php_pq_object_delref(obj->intern->conn TSRMLS_CC); + php_pqstm_deallocate(obj, 0, 1); + php_pq_object_delref(obj->intern->conn); } efree(obj->intern->name); efree(obj->intern->query); @@ -87,60 +87,51 @@ static void php_pqstm_object_free(void *o TSRMLS_DC) efree(obj->intern); obj->intern = NULL; } - zend_object_std_dtor((zend_object *) o TSRMLS_CC); - efree(obj); + php_pq_object_dtor(o); } -zend_object_value php_pqstm_create_object_ex(zend_class_entry *ce, php_pqstm_t *intern, php_pqstm_object_t **ptr TSRMLS_DC) +php_pqstm_object_t *php_pqstm_create_object_ex(zend_class_entry *ce, php_pqstm_t *intern) { - php_pqstm_object_t *o; - - o = ecalloc(1, sizeof(*o)); - zend_object_std_init((zend_object *) o, ce TSRMLS_CC); - object_properties_init((zend_object *) o, ce); - o->prophandler = &php_pqstm_object_prophandlers; - - if (ptr) { - *ptr = o; - } - - if (intern) { - o->intern = intern; - } - - o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqstm_object_free, NULL TSRMLS_CC); - o->zv.handlers = &php_pqstm_object_handlers; + return php_pq_object_create(ce, intern, sizeof(php_pqstm_object_t), + &php_pqstm_object_handlers, &php_pqstm_object_prophandlers); +} - return o->zv; +static zend_object *php_pqstm_create_object(zend_class_entry *class_type) +{ + return &php_pqstm_create_object_ex(class_type, NULL)->zo; } -static zend_object_value php_pqstm_create_object(zend_class_entry *class_type TSRMLS_DC) +static void php_pqstm_object_read_name(zval *object, void *o, zval *return_value) { - return php_pqstm_create_object_ex(class_type, NULL, NULL TSRMLS_CC); + php_pqstm_object_t *obj = o; + + RETVAL_STRING(obj->intern->name); } -static void php_pqstm_object_read_name(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqstm_object_read_connection(zval *object, void *o, zval *return_value) { php_pqstm_object_t *obj = o; - RETVAL_STRING(obj->intern->name, 1); + php_pq_object_to_zval(obj->intern->conn, return_value); } -static void php_pqstm_object_read_connection(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqstm_object_gc_connection(zval *object, void *o, zval *return_value) { php_pqstm_object_t *obj = o; + zval zconn; - php_pq_object_to_zval(obj->intern->conn, &return_value TSRMLS_CC); + php_pq_object_to_zval_no_addref(obj->intern->conn, &zconn); + add_next_index_zval(return_value, &zconn); } -static void php_pqstm_object_read_query(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqstm_object_read_query(zval *object, void *o, zval *return_value) { php_pqstm_object_t *obj = o; - RETVAL_STRING(obj->intern->query, 1); + RETVAL_STRING(obj->intern->query); } -static void php_pqstm_object_read_types(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqstm_object_read_types(zval *object, void *o, zval *return_value) { int i; php_pqstm_object_t *obj = o; @@ -151,11 +142,11 @@ static void php_pqstm_object_read_types(zval *object, void *o, zval *return_valu } } -php_pqstm_t *php_pqstm_init(php_pqconn_object_t *conn, const char *name, const char *query, php_pq_params_t *params TSRMLS_DC) +php_pqstm_t *php_pqstm_init(php_pqconn_object_t *conn, const char *name, const char *query, php_pq_params_t *params) { php_pqstm_t *stm = ecalloc(1, sizeof(*stm)); - php_pq_object_addref(conn TSRMLS_CC); + php_pq_object_addref(conn); stm->conn = conn; stm->name = estrdup(name); stm->params = params; @@ -178,33 +169,33 @@ static PHP_METHOD(pqstm, __construct) { zend_error_handling zeh; zval *zconn, *ztypes = NULL; char *name_str, *query_str; - int name_len, *query_len; + size_t name_len, *query_len; zend_bool async = 0; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oss|a/!b", &zconn, php_pqconn_class_entry, &name_str, &name_len, &query_str, &query_len, &ztypes, &async); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "Oss|a/!b", &zconn, php_pqconn_class_entry, &name_str, &name_len, &query_str, &query_len, &ztypes, &async); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); - php_pqconn_object_t *conn_obj = zend_object_store_get_object(zconn TSRMLS_CC); + php_pqstm_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); + php_pqconn_object_t *conn_obj = PHP_PQ_OBJ(zconn, NULL); if (obj->intern) { - throw_exce(EX_BAD_METHODCALL TSRMLS_CC, "pq\\Statement already initialized"); + throw_exce(EX_BAD_METHODCALL, "pq\\Statement already initialized"); } else if (!conn_obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized"); } else { - php_pq_params_t *params = php_pq_params_init(&conn_obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, NULL TSRMLS_CC); + php_pq_params_t *params = php_pq_params_init(&conn_obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, NULL); if (async) { - rv = php_pqconn_prepare_async(zconn, conn_obj, name_str, query_str, params TSRMLS_CC); + rv = php_pqconn_prepare_async(zconn, conn_obj, name_str, query_str, params); } else { - rv = php_pqconn_prepare(zconn, conn_obj, name_str, query_str, params TSRMLS_CC); + rv = php_pqconn_prepare(zconn, conn_obj, name_str, query_str, params); } if (SUCCESS == rv) { - obj->intern = php_pqstm_init(conn_obj, name_str, query_str, params TSRMLS_CC); + obj->intern = php_pqstm_init(conn_obj, name_str, query_str, params); } } } @@ -214,27 +205,26 @@ ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_bind, 0, 0, 2) ZEND_ARG_INFO(1, param_ref) ZEND_END_ARG_INFO(); static PHP_METHOD(pqstm, bind) { - long param_no; - zval **param_ref; + zend_long param_no; + zval *param_ref; zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lZ", ¶m_no, ¶m_ref); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "lz", ¶m_no, ¶m_ref); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqstm_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Statement not initialized"); } else if (!obj->intern->allocated) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement has been deallocated"); + throw_exce(EX_UNINITIALIZED, "pq\\Statement has been deallocated"); } else { - SEPARATE_ZVAL_TO_MAKE_IS_REF(param_ref); - Z_ADDREF_PP(param_ref); - zend_hash_index_update(&obj->intern->bound, param_no, (void *) param_ref, sizeof(zval *), NULL); - zend_hash_sort(&obj->intern->bound, zend_qsort, php_pq_compare_index, 0 TSRMLS_CC); + Z_ADDREF_P(param_ref); + zend_hash_index_update(&obj->intern->bound, param_no, param_ref); + zend_hash_sort(&obj->intern->bound, php_pq_compare_index, 0); } } } @@ -247,17 +237,17 @@ static PHP_METHOD(pqstm, exec) { zval *zparams = NULL; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &zparams); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|a/!", &zparams); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqstm_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Statement not initialized"); } else if (!obj->intern->allocated) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement has been deallocated"); + throw_exce(EX_UNINITIALIZED, "pq\\Statement has been deallocated"); } else { PGresult *res; @@ -266,10 +256,10 @@ static PHP_METHOD(pqstm, exec) { php_pq_params_set_params(obj->intern->params, NULL); if (!res) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to execute statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); - } else if (SUCCESS == php_pqres_success(res TSRMLS_CC)) { - php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC); - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + throw_exce(EX_RUNTIME, "Failed to execute statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + } else if (SUCCESS == php_pqres_success(res)) { + php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), return_value); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -285,17 +275,17 @@ static PHP_METHOD(pqstm, execAsync) { php_pq_callback_t resolver = {{0}}; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!f", &zparams, &resolver.fci, &resolver.fcc); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|a/!f", &zparams, &resolver.fci, &resolver.fcc); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqstm_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Statement not initialized"); } else if (!obj->intern->allocated) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement has been deallocated"); + throw_exce(EX_UNINITIALIZED, "pq\\Statement has been deallocated"); } else { int rc; @@ -304,17 +294,17 @@ static PHP_METHOD(pqstm, execAsync) { php_pq_params_set_params(obj->intern->params, NULL); if (!rc) { - throw_exce(EX_IO TSRMLS_CC, "Failed to execute statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_IO, "Failed to execute statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); #if HAVE_PQSETSINGLEROWMODE } else if (obj->intern->conn->intern->unbuffered && !PQsetSingleRowMode(obj->intern->conn->intern->conn)) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to enable unbuffered mode (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); #endif } else { - php_pq_callback_recurse(&obj->intern->conn->intern->onevent, &resolver TSRMLS_CC); + php_pq_callback_recurse(&obj->intern->conn->intern->onevent, &resolver); obj->intern->conn->intern->poller = PQconsumeInput; } - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -325,24 +315,24 @@ static PHP_METHOD(pqstm, desc) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqstm_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Statement not initialized"); } else if (!obj->intern->allocated) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement has been deallocated"); + throw_exce(EX_UNINITIALIZED, "pq\\Statement has been deallocated"); } else { PGresult *res = PQdescribePrepared(obj->intern->conn->intern->conn, obj->intern->name); if (!res) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to describe statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to describe statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { - if (SUCCESS == php_pqres_success(res TSRMLS_CC)) { + if (SUCCESS == php_pqres_success(res)) { int p, params; array_init(return_value); @@ -351,7 +341,7 @@ static PHP_METHOD(pqstm, desc) { } } PHP_PQclear(res); - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -365,23 +355,23 @@ static PHP_METHOD(pqstm, descAsync) { php_pq_callback_t resolver = {{0}}; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f", &resolver.fci, &resolver.fcc); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "f", &resolver.fci, &resolver.fcc); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqstm_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Statement not initialized"); } else if (!obj->intern->allocated) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement has been deallocated"); + throw_exce(EX_UNINITIALIZED, "pq\\Statement has been deallocated"); } else if (!PQsendDescribePrepared(obj->intern->conn->intern->conn, obj->intern->name)) { - throw_exce(EX_IO TSRMLS_CC, "Failed to describe statement: %s", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_IO, "Failed to describe statement: %s", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { - php_pq_callback_recurse(&obj->intern->conn->intern->onevent, &resolver TSRMLS_CC); + php_pq_callback_recurse(&obj->intern->conn->intern->onevent, &resolver); obj->intern->conn->intern->poller = PQconsumeInput; - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -391,17 +381,17 @@ static zend_always_inline void php_pqstm_deallocate_handler(INTERNAL_FUNCTION_PA zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (rv == SUCCESS) { - php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqstm_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Statement not initialized"); } else { - php_pqstm_deallocate(obj, async, 0 TSRMLS_CC); + php_pqstm_deallocate(obj, async, 0); } } } @@ -425,20 +415,20 @@ static zend_always_inline void php_pqstm_prepare_handler(INTERNAL_FUNCTION_PARAM zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (rv == SUCCESS) { - php_pqstm_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqstm_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Statement not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Statement not initialized"); } else if (!obj->intern->allocated) { if (async) { - rv = php_pqconn_prepare_async(NULL, obj->intern->conn, obj->intern->name, obj->intern->query, obj->intern->params TSRMLS_CC); + rv = php_pqconn_prepare_async(NULL, obj->intern->conn, obj->intern->name, obj->intern->query, obj->intern->params); } else { - rv = php_pqconn_prepare(NULL, obj->intern->conn, obj->intern->name, obj->intern->query, obj->intern->params TSRMLS_CC); + rv = php_pqconn_prepare(NULL, obj->intern->conn, obj->intern->name, obj->intern->query, obj->intern->params); } if (SUCCESS == rv) { @@ -488,35 +478,39 @@ PHP_MINIT_FUNCTION(pqstm) php_pq_object_prophandler_t ph = {0}; INIT_NS_CLASS_ENTRY(ce, "pq", "Statement", php_pqstm_methods); - php_pqstm_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC); + php_pqstm_class_entry = zend_register_internal_class_ex(&ce, NULL); php_pqstm_class_entry->create_object = php_pqstm_create_object; memcpy(&php_pqstm_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + php_pqstm_object_handlers.offset = XtOffsetOf(php_pqstm_object_t, zo); + php_pqstm_object_handlers.free_obj = php_pqstm_object_free; php_pqstm_object_handlers.read_property = php_pq_object_read_prop; php_pqstm_object_handlers.write_property = php_pq_object_write_prop; php_pqstm_object_handlers.clone_obj = NULL; php_pqstm_object_handlers.get_property_ptr_ptr = NULL; - php_pqstm_object_handlers.get_gc = NULL; + php_pqstm_object_handlers.get_gc = php_pq_object_get_gc; php_pqstm_object_handlers.get_properties = php_pq_object_properties; php_pqstm_object_handlers.get_debug_info = php_pq_object_debug_info; - zend_hash_init(&php_pqstm_object_prophandlers, 2, NULL, NULL, 1); + zend_hash_init(&php_pqstm_object_prophandlers, 4, NULL, php_pq_object_prophandler_dtor, 1); - zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("name"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("name"), ZEND_ACC_PUBLIC); ph.read = php_pqstm_object_read_name; - zend_hash_add(&php_pqstm_object_prophandlers, "name", sizeof("name"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqstm_object_prophandlers, "name", sizeof("name")-1, (void *) &ph, sizeof(ph)); - zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC); ph.read = php_pqstm_object_read_connection; - zend_hash_add(&php_pqstm_object_prophandlers, "connection", sizeof("connection"), (void *) &ph, sizeof(ph), NULL); + ph.gc = php_pqstm_object_gc_connection; + zend_hash_str_add_mem(&php_pqstm_object_prophandlers, "connection", sizeof("connection")-1, (void *) &ph, sizeof(ph)); + ph.gc = NULL; - zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("query"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("query"), ZEND_ACC_PUBLIC); ph.read = php_pqstm_object_read_query; - zend_hash_add(&php_pqstm_object_prophandlers, "query", sizeof("query"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqstm_object_prophandlers, "query", sizeof("query")-1, (void *) &ph, sizeof(ph)); - zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("types"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(php_pqstm_class_entry, ZEND_STRL("types"), ZEND_ACC_PUBLIC); ph.read = php_pqstm_object_read_types; - zend_hash_add(&php_pqstm_object_prophandlers, "types", sizeof("types"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqstm_object_prophandlers, "types", sizeof("types")-1, (void *) &ph, sizeof(ph)); return SUCCESS; } diff --git a/src/php_pqstm.h b/src/php_pqstm.h index 61afa42..79e6aa7 100644 --- a/src/php_pqstm.h +++ b/src/php_pqstm.h @@ -26,9 +26,7 @@ typedef struct php_pqstm { } php_pqstm_t; typedef struct php_pqstm_object { - php_pqstm_t *intern; - HashTable *prophandler; - zend_object zo; + PHP_PQ_OBJ_DECL(php_pqstm_t *) } php_pqstm_object_t; extern zend_class_entry *php_pqstm_class_entry; diff --git a/src/php_pqtxn.c b/src/php_pqtxn.c index e0574e8..5b12545 100644 --- a/src/php_pqtxn.c +++ b/src/php_pqtxn.c @@ -15,7 +15,7 @@ #endif #include -#include +#include #include #include @@ -47,11 +47,11 @@ const char *php_pq_isolation_level(long *isolation) } } -static void php_pqtxn_object_free(void *o TSRMLS_DC) +static void php_pqtxn_object_free(zend_object *o) { - php_pqtxn_object_t *obj = o; + php_pqtxn_object_t *obj = PHP_PQ_OBJ(NULL, o); #if DBG_GC - fprintf(stderr, "FREE txn(#%d) %p (conn(#%d): %p)\n", obj->zv.handle, obj, obj->intern->conn->zv.handle, obj->intern->conn); + fprintf(stderr, "FREE txn(#%d) %p (conn(#%d): %p)\n", obj->zo.handle, obj, obj->intern->conn->zo.handle, obj->intern->conn); #endif if (obj->intern) { if (obj->intern->open && obj->intern->conn->intern) { @@ -61,90 +61,68 @@ static void php_pqtxn_object_free(void *o TSRMLS_DC) PHP_PQclear(res); } } - php_pq_object_delref(obj->intern->conn TSRMLS_CC); + php_pq_object_delref(obj->intern->conn); efree(obj->intern); obj->intern = NULL; } - zend_object_std_dtor((zend_object *) o TSRMLS_CC); - efree(obj); + php_pq_object_dtor(o); } -zend_object_value php_pqtxn_create_object_ex(zend_class_entry *ce, php_pqtxn_t *intern, php_pqtxn_object_t **ptr TSRMLS_DC) +php_pqtxn_object_t *php_pqtxn_create_object_ex(zend_class_entry *ce, php_pqtxn_t *intern) { - php_pqtxn_object_t *o; - - o = ecalloc(1, sizeof(*o)); - zend_object_std_init((zend_object *) o, ce TSRMLS_CC); - object_properties_init((zend_object *) o, ce); - o->prophandler = &php_pqtxn_object_prophandlers; - - if (ptr) { - *ptr = o; - } - - if (intern) { - o->intern = intern; - } - - o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqtxn_object_free, NULL TSRMLS_CC); - o->zv.handlers = &php_pqtxn_object_handlers; + return php_pq_object_create(ce, intern, sizeof(php_pqtxn_object_t), + &php_pqtxn_object_handlers, &php_pqtxn_object_prophandlers); +} - return o->zv; +static zend_object *php_pqtxn_create_object(zend_class_entry *class_type) +{ + return &php_pqtxn_create_object_ex(class_type, NULL)->zo; } -static zend_object_value php_pqtxn_create_object(zend_class_entry *class_type TSRMLS_DC) +static void php_pqtxn_object_read_connection(zval *object, void *o, zval *return_value) { - return php_pqtxn_create_object_ex(class_type, NULL, NULL TSRMLS_CC); + php_pqtxn_object_t *obj = o; + + php_pq_object_to_zval(obj->intern->conn, return_value); } -static void php_pqtxn_object_read_connection(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqtxn_object_gc_connection(zval *object, void *o, zval *return_value) { php_pqtxn_object_t *obj = o; + zval zconn; - php_pq_object_to_zval(obj->intern->conn, &return_value TSRMLS_CC); + php_pq_object_to_zval_no_addref(obj->intern->conn, &zconn); + add_next_index_zval(return_value, &zconn); } -static void php_pqtxn_object_read_isolation(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqtxn_object_read_isolation(zval *object, void *o, zval *return_value) { php_pqtxn_object_t *obj = o; RETVAL_LONG(obj->intern->isolation); } -static void php_pqtxn_object_read_readonly(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqtxn_object_read_readonly(zval *object, void *o, zval *return_value) { php_pqtxn_object_t *obj = o; RETVAL_BOOL(obj->intern->readonly); } -static void php_pqtxn_object_read_deferrable(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqtxn_object_read_deferrable(zval *object, void *o, zval *return_value) { php_pqtxn_object_t *obj = o; RETVAL_BOOL(obj->intern->deferrable); } -static void php_pqtxn_object_write_isolation(zval *object, void *o, zval *value TSRMLS_DC) +static void php_pqtxn_object_write_isolation(zval *object, void *o, zval *value) { php_pqtxn_object_t *obj = o; php_pqtxn_isolation_t orig = obj->intern->isolation; - zval *zisolation = value; PGresult *res; - if (Z_TYPE_P(zisolation) != IS_LONG) { - if (Z_REFCOUNT_P(value) > 1) { - zval *tmp; - MAKE_STD_ZVAL(tmp); - ZVAL_ZVAL(tmp, zisolation, 1, 0); - convert_to_long(tmp); - zisolation = tmp; - } else { - convert_to_long_ex(&zisolation); - } - } - - switch ((obj->intern->isolation = Z_LVAL_P(zisolation))) { + switch ((obj->intern->isolation = zval_get_long(value))) { case PHP_PQTXN_READ_COMMITTED: res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION ISOLATION LEVEL READ COMMITED"); break; @@ -160,17 +138,13 @@ static void php_pqtxn_object_write_isolation(zval *object, void *o, zval *value break; } - if (zisolation != value) { - zval_ptr_dtor(&zisolation); - } - if (res) { - php_pqres_success(res TSRMLS_CC); + php_pqres_success(res); PHP_PQclear(res); } } -static void php_pqtxn_object_write_readonly(zval *object, void *o, zval *value TSRMLS_DC) +static void php_pqtxn_object_write_readonly(zval *object, void *o, zval *value) { php_pqtxn_object_t *obj = o; PGresult *res; @@ -182,12 +156,12 @@ static void php_pqtxn_object_write_readonly(zval *object, void *o, zval *value T } if (res) { - php_pqres_success(res TSRMLS_CC); + php_pqres_success(res); PHP_PQclear(res); } } -static void php_pqtxn_object_write_deferrable(zval *object, void *o, zval *value TSRMLS_DC) +static void php_pqtxn_object_write_deferrable(zval *object, void *o, zval *value) { php_pqtxn_object_t *obj = o; PGresult *res; @@ -199,7 +173,7 @@ static void php_pqtxn_object_write_deferrable(zval *object, void *o, zval *value } if (res) { - php_pqres_success(res TSRMLS_CC); + php_pqres_success(res); PHP_PQclear(res); } } @@ -215,19 +189,19 @@ ZEND_END_ARG_INFO(); static PHP_METHOD(pqtxn, __construct) { zend_error_handling zeh; zval *zconn; - long isolation = PHP_PQTXN_READ_COMMITTED; + zend_long isolation = PHP_PQTXN_READ_COMMITTED; zend_bool async = 0, readonly = 0, deferrable = 0; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|blbb", &zconn, php_pqconn_class_entry, &async, &isolation, &readonly, &deferrable); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "O|blbb", &zconn, php_pqconn_class_entry, &async, &isolation, &readonly, &deferrable); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqconn_object_t *conn_obj = zend_object_store_get_object(zconn TSRMLS_CC); + php_pqconn_object_t *conn_obj = PHP_PQ_OBJ(zconn, NULL); if (!conn_obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized"); } else { switch (ZEND_NUM_ARGS()) { @@ -244,17 +218,17 @@ static PHP_METHOD(pqtxn, __construct) { } if (async) { - rv = php_pqconn_start_transaction_async(zconn, conn_obj, isolation, readonly, deferrable TSRMLS_CC); + rv = php_pqconn_start_transaction_async(zconn, conn_obj, isolation, readonly, deferrable); } else { - rv = php_pqconn_start_transaction(zconn, conn_obj, isolation, readonly, deferrable TSRMLS_CC); + rv = php_pqconn_start_transaction(zconn, conn_obj, isolation, readonly, deferrable); } if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); obj->intern = ecalloc(1, sizeof(*obj->intern)); - php_pq_object_addref(conn_obj TSRMLS_CC); + php_pq_object_addref(conn_obj); obj->intern->conn = conn_obj; obj->intern->open = 1; obj->intern->isolation = isolation; @@ -271,17 +245,17 @@ static PHP_METHOD(pqtxn, savepoint) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else if (!obj->intern->open) { - throw_exce(EX_RUNTIME TSRMLS_CC, "pq\\Transaction already closed"); + throw_exce(EX_RUNTIME, "pq\\Transaction already closed"); } else { PGresult *res; smart_str cmd = {0}; @@ -291,12 +265,12 @@ static PHP_METHOD(pqtxn, savepoint) { smart_str_appends(&cmd, "\""); smart_str_0(&cmd); - res = PQexec(obj->intern->conn->intern->conn, cmd.c); + res = PQexec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); if (!res) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to create %s (%s)", cmd.c, PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to create %s (%s)", smart_str_v(&cmd), PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { - php_pqres_success(res TSRMLS_CC); + php_pqres_success(res); PHP_PQclear(res); } @@ -311,17 +285,17 @@ static PHP_METHOD(pqtxn, savepointAsync) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else if (!obj->intern->open) { - throw_exce(EX_RUNTIME TSRMLS_CC, "pq\\Transaction already closed"); + throw_exce(EX_RUNTIME, "pq\\Transaction already closed"); } else { smart_str cmd = {0}; @@ -330,8 +304,8 @@ static PHP_METHOD(pqtxn, savepointAsync) { smart_str_appends(&cmd, "\""); smart_str_0(&cmd); - if (!PQsendQuery(obj->intern->conn->intern->conn, cmd.c)) { - throw_exce(EX_IO TSRMLS_CC, "Failed to create %s (%s)", cmd.c, PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + if (!PQsendQuery(obj->intern->conn->intern->conn, smart_str_v(&cmd))) { + throw_exce(EX_IO, "Failed to create %s (%s)", smart_str_v(&cmd), PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } smart_str_free(&cmd); @@ -345,22 +319,23 @@ static PHP_METHOD(pqtxn, commit) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transacation not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transacation not initialized"); } else if (!obj->intern->open) { - throw_exce(EX_RUNTIME TSRMLS_CC, "pq\\Transaction already closed"); + throw_exce(EX_RUNTIME, "pq\\Transaction already closed"); } else { PGresult *res; smart_str cmd = {0}; + zend_bool just_release_sp = !!obj->intern->savepoint; - if (!obj->intern->savepoint) { + if (!just_release_sp) { res = PQexec(obj->intern->conn->intern->conn, "COMMIT"); } else { smart_str_appends(&cmd, "RELEASE SAVEPOINT \""); @@ -368,14 +343,14 @@ static PHP_METHOD(pqtxn, commit) { smart_str_appends(&cmd, "\""); smart_str_0(&cmd); - res = PQexec(obj->intern->conn->intern->conn, cmd.c); + res = PQexec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); } if (!res) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to %s (%s)", cmd.c ? cmd.c : "commit transaction", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to %s (%s)", smart_str_l(&cmd) ? smart_str_v(&cmd) : "commit transaction", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { - if (SUCCESS == php_pqres_success(res TSRMLS_CC)) { - if (!cmd.c) { + if (SUCCESS == php_pqres_success(res)) { + if (!just_release_sp) { obj->intern->open = 0; } } @@ -383,7 +358,7 @@ static PHP_METHOD(pqtxn, commit) { } smart_str_free(&cmd); - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -394,22 +369,23 @@ static PHP_METHOD(pqtxn, commitAsync) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else if (!obj->intern->open) { - throw_exce(EX_RUNTIME TSRMLS_CC, "pq\\Transaction already closed"); + throw_exce(EX_RUNTIME, "pq\\Transaction already closed"); } else { int rc; smart_str cmd = {0}; + zend_bool just_release_sp = !!obj->intern->savepoint; - if (!obj->intern->savepoint) { + if (!just_release_sp) { rc = PQsendQuery(obj->intern->conn->intern->conn, "COMMIT"); } else { smart_str_appends(&cmd, "RELEASE SAVEPOINT \""); @@ -417,17 +393,17 @@ static PHP_METHOD(pqtxn, commitAsync) { smart_str_appends(&cmd, "\""); smart_str_0(&cmd); - rc = PQsendQuery(obj->intern->conn->intern->conn, cmd.c); + rc = PQsendQuery(obj->intern->conn->intern->conn, smart_str_v(&cmd)); } if (!rc) { - throw_exce(EX_IO TSRMLS_CC, "Failed to %s (%s)", cmd.c ? cmd.c : "commmit transaction", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_IO, "Failed to %s (%s)", smart_str_l(&cmd) ? smart_str_v(&cmd) : "commmit transaction", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { - if (!cmd.c) { + if (!just_release_sp) { obj->intern->open = 0; } obj->intern->conn->intern->poller = PQconsumeInput; - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } smart_str_free(&cmd); @@ -441,22 +417,23 @@ static PHP_METHOD(pqtxn, rollback) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else if (!obj->intern->open) { - throw_exce(EX_RUNTIME TSRMLS_CC, "pq\\Transaction already closed"); + throw_exce(EX_RUNTIME, "pq\\Transaction already closed"); } else { PGresult *res; smart_str cmd = {0}; + zend_bool just_release_sp = !!obj->intern->savepoint; - if (!obj->intern->savepoint) { + if (!just_release_sp) { res = PQexec(obj->intern->conn->intern->conn, "ROLLBACK"); } else { smart_str_appends(&cmd, "ROLLBACK TO SAVEPOINT \""); @@ -464,14 +441,14 @@ static PHP_METHOD(pqtxn, rollback) { smart_str_appends(&cmd, "\""); smart_str_0(&cmd); - res = PQexec(obj->intern->conn->intern->conn, cmd.c); + res = PQexec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); } if (!res) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to %s (%s)", cmd.c ? cmd.c : "rollback transaction", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to %s (%s)", smart_str_l(&cmd) ? smart_str_v(&cmd) : "rollback transaction", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { - if (SUCCESS == php_pqres_success(res TSRMLS_CC)) { - if (!cmd.c) { + if (SUCCESS == php_pqres_success(res)) { + if (!just_release_sp) { obj->intern->open = 0; } } @@ -479,7 +456,7 @@ static PHP_METHOD(pqtxn, rollback) { } smart_str_free(&cmd); - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -490,22 +467,23 @@ static PHP_METHOD(pqtxn, rollbackAsync) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else if (!obj->intern->open) { - throw_exce(EX_RUNTIME TSRMLS_CC, "pq\\Transaction already closed"); + throw_exce(EX_RUNTIME, "pq\\Transaction already closed"); } else { int rc; smart_str cmd = {0}; + zend_bool just_release_sp = !!obj->intern->savepoint; - if (!obj->intern->savepoint) { + if (!just_release_sp) { rc = PQsendQuery(obj->intern->conn->intern->conn, "ROLLBACK"); } else { smart_str_appends(&cmd, "ROLLBACK TO SAVEPOINT \""); @@ -513,20 +491,20 @@ static PHP_METHOD(pqtxn, rollbackAsync) { smart_str_appends(&cmd, "\""); smart_str_0(&cmd); - rc = PQsendQuery(obj->intern->conn->intern->conn, cmd.c); + rc = PQsendQuery(obj->intern->conn->intern->conn, smart_str_v(&cmd)); } if (!rc) { - throw_exce(EX_IO TSRMLS_CC, "Failed to %s (%s)", cmd.c ? cmd.c : "rollback transaction", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_IO, "Failed to %s (%s)", smart_str_l(&cmd) ? smart_str_v(&cmd) : "rollback transaction", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { - if (!cmd.c) { + if (!just_release_sp) { obj->intern->open = 0; } obj->intern->conn->intern->poller = PQconsumeInput; } smart_str_free(&cmd); - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -537,29 +515,29 @@ static PHP_METHOD(pqtxn, exportSnapshot) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else { PGresult *res = PQexec(obj->intern->conn->intern->conn, "SELECT pg_export_snapshot()"); if (!res) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to export transaction snapshot (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to export transaction snapshot (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { - if (SUCCESS == php_pqres_success(res TSRMLS_CC)) { - RETVAL_STRING(PQgetvalue(res, 0, 0), 1); + if (SUCCESS == php_pqres_success(res)) { + RETVAL_STRING(PQgetvalue(res, 0, 0)); } PHP_PQclear(res); } - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -570,20 +548,20 @@ static PHP_METHOD(pqtxn, exportSnapshotAsync) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); rv = zend_parse_parameters_none(); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else if (!PQsendQuery(obj->intern->conn->intern->conn, "SELECT pg_export_snapshot()")) { - throw_exce(EX_IO TSRMLS_CC, "Failed to export transaction snapshot (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_IO, "Failed to export transaction snapshot (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { obj->intern->conn->intern->poller = PQconsumeInput; - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -594,25 +572,25 @@ ZEND_END_ARG_INFO(); static PHP_METHOD(pqtxn, importSnapshot) { zend_error_handling zeh; char *snapshot_str; - int snapshot_len; + size_t snapshot_len; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snapshot_str, &snapshot_len); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "s", &snapshot_str, &snapshot_len); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else if (obj->intern->isolation < PHP_PQTXN_REPEATABLE_READ) { - throw_exce(EX_RUNTIME TSRMLS_CC, "pq\\Transaction must have at least isolation level REPEATABLE READ to be able to import a snapshot"); + throw_exce(EX_RUNTIME, "pq\\Transaction must have at least isolation level REPEATABLE READ to be able to import a snapshot"); } else { char *sid = PQescapeLiteral(obj->intern->conn->intern->conn, snapshot_str, snapshot_len); if (!sid) { - throw_exce(EX_ESCAPE TSRMLS_CC, "Failed to quote snapshot identifier (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_ESCAPE, "Failed to quote snapshot identifier (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { PGresult *res; smart_str cmd = {0}; @@ -621,17 +599,17 @@ static PHP_METHOD(pqtxn, importSnapshot) { smart_str_appends(&cmd, sid); smart_str_0(&cmd); - res = PQexec(obj->intern->conn->intern->conn, cmd.c); + res = PQexec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); if (!res) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to import transaction snapshot (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to import transaction snapshot (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { - php_pqres_success(res TSRMLS_CC); + php_pqres_success(res); PHP_PQclear(res); } smart_str_free(&cmd); - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -643,25 +621,25 @@ ZEND_END_ARG_INFO(); static PHP_METHOD(pqtxn, importSnapshotAsync) { zend_error_handling zeh; char *snapshot_str; - int snapshot_len; + size_t snapshot_len; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &snapshot_str, &snapshot_len); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "s", &snapshot_str, &snapshot_len); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else if (obj->intern->isolation < PHP_PQTXN_REPEATABLE_READ) { - throw_exce(EX_RUNTIME TSRMLS_CC, "pq\\Transaction must have at least isolation level REPEATABLE READ to be able to import a snapshot"); + throw_exce(EX_RUNTIME, "pq\\Transaction must have at least isolation level REPEATABLE READ to be able to import a snapshot"); } else { char *sid = PQescapeLiteral(obj->intern->conn->intern->conn, snapshot_str, snapshot_len); if (!sid) { - throw_exce(EX_ESCAPE TSRMLS_CC, "Failed to quote snapshot identifier (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_ESCAPE, "Failed to quote snapshot identifier (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { smart_str cmd = {0}; @@ -669,14 +647,14 @@ static PHP_METHOD(pqtxn, importSnapshotAsync) { smart_str_appends(&cmd, sid); smart_str_0(&cmd); - if (!PQsendQuery(obj->intern->conn->intern->conn, cmd.c)) { - throw_exce(EX_IO TSRMLS_CC, "Failed to %s (%s)", cmd.c, PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + if (!PQsendQuery(obj->intern->conn->intern->conn, smart_str_v(&cmd))) { + throw_exce(EX_IO, "Failed to %s (%s)", smart_str_v(&cmd), PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { obj->intern->conn->intern->poller = PQconsumeInput; } smart_str_free(&cmd); - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -688,36 +666,35 @@ ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_open_lob, 0, 0, 1) ZEND_END_ARG_INFO(); static PHP_METHOD(pqtxn, openLOB) { zend_error_handling zeh; - long mode = INV_WRITE|INV_READ, loid; + zend_long mode = INV_WRITE|INV_READ, loid; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &loid, &mode); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &loid, &mode); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else { int lofd = lo_open(obj->intern->conn->intern->conn, loid, mode); if (lofd < 0) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to open large object with oid=%u with mode '%s' (%s)", loid, php_pq_strmode(mode), PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to open large object with oid=%lu with mode '%s' (%s)", loid, php_pq_strmode(mode), PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { php_pqlob_t *lob = ecalloc(1, sizeof(*lob)); lob->lofd = lofd; lob->loid = loid; - php_pq_object_addref(obj TSRMLS_CC); + php_pq_object_addref(obj); lob->txn = obj; - return_value->type = IS_OBJECT; - return_value->value.obj = php_pqlob_create_object_ex(php_pqlob_class_entry, lob, NULL TSRMLS_CC); + RETVAL_OBJ(&php_pqlob_create_object_ex(php_pqlob_class_entry, lob)->zo); } - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -727,28 +704,28 @@ ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_create_lob, 0, 0, 0) ZEND_END_ARG_INFO(); static PHP_METHOD(pqtxn, createLOB) { zend_error_handling zeh; - long mode = INV_WRITE|INV_READ; + zend_long mode = INV_WRITE|INV_READ; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &mode); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &mode); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else { Oid loid = lo_creat(obj->intern->conn->intern->conn, mode); if (loid == InvalidOid) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to create large object with mode '%s' (%s)", php_pq_strmode(mode), PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to create large object with mode '%s' (%s)", php_pq_strmode(mode), PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { int lofd = lo_open(obj->intern->conn->intern->conn, loid, mode); if (lofd < 0) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to open large object with oid=%u with mode '%s': %s", loid, php_pq_strmode(mode), PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to open large object with oid=%lu with mode '%s': %s", loid, php_pq_strmode(mode), PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { php_pqlob_t *lob = ecalloc(1, sizeof(*lob)); @@ -757,12 +734,11 @@ static PHP_METHOD(pqtxn, createLOB) { php_pq_object_addref(obj TSRMLS_CC); lob->txn = obj; - return_value->type = IS_OBJECT; - return_value->value.obj = php_pqlob_create_object_ex(php_pqlob_class_entry, lob, NULL TSRMLS_CC); + RETVAL_OBJ(&php_pqlob_create_object_ex(php_pqlob_class_entry, lob)->zo); } } - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -772,26 +748,26 @@ ZEND_BEGIN_ARG_INFO_EX(ai_pqtxn_unlink_lob, 0, 0, 1) ZEND_END_ARG_INFO(); static PHP_METHOD(pqtxn, unlinkLOB) { zend_error_handling zeh; - long loid; + zend_long loid; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &loid); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "l", &loid); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else { int rc = lo_unlink(obj->intern->conn->intern->conn, loid); if (rc != 1) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to unlink LOB (oid=%u): %s", loid, PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to unlink LOB (oid=%lu): %s", loid, PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -803,19 +779,19 @@ ZEND_END_ARG_INFO(); static PHP_METHOD(pqtxn, importLOB) { zend_error_handling zeh; char *path_str; - int path_len; - long oid = InvalidOid; + size_t path_len; + zend_long oid = InvalidOid; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &path_str, &path_len, &oid); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "p|l", &path_str, &path_len, &oid); + zend_restore_error_handling(&zeh); if (rv == SUCCESS) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else { if (oid == InvalidOid) { oid = lo_import(obj->intern->conn->intern->conn, path_str); @@ -824,12 +800,12 @@ static PHP_METHOD(pqtxn, importLOB) { } if (oid == InvalidOid) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to import LOB from '%s' (%s)", path_str, PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to import LOB from '%s' (%s)", path_str, PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { RETVAL_LONG(oid); } - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -841,27 +817,27 @@ ZEND_END_ARG_INFO(); static PHP_METHOD(pqtxn, exportLOB) { zend_error_handling zeh; char *path_str; - int path_len; - long oid; + size_t path_len; + zend_long oid; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lp", &oid, &path_str, &path_len); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "lp", &oid, &path_str, &path_len); + zend_restore_error_handling(&zeh); if (rv == SUCCESS) { - php_pqtxn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtxn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Transaction not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else { int rc = lo_export(obj->intern->conn->intern->conn, oid, path_str); if (rc == -1) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to export LOB (oid=%u) to '%s' (%s)", oid, path_str, PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to export LOB (oid=%lu) to '%s' (%s)", oid, path_str, PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -898,43 +874,47 @@ PHP_MINIT_FUNCTION(pqtxn) php_pq_object_prophandler_t ph = {0}; INIT_NS_CLASS_ENTRY(ce, "pq", "Transaction", php_pqtxn_methods); - php_pqtxn_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC); + php_pqtxn_class_entry = zend_register_internal_class_ex(&ce, NULL); php_pqtxn_class_entry->create_object = php_pqtxn_create_object; memcpy(&php_pqtxn_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + php_pqtxn_object_handlers.offset = XtOffsetOf(php_pqtxn_object_t, zo); + php_pqtxn_object_handlers.free_obj = php_pqtxn_object_free; php_pqtxn_object_handlers.read_property = php_pq_object_read_prop; php_pqtxn_object_handlers.write_property = php_pq_object_write_prop; php_pqtxn_object_handlers.clone_obj = NULL; php_pqtxn_object_handlers.get_property_ptr_ptr = NULL; - php_pqtxn_object_handlers.get_gc = NULL; + php_pqtxn_object_handlers.get_gc = php_pq_object_get_gc; php_pqtxn_object_handlers.get_properties = php_pq_object_properties; php_pqtxn_object_handlers.get_debug_info = php_pq_object_debug_info; - zend_hash_init(&php_pqtxn_object_prophandlers, 4, NULL, NULL, 1); + zend_hash_init(&php_pqtxn_object_prophandlers, 4, NULL, php_pq_object_prophandler_dtor, 1); - zend_declare_property_null(php_pqtxn_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(php_pqtxn_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC); ph.read = php_pqtxn_object_read_connection; - zend_hash_add(&php_pqtxn_object_prophandlers, "connection", sizeof("connection"), (void *) &ph, sizeof(ph), NULL); + ph.gc = php_pqtxn_object_gc_connection; + zend_hash_str_add_mem(&php_pqtxn_object_prophandlers, "connection", sizeof("connection")-1, (void *) &ph, sizeof(ph)); + ph.gc = NULL; - zend_declare_property_null(php_pqtxn_class_entry, ZEND_STRL("isolation"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(php_pqtxn_class_entry, ZEND_STRL("isolation"), ZEND_ACC_PUBLIC); ph.read = php_pqtxn_object_read_isolation; ph.write = php_pqtxn_object_write_isolation; - zend_hash_add(&php_pqtxn_object_prophandlers, "isolation", sizeof("isolation"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqtxn_object_prophandlers, "isolation", sizeof("isolation")-1, (void *) &ph, sizeof(ph)); - zend_declare_property_bool(php_pqtxn_class_entry, ZEND_STRL("readonly"), 0, ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_bool(php_pqtxn_class_entry, ZEND_STRL("readonly"), 0, ZEND_ACC_PUBLIC); ph.read = php_pqtxn_object_read_readonly; ph.write = php_pqtxn_object_write_readonly; - zend_hash_add(&php_pqtxn_object_prophandlers, "readonly", sizeof("readonly"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqtxn_object_prophandlers, "readonly", sizeof("readonly")-1, (void *) &ph, sizeof(ph)); - zend_declare_property_bool(php_pqtxn_class_entry, ZEND_STRL("deferrable"), 0, ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_bool(php_pqtxn_class_entry, ZEND_STRL("deferrable"), 0, ZEND_ACC_PUBLIC); ph.read = php_pqtxn_object_read_deferrable; ph.write = php_pqtxn_object_write_deferrable; - zend_hash_add(&php_pqtxn_object_prophandlers, "deferrable", sizeof("deferrable"), (void *) &ph, sizeof(ph), NULL); + zend_hash_str_add_mem(&php_pqtxn_object_prophandlers, "deferrable", sizeof("deferrable")-1, (void *) &ph, sizeof(ph)); ph.write = NULL; - zend_declare_class_constant_long(php_pqtxn_class_entry, ZEND_STRL("READ_COMMITTED"), PHP_PQTXN_READ_COMMITTED TSRMLS_CC); - zend_declare_class_constant_long(php_pqtxn_class_entry, ZEND_STRL("REPEATABLE_READ"), PHP_PQTXN_REPEATABLE_READ TSRMLS_CC); - zend_declare_class_constant_long(php_pqtxn_class_entry, ZEND_STRL("SERIALIZABLE"), PHP_PQTXN_SERIALIZABLE TSRMLS_CC); + zend_declare_class_constant_long(php_pqtxn_class_entry, ZEND_STRL("READ_COMMITTED"), PHP_PQTXN_READ_COMMITTED); + zend_declare_class_constant_long(php_pqtxn_class_entry, ZEND_STRL("REPEATABLE_READ"), PHP_PQTXN_REPEATABLE_READ); + zend_declare_class_constant_long(php_pqtxn_class_entry, ZEND_STRL("SERIALIZABLE"), PHP_PQTXN_SERIALIZABLE); return SUCCESS; } diff --git a/src/php_pqtxn.h b/src/php_pqtxn.h index 4873d8e..82e4970 100644 --- a/src/php_pqtxn.h +++ b/src/php_pqtxn.h @@ -32,9 +32,7 @@ typedef struct php_pqtxn { } php_pqtxn_t; typedef struct php_pqtxn_object { - php_pqtxn_t *intern; - HashTable *prophandler; - zend_object zo; + PHP_PQ_OBJ_DECL(php_pqtxn_t *) } php_pqtxn_object_t; extern const char *php_pq_isolation_level(long *isolation); diff --git a/src/php_pqtypes.c b/src/php_pqtypes.c index 6cf5741..a95c257 100644 --- a/src/php_pqtypes.c +++ b/src/php_pqtypes.c @@ -15,7 +15,7 @@ #endif #include -#include +#include #include "php_pq.h" #include "php_pq_misc.h" @@ -28,158 +28,116 @@ zend_class_entry *php_pqtypes_class_entry; static zend_object_handlers php_pqtypes_object_handlers; static HashTable php_pqtypes_object_prophandlers; -static void php_pqtypes_object_free(void *o TSRMLS_DC) +static void php_pqtypes_object_free(zend_object *o) { - php_pqtypes_object_t *obj = o; + php_pqtypes_object_t *obj = PHP_PQ_OBJ(NULL, o); #if DBG_GC - fprintf(stderr, "FREE types(#%d) %p (conn(#%d): %p)\n", obj->zv.handle, obj, obj->intern->conn->zv.handle, obj->intern->conn); + fprintf(stderr, "FREE types(#%d) %p (conn(#%d): %p)\n", obj->zo.handle, obj, obj->intern->conn->zo.handle, obj->intern->conn); #endif if (obj->intern) { zend_hash_destroy(&obj->intern->types); - php_pq_object_delref(obj->intern->conn TSRMLS_CC); + php_pq_object_delref(obj->intern->conn); efree(obj->intern); obj->intern = NULL; } - zend_object_std_dtor((zend_object *) o TSRMLS_CC); - efree(obj); + php_pq_object_dtor(o); } -zend_object_value php_pqtypes_create_object_ex(zend_class_entry *ce, php_pqtypes_t *intern, php_pqtypes_object_t **ptr TSRMLS_DC) +php_pqtypes_object_t *php_pqtypes_create_object_ex(zend_class_entry *ce, php_pqtypes_t *intern) { - php_pqtypes_object_t *o; - - o = ecalloc(1, sizeof(*o)); - zend_object_std_init((zend_object *) o, ce TSRMLS_CC); - object_properties_init((zend_object *) o, ce); - o->prophandler = &php_pqtypes_object_prophandlers; - - if (ptr) { - *ptr = o; - } - - if (intern) { - o->intern = intern; - } - - o->zv.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqtypes_object_free, NULL TSRMLS_CC); - o->zv.handlers = &php_pqtypes_object_handlers; - - return o->zv; + return php_pq_object_create(ce, intern, sizeof(php_pqtypes_object_t), + &php_pqtypes_object_handlers, &php_pqtypes_object_prophandlers); } -static zend_object_value php_pqtypes_create_object(zend_class_entry *class_type TSRMLS_DC) +static zend_object *php_pqtypes_create_object(zend_class_entry *class_type) { - return php_pqtypes_create_object_ex(class_type, NULL, NULL TSRMLS_CC); + return &php_pqtypes_create_object_ex(class_type, NULL)->zo; } -static void php_pqtypes_object_read_connection(zval *object, void *o, zval *return_value TSRMLS_DC) +static void php_pqtypes_object_read_connection(zval *object, void *o, zval *return_value) { php_pqtypes_object_t *obj = o; - php_pq_object_to_zval(obj->intern->conn, &return_value TSRMLS_CC); + php_pq_object_to_zval(obj->intern->conn, return_value); +} +static void php_pqtypes_object_gc_connection(zval *object, void *o, zval *return_value) +{ + php_pqtypes_object_t *obj = o; + zval zconn; + + php_pq_object_to_zval_no_addref(obj->intern->conn, &zconn); + add_next_index_zval(return_value, &zconn); } -static int has_dimension(HashTable *ht, zval *member, char **key_str, int *key_len, ulong *index TSRMLS_DC) +static int has_dimension(HashTable *ht, zval *member, zend_string **key, zend_long *index) { - long lval = 0; - zval *tmp = member; - - switch (Z_TYPE_P(member)) { - default: - convert_to_string_ex(&tmp); - /* no break */ - case IS_STRING: - if (!is_numeric_string(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), &lval, NULL, 0)) { - int exists = zend_hash_exists(ht, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp) + 1); - - if (key_str) { - *key_str = estrndup(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)); - if (key_len) { - *key_len = Z_STRLEN_P(tmp) + 1; - } - } - if (member != tmp) { - zval_ptr_dtor(&tmp); - } + if (Z_TYPE_P(member) == IS_LONG) { + *index = Z_LVAL_P(member); + + check_index: + return zend_hash_index_exists(ht, *index); + } else { + zend_string *str = zval_get_string(member); - return exists; + if (is_numeric_str_function(str, index, NULL)) { + zend_string_release(str); + goto check_index; } - break; - case IS_LONG: - lval = Z_LVAL_P(member); - break; - } - if (member != tmp) { - zval_ptr_dtor(&tmp); - } - if (index) { - *index = lval; + if (zend_hash_exists(ht, str)) { + *key = str; + return 1; + } + + zend_string_release(str); + return 0; } - return zend_hash_index_exists(ht, lval); } -static int php_pqtypes_object_has_dimension(zval *object, zval *member, int check_empty TSRMLS_DC) +static int php_pqtypes_object_has_dimension(zval *object, zval *member, int check_empty) { - php_pqtypes_object_t *obj = zend_object_store_get_object(object TSRMLS_CC); - char *key_str = NULL; - int key_len = 0; - ulong index = 0; - - if (check_empty) { - if (has_dimension(&obj->intern->types, member, &key_str, &key_len, &index TSRMLS_CC)) { - zval **data; - - if (key_str && key_len) { - if (SUCCESS == zend_hash_find(&obj->intern->types, key_str, key_len, (void *) &data)) { - efree(key_str); - return Z_TYPE_PP(data) != IS_NULL; - } - efree(key_str); - key_str = NULL; - } else { - if (SUCCESS == zend_hash_index_find(&obj->intern->types, index, (void *) &data)) { - return Z_TYPE_PP(data) != IS_NULL; + php_pqtypes_object_t *obj = PHP_PQ_OBJ(object, NULL); + zend_string *key = NULL; + zend_long index = 0; + + if (has_dimension(&obj->intern->types, member, &key, &index)) { + if (check_empty) { + zval *data; + + if (key) { + if ((data = zend_hash_find(&obj->intern->types, key))) { + zend_string_release(key); + return Z_TYPE_P(data) != IS_NULL; } + zend_string_release(key); + } else if ((data = zend_hash_index_find(&obj->intern->types, index))) { + return Z_TYPE_P(data) != IS_NULL; } + } else { + return 1; } - if (key_str) { - efree(key_str); - } - } else { - return has_dimension(&obj->intern->types, member, NULL, NULL, NULL TSRMLS_CC); } return 0; } -static zval *php_pqtypes_object_read_dimension(zval *object, zval *member, int type TSRMLS_DC) +static zval *php_pqtypes_object_read_dimension(zval *object, zval *member, int type, zval *rv) { - ulong index = 0; - char *key_str = NULL; - int key_len = 0; - php_pqtypes_object_t *obj = zend_object_store_get_object(object TSRMLS_CC); - - if (has_dimension(&obj->intern->types, member, &key_str, &key_len, &index TSRMLS_CC)) { - zval **data; - - if (key_str && key_len) { - if (SUCCESS == zend_hash_find(&obj->intern->types, key_str, key_len, (void *) &data)) { - efree(key_str); - return *data; - } + php_pqtypes_object_t *obj = PHP_PQ_OBJ(object, NULL); + zend_string *key = NULL; + zend_long index = 0; + zval *data = NULL; + + if (has_dimension(&obj->intern->types, member, &key, &index)) { + if (key) { + data = zend_hash_find(&obj->intern->types, key); + zend_string_release(key); } else { - if (SUCCESS == zend_hash_index_find(&obj->intern->types, index, (void *) &data)) { - return *data; - } + data = zend_hash_index_find(&obj->intern->types, index); } } - if (key_str) { - efree(key_str); - } - - return NULL; + return data; } ZEND_BEGIN_ARG_INFO_EX(ai_pqtypes_construct, 0, 0, 1) @@ -191,32 +149,27 @@ static PHP_METHOD(pqtypes, __construct) { zval *zconn, *znsp = NULL; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|a!", &zconn, php_pqconn_class_entry, &znsp); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "O|a!", &zconn, php_pqconn_class_entry, &znsp); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqconn_object_t *conn_obj = zend_object_store_get_object(zconn TSRMLS_CC); + php_pqconn_object_t *conn_obj = PHP_PQ_OBJ(zconn, NULL); if (!conn_obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized"); } else { - php_pqtypes_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); - zval *retval = NULL; + php_pqtypes_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); obj->intern = ecalloc(1, sizeof(*obj->intern)); obj->intern->conn = conn_obj; - php_pq_object_addref(conn_obj TSRMLS_CC); + php_pq_object_addref(conn_obj); zend_hash_init(&obj->intern->types, 512, NULL, ZVAL_PTR_DTOR, 0); if (znsp) { - zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "refresh", &retval, znsp); + zend_call_method_with_1_params(getThis(), Z_OBJCE_P(getThis()), NULL, "refresh", NULL, znsp); } else { - zend_call_method_with_0_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "refresh", &retval); - } - - if (retval) { - zval_ptr_dtor(&retval); + zend_call_method_with_0_params(getThis(), Z_OBJCE_P(getThis()), NULL, "refresh", NULL); } } } @@ -231,18 +184,17 @@ static PHP_METHOD(pqtypes, __construct) { # define PHP_PQ_OID_TEXT 25 #endif -static int apply_nsp(void *p TSRMLS_DC, int argc, va_list argv, zend_hash_key *key) +static int apply_nsp(zval *zp, int argc, va_list argv, zend_hash_key *key) { - zval **zp = p; unsigned pcount, tcount; php_pq_params_t *params = va_arg(argv, php_pq_params_t *); smart_str *str = va_arg(argv, smart_str *); tcount = php_pq_params_add_type_oid(params, PHP_PQ_OID_TEXT); - pcount = php_pq_params_add_param(params, *zp); + pcount = php_pq_params_add_param(params, zp); if (tcount != pcount) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Param/Type count mismatch"); + php_error_docref(NULL, E_WARNING, "Param/Type count mismatch"); return ZEND_HASH_APPLY_STOP; } if (pcount > 1) { @@ -262,15 +214,15 @@ static PHP_METHOD(pqtypes, refresh) { zend_error_handling zeh; ZEND_RESULT_CODE rv; - zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh TSRMLS_CC); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|H/!", &nsp); - zend_restore_error_handling(&zeh TSRMLS_CC); + zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|H/!", &nsp); + zend_restore_error_handling(&zeh); if (SUCCESS == rv) { - php_pqtypes_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC); + php_pqtypes_object_t *obj = PHP_PQ_OBJ(getThis(), NULL); if (!obj->intern) { - throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Types not initialized"); + throw_exce(EX_UNINITIALIZED, "pq\\Types not initialized"); } else { PGresult *res; @@ -278,39 +230,39 @@ static PHP_METHOD(pqtypes, refresh) { res = PQexec(obj->intern->conn->intern->conn, PHP_PQ_TYPES_QUERY " and nspname in ('public', 'pg_catalog')"); } else { smart_str str = {0}; - php_pq_params_t *params = php_pq_params_init(&obj->intern->conn->intern->converters, NULL, NULL TSRMLS_CC); + php_pq_params_t *params = php_pq_params_init(&obj->intern->conn->intern->converters, NULL, NULL); smart_str_appends(&str, PHP_PQ_TYPES_QUERY " and nspname in("); zend_hash_apply_with_arguments(nsp TSRMLS_CC, apply_nsp, 2, params, &str); smart_str_appendc(&str, ')'); smart_str_0(&str); - res = PQexecParams(obj->intern->conn->intern->conn, str.c, params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0); + res = PQexecParams(obj->intern->conn->intern->conn, smart_str_v(&str), params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0); smart_str_free(&str); php_pq_params_free(¶ms); } if (!res) { - throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to fetch types (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); + throw_exce(EX_RUNTIME, "Failed to fetch types (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { - if (SUCCESS == php_pqres_success(res TSRMLS_CC)) { + if (SUCCESS == php_pqres_success(res)) { int r, rows; for (r = 0, rows = PQntuples(res); r < rows; ++r) { - zval *row = php_pqres_row_to_zval(res, r, PHP_PQRES_FETCH_OBJECT, NULL TSRMLS_CC); - long oid = atol(PQgetvalue(res, r, 0 )); - char *name = PQgetvalue(res, r, 1); + zval tmp, *row; + ZVAL_NULL(&tmp); + row = php_pqres_row_to_zval(res, r, PHP_PQRES_FETCH_OBJECT, &tmp); Z_ADDREF_P(row); - zend_hash_index_update(&obj->intern->types, oid, (void *) &row, sizeof(zval *), NULL); - zend_hash_update(&obj->intern->types, name, strlen(name) + 1, (void *) &row, sizeof(zval *), NULL); + zend_hash_index_update(&obj->intern->types, atol(PQgetvalue(res, r, 0 )), row); + zend_hash_str_update(&obj->intern->types, PQgetvalue(res, r, 1), PQgetlength(res, r, 1), row); } } PHP_PQclear(res); - php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->conn); } } } @@ -334,7 +286,7 @@ PHP_MINIT_FUNCTION(pqtypes) php_pq_object_prophandler_t ph = {0}; INIT_NS_CLASS_ENTRY(ce, "pq", "Types", php_pqtypes_methods); - php_pqtypes_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC); + php_pqtypes_class_entry = zend_register_internal_class_ex(&ce, NULL); php_pqtypes_class_entry->create_object = php_pqtypes_create_object; /* @@ -342,11 +294,13 @@ PHP_MINIT_FUNCTION(pqtypes) */ memcpy(&php_pqtypes_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + php_pqtypes_object_handlers.offset = XtOffsetOf(php_pqtypes_object_t, zo); + php_pqtypes_object_handlers.free_obj = php_pqtypes_object_free; php_pqtypes_object_handlers.read_property = php_pq_object_read_prop; php_pqtypes_object_handlers.write_property = php_pq_object_write_prop; php_pqtypes_object_handlers.clone_obj = NULL; php_pqtypes_object_handlers.get_property_ptr_ptr = NULL; - php_pqtypes_object_handlers.get_gc = NULL; + php_pqtypes_object_handlers.get_gc = php_pq_object_get_gc; php_pqtypes_object_handlers.get_properties = php_pq_object_properties; php_pqtypes_object_handlers.get_debug_info = php_pq_object_debug_info; php_pqtypes_object_handlers.has_dimension = php_pqtypes_object_has_dimension; @@ -354,14 +308,16 @@ PHP_MINIT_FUNCTION(pqtypes) php_pqtypes_object_handlers.unset_dimension = NULL; php_pqtypes_object_handlers.write_dimension = NULL; - zend_hash_init(&php_pqtypes_object_prophandlers, 1, NULL, NULL, 1); + zend_hash_init(&php_pqtypes_object_prophandlers, 1, NULL, php_pq_object_prophandler_dtor, 1); - zend_declare_property_null(php_pqtypes_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(php_pqtypes_class_entry, ZEND_STRL("connection"), ZEND_ACC_PUBLIC); ph.read = php_pqtypes_object_read_connection; - zend_hash_add(&php_pqtypes_object_prophandlers, "connection", sizeof("connection"), (void *) &ph, sizeof(ph), NULL); + ph.gc = php_pqtypes_object_gc_connection; + zend_hash_str_add_mem(&php_pqtypes_object_prophandlers, "connection", sizeof("connection")-1, (void *) &ph, sizeof(ph)); + ph.gc = NULL; # undef PHP_PQ_TYPE -# define PHP_PQ_TYPE(name, oid) zend_declare_class_constant_long(php_pqtypes_class_entry, ZEND_STRL(name), oid TSRMLS_CC); +# define PHP_PQ_TYPE(name, oid) zend_declare_class_constant_long(php_pqtypes_class_entry, ZEND_STRL(name), oid); # include "php_pq_type.h" return SUCCESS; diff --git a/src/php_pqtypes.h b/src/php_pqtypes.h index 1c5da1f..9e9d6d6 100644 --- a/src/php_pqtypes.h +++ b/src/php_pqtypes.h @@ -22,9 +22,7 @@ typedef struct php_pqtypes { } php_pqtypes_t; typedef struct php_pqtypes_object { - php_pqtypes_t *intern; - HashTable *prophandler; - zend_object zo; + PHP_PQ_OBJ_DECL(php_pqtypes_t *) } php_pqtypes_object_t; extern zend_class_entry *php_pqtypes_class_entry; diff --git a/tests/async001.phpt b/tests/async001.phpt index d1aa35b..7272272 100644 --- a/tests/async001.phpt +++ b/tests/async001.phpt @@ -38,11 +38,12 @@ while (true) { break 2; } } +$s[] = $c->status; printf("\n%s\n", implode(",", $s)); ?> DONE --EXPECTREGEX-- Test (WP(RP)*)+S -(2,)*3(,\d)*,4 +2(,\d)*,0 DONE diff --git a/tests/async002.phpt b/tests/async002.phpt index 4cc19c8..bd09863 100644 --- a/tests/async002.phpt +++ b/tests/async002.phpt @@ -40,6 +40,7 @@ function complete($c) { break 2; } } + $s[] = $c->status; printf("\n%s\n", implode(",", $s)); } @@ -54,7 +55,7 @@ DONE --EXPECTREGEX-- Test (WP(RP)*)+S -(2,)*3(,\d)*,4 +2(,\d)*,0 (WP(RP)*)+S -(2,)*3(,\d)*,4 +2(,\d)*,0 DONE diff --git a/tests/async003.phpt b/tests/async003.phpt index 9872642..9eb44df 100644 --- a/tests/async003.phpt +++ b/tests/async003.phpt @@ -16,7 +16,7 @@ do { while ($c->busy) { $r = array($c->socket); $w = $e = null; - if (stream_select($r, $w, $e, null)) { + if (stream_select($r, $w, $e, 1, 1000)) { $c->poll(); } } diff --git a/tests/basic002.phpt b/tests/basic002.phpt index 2afb785..e43b27d 100644 --- a/tests/basic002.phpt +++ b/tests/basic002.phpt @@ -13,12 +13,13 @@ $s = $c->prepare("test1", "SELECT \$1",array($t["text"]->oid)); $r = $s->exec(array("fooo")); printf("%s\n", $r->errorMessage); -$r->fetchCol($val); -printf("%s\n", $val); +var_dump($r->fetchCol($val)); +var_dump($val); ?> DONE --EXPECT-- Test -fooo +bool(true) +string(4) "fooo" DONE diff --git a/tests/bound002.phpt b/tests/bound002.phpt index 3633902..cedda91 100644 --- a/tests/bound002.phpt +++ b/tests/bound002.phpt @@ -24,22 +24,22 @@ DONE Test array(3) { [0]=> - &int(2) + int(2) [1]=> - &int(4) + int(4) [2]=> - &int(6) + int(6) } int(2) int(4) int(6) array(3) { [0]=> - &int(3) + int(3) [1]=> - &int(6) + int(6) [2]=> - &int(9) + int(9) } int(3) int(6) diff --git a/tests/lob002.phpt b/tests/lob002.phpt index 3625d89..1eacfbc 100644 --- a/tests/lob002.phpt +++ b/tests/lob002.phpt @@ -35,7 +35,7 @@ int(488) bool(true) Warning: ftruncate(): Can't truncate this stream! in %s on line %d -string(123) "KG@M+(0W+ZBU?7n^0j^-^TQ6qXKQIDi%c2={d zDUy=t;SW8M(#-7awCO)>&>}?v*9F`L{U=4yA3@TlaDxVjfdT`2QP(JJ^z%9A-21)XFG)!=PrGXuo%dEG@6U73J@=e*&pr3tZ(dtE9SxTbI{l@S z$_U~Hu7F& z_+xpw(;v5o&GyN7qtk6~oc5cj`C(>+mOA}r_q5fnpESnD+SBsV()B1G)$1Fjtzx~7 zue*iXX1!Y6EmR7%as>$lAyM%LTGO5|8h*+3PrKcPh=W6xm5pR1lkH!Z4vR0w!$xyl z*LJG4LZ$X$X4oE|4*MTwUMo&M%5_G7IyVn+Dvyel{p*$D_x6g_T79oly8f9UV^)dn zVr{d$ZiS|_;PRst%*MlF?RxaZ7tv%#iDJ9uYVG#3_FUCtJ-A1Q>or%*^Pfn&5zIAI_a%XmG_^w#GzWVJ;{qA@?~SvLwsO{KwFgW5i4q4r8)K)}IBGBPC-E^- zgejW%3yDXaLv28d@+VS{$30CIjN(_`X#D3++F?3=9%-`S zNg;`ok9m)=f7)q28-o}n@8n*hA^c>G6N6YMrDp?_PZ>!v{iJ165DtZj zXzIifj}D$ckve)lrN-!Z(0um1an@cu1RpzQxp8uG@lzU=&j6(^9hJk;@FyC1abUEd zAn+$sK@!r0PzZl5WUx##$KcHEVJ^GYXdbs0*9QIZaL`?j`h&$LQx>A$>1ez-Y@ao{ zomOMq&Z3g5vpZ}Y^%`+u=4Iv&8l!f<(Q9MvyRSLNRZ)OE{u+4t$zU{v8wo!H19dfp z$25;yonbD?Y39f6-U*viMlLKj|7N`tAO>`|^5>+Ur{bT_Vd7 zh0-KD7Ca$GWeEC0T?oQ4MaFysBZtiFig25PHq=`$Rf=nnYEKdZPTP?gLL(TG4H@X? zjOOMWn2-A|bxO-JT}B>mw6~-8Zoe1p493yM;I!Z3DBI2BL6p5u#`EB5Kf2Ev{1V+C zcgEfJ1B&aoh9$D#k}G-tV9YCP zhZy3h^SR=bgxhE_N&9v)Df*B~ei5hp^GQe)6qZtPJCP51T#4=wUcXKn@u)AVcvlA6 zIXdp*zj1vMzUfE+#m)fdDsTdoNc6raB)`n7%xDam(u{;JK*zIRgJI_g)cawkIp~kZ z(Zf$M&$nOPxqbV#OIrQ(uB6=!(zXlLk0tS5kSMAdQbn5sIY1ReFWqi?XzHtWu~pnb zp>Kctr#=8PG%yaKdQ#v;(2wR-w?mo3Mt9V{0nq0UPxy0i0`B5CT}S$8^f134oOd1={+i`^F5Synb)am zw+0{zz|v?T=R0?P>aJ4!{MP=R&#;ypuj_HWGh0}i6`w35YzI<|JlAy-z##o782OcG zo&`}OdVb7xo^yRMSyWka=s$i`Uvu8s>#HA}>U(B{bwFeF8M-OxSX<4_KfF8TY= zWr@5*_I-J6f0mhs0W|7 z+ODNZXb(Q`oZP(-+^~%q5FdPg_Z)y_QTurq_fDt}IGVVoxsX=ZIwNcmJ7eN1rwW3Q z?Fd-F>LY)bM&wt01l3FTe`txU5X1qc1iUmT4?*%__C|CKY}A%(n9J5g!$?<}-PEl+ z*4s6*Q%4bDqcP1&O~{sn(WRcyhTQ3$42D?w5h}Ht;{m>n2b>u0EhA39 z&c4HB*shW~n~1PFuVdfd7+TGx>v^Y%g`7#~i4E$)@Qtz!pJ=QXIKsZU`Mkvm`>6L! zM#X{)(d`dD_+TM&8%6;jP+W8ZZDA#`rLfLWVtTFjRa7}vsvA{X!^1YV1?^hzWP<`& zsbs-Jcs__9$&{U(j_Y9cl=@cR>tT~!gN+kU8LY}S^l8uuS<3$P-u2HSFr|5=$p_Iq zn-*fF@|GAa5T?qPjoPVvpk}gmL+N>?QkZUb+u#NekfP!HbtJItI}S;}Za@$~8pJwn zIDLN5Qct@8IIp8Nq#BsoMYytRIxR+SoRgeo2u2{*4o_s1&Ewtx5^WL(==s~<{x*A- z|7CQukR%?Hxx(dazo7k^xrJ3HWVK^65YRDq$n9?K*2`5)>*LZ6^!%7HV926Roi&C^ z^6mav?s{!|7p1;S0t4xRxW2?uqZ#l8T|X`*s0Z>=ec$D= z5o=R8mur+ABmu-;U@8b!J8YR?u%QWL1+tL}jmgbWKXF^J9wuxd60HQ903exB=#DET zx=T>|&U@I4&3B=v0F-%}m}a!#8=we>zBdn=A5ue+21aNAX&9ska4o`h$~7v#Al{+; z=z>LAe7kjv7)R&rK1$5!R=cqwTA#Pj>4&IDnd8KeZB2m>SA*@kVF{?HW@)G#MG7of z$G&d}t5Yp(b!^a2!O%QVjipBiOOKjMk6KHQ+DngMNbtMipv$|M2%=HYkZgJX9vdH> z3}Hn*%w2!?luG9Ga+z;IsXnxSvzq&W&CL(c*&yP;rZsh!Q=-#^B6nq?rj>g?F?CJq`%$PHH;FJd1QPY!6A6n>FV`MZ)kG)f5S%`zPy|C(1=N8XtBjI@KD965Src_l zC3KY&3Y@Q>RLMCu@8RW zTpnp?5*b1k<9!ej(r(bwlpHvS6$Kr&X5T%9A)q;I-n*M~`w@j36cLc>eF?Nc~gwI^GgXUuO%FH2M4+9H^K9%BpfS)Y<4v zibOfA&FxO}xY6!LkFkC4w};XFUguf+BiQWo{q`7kAyiz>f&$z8dgu0X_U`RF?=Rl| z&f@J4ERz};zoKWHNgW^ZJ75~Np<9hy4jSwqSq^O8upeoI_ufObwZX|t7$=U$0ueg6 zw{QVm`AnhPjik;9``S@^2m@k1lc}^@H~|}W4o=0!(CD|KQ>b8_el!}K;`l3KiW&yE zJM4`XqURlKg|OoIIXE3h87NnsLo>@SK%%rGoU`>h<1u!RCqo$0xwRZ0H^%tWMl0R! z;CZKi6hRSgb=d7lD)rjqF4X)Qt#Y=yfRC)){o#n_S{0U0n5!Qem4&wvCy2Iz2*V3@5_V2iD#fiWN)Om71W z=YvgKQ>{VsvQL~JKI2S1su6nYNfTktwJT*-K*f3 zu^4e+ne|e2ZL3h)F0SX%Kl+S{kBU3Bs0z-pl^SUI@lLTq;1i=J}Q4t}sru zfpb9dw>2OS0B$Wr)!pJ+iC>DJKt~5ePZq4vD$ibljKUTGD{L1Y7OPS20<2(O*7hpJ zZ2}EURQFb^wNh=bR*W8&%j<&c49|8;YsKn^(N>x0--!0A#f50SP%B8+Xam?nHpaHP zS1k$NN;@@JzV>!&rSi@VO!8wOrV?e=3aHEJT#w2-GOM5lnETl(@gNhh5Ix?+=`hLz zr-H4*S`8xyZLD!peX$IB1g+G9VMaT}hg+qG#htYx;VHA3$E9lV1}3Zo*dDS?Qq$uC zIt87eV-h65iZb#&pj;ps(;1aEqQd$kGy(<;F13^D86*lsvWNXFq)XM<7>BLM*LyJ4=P((P(M2-94dE_s{>(JMa9$ zpZv>v{JeJk$A9rZS2^^~k4>q>^8W~}u{=M2|BwFs2d?}dPL*F9^kAoKvC6HCR^jJ( z_{-mSRsPwqN?iO8{XQ+u&%ZlvJ$1$ZxuAIQ1zjG%li7X~AQL2h?)}UE%_~!3zqFqC z`K`aZ`$t{Pu%}&E&vD=`2K>KyO$Wly-}vkQ*RQ+sKN0j)6?wYe87{3hMx7?R`TU>M zYW)1oTfg?VUA2&|;%W~&V^;bUiVTs)&tLhWzwT%8k527tx83Zr*8dGnh_(3nKmX8g z{i^FKoEzU2EBvK@Tr2SN-e36UkGKjUY_-Pd*-`S;YZhxBajUrK;KMw=ju$L5Hq{h9rUH6-anxzkn!_R{jcBt zVOL?Im)*vTjm`^2!k@8T`1$g0|GA%Vl_rot`th~?ly$|=_HT{94x}CJ};a)y|Qyy8pl`@$+x~#ecu!DuvwF`Z~d;ll}aNfyd9^`U7|WhO6?8 z^th_xgth@g_A%@ILBj_>|HMBS`2~zEiS){nBTD-W7pde`kI0;w6#!J2!Qn`1y~1qV=a;88)*8y=*pZrUSV#gUC#CmIW#i|QU;oB`?Arbj54T{7K>sqxh{)pS z{NMWfUh;q!yi+T$moXN}=jY4%Z+czDJXpD)MwoSMmBECdQ$B_M_>}r141wH$Pf1qK z1*(@Y{>;I&N~w#Zd#yC*&vNTLVZxsNv+7E?(xg=(>{H1p3dX!lPzj45ANeGF~qq! zZpUF>>NbvGQh-Snu6DzA3ttDKem1%{2!d8(+3HEVNrTVaoLC*DqCzm)N$V6xbZpr= zkZP}8RoB;fwJQb>JuVcoWE(M%#KCk3$~KT(JS2iobk5BmV;bWD5@1fO4iNdyK4|ER zvP3IQoLUiPO#DP^iMff*F{f6HC^XTt0oD|V{0cYU3te_HBVHoL@9QfU#j|S!BOvD5z9?Y=9k{Wfm z*0;AdNBfKKjy^+so!&_o#;sfy-=!MXard+br$MQWqc1sbne53Et99mJ)c)oP3}!eh z3o@QzS4t)oKWs9zI2LRSAmEGczdL#WxJX3%w?DHla*9Tj#stgGreVV`27}Sz?i`#% z_d$LS5}5g7aRN84q3P&pHoDF2#tS&lId(NVk#iSiEGhbyWzuWB0JiWqr<2fYoaC}# zr#N4m=p2nLz(tOyV4zOcS9DN=ZkwP01k<9$GvZNSa*r;SCD+suS?=~xQ z?*I)>o6@YLyo*Z@p4-Ir_l}+b_hsaxSh|G0to)Bq};Q zTE#oSLR_(oyG0Rp-;tbxFGTG#oX|f%#vdqREm-)w;|{=%cn@HdXqKi*7=@=nQ#d*r zwvVWwHTufUad2{(Hn;b-Y9(#*4i0rgI7Od`#@P4MvCm^U0n$zx%V8=+iddYQhycTp z3*pjvO0=NzTbh8Y>ud;6-|^n*4e8R9hTtDNt)b&a7nA_)lSBZOG64tA^&AwK>vRh^ z%7VLU*IxHhMasFKR=$fDA`;QB+3khIo2_Bf{95GqD3Opn17WxjVTK z&Ta)q%FDz%NLU08ns5@`Z?SLC4-4nfdPW}X zgoKCipn1l)lYogxjrASD15d;;3pO6bgz#@9La(9xizwLK4vCfavy0h0YoUOsr})Z2 zoAgthSV33vPO_w_)0|#aNv(-cb7DJaHi5*4Z5&xn(u83qLFFkDh;{Z?0M#l4U`*@D z&=)R+%k^Y)-Kqjxre`I4BzDq0%Cez`&C`sO+=v>@=3v<3Au&8rd3KqAEida#{?w4? zO~TR3PP^M8YkP?c893obeen(%X$^MCwC5e1g^$LA6J^Ob$oCvfkD`qwVO8T`mE9k9 z;Pe=Xq=+i{5%RHZFJM(KFAKY(uXwxP#8nlX!t#8b97+Csr0W=7EJA?Bt29yOQIgNJ ztRc^ji>VNTC#gB+5P9iicmyppXhf+Sl%MuSW62MrTes#rZb8$#jSZab&v#^(h!s4i zddlF{?bmVz(-5hi7cewkVMn+rjCrp2bo`|xCZQNeh{mYvXbIG z;9mb(fAHK%{OH{gwfli-lcHUdm%^J~>`It%Dt4In!te;@k9b?b{C)HT+|YGf5D;Ly zbL$ShCWSaaVAEhUV!Z_pJGEJ*X41IQbI`g6&Q!%Tbg40$!nDZE%rvcuDDX{g4f;nr za?K5+4TdE`XpXBw)ghT6sb*-1n^1b=-a?qzMX-NxL5Qa zlY-w9+c{JMFC*73iGwxW=9iM*re%_mj|T;bTA)CXf}NT;Hy4Afc;Fx>HusoCGBHn$ ziXPv&vqsf z9CZg9K^e8!YO(hdL-(7FSn+Vqkj44~4*7P2z3a(x#$aiAP({@Wh!rqBzcNzbAM5%0 zNK_l!$*6uZeKMiSoHMQsHNU^*z}#Y+F{*p%QB9k|H9Fo>!Gr#W9if+9SfoyQql&~m zC`lEhFE)$Rb~G}@Z8{DP1_L@4oP!6?s%3(c;{nEFG`XvP)Fac>IBO`pwKuVm|3M+H zn1R6L&}HFPv%w6=({ljzp4x#Z>JITl;tvXYQtP-Fba-=%T_GVYXJNYu8aim3Q3$8d zl%}96Y?iMA^wMaXh9*k&i{V!JCZ?h^#w#JehEvH=M9bY9GU^N2R;ca>xHI^4lHf%^ zlS%XTOj1QjfUWz6F9Yr>cO*_vdkesCpAR@lWYC8vbXSp{TU_J}EOI0_u6hbQrBD`P zD~8<~FOdMUQ! zisr&~H{x<`MQ5Gi_!J1h78+jQwp;?X(-q6y8zgJalrXiEZ1M2AS#+zFj01y!Aqt2{)>mJ<-C z>SOv7cbLz#2SI=TKF|is5;ryVRED^4A77$wVum?QL1|MK&FzP!o?yPBoD$>}f zpZ!b?VP|YrFq0~TQr%=J-O0(K6*$~%U(gRnd{HmH45lbaQeqs$_TA&q1~23iAb9Eo z?BUWzJbkD7E1(N8EP8AvW<&Sz)2h(K=<9^@Gi5CHZfRiFj0czlHr^PeU*qn`R z)(DalY3k?3LPP`VQ#^?Zot{ZS2ptyD)^cUa0k!KhUQrnrjNr_mK``k96zpF<>hz)YcE-3VqKzOB zNc7aVqP;CIgS!;KO>;L~gDDH6&zDt~nh;k_mCoi^63~c4jjEkXP@Ms=d(KZi;#<(RxLxu{z0gHw3N%^0ob&L8#=u7=~{fDH_; zsKp03;X4>0wvUeb%wT2(XZ{|EVVo>e0$Z|L?uOX3F&PB;ZJ_3@`s6p} zrrfpx&AlbaZ;a>XjUl{xW}sOzFAK2{oh<}TjNyKc^|6A4Ub4ik9$X+vPL%}v3_O&( zv7a^jPcMcd5DllCb(=FSdn(yKMxx~pJyKgLkOHJ9N?)*F*<(V`eMWwPHG za{~QL)M;)CcazweL=K_47&oCBXEiQ?86sv9FBZ2cg_Y2}W&9{{%oy79RM;eC5Zz&C zkQJ+{Q?1g7Oq9r&0#@NuwdS$D=Pkg=$aX66JUx;%-WexlUCNr2l6J}$P{$1B7cdUv z;_j4X;uwT*Ej|d>t<|uAA7CVb*OcX%olSYnY*lg6El6(fAHv^RJc9hMX{rzqsfIYA zLz@Tn|0%+^r3wn8|BkcN$~6;RkIAyDd!?;)6s8ZJD_nJAds>BR=^>-9-3!XwWu7Gs zj4`cJ@snBw7avg%F*|Wnd&yC^DYK`f1A>_{@~#d|n(OoEKF3Ksu0ZQ~IP3nbIZ~@08>V zx{4*zl%B}^!7it?`gWbg!i4&wBPPY9r_w9IV8DCBu6W7vl%cxR6M|cXaB!SaveM>s zcM7D!At9`wJ0n&(n^A?n`_JlWYv4+XN-dPuYe`^0__T~*(}Xi4<2iKB;QMu?W(FWKy1G&hQPiqKEGYtwuy_{m}9CMP?8Iz4!p;6U@LyBw+uD$b? ziZucHu}UCv-SWz|!ZsXE)L?TPf3>7U8Oh z{25TAdi4~?)ofuJh?e1~Dbc?p^ahR1M|6{vP#4pP6~}zIJWRub=pMM!!6R*6L4FQD zGuH2&Bsio4eb!t!oak^(E|U*4{4QvjQ|yMEKItBv5^{uhQZr0ql2Xh|bWQr40>Wlp zg1pAn_OU-G?JVqPPdW%su#kNYYe4ve*EEe?avOfmV=hUd%`ltYj*No3@-$NbGN^t4tRpX{2iVUGB?0}jIwwK6x4jne#M{D-g? zf4AMbgr)aDhZ(`^vrwLSC&60(sPk4q-+T2XHebi1uxxgvXK& z(Di7;cMe`GOM1e8Iq4cZI!AhD{{&D0(j2~SiKfdu*=N9VVOAs!Mabo1qaa)ld?l=;yImCLH)B%lw9<-(o+p#X?(+o&z0k!}fq2zyplo>$U^6=2{ zCYHo(+^g;G)evcFXB{!7@W==5AV|M#(AIu>X~}|Zc45iUHO%r;Hm1UtfPC@HGSe1p zhXWkhIxyhFfR%`}#xpW79o$qlD^53Ijwpuob})YqgH@T^EcWF3<-(*F50;cPp_4$~ z!BE-eMBs~ytDVng8> zfcW#`PM2Pw38%3F-Z(=mkCp5s_PrV2^e~C}tg|MJ7&@`r;CXiJ<|-xgsfq{P0PFFR zn{PwNAcf)(G60r~F4P=nYc$y-R4hvZdjaQ2t2MEDaPui2UrXdQD7DncmAIf?)J2{` zazl0^5IH(4ep21~fS|Y4>{CPN>Gm`v2Lt~F;7fv86|(y7YFnw^Ke5=_5_?kdVi?v-_`1A8su6jO_zBgbrk zHOHE2#Ti#bJDaMk8}A78_0(E}Ii)IaPru%@F|}W9So%G8 zZ+PLcZMuM)0X^EaU*O;@$D_0lIcam5Vh{;8@JiH1rR1sP$t(i5C1-;Mux7zS3n!U zULJWuM10Ky9Jo8ct5q$Sz~#DyEAi%VB@jZrix_bS41@^|Jp^u-JK?0d0*J&O%Bb1^u#tD-Z!gWZy|V-#1&F87rR=i zy6HqI@6_0LQ}W!;#RuH7IJHo8G_nTDS>Fvt%ZEqAVFzX<@n&sNXktoU7DKsCShVvodszGb9CEk zpU8tS=uTtx3kndyv%Ld}ukZ+75Bmtc+&s=@Z|2brrm8W#35GoH8gS-K7$4E3bf%i2 zj36tJF8R{l;znfb`zrqW*5U&{7T26k2ocWz@PF(osaj(x(I49Z72yV;Jhmk+QS;h9 z!O^yr-n~(a**0hH*z=>yxfaSgKgVn#=ao~gEzRe0O{E8UKdB%&Ey787udgu97I?C%G*0q;Cc}YV z?-*4YXu06%G6PfbR98P1_Dsw{t!qa)*Ox#NbYF?-!DGcxsS_Doi=}vwX}Z+xacZp~ z5fl37?b}Yx&F9n!6`mc##O56RIGh@w0+V`ClEdMrl7zHy`M#5cBbCGTlSG!MC9EQt zgyCVTQDYLTJceGDJMl+p=fUTX#RoWYEKr06XpiClGB`nUBr%V2dxMcO0YAie7$OQ& zT7sKA@qlq#FCGlQ=NL{iLhSzCHIa0}sdn)u7ub}JG;RYNsoPafxG#nE;(=fDa#9NQ z?3^MBNcB|i03Bi<^wKlo7J#~TDTp}zUk2{Y-O5%SS9YN9ss-T|LJ?q#sLpsa@1zw{ z6Dg)1igdz#ekfzGKLBi?O)L>A&P6fZl@zVut*6GQ#kP@3e3h^;ycTG!*>jXy%9JIT z)NHd)Q2Y;5j|7@ES7ItazDf!vwX`G>r-JG0UkGUrk*f$KKSTH!$=Z-h(INR4HfEE; z^5!F8s&gn6nZvhjf~Ai2PhSH(JgwKh=kP|CEQ09}E#Mr>3efN_ed+XA>N$XlXq}*@ zctue;Ro;}6WQz|#kH)p+DLc^(5`#bi(G|iYQ(sgS2aBH&9NB=*d*ImZ7Zzx80Y5;z z2-)1J4{gg(#vb|NIE6V}j>4xG z&>{PDxD4m6VDacZvCD`^$LJwJ&J2J{Lt`Q_MdRU=t7vn5&YXBRaY~5F9gFVO2t?n2 zNv!pfYPsxt@xZDu?U+NIYsc3cL|ba`p#j`)n-4qvmZjrZy)y*l963<~N{{Kxd2%Dq z?MZC63&8Xlz%1)8Np(;9U#J78fEX-pAM+*UIM9>SlFl$m=>Sz)IuW8uSfh0DYQFPY0#eOO8~kZA6XTRF zA3m1=B)r%Y<+A${PuZ7daOJokoTYvyBhbwNT5={K!z>yXRHaVqxVZf){WS|f-?#ZI7&MkPa&Wy#YufE!LgYnQ!zJp0KjRTk>R?bGGE4dE=y9+UU##MJPGoY zJ|dnq*$yswfazXcQ#_`tBrb&+JkCYH*~OwWsJxeWk_~)A9zXYBaLk;%bf?^hCV@Qa zNm};FVsEh}yl`4Qs?a*m2I)Shz&|n<-#^ix0LiM12i$l!cQb0w>86Ms=P&feh)VJ;V+S zS0L?4I7D9=z|mU0`RDAitgCebR0~Hk)Fak8ki5KP;y=U)W?D?0d|%uRLhjx=9yG(1 z}b03d}?*-sD;m}#OG+%s@IffoV0*x9rA zeinb_Iv$s-qch$B5|iTYW}y<2(o@=DIsI~6#~f@0J*5b4lSPcNTLm#IuyMIMT<9Jl zZ0Gp6myna|EOO7XmtSG})bEjWLI^(m*K2EHyL9C4ZN*42ub?AwtfkjqJx}gXi(5%9Peg-xPT~_b{qkvv?eeAA8V(e-_`P?r0I$1KK}J4hp%z2Wb)FovcY-f=&1N zhVD-X?CW5NNZI1awZ>R;@P87)j|lBYOD-=tR~Pq^oGbN)!V_$6Xn0q2%bAV&TGWiu z;RXa~N8&O0gOoRgM0`M;k4=jJ@bsUb>-a>JatZ(G8P%I3REMhTJe&9KJfE`*yf`jn zHy^x4?BztcO`Z(X4PIVosS>8ef1nY5%5D$dtXnPq19e+vx7059nNUu2WJz`JjhSMS zoQmw^bNDCoa~oz4ipWp#8+QiXtET65QDLC#G%61hYNBGc z8b}lyr#qSC)QPW`_2|>Ds>k0gzB*2e{*rwFzTV^T^p%CL@Ic&?s(9^+zt{iQPQCpp zC*2`LIj}p%y0dQM{QDF;Sa^oFX~lI~J|AbXkkjfI3ypm=P+wm!>ulX|`^;TB-h>|x z@%TKq!ah>Jc-5kEYXDm|ccqjic=8>E4k*EUu#Z#i$E>@^3vTD^PEC0LqFT6lvYqQH zz=L#ixk$Q<*gl8{8QxxP`zt*vd}CLDm~z>v?ZEWZLicS-%IdcLRX77+Zz2Jga0IM& z#>)e9dG7!{3eo}6-+0`%jhM_%;>33yHhys`8n$}__#7$$hGqboM=|@hnbI6*e$=e) zfbl)!n$u2X>t+$efs+WS(@C1;~ z5kxuLk(-?oF^eH;ogY+-4;|S>YZ4%6I@NPEeyuj{+!;c0^9L{S24?-F3CMBxBKNI% zwrHbJ>rf)atr5$ik71 zy*GxeU=g6KWJpCB~ooQdK}j@)Ei0#Cs3 zd0dx#Mz4|bVGhubTq8~S>_KhQJJF{-vVHO2jPGNsF>~JDs30N04O3u?9gy9V+HRrT zINt}ElyKPzW?zZYi51cP0|0AlNa0T!=@vt2yfLR0A6k6l)aFnHjb7xQ5z zmO^ofFTO|xyW>tB4}DB=-7pU4Ov^@7LK(0TEk2lFu}VHB2GpTj#I9$l-pku~GAqd1 z)Zb_tQ0oD>qhJ=15n(7Ge?Jh%wS7%v2I&>>Rxpu7jFZMv8>)jB7Vvmc#VPcK-*peQ z$3ULLX3ztN&i@?$&^7^a$UwH72d?!9Bq;m1$l&a(lAbw)O4BPtYak5a8LE~dr#aIby3F{QJC0fO68C~zk>R78sA8Dg1{jPV0Pl-a0J(;?RySu7DVJa@$Cgk|6 zCP7m)N5Ocm@HmTd!rkA|{{-mH>;K%^!5~bQ8FFS|0DkQqTm#lzm5ii@Bsp4L@qf~n z;;IgXPGTzWBzC=_J(qQF2w8oQl2fxxIn=Jwy08{EA4WNxDM_eG+Aj1g3$ZPrD!aae z>0f+chh5B9Tqx0pB(5eVoa`m-|JcgUl5;5~Q!pEgIl3-^mzdiXeOYquYu{=Af8Mw6i);-z*7EQ};+SV$io6ELWt%(_T6 zaGiV!sAi1C7}FC7rXAN1>}O$ao~a3hao{-C6BDo-Jkyq!AAaiSN4XcANnr&*Wv>OW zTt!bUrQsCXsAZ*+#JrGatoGzOwKeEEl48IvJ3I%wvht0plz5Z@wIUAl1bX%fAY>2{ z2~f;d(Sy{QKo=*{(c^jKAsi(M{3Lm312ZA#jU%4R2S>+jHlNMoFqkLph6iQh=hBXo zWfE5L{AKEt6pVjj^t8TD5(`r=Ni3_M-hC5lVaqAf_!_B&(ER_@lDvMU)B;-Z%;VhU zPwnf9CRF@3$y+b6`ll{_^)8U$h_lu|7l3V)$jM{PkiRauJY{vByEv~vhGGYCj&EAk zDU0B0jNZZFLXmjtTsxAE8m7D?6Vpv>U?MfzWeEqp4fsuHdH2gd#;wT}#2&$A>a+G5 z)Ug9NZJ<8txzedZ*cqrR#*BQI>^?Cp^R5$ZI&=ncMLawU@$SO~Gw}n)Hqa>)kmBQG z2yvvO+)Wc6Y%HY=(I$}zBucA}58p*ek3Zw;xp9?1HLhX*G>Js4lTo zW_9Q_Qg1R)DNb0m+k`W_CWU}{uh%57*uSToZ>jl^D_FVg-p8cCcviw_^lr^M;pRi3BSpo1W_F!7k=e zj~YY>N+CW~k>^G8z6QczElj*rqQqcd3FWk3!Maft62HD=nJHD!);jY#J4I5PmH zR^?aI#6oe(GigXS6_X2fd3kNGQYr4#>V;~(THM-*zKC$CiQz+_3eiRU{rvlYa&B%~ z-H(e;SdVVeJB96H^u^4Q)sIWN_4RU1?_bUjn-kzqX9hWr6dN|7OBf7w9`3W&W6NsXy%I69!-8G5+p;<06kkKIMx@{#&`1`hWzFf^qp_Ka4XEBl zBFBGUCFeE2Ihb*E6X=ffT8?2da3LJp;nCH=)3Rfj*G>k3yBtg-A#;4{Fm_q)=nkXF zzLMt3^THAnWth9zBlP^UY%gk(ahh*9+rSUTkKY1{kPXfNA}kUzvOp>r|8ppuz=82g zF=EW_PgE3RdIX@+S~m;W9f8G;u9!hqr^^%Bx(+BDuXu`Cpe={9^dqu z$dX6BTxxC>pTf}NGE;a&YQ6=uE7R${O?akOAMOjhLhKy13z2w1dgJ4y+~MUacyx#x zM|5^KbeIg}56%5oB7o>QexknL^vTr8;hmXkhwo&5((4wx?H*z)J3eQtYku^Cr;G8F zv!R2xkY>pirh<}Wvv}-N(AK56a^u1Nkn|=TBgX9<0@oAQ2fj zOl;`=WXEA_HQTC7HiBW<-M`uWT}5}=M%=wpRU1z|XdrW4Q2%GGD zSL+6wRh3K>J-|eati=Z}2uv=!L|iXhpZbG^W5J{fd3=x~ao+n!2!hOV`|@0{@OkaY zOvab)%pBUZXLlInrJ{B2(z%m}`?u5-2$vfp4|%{|M?;)+X&4?S9<599A!dKhAx5?y zF&mnonjb*j>#Fau2lzkRt8H*&|*4i#=QZ7oi>J;>Zs z&c6i^ex40^=XT`!aBwF#{4N!vVR&brWQ5~89d`8HI<{iHrA;MHEt#0wSrP)PUA5lX z+#t}36Ol_UN2Li0)g|I%ks!Dek0nLTiuc_5ua;KIuSF{uS{9ht|#i!O*S zEPacMcz`7?{CedTBfOs-Fs=G=U^X+!$uf) z$DxeVWQ6@3j__1r*Bj+eO=sWUGMydqJKUY~sX{EhQ%0+0ylI0<%3R#mH7k>2+f>Pi zMDr0iP~0mW`Mk(3xW%y*u>n)R!>*eKUbOG5xvpv1&9ZFFw(#Tz!-Oo6(+dJbK?PCR z7_8(U1r*?)A>0(xIxkOP zHRUvO4#yCXf>H;c^tsLYXs9sh%)`4!WhJ7WSW)yfwdlbOuy+2FS;Ah z*oeSJXltBdnJnV9lC@qdX|B}jVeJ}31t}Yi+OpvD6{Ve$3-*RBNnn3;f$BmVBpVH> z`J>sPcVKi6=Tb^0&TE{J4~Ed>Ym>9vq|fI>qsf)xT4gjqRZ+o8W0E=tV8&fcG_Dh^ z&0~**(*!)mC~usBafab9w4e+QC*~Lq6emQ^=?QLeMC^__Xdr|vwNQqV%lSwsc&U3*GO}s)x3tpgS3ZK;% z2cSaANTIO0Epjj%lm*C??gE^aG2K_iAZM0N4J24^leB)MzaZJ#khYji#m0p)mYGLG z{4_~C)y}#z5FBISjd1RK);2qU?uqcyD`5!+fKYFXO39+42fG#>wlnz5^OacCHDsXL z663%~6ggxOTIoUu9j_1RPx2ExU7cNd*mde-qRhcN4Ek)VyvggQBzg{oWFn9x>0!#L zAp^0y4ggB<3M@zJbNp*$hFQ5sh!-a-r+qm{NwTrfrCA0Y!?q$)mz17!+Zzo`=oC`W z!Rw{opmmCsxpXr>8gRQq#t^!ADtU0jLsLh*EW^DIGz>;j#C#mpzkiDRoH=naH*W0? z3F3)x&Yt_&PJ4J4xuN_I|?B&paL7 zbhJV;c#YpH_;3Gd_WEbvedW;pT7M%W_hJ6#jqg64$1{_(Yock_w%e|FhbP0++~ISC z=dz%~>SZNY)^d#3DJ}SMa?Nt@$E)Ipym$Jc#Dc>u2)OvmLki&KRBY(3gkd^;7eb0! zTaP!(VRLY=4as@&lxcR$&6EPpGb&DL z+gg5?(MRyKXk)yeJ?*qKs2Z|__7pXy@+?O^80yZ%S4bjHQm;z6aFT{O07$qvvHrIrD%K?OQ2*1)s z6b8mPoI&%bZCf4hsd$b#dx()Xw#!fQ01s zjwy9c3(Sz&2_;QSg5a{d2Jo^;K_hBkfDeb@d;;|SMw*7Iw=+PQtv;y7bq@E*#xJAA zHrA)IeaFf$kt8lthXgWR7sNY;qy9JghB+Pvzx$r#y4vnWeWI7R6H<~hA+fy$yk)Ki zQdU%J6;`u!lq`2!iaH)(G$lm^Z*N6Z+y&0|gH1VAFTluMrrF%RFsYxDA3La@M& zVL$tr1H{Hx^5Q73X)(Cz4&n^6DQgzwXH`A8RfLLBS=xpJxZ1Wwcf-)nb>5xL(MWt7 zB$Su%7U{)Qbwxz!=^DWWEG9*?QI)6SVfzkf&+gZsOLMbL55pdrW!gHHV1&b-V%}Ja z2;q6wyA->7>#dPZw_{8)OcF5Oj16U#@;SihSc|Lzm#Rhsy)NzSMAq;ro^FI1;Ywx2!`qd(}mzyV=iuH0*(~#4b_XU&)NPV~~$d``9KtOO_z0WQi9=OY~DO4@OuNCf$4vT z_AE2VDLolmA(jFYobCj^0xOt7jYo9s>0#Ih%-FWV{fN3938!RH$J>w82FFmG5^3dzVi3nTIvH2TLH+9Dn>ZX_AEUM@BIxn!fbWvrj zYYB`+PchfbdB$>WT1iysM-xKHPPp_wo_GtUvjk$>n<$A}6IhxK@T8=%WehGR7VqskE!+nGtewy(OCDP2Cd<7FEca^j+MV6Bv zYSQGY+|O$3IAvH|gm2H7fynR3FRc>WUi7y&#pul7r<_)*Z7$Sqr}dFoZ>g#nowK4y zi!z;8u-IlOut_@}bXC~c@tz>8<+QgO*^#5gVucS3UZ|!{Uv!Y&i8aIp_k$|5G(rcB zlJ%w!d#SHoTC3&wp`}CYyNI=u4a&Ky{0UBv-(LTemZq%wl%8qJ1>>dmspH04&}6D9 zOy*~j1%w!xBEsJE$oq0aY$hWBiOC5l(QF4>BL3r1nEVU2o^hV+KruvD#-HcGc)%sf zEHVh&I?Ddh3DU1i+mw+4w(z7y_RBMmT1*LrA)`8Z)}otYnP<*-j2juZ=*zw<+hDuG zq3)lPAGlgWg5kTIiz7QOvJRj(n;y&(%AT)U13s52r4?gt^s&(Gt*yq3jm`@gjiyL{ zO!yh%7ROrPgQqWUf5+S554rg~WY0N1bc@aF zXq5jPMs7YcrLAKr@WL-CA_%(Zn_d0%`25xw4(aYW&6(C6K;nnx`$gYEj4-*y&s!Z{ zX7A?Y-yyv~1nsGf#1F`VKsaV`Y~Xc~;Q`MG-pwK+I>SsxGT`qOQ+6V##$*Jw`+bMYB*)t{d)LJ9GwInz&> zy~1Gr8lu?e;=5~v**R-?&LEh5J@d)CDfaPm*Qzsi>6)}HDKB%{p$qg0IN#XD0y{^! zbDUHwc!7B4lJ>`bvsHA(WS|M8wE!&;=rplY+(n|>W=U6eIC12_uH!dTyH!DoMh(1` zjkv!p2N#t-w}*~C^1``soP2cf2ijrI6wXzJhO5KP(8LnJtWnWOdLbzeUN7AQ=aDB; z%R5_7aD6~nkephxj>?}_=kPE$t2$jq*n?J-fYQDqJo`^^WmlUEo$C2I@0qCtj(MCh z67pf+++d6%Z_54Rh1jPG)s#yv$mL6XH?}3O5X#HHFr(3=b%&M+Mv}qXMAp?5^HVOn z?p{Jb2=-?e?+>YIOd^wCDEB1RL?}3_{^raW^;S>#%{!ahd zhI_JZz~Bi!2v1vLV*(q+6vPQ)01yy`fTR&{#d9yNCk?rM)-+cs(N?IR zk-_^d54%&=H2XQu%k!pc92_m7Oo*#;A_Xjx))Y*CYcmbGeoWj>B33S5_8divEgH=7uF%RIyy)uVIi!Sr zsH#mu?rioUY%XoywGR$LH zg_y+A0IMIlr-;S^CP6#1A`WLns%h&J3VY`+jE4-qIP(QNk|?kgy_3``)=iM-f9CiE?kMy+on zs(rY@qo>a}685Apr;e#F(<~a0+n~-%ij6@#;oz~(csVrL@!|u##1eEpWSpD5$wnlQ|GQX|AX&0sFd%nW;8-7&YVO16@ipPv z#hPojd7frN@Em>ihC}Hjb$q~f9n*I5-IULSBxbW%>gl4m0y}7dsZEsC?ZQNH=Tx64 zuR_Q+7(&k2(jq(!_&KF8-cml|L8huSf#e1}xFl^5m>7BZDKGPIRLjeV@azCc$)iw4 zn^x!>N=RMeEL>wopN1ji#9W_6g+{H62MkNpedn;}M%cR}Fd}Y&8|cOdnvDIVkU#u% z83iecj``XNB#s4HgpDPC^m$g7`vJHu?y#X;P!)qdr|!Y$chi+Y})|lg&8}p=jhtBeT|nND)ov5L;CbH!xPLnCn{CcEiEUXJj#hSQJ7eXm8DrPbY&s~ zK|4*v@=7?KZI4FB?Slq3Dxy0$P6z!kA$JoEuye8&&sSuYh1PtOc|YeU{H6!>ULBiu zXVGyV4TCQ$OprHu9#2}dQWtF+l0@Md2^vVO^x4cwH&Ou^&Ms;jpESif{vm^L{DVKp z1Dvw&3b8x5@F!lfomP&0d5;BE9c7-+^;Bf15M^v0AFP$&DFUETosgl@tbl}Meg??` z0h0MCq!8ffa!b`SQ{4vZ69YQftJCA-i%(ckrc40Y_`h3vij}kqy%2pznWl|1zAG|X zdUwR|0eVmpgEyJEZ8sS}=gk3-^1ygJSRlF4uFLmcVZtE1T$iZ>xE=DfJFIw{~ z=;Z6UE8cG+4d$o2TKr@5t6MHe0zCm?F#CXGgiF#~cx3g+AMw)T4Yd#L0g7f!35Hgg6u6L)+U$VR0OqmNDrz zB&7ld5^CB`0J6nUJ7FDJAe1|<5P-8nlQRS7)&TZ5|@)Y*oN^>BcUZgc(;L}wG zTj&@iw#jHHT*rc{qL$%zvAe^rRblYabDZc@ z5;{`$>rX0AtiajAIPD>k)a5U9WN`BM${la9lj5EGX;yq`H2ci4xlYMm}QHTJTcVbt_Q9=ZBv6}Fk}q#_)d%KJta62VpqFc zkUH|5j&Coaf*Vv=H*UnSP;~uM!20pY7TKu)-kU<70#vl)Mg+t2z*_x^64q7a+B9PK zjUgX<$Hv(Jx1;sR;~q}%4^EG0`5AP1j?X9|pi5ppb}`3LMhc_F+ay(!PMAnNz?bgp z3Q}(Wvjv2i8jL%K9X+0vC;uGax%n^)OJLMSXPq%s6$Ba{HIArQ!?Gi$KzZ^RM|()} z(CYKgev}K*x8@yuruqtN@Z}@izeyFq_B$R?+_J1fDk-s@Bm~x4SBporRw)*?>pSII zY2!(Kt-P~ST&t<|Bc6fWZCS}^Ft(RWtG-()Kdcn1)rtBsoDZVgjOVGN0!EhNtmP>G z{^j~vD{t>^6>G(H>jeu#G$Y!oG8MYT3qP54A}!jy)q+QGDwqREE4@UF_DF3!D+_3hk$f8md@oT9 zS>(EP>@A0Nat*H=8xw<*4`?suLJB$7?s=vvR4`GdVK(8+gnRg~;%clo*@OCD{_02C z)H0R4&I|Pwce@5w2|qh{QGvh*a>qJ8IF2=Fl0Q$0MBQevx#|f#eY$Oi4o_T0Ns2nt z80`b*h0}iL`yITE@pj87A=gYvRM|r416rd20lPKPSA`)6srj3uD13vyCD(e-FepqU z65zo1!EN~P$tm+}3d?2JBy1lkMVFRf4$a`f*StKmTBoxh1EDbVyvYvp%Oq_AL+~O@ zzMkXHM?I}XnG6RZ5$?sx56n-QH7>4r=7d2dCr#9g3uld+8Ry~WSeV=Y9OLX+yf$ZA z7j;|Urq-?q>I^5zVT1$U&WlLGgT;VRqF)(3fMZxMJQqO3R38~)sDVjEQJ5d}xXxCh zQ-0! zAgwC&IFED3_UP8F=sp|#-?*AssP&LA$3c4oDdB%?T3=&V6kaQjkOX6(^S!wSUCOxq4a7>^)BcBgwBwWw5zx!cai7_?VMf( ziMd1}#Tu48XBQhlVBjQsC)N|Je71#yMbXWd%@8iKN+^H#3z7>qxOAlw0WlziACpPe z$?V~VfiryC{=gL%8LJLac{?vys5`)+sz#u=GI?PH>gHDIpk~otO@JAQO*GU3!Eh zWL12b!}1U$N42YWfI*-blq)lJOqp*+OPQPh0u;ym_~`S@QXZGxM*P(s$lpfBu4m`> zf2Q~RvzzWG{K4=YmkjW?(Y%@Oy@y|8#$(Hmjx$S!?nQp*{Vwq+`~tx(?i5zHin(FqoBe{0a&T%H@u492LMSI4VGGm5 zBe*YJo1fjtWU#~u8GK&}R;94Jxsk;VEP{<7`yu5AloIBYcB-|))>fUbuoWxS9M-{- zL5?xi7z<3m;E<5p|s(hD3}Zh?@(5uqNi_3TyTC;zntwn9FV!9u*A< zvXNmk(?-u*$2xq16E}+6D1htr4`&4A%r@S+Y_z-4V=Q27*+H`FgBLGF=ev{t4jwSg zd~@;Y{-OEZ;o#@s?h0YtrG3B$wh%}BNMAo0U2Ui9=e6>BY3HF5+j;nUfCfh}~p zuwBtz2!U~7yP}XAbq)~tAXpquM;W=;S?U@B%4gAb1OUL3pJw9LQ{S?{I^$)-Ow+-e zfY?Mh&fk#k#dV&Vn1n2qpu}hsZY-x`?Xow3kLqC;AvF)A0$1dii+lTjhu4 zpl3YMMaGdo0aGgP)pqx4eB}VBE?1sdv6U#Z20K`-Sg-D_BD3nNuS7d#S8J=V^Kh^5 zu;?;ZqGJCDP#$LlsrBt5agHTYUDF~f(UW2|Qz`DE>3RzBz&tYxtE-jbqY}Fg3#?=c zTaOD*s%WfM0L`r9X-Oj{dD0`VZFRoFYMLI0r1+@_wXQbGF^I; zirafzwUP{BZ5Ir)YD2fN$)NDm@LJfT!C%}hRER4>^)6-urKDo5uv)K{KJ~L>gIkH- z11?L2Dhnq6tz>FzTb%J~EuDd9iAvjOtZoFeQLfa1e}y8QNj#tdfx_pp2L7v63Of^d z*65?n^(~j@S#W*3u)7;Ghs<`N^6@%e+yN94-&qORZ!KOd1XHw#sXTEk8dxL9U+WZ5L~s<#o3vU0z|Qyi?z)?iSW$6$&hz zv-;i+8HlcCU7zVZM+`bZz#{cFAjNh-DL4oyqYc-e!eA{2X%fWQw2^q5@|K4SgljQRqJ=a+~Pc4m&q}580>HrE834z$VTg7 zO@r33>T6{%ryAnLQFW2LhsB+u@Z(x}9gN8FQ3W*4EP@5i%3R%h80Xpeea-daE(A5G zc%5a8zGX8Y0E19jr6EJz{Op4o|mCPFCb$zw8nuG&2u2{dtS?Xcu z=oE)v48Cmotk-s-=RI!>#qUQpK<>cStj|}h_=+yNn=L^6{Mq*$qxP1y}Hcgj#?Dur#7aQLT&B&}j?f|gx({DdYfe(cK< zzkHcCmlxx#mWD>jsSb*N^%F+DxYNh0Yl>8@8?M!ouEn;MR5P>9AVQB4gyOH^7d zZ@D^HUByodqCZeE4*E)Dq?^(jDd465(l&&rSCV~uD~6$%5m?qrMw8M212D^|miH(t zh(du{x=H5w!LDS$$m-kcEL<;C!ILpDl;&SOO_~wqU^sX#HlHhHVuq8|O8Id$+{$td zJFQUA=I0q}n8HjpIoM(ssUMJQ7)r^`E5(gs1siZk0?4~caSO^$dB<3a&#cBdm_lha z$Wx75y0(f2YOP#`#=Yy|QC`H^+N>4QJWg7L>{tZ^+s<0#2uAjXSBlMVMi+_%a+pRJ zX43<>P~h+y(TW-WTW+UaExRdf?QRxUi_kNnkCk@Ti=W8A6<=#uxk!X|i$ZbkO7woF z^l+zK!OFvAl(dT0yISZjiK@-o_Et2I7f-IXf3N;X4@MGB>@m%Dr9KB=R-)r^ubYuv zVGK~c)vCx+D^WhqR>NeXvehe>O@VQlE1FTQJpo_ZEXGpYGDN?}zAMg7WO#N)5VR>w zF0@issBi9xKv;?H-n~7MSykbTAPl!BGanYVx3S}1iN0fbSV7P+!LS|R$O9)3Y^*0mbyiI8R8gzO%OtsRphA-m4w@8K8z8jGB#VQhlRXT&G&-dW8BwlO?=CVvi6! z0@EC2U5!<2R50ukRT%zTf!F;}zNMA&W{`A+clTDI^1>8iz!_=WmLmrRt_Jg&t_}Jx9Bo;~kj|y9RFrmP(Bl{+f5{5HZ zy#Bbf9w<&&vhUxf!GL8y7H0hz^In!_r9-OMds_vd6w=q*USxG~TP%4rjlm=UX)Ky& zEG(gzZ~k;4;O_(mE6>ttRtt6am57ABxK^$D5|Hbmrbp&DK0$D+W~-k^c$nj#YrM#V z8kX$)63+leV_)6#PL<>87yGb|hXouP^kZzzjL!;2` z*P&``HEQiozFYwc?aovSk6cNb6rd}3iV7P(Y}`?!zP7#Y7CS3)LN$B4@NrQ&T%yQ| zgwRw)i8d)3=aPLZ1@9KPz-YD9X6-M+B)w;IgQ~R5c@+{grXWp7ZI`i;mf9{uCp(bA zI0RaUtrWdi!Y!2}SL&%Kkb>K2S%HAA3LcL|;J}x4X#mom2i%m@#%F6*^GrYH^3j?> zJsLwqA&A?=Lq?tc)#_B2)afdD0>@aW4WO4o_vNbqV&Y21n~iV$1Rz8a25KN4C33UJTC3swl`xC;-ENo>5h1p*Yws ztX0aomE?Jh;nfhNJIp#`R1!H#V@74FZ$ozxQ?ysTv{iSw7w#uWo-jeir+$H9m!39k z9vcETwF=2fLRvmsYRNuKxrp-6e0X7C7)2(A~ zM=Tsr?12al~m z75s!dF*zIc*@` zPSrf7jLf#HYvkUkb%I$54*H$FJtj`^BU~@1&z=n6jnW1 zmqZV!^hWl)2c?MqC}ES53Hp;fI2-9uH%i4V8L5C-E8^4&J5qlfp-l@kj{kT#9Hi{f zGUbpXD4?Li=)M($?_r8Fu}2LmNdY%V;6;q~n(xi*7ir9y6P=nR0<^*@Bp0ABUjpG75aRR;gc?kr;FarN)c(cn}sRP9JgL`!ccbT9A@)P=Alz}ef??Cf4 zH3)b<>x`${;X17jop{Up7;jor_#Y0s-2vVJJ)%o(%k)N8!oA$(jQED$jFMo<1FZ%R zZ%jwMQ}|iq5&)n6mP0AIQ^~-7iWOX@>ojr0)I3e)?yq=@;_`RcD@L0H3CO^i7On>m z^D`hpj{!OyBp4>+P)`NMfN(Iq4KSP!0%}dc^epd?sP6{mYzfn$p;%$C#4U5&uZ=M; z^TpcXOk?V6o26=0EpOD|?@)~J9V*i!*l5vK=U83lZD^p~2Up zEwVNgtCbg|*UV(SsJszv7r{)>Okov{p-^wx;YO(j51wiSju90iSc-982%~Z(+TE+{ zmaD~x1Ixhc5KJ2fKx0--uwXTZm{1mafqTu!U?CUfqLQOuPwOt?a>- zwY+l!ll&NnL0fAD)a7)pN6?Zvt3VQcq0uVwAQP|G;XAIbx#f-Uf8j9i?-!eSZp z2uHJ8FwAJD2%j$SJRH9ux6Ec9m#W1Zn6Q$l>}Zqy!oxX&n-n|dJOQjIBi{qc1(GqH zQE4M8tUp2{09s3f0;(mW79>^oU|m;~=W&gP?+{q@hn4J|{Ov66ifEk8m8`g{WWW0$ zbKmaGVBxtNG(nyB@^|il^y6mkvYAYTru(CntQ{$w!1T_`DrCb;t#NC~T3QTCFY}uA zIdvp^QNXnJmtTxJzK`e6pXZ<7lM{=(w{PEBf{mq$sPw(YqFlm(hAnW7I?E$T-m(V; zd;=3e`VKR*hT%)(UyNEaO9g|yOc}P7eUORn^FG-Fam&BIB;S#S8zB9DyZhh-uR=JC z-d}R5C@?zh^&qGooPQs}U*5UDT-~{kD_Qa#{ViFC_i+H!egJjh{l(iKEZ)5Xz?gs% zM%B^-{FK`WlltIJ9`ts9$^De(PdZ4x&Ey8Yvgx?yecY})kZU4|W|-Q=2-5Aibk|T= z`+gVV8;>?WSgo!vU^31+qjn3!uvGL5Y1$q=xPNVbjVx|Ia}y7A^Z7|EG-sQ^m9aJg zIQN@)Rhus~sNzzo;W6W_!lzF%x1y?q;( z$ae-y*v0DQvCL>;h@`I$)d}w<>GS5 zI@ohIS~{=P7C1aykS{3ZE=El&HX8aa0VfjSMK?}yB8D;JOM9V642O)V@%2Q zKE+l7T}*fQ;*@~VkqaPAo4BCx-8U(G?@bE7mne)y)zPJDU%;Ybk^rAEs>H>7TPNQ? z#mfr95Tg4SkWc{C_x^+T^Y`xKzGPpC0+)<6^FGacXgqi_1Eh{pAShedn1uUIwmrz;;wZ^Ix^)%Sy<5`M7yACp^0M7x zWb<$Q?~AL4D!EsAt1Xm5^#wWC8|2}zR>k|v=N(vT#{UY3N0Y-w!&?>YBkX|IWuy_j2y*T<6-a z>s;qQg$iwW6b5;DxVd}qXrKv(teM3`zPZ969J;`4F2{LlR8V>MRXG}-wvf~00DMawl(GkGhIl$A7YC0Uk z;)$*D*eUNow$2!tqGpAU{KIs_P{{dBhL*O>24rkaZqc`zKrxmXnT#%ZTy8BK>}(}X zcp^_#mG1ncLP;9q*CXsdQ7O*v+ zZf1sQ+1T2U!YO82+<1I1H#O|%9^{TDRZ^f(5d(lc%Mb=doC&J3;CMDO#YXFEVv0R3 zeAKd%@;`|a7k@&y<{(`WdJumKpf9E$@*?e2L}tSM&caNokKI7bXScQU19|EauaiWd zs>C~Z!-JeyC-J7QUjP{ry=)LaV%7+jr!)Jrs=6EY(yOtHM{cO8k;WmkXNCvU+{FWt zFPOOq9l5FoprNI&hpM^w*I5vlGt5(&($wPRmEet0rPq0Z^2Ul zi8r^N0|Zhy)z! zfw!e%&)Vz_^u&22RoRTS+ zm4~EzgH(7yNDPq@a_5utV>$4F6hc3mtp-6%GRNkq)KKvfmy0U~;+mLWW>LFEqDrjccC@|^hWrI}>TetzB| zI1Sc0P&E|CdqLw8fe}bf8An@}AZI=qiu@KtXh{eU=_s#`zvyfw(*=2xV3m$Aj_1I) zwnNE>Dm^icek&B+ir_N%qZ_R{M#c}AHa>~3snRd<7?40&3i8YmoeUZTFA{kHjmF0Y zAYWHLF)8`(!Kx~P`x-oI3?UwDsj5uyO3suc@Gw~Zq1Or4@j9>|f(D<(3;Bpt(e~@2 z%R`L=xce@-&2gYQq7kxAMS(?^VSgua40Qjd)Y zM&u^J6hmf|w3^Tmy^4oKxs2fklB*&_NYh&Zswx~*!wm@OXj1kgWFVRBg&YN@BugOt zP*Z{sGSp%}7&`8%o;XQ{qXp5IMHgN860`J;U!@DreHC)$KU;QJ#AJOI`%${(gau=x z09yh{z=fX$Di1QipBPAZ2y4Q;!06&eYfC&Y>8^yl2l{gR1bU$B8#-sBOSLjm<90Sv zXX){V_~8sf5hH?ig(Uj{qBes+tSr_n0BEfAY|I_VdQG)A{Sp3P5hdi0AI6eo+G<9m zeus=jg;O(D0YkjPbw=EqTEc{KMdT(GW>T=l$P%K?gmg-qWctDZV#XjG1kU@x)wZ;? zGsDIp!D^GS$S8~pDeuRa0Y2@odDVx#af%SxeUY$TX% zjEvz3OdyV%r_{z0xH%-z)uAj57lG5xz>>TJ_T>@lP8Cp)iI8hQ%6yX9gT5MB87$BElx* zA;wuAKvb;O2?1sWv3?5tSg)WCFJ$1SU*_m<0q94uEFn zPK|E5u56QfiUO>)x_=NxV&uFKn`Dkcl2E~O5DmMDIhL7O9Og@Gf=Cr{RSF=PyMGWd%fEx?W)aO(MXz!-YJ9Mh zql7d>e7f&^oP)WsHzEahVn7hiUCC9VKBMq?y2LqE(o1V*9uA|xk7x4?*zFgiz^O`ID#=_XiZ zjZtnO#vlc%DT+~>h}M#5`+|L@k^yGlWAaQK2ayUS&gy9b1|oL^pDjvmFo}(3zuedZ zZxXrUW`=kQb3h1TJIO;50m#O$xVM;PW4Vocv&o#8V2|(};;bMnh_CjEb&K$ zDoI=?`H+LFept-2m8e9Y@`eOZ881wGqIQ(52N7=|4KDSDpn$*@B8rcLoluXwJhrAu z(0*hXR{1eMis(N1W|W@@EW=Ta#x;j#bFG?$BLO2)U92(`MF}Fmw7g2yCjg)k*o5j3 zzi_4ksujuhB?>%IUsS|2StiLGK!qBHX6-;T^oK?HD0QM~2)zl!qTvF`goGTptGin> z4uVLCoQA$d^gmCXvX2DIk7KE(04+hka6~)M)tCMt{Xxvp%ikRjGCxq+$C`;81qfE2 zvtbxhv1N-03ZctH7Ace)kPPw1inqdLK6tis!zLQMjm_5F#=No?%q8IH{Aec-UUV(q^Axkcx4bAK0r5 z262`7fxSxS;p@X^Qw_My%nY|h6epP)VyzFf(}C?6aq}O5;zkgvlX3>2!{z|3P%BCp{0`(B~UgG%S3KymX{nA#AJAB zO0p?aI=j-!u@+#4^N5KW5#~>k+kkls&{)5j{6w(F6r|9ADlRd;v>-^yQk7(}MD?49 zbxMB6Dm3#j<$V#1V!sN@H3VmbbIBMY3{K4}dSVuKEb{$)>5qJXEgH)q@5&R?o#j0G z5=ryn06TIx6Cd|PpXV}1DsVoO(je=orUd6q$vUR z$CGUWICcP^WaW+kmz>yOTr@gc%$^Yf?6X9OFc(xIh*X3DT1G~Rm~0euzMH$ZC~PEy z<>nqtK@<@W@&XXZ(lk+H%w0as$*YJg4l$I)ljx8x%?p>NE+f;oUFe$&rX+9|2`<^I zjG!JiObiG@5t<~0MOImU*f8=tlf@zzhzB85w#+y}86%aIP&SF2gJen-6*3$vu>g`n z1cpQ4{jvrJDCdW`MC{FG7ldezrVAp#Af+Ht%>7UKuMq=E!Zof*T^x~h5YAD!7Lt+8 z*<+ILerG8pzeLbLTmtehu?YUBXb~4nmLEQx{3_shp`Mhy`hpCUXoN+Y3H*c3Is}g7j}iz)NsbT+`6h$A|IQ*N z5>TEFEHHHiMkrB7s?A!doFz=4V=Pie;I@=QxWT!g5f#Xdg@$O6fW!y}vzo+CW5Yr} z7)6p4M`G2ZsLm77l@h_=Cet{O0t8E5V`dbVyg1OC#6K8Feju(DKtlMKQ%f8o`eX~B z<0J4%bMOMcgK~|zpx9W7UL+|P5;GNf&{J5}Beajii$7Wbxk$icAVy@!4*NgRIFVRT z*j9@3qi};#l<+$=4nhh8;F1v?i>ekj;ld|LKwM``9pFXyl7!X%PjSp5iQ<<5nI${I zR@~%hfrii}rb^K~HyX)$3)1_6Ay=8H*Og^86& z#)d!?kXos!W~ySZa*BkxNCqMi6r$!BLqqIg+{RsWMVgM&0?e?Dfr*8E535wrO2C2$ zTIJ~&0-OTZR5c5QLEj(Fir`2Ov2}zb0@C7{B&=Yol!>q^+z3D5O2w2n=bDQT~^Jdxl0OfX3P-YyqbL8SG`y1)~TdRiq9< z!^NbSQXHS`<(3cOhGJU@L%6xOXbAMXz-bswhF~wZXb2Jg)ff_yTR$`uw3xJ^aO+2g zBDzev`JvYmy<(-ca+Q+=k>ib_iq1tSsDBtJq2U@JkyHd4{I#jdCcAca5$oSe=Qu@5B* zBAn6d?dt+%}= zpitdG`3LGsikVNIqgsr~?@{;W`;%lHJ>qlH0cg};e4mHM^P)J# zhB`ZX2%QAH3K1p9^0o+9un!Q>Axkzz+LC=AEm*FWI5r>=Ng`74an>#(s!0v)T37<2 zni9>YY;DniY&zf-BpYn7c@q49=KNqX!cXXaLl1&x3=`6fgh}slGi(NdQUT-M5d)69 zNGV)8fYYs{g4iOYvYv&6>9Ax$b}~pDiO;x4WE-qlH8XhuWy-EZ2>cJKV?+ZXSbVXN zw~!J^tX>_*;JW*h&^(@NS{p;Th(1RQRdgBgC!Mj}W{(;<2f1(r56Dj>2om7UCbYz4KD~G758+7p$lfyBEc}lBn5%bl)~Y# z9aU`r!cA|u0jAMpcLQu?4LT!cHULbJF{Uc_f3Qb^KqM@{{*M-x3zv{67x#0c1s1I+ zk?4er1WO1eTehEorBv!}1CcF46e~F3r%4cq5*H0@;~z*xgv8sPXc^<~uR4mV$d(@X zD{{^=bJ{gF;eh@met;0oDA21Z*ZF~KYsBh!W-B^-l%3R3NM4L0Na8oXGe=in?*Oza z;InfD2`gI*j0eHV+qAKPR{)Rfx~CiW$!2lrFXcc_e;|qY4P@gsxdJjFO=bnIguGO^ zML)?_X<^>V79?v*=7YZuVuUO1s61zlWI5;84%EZt{usfeQQUEY=z7r$_HIf9r7Vb6Dk;E&Z zmpDblXeV-+wR_lq1S}$afLs!zGrUA)k;HBR?1!j5CqBkRso!oqLlhdJGcxH-hky#P zj7O;RmM>q<6X^><8tl_Hl9mi?j1P}ij_d}1_R|90Pa2=7^GJs+Z)g?t;zReN06lUI z(s}q2FSkHXJ)E3^-(82hI0tySlI~L2zRq4W^>L#Q2YD^j(bCf6`S`jA@&cBO(?&-F z{N>@ca2$GEEx^e>7y%FIOLz*mM*QCfED#he?qSJwP5HkKSls;^bq@XC(txE=M-22| zY0~Y)T-X|g?USvbfIJ^MNi)`xm^fp^l;|ZG=j@OWw8{E1f6jrn{vl1JlyAt_yLX``~!=kuKdQRV+o{~h;9{Wg+tn>(B3srJG2oF`|k*KD)dO-JVBdQMC(XD8eh^$ zmEN5|R)_zSGD2k##ej~#?7ED{+;a7i!}2aKS+ zkvi(kFs$Q3+M*(FfbE}dNL>ny4K>!-O1K-gj_7c!j*C7Xd_)DM+LVFbRgee0@d&YT_r(YfLs6fAyD4~CjHr2JsxU(v4+R2jLc-r2 zkovA-;=+MDENZa-MJpIXtH6do&Kg zaDlT(z?cX%mfty#UxVl3j>rbug%df3QUNJSgG)rI(JulRYAh4p#RjK4}Pm z#&Rt7@%DumkGAV#3Xyq_TPA#mC<+F}W67w*U&27>d_~n1y0nw;z+?3z_+b?yp)Pt| zK-ctwFAx1W(36UQPu^m`BJv_3I8G-E2y!frt0O?uZ;L)m1so%J8OhEa21Mz$$y=W)sxqJWK{T*xOAG--W5Mug zJbCt7W4>kpmPmWtq%l}aCe1u9GG&ejR5>O|P|Zkg zveuWe?_yXB#5Z7e%MeqaA#CO)X0r=4Ep`(y)|O-tMD11TK+uy?=)fWtQe*RoNEV*C zueTda55b2y^+WZqgqLY5q~!<_SWZ9^k66_5Jbcs+1VjcB;EGwx08QpL!4WM?#BAv9&E^24du4wBGAI?gAM}42G7hxw^PGTQ7zIfrbyGCZk|%7ORfBg! z4q#$8Au>({asOeV6P}g)Hn-yN0^k>M9t&r4LpPB+J1l4b8G`y4A|4Js_eb)$>`%U zpfxI;nnKMG%a4A6BQdg=pfy&W&`(g|MlGKuo?fn=AZ($ifOF&nMMO{EqUTO9`haHV zumHk-INX3UJl&y{{drzEfdZ~1C9x9kf z8JK_#*_QXUcZYie`x!1^OxUR_~ z_BMkwe2h5l!f+RP#*j{$dz!m^C7jSdb{- zn1ox@rV9gyS<(xF^&za?SaK5q&oU2*Eh7Lx&?lKFxGz)UCqjgqasc8;lt?iWl}ls{ zf*I6U;G{Z^_61&<&?~nC6^IL80u6hG@C_j_M)+~ElRUs)VFxB(V`5K~v*C^x{%&5N9WC_o;l1?WYf2BiSQEej__Th(3({G#G8#-t=aXUx>}+X z~3v@EHxvGIjt5Elcmt&CiW+Q473sA#OO8#TgYXT5J(_+>mjB zB?&+dayw6mOfPIza!2Q1s9v}v@Qv{XC&rk}FyTZpW!A;?XLUUz99bdE4M`;~<7tqj zhrnf|d10}EXrz*$xmhOA(_@*IAm7EA9wY`c1!~(p*xeOLcLWl_f#iTwG8Xe?4w#m$ z40(@zl8aE$r6i)8ZJ|NGLEz*NBT#9~2bt~(O_JM!*>kVqQ;kJ{Fw!Jp>DitiEn50! zGTk;z*P|aH1?=4*^iMI43=EsV5D)>uxi=zr0-C|^H0y(x2tF74F?L*YIAemi+*&mv z9P)iBA8#q)uyXr<3*oR7PY9g*(HC4q9cXEbE}8DRjtD=r=FB%mnBN%D$>x^Z5_N3^ zSaL{>zc)Rfilb3Z(=#Di@(>t-`2e?8Kg?GgPB56@GsO9Jh2a#)ga;)=DW&Z6WZ!C0 z^ngO8i;#@RV0LMhb)UbQ;Yx?0%C{+6NzkJh%-bbVO)St zCQi^~Y_GrocW&OWdcN$(oy8zPah3gqKWUPeF{IawS&%m^rOkupP?>+NCs?vbU5-T{ZHaoS!V?QkWX`u zGUaSsNI-JuI^~5SC`U%UHt7H;gqjS2(NGpInX{$tP^O~@0PrI%<0X&4*?qK#m-e_5 z!GagIKQK4Q-{ND^HuRFm9NlU8Zd~wBlvW4A5vKu z0?bK5Ke*^bGa*SW&&0x+EKVN ztXL5dAux=nVac!%q(+kwnDC*HpIHG)k;Fu|mLTXsLjy!YvkomuchKmT01}99KM#)C zzazGr00F5+h=HkwAauYE0171^mGnG;s->#{K9#Zp+{ofIDRC(=2=#CzFC{C$sV60x zhc;%8q-A4#67Ww<*QQI@WXcjT%Rw(#1mKaLfhz$qG;-3?V}n?efE!;vkubECtQOapH{cb#{lBMBH0YU^|kqi|xNsLR2Y{*y=Cd+=5FIxOn-H04|K8g)s4`fQNlV{v}-V|KH6& z*kU;ac}iz@Z{7@$x(|XWICp%3`vizA64^EoSv%&(|8xZj%LtB6CP$xZdgA18tR_-M z#Od_sySk8aYbp&rh+?9fop~OvUdS9by2_mLi+iq2Zj&8`+2%tABO^5$n=NT?d=-%k zjNj-g(Obf+7)#0nOm|ya4@+7kGe3}IE0xxQ;}EH4VCTqZt27&ZQQg&rHl}dk8=9Ed zn3}1&x}d$VtCuFX{gO|_E))Z85y9PL+AT5dAhb&i)cx7Y;foV*y~|-!?I|1k^46HvOn@y_il;^rAYmlZIl01w;58&O%uXf0cOz zcy2-%=qli&s^Y(xInY*tHXvqGbaV`O1noOmwJzb3J$Q8aiEZHlOBu^swCRUh4#PQF6f^+ovkuP|`YDF{6Xp+F92Ri<$-l1>xMGLjs0^gei~!j(odO?_9!hEy}4; zKK7&AujHxfQB`MJBdB8uB;%SbH4@AiC*}Q5XUwL!1R9e|sVftyEUzpvQ}$!nU_}WR z`WBSvi1jQc=Q)c>G;iX%H_N?Tr&21ch@+t%N?7VY5K{g`NMSHZtRO0*IC;)BdM3rs z@L+ud+*KX;DA0v-Pe=LQOc?8$)+jNemzxd5P^f_I?Cs7+r%4xgD(^+iE^l}61~pHF01z1?#d4u4F(Xm=Wg-O&6L-X9` z1OmnXSCTpFt*s_@ROqK5BO}w%!ra6L|5o6C?{;nQcXd|pqxeT|p5YWj8JYCx_Me?w zd+j|}4+I1OPI8JSi zj0{i4!o<)n`1Z@3iP3i(7XPwLy?R%`jA{>0|KC+S&91A?dSkwsSJXyP=FaO2I;T&> zwK-MS_VrM$4hv5l8+=Ynu5HEW=)v8(>kb|p`TX#%fUEB{&8qi?YBXf*uU_6;Zo$5i z4zns(tf;&nP&{TvUFUDFJ4Y3|$sQ?>nv^7)Gq>|@tH^o9dkV*Qjx_$;W3)!E_U}F| zKUg+jyI;rCA8s$OPO-b>HtJdZrP}E3@0G zt$k|GVZ(+UovEQacC2xhT~zpGK0vXC*fxM40Yny_RRzh+5v18%O45EYee>2;+D(q}@UGPTyiT~BN3gD>6DhwSu)HA~&`0bTnMqc4tBiXOS!sxl~hT8iE4&kX?`B8~6W-o;`vU4vyD%cSDeABP@gKyOY{$Z2iw`|!)pUf!p!LpmoBAm3= zm3Xc;+t&(cEb)|+=@WhN^`|d=Iz^s3b!sKxD{xs=Hs3VK#!$6Ko=f`5{K|93=M@7_ zf0WHn#Gld{C+&XI((DsUJpZs(1(;e&(YS~ooHFlJzHRu!PQAn@(^;#J)2JQzIni1b z4|HuOXPsJxD_z!`IO)W9?a-#gTW4ha6~Av^mv6l2x~<6FM7gVK4+YC)+e3#B?=64f zJZguG%+t4HKGfG^wDjZ0BPzVt&d*SYDv*sUS_4GBeM`{b?d$8RtGL%u)72p1Cz-oG zzk2KR*W2AGQ153@g_V`nHBaq_fqLlx-X=vx#vq|{XpR!_trXoB6i^$~zr?dgX-$tS z9^K!E{ygGQolAl7`>SJL>Awrs2Qtoi>qO)_odXVlk9{R8@w2CP_{B%7fD%95)rD^1 zpp#KMR$uXmxZ+`ayuxH(2_7&S+-((p&AzvG?vaVOsJGh;S0*Lp;a2uNvm@mZMu`|| z0)B8vTl?VE#bEvID|cF|1nVowhnK&I-P%Rwgv0QcL1S;%>depR2Y^B22TIjIiol1Z zO82$-16|VlT(3Ft`Rd#wk%4-fcJKcA_bVQ!zkU5=t=i*M*cUxK0doKMivdQ#o88vS z^@?ikbN{sbk@EIfbW0U{xlR0)wXv~1XL$o1z{MuBpXMIv4bC`T(IF`NXD|l{8{{2h zF88RePoY~kAWJ8{Ba5T5BVq5I4H64k1vZ2h$RRpxgdf8I&!+?DuWr=^wwj-y#w z@*p-)omKKr_@Th1Ra8NErC+<~ixD8dM~_^we4g6TrkCmGCHWE5|V@+;suMru<;$1np7=ZC z-3QZC?8xg@$-i5we0;Vq`e9u#{y1eg#7s(ZI$p8)iU*!& zofU74r>g@us91!Sv|`MGOT*;SM2EDh*RQ*PKrwK?O>OW^{0;a4LhK|{t4^R($o|wag$##H z1ug@}-+ENX>$gc(#%k)+A?Bb>kK?nxeuCHrp8?MxE&Q33WRzkT?vQrj`Ezyf4FJ0E zXk@RbHM{;SaOn!##@|5HnOELATen(+)_gLHTvE#B`(@vI7L=Xv_;2-|U^_eYp1>9U zUYnn&VHcUd%2H)e!Dtzvs?R2~ccJ5U?b+k9U_pBsEyYd{W+f1`cIuUZdd?XRAQ4cE zUszbDoVn4N_e0x*5U@g4$+lK2z<&%HK7Km;?Nb2=A^YA1z!3={1tAO0>C!0@V@y+z z#dr{dPyvf-Z~xLmp|y7Wl$mMvY6fNVe*qJiL1uQq71-j?F( zq;)=-cdpe0f)@^!zmVb8{01_E0K4Y{fxj*C?{NKuV(^PmnmvRkUfKr&dGX!_%#}V9 zoK+NET>TbW0q6inU<9olmPaeRp&{@yRE4KbJkYeRz{PxUH-F`BPJX(I;i2z8EtiWh zJZPu>*ndo`-bRUCKt+&4Pv2(gFW6d$MH#HN2Lch3Eebw8v(9>XT@-&=@S;VlLUVqD zM#{+e1$=ko#bUgE>Yfio9;5;&6zB(8VOWTV4sCwIMf{4NfeX+bt^+U79=E)84yC0* zLYPmRnOe5FxcZ5l+axGzi2XlGYlxom)@j|wW7XyE4vE&hxFUI@n?9MXWWYRI3*{>P z`asw9f=r9i=4stxX)DQwlR}msUvTS~V zpDv{QTC3!Ui;ud_oDE}Pe=YQ2X$=;0vsE&bopa`$kvl9w6I%T?9X)nT7NqQPd_Dd^ z*D}=breRs?)a^R}SnqfZhaZK+TW_ zzz+U~)WKsLLL>8AB@{v=j-Z50Kda}kT|(cG8qoT{c0{;SbKUzqSG3q zR``Plp^7FYDQAs6n|jY@;;0?xA%Kgk^8@u_P4l+SNG)@L>GI&!zOwm5Ksjm}Czo0j z13iVlGJZ+t26T!9^1%V1FOdG5-HfojSzccGJ~YNEdC0?Dr!G(Y`+oc2`)zGaph9x# z`mI~L!@h%MQ{}Ed_fYV`uy6G%zEwJDZT@O@ykfOg^47U#ASv}&qa>S{7a`!uC;qvf z+RFVl?Jb*c5f`8Rt74}?TMK!8I^(QVnGYF}z-4uH zHPN`?rpjHR&u`5C1%E)b(C3CJAX?BfEeNZDs)L;DmVg=HXphm*%?(RokI6v7 zXzjM@y2%VA3;uoRrwel4e{`2sGGKa>KWk->-p{ZN!S#3r#sX}k^DZMHn8EdTbC&i7 zqG6gq4=h-);L;O+3t7hpzM+uqR-IM4|YexR!E531kFuRB){yx2{Z?JMj3 z?zZ>IVdlL{2Y=WM9bvXFX8*6Oku&z}+p(P&>h#APAZ2gYo_se3+E8DqGpw)Eb4RFb zU9UZ+u>7ynr%lrAyAO_BRT-@sSA;(^`TV&17u-h097rmyF*#Dcwco1FX%*heTMM1^ zcIQD6C)t3e_C0t7o1L)7tNQk)2TDB6Ck2FrsEvm@g1B;8zI=|;GyklOe!3ge(uRBW z+Y)K79!rEtJGuS0RBXeO&qDOTdhG!MhCS0RFl^DHfyH?+h2|a^6l315UG4)%*kLJl zNB{auA+=0hBT7X1ZuXp}t7yjSG68OnO^Qi|L(e}gd0kdQD>_*2E13Y>V^UH$Y&+O& zGO)-iBS-$aB+Idz+ku|>mC#Nw=Zt@Eqd#k=+Z}Hm=t5`BXMuV!C9vqkc3Ng&mpZ*> z;?bk-(YOfPD$gf#-T6JMCH zv~P6pp-O*#s(&?p*A)*)i*|Cd*K?1Qzwn2N-QDf@EJ(Z6`OZ)uAXga}_K@pXE6B|* zsweK$D)&$r*r!AID}I`N$&2@^)5rDc04clr@Ue|9eLJ)X%${R-8A=z-2bp|&?vc+~ zLD?NM?`*0GRBttA{P;-dlXkb=M!__8)q>v)6A0!v{)Fc2d0h_jx-mcFnn!S6?)zu*4INl9Q{eu>p(+!pQI5^#I=+Busra zp*UguMA)=YncDr}XgsiXhTL%cCPV0g@MC9_k!(pR&+H1z;!>QUD z6Sbzt9+-?nPgHnscbS=JO%RQ7OFY{hI{=daG&jk(W^I1u<~<61pMbPs1vsSHpD=dx zl3leZz2H`3ccAwuh5*=)9b`Vwa03-iz8cwc}A z3)@k%H-5k$nBDODKwG%gsdHyyio!Xkw<2WJ zRgclIx}Z;Ce&Kcej6dfeErLPD&ghQs*)P{#)fdIyg}_$qloU|wrwiA5QAkKgQkNlP zwhgs{q=jjHG6)g`zSi8<@#{Z3hvv+^b|5Hw(@YJO8UFBWbQQPX?~vv5_k$hb7dU?+|sLytBMuwm$CoR?StN*lx1rIv{Oa}h?bIuk- zG1P%>D79l18sIE=*dE7soJ)bxb?MOGI|^lq4)WA)x5kJ_!{Ta)A8;1l!q3nRw<;>S zI&_|XuEWDo>hlmfI5t`-ddR~bMmEbWuPT1hd;DmYMlVPx{5j>Q358dAy5P|w!@c+l zq#h&>BnlhcN#%ceZv1t?(_Q+tP>EzFfqJks5kJC|;DWDqkd^5bWqLj^*U9=?-}&Be z8cy&3dAHR>&(TnnAR~xuzy<;N@pXRZ)|Dlm+PY)L#Dv%Xb1xfOHjJ+5jJo(MO?Q-j@&f_e&T^uX0(P+n@HSka;ub z%rQ+ZGlGW%_a22kldVRh!;g^MbPP?H%Z! z~)bQIH#=YD3$0Z*C*>6-rF*p*lKCJD!LpjF( z#7qr@rdB%^-S1YI3Q~iD3OhTXCeXn=6Ev(4CIeT)FUt|?h9Is@1Pnj$6R`v9KjBI+ z)Xp%aKZEtZ!qISDy0kyEqxJwLMY+O2fMv+n5Q5jvRp; z3%kDP+n6K-lqPrLtH(lZ!oW9uu^(oC`3oqo!x{>R-@sgtzBs6+OY3lry(zg>;kKz| zpirB(F+=XZswe(LpAII^r;en*Xe1wm*+;o4bqI; z+WF~vFSPn}07hYnUQbW3R8f9D*1%x9$KdxrLvHdMbI z>1sKQA_xXN|84}N8tmp%UD99uQR0cn)tZgZ>w-ZIYkoPi>ukKG%CxF(K!y>7Q*iyg zB_*%w>n`;7MNDnO-*@L{LBz*RE$h~?^umQUz%vv*Y18kcEPa%|5&=)L0X1Rn2bR{4tp`1rx_@f(WxVY+=fblGGE zxzsu<@%$?LnSU3;rtY_C?J`3|&O&oE%T?6ACfQiL3EI<3f10OX;Ww*2eJm0zd*9OC zSm09CZgS@d$97Fo>Hg3CoG2h+*~iMrTleqx^38QgZ-+GpeIqS^035vUnHmUcs%ZE| z z|Azd0V+dUm215W83(qKyG4WSkKaKZAlw{CuEAlKN1ch!kZqK1(5J0r3gvC^Y@|f zaUfEH-%i^Gr)yzi!Ll?^qw8 z=eYo-mgEC2_pjFe|#9x`E^Bc zn7!g0wd@1hFvO#hMvtw{nLG8ALyWn};dy$w$9~OE-G1OR%*y?3d*szU9<&UO0x~R% zkcvouviHbR^;i-vPA%IaGjZQEXEgwb5Tdt_k8(os&!dDlb?9&bZ?{c^Ttav=kYgmcny|#);+_r#M92|3&NmS*UknX zWqfnqZ+~{MPiI&ab$^)0)IF5{8dYU@>dTBxZF}ZgcK-HlBP{0LZ+8RXb$?hs{q`bw zv)q^Xmz~Qp&wi>c@Ru&_%tx4{ zmQ8xF_VWl$<*#2XRep-T_>&AQ6IdfquP~(ZDk}O01qI1Y#Xq~?r8 z&-*|4cp<<3{?g9yQo;?d59+^h|90qGXeGoGyVi8IPZ}y)Q3`deu%>E5Q>mKackJbhNnP4X%NJ`UHhgp_^n=v*Asg%@_BnL9lU7-YjbOJN%KO zE4^DE@PCz4uLQ}i(dWZDXfEipzwRAA)!?59Zh{%Dc4p|-^#^~C+r4z5PW*&w{b%NV z4%??H|2%7tb>7!4pk-c{&81<;M@*bJ5wc$ws`lRl4r$=rM-LxP*tM(O_G`mWA#4zT z1+LMh>VRoBlg&Eqhra7LRHslD6k$+dwi z4f~IC;9ZOOHgtT0JiKBpi?0tpL?YM>sWk8K$A6Zb&E|C{YG!0_^!_T<@sXnDIt^<$#3DkvWQ4BZK?+k3*{J59B!m0=feME+5WT40vaTm_&l3 z>bH;4-%dFxz@BZr2%*0>?jKc-S6C`Kd-?7vbn^=iR{f>@lz}1Lx;i{5yj1E^u^{@I z`qUMO)bI2Z1J+E zqlta9ChvTOlcV2>)_=T9SdaopOi4tzxVpP@3N%=fO>Rw1%7o|detEp`%D>wp^>+Mh zIc$eVfNja#Rx)tuWV8bh?fp>uzMPMVZ?=rS@{)gY{O>u74z5MS?uxlzmz+>^-Eh9-7l`Qf zCPr&7)z;P$dt~9lj!?$m>IQrp_!|O+y?*t*zs+`oobB_CmJrq^$L|jsRQd5^9~tX3 z`}EArp(p-;#KfFQVhMimr%yCG-X@|dF1Ofal5wooyrt=83v}X9*N|VDJati6m}W0; z?+ah|_D(2HPU!zF1aYz}?pl4$pVy9^R0&)8*r`_S#>5R;{&8%|%BL@S7yOoRF;u_X z`b(SUkJ>@fxCo^W`1bMQvA*^7^)Zu@kk`^oxjka3@0syw58FjNIJL<5c{S3|Zll!N zei-2}&$4?(pX#>`Ujsh-em1ak9MP-2S6=i*S2!(?{(b)fA`9mBCw^_Tw@#E#=CGS> zQ|uI;!?FX(#rz%+UI3F5dBfj+`wh_rq&DTI?Ck_&v(VyiyRIuIoJwJI56CI)sup(&*Kbo za)Xz`Hi0ZqM4qYq2)}nl+xSB7e~xXNIrpREwW1L>rzpnWcvU}5qgNeD57q^)ey4Uj za>c*PZyi*z*m-t+Lg9OhcQL$P<*(mFjl5d@7PzRYyOdwI;`RWy9ep~ioob$U=gytZ z4F#8azy0)O)c8}SHS5;&De3(|^_hNug*7DG1TH!IV1(yp`_$M#gixFpFYXCVooL+- zu2iq>$a}z=)NtJJ4tdUNPM-bxDy(_2B}bS8v6e$MXF)U5I@!`Ssd&1CNvs>!Q7MoZ{aT1{jUXE-Xv6PX+mP9}t4z=z{XY z@;7`yZwC=Y$gA{2e%}RBj8OTBX-PJa%&kGjko@uS@&3k(?si@l1xMECE*58MgA5=Z+kaoQu$U1fv#)D;l7^^U; zW3*v3wOd{M)E{ZR;_B=wr4AF?o&8q&6@d$^AEFYfy`mDfnZaFz<7!i+^^0@luH3!t zVdBT?BZD%iheD!#>iTNMi8rkGXKu92`TFmRQ_DY{+^o00%e2>-XU~q%DcbcEJ{NMu zNu|X*3!JogO40nfcl-91dF$-E=TlVw_~iqTk-2)Ar?%Xzs)J>Sl=^3BB=`L^^7L>| zf3FOOf<e>HYor;zr@$)NnDsLPl(q4Vaojf;ze9sTC?7|pU5@2gF0sA!>7^AZKa4wPqZOd!9VC zO0voGUXp#UN^Rg8j02`L36i%(;7RPl$-d5y^TK>vLK@$TyI|G=~`HS zuoiR|O;_)Uh_v(T-U_XkRgZnJs{BRIfPuFozD@lUQ8T*Y+o}lFcw z|IToryV9+sU^;?sBQG^rx^?qgxeGC6kTEZC$v=0yUKs6uAJ)EGcf~DN?j!Zw!-+To zx#J^}OKZ*trP`_IB2m5p#;{xE>p)!$R`P1$+nVpxBQ#17Z5;i`pe#wg7{7<*b z5ivV@^5k0R<-uDmAk5M?4szY^s0jiq%sn5}#&qkpo7ehOBTn~m>-dK55UU`bLEYB3 zQwVuaG5>XU`tB(4*q&%Hjve#5knwbx4CRQ{;U4 z*vc1iFM>jDl#aMP;BOLlIM{yM4ofquKJ)#5pS0-m*l|kjKEcPeh-{a5{nM%(#ZlX$ zqodaZm`zihW`KGK_$E=vR3dTFK4x2K*BLWrp!|zyhvBk5Ryv(#%{zL{BOxMZSa|mn zYgJ^E5&6Tka&pEkTJ3Iil?O#x;xdxAYf6FFW@PY?3!FD^9t!vN<~=#BzVqs}T}cmK z5&P81`DAxbedJzwhLQ1wnlgZkvZ(?s?JRXO&lm2cj38~>$dYJp8W zZ#@cZQ1OQl4x;vmJo$YN&*i~rhTVN*J!)4_+YuQV>51S)h67wurcAJE6LOxb_rmO5 zed6ykgUdV5*^rr;316>n&4^{KUY-4B08`J~sZ+u_6Xj7ecQ2p%!5Eyd|2C4znLhW7 zbmC1BZvo}DS&P^v%v_CLTSKEge;KVOi|~&^&fHfka>hUFn5VND=EL>sx1^G;!h2F? z_DqdQ>0#AZe@@&1r4^$MSKs329cQ{$?Z3Y+{4A;*D*MbTc})_fkL1mrcMsO?zTcP9WViPt#+dKham_k9X+L{x2w21?<0bv!H+im3R_EV z5B!3vsNCL35It=XH3Ax-4B@IP8&(J3aMT?7Y~a)>N;2?jKI?9*)_vIEc z>o*IZO;w{EmWy`9^+yRF5j;SKP zZt$(4I7(-7n*AV{C?IwJ?we;Bzxo$?d1E(OPsF1pCD}Y5;_$HK+%~6vvnJF8_JjNz zH6vbOL8m{H%Vul$i}imrqhf$#DT)~`&(8>5qnH1A_oYiEB{3b;VBpIx?>1an?HKrA zw^jQ?mR5?TX=9iCgZOD>$-aqXfj?|JBoEbvoDPyZFUpS;k>G-j-H7Pg#Ng=u1LLo3 zDA<9VPtlWZuOnWo8=@>x`7f0}mlr)bwtor83$<6l5$|O8|MJ#P7a93gaOBS1US`mH z=&bB}nxmr&mjQ)uW9%FljXJaXEQF7HzRi7s%dTQ9e^ z;|UaYSd0LVX>4$RUW{3|1$Jl%HW@tY*{ENXyIr^u8Stl$j?U4{%t%!H*r_80JlMQP zTF$LokEi?S#HXjH59~01&z3_2En(ZJJhuZ{(Q1;2T`{_e4t@gskJWQXD+%|n47{=k|erm7sX&T`-2aU0r)FII5& z*c*$=79axw1!OFat!uv~T>I_V-JK8t8LR|<3`tIS$NtIzpEYI=x4h!zhREsQf}f)= z!eoT{e={d|&=dbLi0vv47yzSVhJz|xtev-Cc13wY;{J}2#)(O>lZGT7STu0dPZla$ zkFEW92IJ**+ECyktFn8~p36HO!#q|$LSQ^-$r5)36+=bTM0)Ei9invN>Y(9A?$l1& zip1L92d|3ey?pg5-{Ux>>bJ|Ej4k3_P_&8o2!!preqHr2Mg8$%t=bIl((WNV!pr;5 zKRMHSTo2v4h*wC($-~b3g?M4R$1aikq8x=%lFRjpQO}+sfK@Z&ro3z18yjRYm#t)#e}_v*q&J4@mwY zOaVh3dbyig(J|vXI8(@pBKz7N0k&89`MaL}vbE4;el3JGOcSqD}SY_VnnXP$jA215K9BdAu zGIfuB)^)|l+8uP}jWI-G{2|;t6pD25>0fpj;9eWMC+PFvFwrixaee!XQZ%te;R1FE zj(tBFf)B;tx{AF#4dSm%n!9|_qE?7IEgyMc!wH2Vw^6VV5SzGl>(;3%x1!t*`$u+c z^V1GDqd!(1`2C$(a{4n&y#7gH*54Sn#K@fgKw3K806Bp@Q{YX1_;9jI45Z7u zu35ZKUknfuRg^`(2FW61J7NFddhp=vmi34|dqr=~`R9FTQX7;oBU~K(^>fz8i@x68 z55Io-1axkh9SYWpon&z&x~uBlgDrf{AzreddVvfOKZARg_w(SbD>rs{ zTKjl{PQQ*Qs;sIhO%8sMmg$EuIZSO_QC94PROEW)dPJjo69fs+blOzCvVnN1RgG> zl=MAZz8HB=LfU}TWTK`Xv7#8%iFU#DiF&)Y7d!uE zl{`>+|KL--kZSO)JTTv~%XhIX_$0)qP(@CwJ6L$s?ue z={wl$PHhml^ZcW_VRgJ#E44@8T#7Qn(<2e&^t^J=jhAOxry76r(8#z_(*qB$c-Z)d3Dr@V-UxA~O6mw^O2H6sUtkA|T{tEp!wZTjtUwmV#vj*O9@3S9G zv22SJ0TD`IKVFYJBZpKXB34Mj;;af=1-r8kqG6h$SZUqzI8@Zm-k323^)0YE>{j-7 zU9p1Ct3Y9=O^O`CYcL+#zmM#{bl$v)2X#M(VJ;g@u~_elb@{;!PRi{J)B1J%bxhT> zxPpirGlgy;|0dh0-95GFCnP!ESh&M{@cxst|LKXq#LL>+!m9gs?reQJBI##4 zN676~3EN35eQmJ5rc$5N%aK+)v=1&F(vXIqRoe}ZE4to>r<FOc|_9>~(X-b++%KkQQgY{AKj^s=&<4wQa5X} zm%OTiH4lvpU;FydL9y#=Tftbkt-8S$0o^Xvqj&rrJH@QFZ|-(fc_G4h>5sSk9-X@# zfgs;f_&C-(Tw~*aFV808!ylv0er#V;*0pv}=Ihecvwzd6I_(Cvk*7V@p>WRJ zxynk>QM+4}os29_`oJy68SMO0*^dGx+nz^g|aB_&F(iW851vw_4pDmZ-sl z?OvDWyL|F#Bb$^PvB5{XUeTGLx4YMy3CO=AQH;Vl1Q}yZG~+&P`Ve`n#FMw%Dk^@O za?DD^i6E}S9Kh9|V~s8Yij?yx*hS&%?c29wcWz9nx_@5@)&3~xKvw0SyIF(sj|ODz zdaZ~oF~adOor=8Ruy;AoI$34z*|0f^b4KszfLgSZnPh{^AdeAp`iLX?-1}=tE>hhj zlHB*@poTADNJXQ9vLs~WnxxV#`IV=xKY;a2L_KN|;kPKqbor}W@8N3JFKbY~&x@Tj zC&l)6v#v3xQDj?KD1XTQMNj{CBQ{JlNQjG{*RUBpUEm462r8Oa zJo=J&_wL;uN(uRu2svO@-7jB;|A+VoilW*kdvwt#L~qQPtZv>Fq`pk4YojuI^%NwbdCM-LIuO;rkik3F z`NLT6YmK`6A+eRCk5_oZ96#Sk>ZV%Vu}^=j@VK zN=W%Y_Q7#{J@wnWsn1#5p`ZxpZ%ccgKZOdh_(#5gt{rHjc$MS zoz*Zk!Jy~tpAL6+P`q}b>e;h)@c0I-_?&*D%sUp5>O#$1CVVsZkbn^b2Jf}{_HpC8;BfHmG!&R_BK(xpqgwfpxWs(yD= zn5^)FPLF7RtM&}M4&8q>s^59vsD1hJ(%JFj#>JNGTRm;ovu}@wj?cw_C}Kad>-@{< z@GC#xd+_CFIOr%{LYNmdM{sP_R<`RMk1BhZuLxW!%i4xIZLZ9f{oV1zgHJgRj0bl! z_RHsQU+m}W`gkMSn zLQyO=V@>D3@Y-S&z4Tns;Z5rYE50q?m5{)}*}R zba?2i&!C(ag@44mi}Wxskf`n?$_5YTe>cG1e5(#AFoQ_$2&#}!iGH7*(vT}II!^*<0X>HHE12)ee z)jKTXddqS0s>F4DwN5#(ABb>4&|`SUY67PAVwG*`FkPCp=Vo!G|A;skQQt0gQ)bhX zJHt6?Z$OLrTs+8EmKu_dknVL*ZRxU|EnPn$x+5cD2YV)Xy4G$&ATb1W1_Cb1BZE7nybBvkpt_s>nlViWhFE^O zKOA!J{*h0P^w~3j3@fY#>1<2Jmhl?{mv3)hkAyx5Z7Sx!()IEg(Pu-<~^>$9JR~*%p=d zAk+kFpnFa?BimQTnW89*Mua)!U_byDf^C0oK!$LZI}@yJv%?(ZyayIRqySX=Ip7b7 zFWZZ%WWr8wWMu%x@C?}KxuU><=O6=t8a}ly^q+cUXD((SO>y)d#XDo8S31JVj#2Ha z4x}2=$G##*?8BZ3C+P%+D9icYSl%j$N|w)6}I;Tu6MP!r&Zs2 zC8Fi?5N3Y(TTL<257dw|QaZZs4N{26@3PZiNs!4DEUM5pzPX;umYN5Vjq|PnA#y`> zu4{>&F494W#8#+Yd6+{sF8nZN{<;9#KFB@cD@DY-@%i>{n#d=Ert8Jj=fVIk!aIlm z)js4sIfnH^Er&vF`SN2F;k%w~NZe72-@uN2#%bs4vAmEPW(s70uv zE*lDlj>YVl!4@gXs*DH>g5o7gKbRfYI~+7((|+_+vk*C{9hFJ+o{w7kx((2qkG+W+2^}nZJmik z0J{QXepKUpfNb3YbPFKZYdd7qnY)f>PCO$5PqpKfKOSs;o;!nh>;Fl=Ya4*6SlaYo)KtPCCDtZSihIH1S5+7ZZe+->tjT z#NIx7NrRWti=4d=d(i9-M1Ap%2Q~s^O(MAul$Dp_xtkttZan64`6eP%n-s&^^^O(G zOYY(@)_f}JIz?V=0=_u9Q zM_I=pa%NJ#@45M&kRjcv7PwVb8l`{pJ%LeKUzXO497t$iwG6vH-1Vi%i4*bfKmGI| zQgYtj0^>rYH34g=E2#N4<=DlY_#D2;G*XCIAlm(!4k z;&RMdB2+8gb$!p3M+p}VKKO%1b8{c|IZ#~>@}Qcs@cXp(^4PX}TOi*HFG<^=SX1lr zkO3RLt+6nT)`X$dCFALSjA=%}4*_^u4vowivAjRE00qd12*qAh)-=l;rx;@p3E3Lg zWDyq$qKg|NNLW-$Px{F43E=c* zcaD0sI=LfuZB;s{YKgkgU)9ycGZa}2#_N-$Y`0i!1g=q_Rn(NuuVhJN{^~4_@_w>C zOw$UQ9Xbb}L)cXxPmO#+U;w2D2;r1XS6a@8QO)L#R1En@gLtZ2$(2Rvae2OqNc|~NBBI%*@&q~M%(X)QZ%)-DVO`jjZc1@2wHkO zxGBES<-5q%VV+=@NK##grL*>l0^di>DU$ITN=4%@HWwUS%*aVfs%*t@=Q=jNsH$3q zT>_gm{KLLVXfw<|417GCLFC$D3r+}xOqTEgLsty%MJz=*8d>rM*w7uHfwr=hS2*Zo z`OgZ*sKNFYa!ZjvmR<9Vph1g5wv*F?7 zORJ`2OH<>u(sff82PtmaXr6HzQY<$ji5D0=G7M6ltvlB;IIbL!>#G{6SNieWNYAIS z?nCl`Fi#t09AP3wUW&&_*q*B08)y|gmQn?xc;5)hekQ{WZ-%HS)>9BEw zEWSe#2uu5lVw~(2v5A-VsJnzXUo7w7xG_Z*5ug=XGzp zq{?$gnq7yt(&iY?{kQ8Px;_plvwX=5E{H!Y&d5j|l(HSc@6%!P#G)TfU|EvehB3I1 z7|slc%y8#i0iI2yMPubdyGN%-eaylc1~?U>#=0CaK?{-v`<|je9abW75yl8 zgeJ;J27povTIxk&%ps~xWtr)Qu}u|X2SOG<2Wt+8n2CY9zrTd*v?fG7PZ5`K%KHln zg%XYs+z#jp&NCdPN1o@dj4(+i#xME;?#HjUj7|``Tix9}%q@4zs0Rl$rI5Kne%2kh zsdYh_*ExfMv3`pMCDN%udaj_z0D>%voY5RPnb1w~gPnN|J*4Zop8(TjsX_z{e=w6D zQ7E6fpIlPr#@L`#2#fVp&JjE14vbq=*9g2tOtYu%V0p6GI$usqPxR8SyoMAX%mC!C zfJ1ND>fq*k<%0+^Q1b!hF4ER3nC7EY z0qCyI_4(7ZJuWVE5hD0W`Ow=$zV>m66$cPDO#N{08l4*GQjc#17(H_eHDzHK zgWKvIZP;ExtRb+aaTkaxQ`MmT@W$AKZOzr{q<;8Vy6OE}<@_g+M9v0m0$65keSM5q zAN8o0EVDZ2(?$M3tQVhi&PCWipIVBQ-7@hR6Y9v|7}I=NjjR}WvPAKMYG~G=VtaFyJmX5Y_U8K= z4D2vs2nGp>mRS6XD;!rH;A#o>gsEIfHGqdIOC9e5+1_rIsA-NzP_j{)ym{S|8!(Ye z^#cYaG9fa~7b)tHH^TP0KD+kBoy`7)X}p*%ba)It3xdK_}~IMaC(wf3gj-mtp*#WKqvHp+Ktfug|4 zaqcojf$OPT6YmTSrGE0rHVnLVKuL+7S*hEHv0?nc`iqtgZa=oA^yy^We=|5EUpe)8 z)O||W*8Gcn&aE{|PgYb`?&prkB%;jwk009&4i2)by1bS3>QkT#EGkkwU2M)mv&as* z^Bm)ZHTi0%?%v&m-;EF;lD8q^y8D@#q%4t^x~VC@_I0g-uPwz!pck)&gHc}?V5-k6 zz3N)alz$;o!LYP!#WKCMQ@mv_seddsDb)~*&k30B2)M5=kapg~+q(|vF8TI`b4Ws& z(A~?dwbrOWE8U{qrS3&Z34}@lCo8@Uf1I8!czLNojDhX_^XI{f@~-jIB!cIH$9O14 zt(a5J*V@X%W*fl&7mR&dYrO!WykLNyBB2U&TwNUNv0tJnwSueqDrx5@ zg03Y-rlvKgYieo^fp*V2C~DnXFmcDj_S|Qt_y@b69!GfsRKU4a@9+tfNf_Aabe1zJ zl5tnfT%4Q^PEAcACm>qP)y>TkD@A*cuAO$yg?K23Dx9H#7ZMf*o~0MEORXJJ5W$sR zz2{7l^RHC5w^Q}eg`Ik%A{MoK_io8MP04ODiInYvA|l@;xY*e40vp=$98`MRi_Qb# zDp$-RRG&lMneQ|FGPF2FE2pYTXTOnAR$bjbzy>3oRqG7IpX~1H8+pAvyRLh^4aeGL z()~%Y-sT9FTO9h1jHrBxRAhqiP3dW*@=}Scf{Y*jL#D>YhO(TwxX1gOpBJ9Hps?%s zp}?^8!a~!FCru_id$md#!b%gcV@a!YS zR6+YZT)u2G$=I8@>m?saRDQCVG0m;x=+3D?Wo$~75KBC|v~JzHgbb&o%h6BIoVm}; zE^cqi`Px`GU2~z6rpUxGl{ekpw?Kt1FsY-dRlP<6Ljs-z<8@v-qLY$s3xyZ}vPjnj zp?>27Xc8R8X(qziVz{IE5n)>>*2R5187Ji+mO43Rv7m>D| zJD#={w!+@QL5q<))?RCs(Myf`BV4Rc8<;L2H&{|Q(7d6*?-STE83nH}6%`dYm=$Vi zky9hNh3{WegoY(^3#vpj1*U%sq)f#Kr@Q@~1|Tc)?2@6S`#|f&{zG?|RYJ1MIPyk#7iJ;L)%*!^Gx1FW1W+kNtuy?^b^w9IrOpuKjWn zlKPkBwG%+_G)ps;|xd4JQeRB>iM4A7GJdWYN-FQc2w7e8b_ zsO1MMWdd*ejY)wo|9)n=aW7d1adC0Fh0Sa&oT@I2oT^WxVW&EKdwb6-ELT{vuL97P z-C{$xOct7NTV-XdzYh$wzbf=H#4y=gTdVfCdXPO7PTavu68=~5qEnl`Gv);MQ>MMM zNlu>WN}Ara>Immj;~F@v?8eCO%7X;ZZ}386PIB_v1*&X}qN6G5bPDa`gB|8;biXV! z_xJI!MLZ!81ouiKsHCJs?Qz?JWS*9eqCGQLeJ&k%V08NoEjfb7GvYzry5PgdRp(GwRI`(UA1LAt$uaKiVDb3fo!0fAX2xd)xQ$6;|>OSvg%SX^oI#>ZCPN5`IOo zn}#GhOZbCu>u zaJ9F$uLCcr&49pHw5nlbTP3pkmmo83G)jW9MXdf2C zvY60mifkjyS$Mh$i(7V22=p%gRwci6>tO`ks9=D^DVtmrDvH(MeXlDLqxRIcs)w8P z=tS8CDaz{ZoPu4hik)@zo#{c6TejF>Q!PiwM$;on_XZ8O-Nu+u4?Ae3aVykjk&wCE zT+}78d2_m+wTp``3qt`(cMnu()D@Gt(b{|!@q;Kxu;fSpvh2P(jMp7X+IL-F3_M!W zATV5Ed*RA_S20nW?Ck7F2Q1T%U%p&j!^w&5GYJbik@9mHjYG-dlQ)h@a6TX~hV@1~ z%vHAl5Ew^pY-WQzmVH2c@MXITUPN-}L%Li_aH*mGb&toVfXR}8I4CAST^a(d`p9-c zGrR6_b)xyD&2n-M8K#AMj;ubxHJE^@63>67>RQ(AWJ|x1xmB1zP^1MnRxM{A&9|YZ*y~{H+9HSC_XsMU0WOWa9z|w6(r;x>tJ$_XIXBzF~87j zZ0$}kzv^kax)&$MD+4}+w0q1f}7|9%HqGxxeGD=UTA&!{EV+ewil zEu~M>j{vT?tp8T=Tq{!`C{yyYXV0>N4n`F5bd633U8wl@`t@0eeT39{*I&xx3J@+6 zH57ov+R7+e?JSa#0BYoA0f{!bZ3u zGTsXpE=Yrc;`c{I4^fd$O=ucT2C<*@%KxiNfmjRlG2G}eiq6}&ZU*4@p|PU4Zl zRVmTUcNAW6=6>Uv?ps`u;bX9}ddSbu@2xj*$7N@vQ_4Oi#Kmb(jCFRFLX3Fmx<29A zY3|;=|Do}o^ksrBa!H%9?uxI-K|X!nYIk%jkBP% zVDl-w-$?~MKV)nB62hbE6|^Uxy`=-0aiqVc*i=Er+4hha+iJL#@$qb~dG#YL#q{o* zyPA*}ig-N5+!^YT(gO?i6-4q^U8T1DabCpK=(_$RH!h2*&P64y&W9z~V_&sbzd;zR zTPdCk2weZWRI@M8%&fJ;{-!(z&?(oM!qumu=MIJ%|5W$`uwpA!dV3MJ-Zm5zh}m$V z!o+7+YyShk{^C^viXC6RL`yI7F!S{_zLcGowjT3*B>XX#@{zloXF;0YUb^4KfcndWvc z`g9}9>6CAfxvXYq&vKH!wO06r-U`7mCe_=!(sV}vu*^^~t(2rrGbS;K!V<%$8Wec3 zQ9=Rr6KIT>f)VmUWgPH!Vco{V+kKg67FE0RFd~gy&3U1V==oQ5AoADm-TIY5#>Y3@ ztF+UQdB>|H+6^m?Qheo@=D2~{CgiPKw~mk-7^}D8*55WMq+5A-?3p~1zB}ow!@^!9 z6V+nHaAack-7hE*UbBiN7N+gWl`BTRo%&D|s_|gDe6YP|2P9xu)EgT`E`-__E?r_- z91*|liz-tiTuQvG86hN3y^Lg=Fa2I_N(1H%kKDiM-gkd!%yKDkA6?!CR=~dk?K21j z!@MqDlVCd-d2k$>DHaB5drpDaE3?CRC4<*og-Q5$w!R*nN?+&$42 zwR^>~;`RWvL5jXw3d;fMYEmJD+v)hCm}7!|%LfR%bPJpGP#A@o8mPv{{f_x*S}p+r zg+d}Ckms({WGy$r;^}@1|58&!!WcL- zcCYP>R*SD}QMl6wPgk4FlLFF$jo-A;|2FSZ&tO6>_o1=T5xHONYO-dW;U$oGSX5b8 z`%ipoG(z9x1D!@)y5THj5%Bqh*2kV%=HjviA(ZT$KVK{Jj{bV9iWy@eWsG8DY8ev*x&D5!RNg74P}RN(Ra&uIAa8I@!r;8!Jwr$!;&R7abYo3`jjoSmvaMpCyv%t ze;c-CZ5%yqI+-%@_5H>?Q2p+C2M*se0@r3>UJm~P)Z7{_u21!Oo|05>eAKQl+OAo1 z2Ns38tl8-r|C8VVCnxQLiG+6Ot@y}`nZBBG@`Lmtj~v3Jg6zBJk!O!E3)V{z$!CHk zAv;@6HTJFwTDDS>=!Ry5KG4<0W<4^jA-C-=eRP<=jp-L zuM8KZ(N%D=Mq*DJ>1*Cz|4f>^C8QJk7bLty)P4l<>=a5@F58v6=Vl$yg-5p~Ua{`b zwt*UU6EC6;x$K&6_ki}qxWS>9QS6!=iEZS$7a14w{qCNdh}-TV@~bLP*}1c4uu?wP zSojb$`m@;&_ZR#UBrU*zYm={XpJ>2br+Sd9EF2v9GeVN*@4>3#jQ8Hd@;T(d>LI zT25G2LV*>lmA=xPD0Z;qhqvm5imPh3FdZR=-NUycXAj>dY@u*UDlQ%?x(r?8k*Oc| zL=P{zJvaf7{SySgZZ6_(NDa6T9moV7dATMV`!0ruA-)J=MnLWEn7nlHV(qh&jPM%j zF#bGt<(d(~!_=XDQ&%|qeexesmseJP>g&rS?2RaE^x7dP`@d48(3meQ3CPXMI}D6Y zhEyupv16NzOx9>)KqK~IH_vIY-o^>*A&Sxe&a6X@vEAtOIWq9uN9rH5XUS`SLYk3mo8&Ipp5F>>&2g z=yq(rSHF_ta#2YiAtjhq7<9WMNA`PObM$RpZM#mqx~)<@{T)b0aFsSsUi*-ic9KI- z$l`QKYr^p=q2mr=!@%~+0$*~RS!$8~?k?;;)slsuuqE3l#-IFPD`}&zbEAnrn8i4w zrUypMh>`pJW%cz@yL67x`aa1$U)f>r?{7jT^F~!QZDnOJ;*GisPxiXVlat$%l(e#yLf|nXSG`^3?`>C<9hT){Tl#hI$vy((qk)H0+Isul`v1OL2p$dmf4`9EMi`W}h zdA#jJ9cv$#+}6wQ0qY~ybrA+2_X$}Y(e12br!v=f-+tFsi#?4hNHOAuLQIu`AM8PQ zOUqM$qVC~q)1vC$w6&$O&g9qCs;jFHNJca>*f12X4i@^ZE8#!=(FaoCJb00k7c}V? zQL1@2w^1)|$m6^?6sK#$D@sps^%mSb@@eKiCsW*}h!zEyyn%pa zqtAWmi==7e1MIgw@E6ULlasrT7?pni=55>T>m5cj?v%(6_z&GV*;*F0;pU_!-XCR0 z+O3iwsnk2WxuvReA6(s{i#(X_9}kURe{U?zcqK5z+cu*efw)h!4!~XN26lcL@}?*6 zzq#*<#xhn~*u|WD&1d2%(ObEx=gBULRGHZ z$IM5tm42tPBPxV(tsuiL(FL`#h#F94YH-{aj?>0G_iwSnLxE(zVx6GCY#4ahj^io{ zi3k9LT|3w49n>htZqrm0q#oyFIU50dxZK`)DU>C~Oh%h0D^BO(<<#_$1;-dA%K$;x zSz5OB8ZmNoH7y1v`e9+N*y_y2-o55bS3(N!aavedVC@L-a0PsTPIfrV5i$9|z`%N1 z)*I(UCT9C-vHV!kSHQ89&0jh?-p8YSP1eQH4{>9*eLC1}4pY8fEVFGJ3Y=XXvAX&G z?dgSF$6hl%Yca_cP4;0*dEf@Oxk4^;&ztp=pyaD>Z$Dhx$1-V@rn@YLWnA~3k-?ET zn*Cbj>3U!+YIMS%e7T~{By5-#xV{WOb7r3eyTMo^;!{8c6<5>K?fv}ffraaj1K@>f zQ2+JR?O~#zlbrc|%Wa($*_>fQfxU0~#u`5adB`yeiF+hig#~!y+!c9>W!0QUQD)eS{AAwqS9on5gLGJY)D1 zJbMAGArD6E?kTZtsP5Gi#Y~&Qmb!jYIsa(mqW4FopEMk$7;9-!67p3;c|;2Y)^`DY zND3)%WnL)?1_?&^1VD`%V_@+rs4htprB{g`m>xbAgJP$*xVq`QH6fe63)Is4o21DS8lV<61$`T+NbC~HMi#Jbov zCMV=Nsq3a=C+=Dnf0v|#nqj&(k--jeYQ|aP=tXVbRojTzDFLK6pP+xrQ#Wo%jNuhpZVgG~uPo2Bn zWZ=x$IXhRO_WCSbQ7r;w=TRKe2atp+1Z%h1x2f{b0oqG4~*0s^!?ho}IOiva_%Bx#f`E(pX<|u358Bnq!Y&W#8j> zU8)8Z(MjL;O0dJ3y{*Mz_#I)wr-p_P2T}oRfC=aUiE-)yuwW|Vrb7!2P71ZpH5YX9 zqpzbA1{NQ_x!Zh>+YQYv0_IE*I%})rq9EYrkK~f|I*7unu~4#I9tTtz`Q;mSYk`G) zLaKbvIYMqGP)JeVik4K3rf@x>wDy3S%`j5a5KXbKRS@AmPshu1-d5ri(-~*=-kzR) zd@J65mxGx&qL3jyJT#*M4=_2z?!f$4Co(({?VpGr> zk?)ZFMz34M=l?b^FRU zXiHkO2BvwrxN!U2`P37edWvF!@Re)VMn^^jSx%Q#gg#lNwkhdCB0VjW?Md^y)^&Ct z0PLgd%d)}?>8DT~c18HHJItwqMl}e6fv=|Vb|zNne0t{cc)oE{H30|O7t4WJ=-E0Tl|BBC~AYx{97b!h||SHT2x;KI|&T zu%E&^j?g%9s|6GufOznRJGLnW<>ut1wpBtfYbC2}NZnl?gzw7ON@pQ~5F0D~$!9Vv zMfsTzo(*9veT|?m#WVAj=(}Y71!GD!9{HSm4{zfb?QJw&e|XjD#rEpY3!m(UyQ_T1 zw+`JS$}U`F&7`wVTtt!WNj29Vu3G!I`>3g@gNsyN2KB9^r;DYuYYf!Y8DLzxRPA2) z?l3;X6~k@~ssd~X6)-j6N}o?Teh`Ss8uxSq zP-m4{zMVHQpBkq}1Wen8hH@A}O?~^1!|W=WJ4uRvUYAb0)*cSx!-reQ+`Zl1s%L}J zj%}gYDdD8YZFMcf)6=v49;6uwbqZeOozyStK#W+kYQ zb$;L?o7|T{?|bKUo$DeR|Gd z6RE*_H?3{aPK=9VT1#_J_B43V@@6MK5&F**1sB1yQbk+XU2&!I3z6OEu|zqo_O0{5 z(FEx-=`Xspo{61$MsMIzxX>J2-<;iAOC=F>h5fS;usNXh%a6*`T;7h_6MLhNJ)nXOhF4E!5-c`Y}yvav05r7T7v zjF_D_O)~Z)C`VBTvrX6Rk!K7;?+xn_+uGX^|JD6_OfKB~((022q7a`ho?Wlu&;v09Vr z;^6H}oOu+s4rh&`Yki#$7GRHKvNIG0_A8t}DMw(p6;W&6)AxLCY}{)!1uvQ+?s7xs z%_x?j8ytD`N(O=}KGTb?9dOkSSZ=MVe&LPlcfL0dKnt$u1|SSzSb#dzjDH3tRPL+t zn8Pc$hq$S&Eb2Y-$PE+_!2oZ0T!XaZ>4dJW+%K^s^uz}1zPn#M_-t8ugx0AogXaOf z+_OLWM*DS>{JKtx3Ce{U+D^d7C|_M3(@K8_3dAiQ=5^&!sS6bXVT?R%BR&@&5Bt=^ z6O6Gs_GrP)o!Be%?wVx0S_pwN(wQ*7mMsrDIS&4V!hm&3`-1hEL)rTXGj@;jY%hvS z+=OU=*`gVGB$r$(F}4eFahZvUYnFT$y#fLcYVS~5?iCk3czZNcPVupImLi7~c@P<4rtX4ZW<)NC)GrLRqZ?=7GLcboVYS78QvAva}4>x^OGk|bYn~S;3HiC z9c>0LGi{Ml$%_|)$i8CMSfcS@^|LKkKY5)L-LK1tt+BX?8!T#P~sCA*R*v*jvw(Z>ubA97wFlPsoD! zgaY}xhn(nIlfS-y?_9Qcjly*m=Jm!*tkKtaalV9dMann#IctU-*?m+>S(%xaEtWqg zm=%vRG;e?$CvIe-F+{ST2Gwzt6~FH#dnY&+v|I|~Qr$MW{AFsX7cW0i@lyNV3q0Ho z)y-FVc&LBy!~hXzq$x5Ji>vK~hzsRKvJ>*MVm7C&i@q zkpswPFarA4I5RzJWrdRH(Oye=6ur3* zGcL?nEAsRWjw3k;=bFHHj%Ob3G5A%JLMI+U{u;qS0rg!UyCU4As0)Y^f$GyOK6!vrXESFwp^^chL+gWd$~0|+B2NR7 z8;=ZsjnSg}SZ!scr>B=dOGUW=Q&>zCb(Z&CsY3A_tNE@Lfl%_MnNVs) zT{VvfFxPgOd}#d}p{TOXj$qomh&*7-N6I!Np;%K={X^HClt!J(*uU>1okLm5H5S?P z{4TL4m-HCro9yNIIzIl;*D#nnP#P9|fd2q|RU^g{qFSPXhWoWh;By2xnV#fto2XSn zAdXn1K%k)cNqE;)opXV-pwHf^3H>jrj^uM)?`Jzvyif0xOj*pSo$=c!dS#J|zLn9U z0pSkxLia9&WTr`K6s+W+eXOQx&#Lj%KsjTv5__z2c3lqq2f(RHXZmMG-rfV6)l)b# zQHX?nK0~B}y!u>{PmCiL9OPWC4~++8L6F06-JPEHpSM&*p`4pQ2OpL8Q%5?KavZ;o zZoP-i31DV6*7>GErqkw`K_A4$#LVGSBS;f$U9-X{D@kWXVCIRb#Sdv#upRBlN#ft~ z;4>#EU%8~*h=^tGshx&qOgxI~nP?^(WgBOXp7W9A+`n(1P6;$8+5%L!RD~>Rs2*aXmQ2D?lyB&Cdq8g_RXpwj5PtwGC|6nStG<>W%Px3@8HIng>$#n^Tg< zvTnwzt*?8FN;z^OA%ezjihLG(QhP3H@K!WCl^Uq4QVTd)Nx?gWHA)p#xK!oK!Ir~AAYfDiVs>eXlz3+RW!9DsO-**l_dXSZP_pLyf`#FIl*TEG zo&)6})EO&J@4!k9Fxwk=9odJNeYH3DW^@CdA)tCtsO>bDHrV<<{i@oN`Z+!!LHF>- zc9$;oFG?nSD^k~4yxm<(>B?lB?X=-sHv<3|q^8%d9M|Goq5Gj9b^$|cy)(5)VMu7f z5Ksf8|GYU2EME#}5aeFww+9adrCxnbv>7s}`Hn@-#O;yD;LP19U=3hjX-QNlu$R>G z6O2b6A5W#H?7*}IJxlCe03rFGV`^KgbO%N+Vr@8a;za79?dl~|F>4-WWb6((@g|s6 z_0pwFMqpg_(e|tnHigu)f`gI!nypbIIR8D~(##L+XtyfR4WZx&f(5!vf`5^eTrcU# z8?|hID?$U0GjIsU?~!;-i6s?2vv8rM^32EVBYSWzAjPg7TFQ5n4jx;FlY%YmL}t%- zq@!E6j-+Vr=t3`l8pn&jD!;|J;)9= z#NF_r1KCA*_VK%jb1&`e%-nFZ*;d%N{^suZ0e5gCTawJ&Nc**SY}YuzXYJat{BqR>*V)cM(~vIiV2Q_* z@Mo@ve%@y8$Z|S5MLSnVL6WDLn}szA9Y!Kf8FnSxSqaTQjyQ9Czmv6@3%X|RX|8DG zA+*5VTo?}!v6u3c5}E%34ofz(IE)T*#e2D#Sy-d7=(PPVWIM8%E7|q0-vDw8s$Id6OI+ z@YgT%#m2$P#SG_ByIbHmb@FU~I=We-8NbXeS79_xk4(%WGHJh}_AU|*$Hs&pyO4hw zPoh_a=X=@4QRLU|A-V;nlZjU+lbAB1%$Wl9Ea^qINen6U^I#!PE_y|*NevVm^ zJ;-)Kv(Ip`#wp3}mUBaCi6gq_mynPUaU83V5Z&yuBCZqi5F-hZ4v{g%al$k4EX+qY zIw2uF^8!{ia>tP$Gxiw3C zLUJIJ@ip$*vxjHzU}1+!2RO17E7f)GYGdQ=cEmcv(X3V&A@X0n8PU?&HDclJVn=d? zM#Is??RQU*mqWW%c4_SRrPX8$Yey2dJ`P?rcHqXr#XQ!SNPK24E@s~Ra}&;(cwN)K zn02mvXtReIPB?eBcbdDv)W!j`$Q4u8^f1|*kH=b&G^<-L^nH_d}72A)g;pX*^Ztc zJ>%`f;2qc|hY#kyB|7&lzd!xv&oTS+EByYU2W^^r5YeFD%$&KV{A|p8lZoA8KQ~T6 zww!-3@e9mpzD@jSCh=!Kx0MT-{D)6P=RPG~pN|}TmDL?&3Ebl zK&SofcFlL`T)X^!PV_(D6J}4ap0l_PX7+PVmW}2Avpd7Tk5&G6vxs!FE}Ze~eE74S za?TX~w1soV5WCAiewFbrmhmq(!hegM`=7Ek{4*@$-(KYZml&V_-u?8yzng!zG5-Cw z)W&i)wD?~;`rq!|{=3=H|G*$RxZBzNuiYb@>p5TaPdwHC@9f^c*oqO}ED=Ed+{=l$ z=9fMBxAD!txLyB&b#*dxakBw>G3%lHKWkY34Py0w1iIj{5c?P79KcD${ud~j2f4)MjY!u*v|f4@TGr>)Bb-Io+I}6<0k)7gD>^>x9eYz=lpFD?0+t#`r9DbAMl)i zB&7OhY~g>q(|#8q{Yz)s-|n>Ewd;?r#jI5$xe zZJQ|G>vtRpot3)-XgIK=1lK`!;p4HfBv55q7c#gm2hz`v`S?k2$w|L_Ogl%epsWYU z9Q+_@1FqX3Gt0Bk(h`ItzPU|wD~ZQOmbitfgS)+{nad$!M@X*XlecMp9n}pvYnYXap5dI<~r9B0TF!oo7S7o zUp%`R()xiBp`-iRc#vr*PCU=^&9(lQ2hZ(r^Pll?6O)2laK4kc32vF2|JNTKoxFeZ zqvhPE+?Hl;W+V?YJ9qN0R}#N7o%_NpA@uvEfO)n6Y4(Sv@VHpPo0@CT{5O6!h^REc%+`--HPv6Ya#?{H)jZC~1zaWYD z`!D)&b_$r;%};@Uv=y_q;#YPH3;1`7fX>{}(T)#XH<_OxrDs3;IV&uK%9A8zy0NDvcp!|X5S*1M<-2xk}Q5%@O2$@=YjAugKx z&L)|kJk{?vIMKO~^silyEoal*H|AL`zh7SGXXA)D{oBUj=l?|G{;RF}PhS7K%kZ-E z-9h@R9XgAv%y-Fes6Rj0Lq~I45ZipNZkF2#hMs@jdP@?B!FjH8*7E&%{Qt}C{?Hm? zzyA{i=O6G*|6;UeO~G$Qi}?9}V6?OhG&KHY{q+xcSpR1I^@sWJUz(l&(k}noAmbmL zN5VeNoATe9%|Er01`dZE96cQf6Zz8`{^AP!o%8rNmU;Gn=M*y#PwDGx(5X*vF3KGc aJWSzO-Wa!jAn{_7d^jb