X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-pq;a=blobdiff_plain;f=src%2Fphp_pq_params.c;h=a691eebd62464efbe897c2f91533c064b7f85961;hp=ffe5e70ba7b06b6d13fd72134c462c4a456b6c79;hb=5ba3107011d4050d5ae5877dae80e382dc228e6a;hpb=9ba862160ca65ed9a1e5eada87dcceba7fbf08d7 diff --git a/src/php_pq_params.c b/src/php_pq_params.c index ffe5e70..a691eeb 100644 --- a/src/php_pq_params.c +++ b/src/php_pq_params.c @@ -16,9 +16,11 @@ #include #include -#include -#include +#if PHP_PQ_HAVE_PHP_JSON_H +#include /* we've added the include directory to INCLUDES */ +#endif +#include #include #include @@ -32,31 +34,22 @@ void php_pq_params_set_type_conv(php_pq_params_t *p, HashTable *conv) { zend_hash_clean(&p->type.conv); - zend_hash_copy(&p->type.conv, conv, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); + zend_hash_copy(&p->type.conv, conv, (copy_ctor_func_t) zval_add_ref); } -static int apply_to_oid(void *p, void *arg TSRMLS_DC) +static int apply_to_oid(zval *ztype, void *arg) { Oid **types = arg; - zval **ztype = p; - - if (Z_TYPE_PP(ztype) != IS_LONG) { - convert_to_long_ex(ztype); - } - **types = Z_LVAL_PP(ztype); + **types = zval_get_long(ztype); ++*types; - if (*ztype != *(zval **)p) { - zval_ptr_dtor(ztype); - } return ZEND_HASH_APPLY_KEEP; } unsigned php_pq_params_set_type_oids(php_pq_params_t *p, HashTable *oids) { p->type.count = oids ? zend_hash_num_elements(oids) : 0; - TSRMLS_DF(p); if (p->type.oids) { efree(p->type.oids); @@ -66,7 +59,7 @@ unsigned php_pq_params_set_type_oids(php_pq_params_t *p, HashTable *oids) Oid *ptr = ecalloc(p->type.count + 1, sizeof(*p->type.oids)); /* +1 for when less types than params are specified */ p->type.oids = ptr; - zend_hash_apply_with_argument(oids, apply_to_oid, &ptr TSRMLS_CC); + zend_hash_apply_with_argument(oids, apply_to_oid, &ptr); } return p->type.count; } @@ -80,242 +73,255 @@ unsigned php_pq_params_add_type_oid(php_pq_params_t *p, Oid type) } -static zval *object_param_to_string(php_pq_params_t *p, zval *zobj, Oid type TSRMLS_DC) +static zend_string *object_param_to_string(php_pq_params_t *p, zval *zobj, Oid type) { - zval *return_value = NULL; +#if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON) smart_str str = {0}; +#endif switch (type) { -#ifdef PHP_PQ_OID_JSON -# ifdef PHP_PQ_OID_JSONB +#if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON) +# ifdef PHP_PQ_OID_JSONB case PHP_PQ_OID_JSONB: -# endif +# endif case PHP_PQ_OID_JSON: - php_json_encode(&str, zobj, PHP_JSON_UNESCAPED_UNICODE TSRMLS_CC); +# if PHP_VERSION_ID >= 70100 + JSON_G(encode_max_depth) = PHP_JSON_PARSER_DEFAULT_DEPTH; +# endif + php_json_encode(&str, zobj, PHP_JSON_UNESCAPED_UNICODE); smart_str_0(&str); - break; + return str.s; #endif case PHP_PQ_OID_DATE: - php_pqdt_to_string(zobj, "Y-m-d", &str.c, &str.len TSRMLS_CC); - break; - + return php_pqdt_to_string(zobj, "Y-m-d"); +#ifdef PHP_PQ_OID_ABSTIME case PHP_PQ_OID_ABSTIME: - php_pqdt_to_string(zobj, "Y-m-d H:i:s", &str.c, &str.len TSRMLS_CC); - break; - + return php_pqdt_to_string(zobj, "Y-m-d H:i:s"); +#endif case PHP_PQ_OID_TIMESTAMP: - php_pqdt_to_string(zobj, "Y-m-d H:i:s.u", &str.c, &str.len TSRMLS_CC); - break; + return php_pqdt_to_string(zobj, "Y-m-d H:i:s.u"); case PHP_PQ_OID_TIMESTAMPTZ: - php_pqdt_to_string(zobj, "Y-m-d H:i:s.uO", &str.c, &str.len TSRMLS_CC); - break; - - default: - SEPARATE_ZVAL(&zobj); - convert_to_string(zobj); - return_value = zobj; - break; - } - - if (str.c) { - MAKE_STD_ZVAL(return_value); - RETVAL_STRINGL(str.c, str.len, 0); + return php_pqdt_to_string(zobj, "Y-m-d H:i:s.uO"); } - return return_value; + return zval_get_string(zobj); } -static int apply_to_param_from_array(void *ptr TSRMLS_DC, int argc, va_list argv, zend_hash_key *key) +struct apply_to_param_from_array_arg { + php_pq_params_t *params; + unsigned index; + smart_str *buffer; + Oid type; + char delim; + zval *zconv; +}; + +static int apply_to_param_from_array(zval *zparam, void *arg_ptr) { - php_pq_params_t *p = va_arg(argv, php_pq_params_t *); - unsigned j, *i = va_arg(argv, unsigned *); - smart_str *s = va_arg(argv, smart_str *); - Oid type = va_arg(argv, Oid); - zval *ztmp, **zparam = ptr, *zcopy = *zparam, **zconv = va_arg(argv, zval **); + struct apply_to_param_from_array_arg subarg, *arg = arg_ptr; char *tmp; size_t len; - int tmp_len; + zend_string *str, *tmpstr; - if ((*i)++) { - smart_str_appendc(s, ','); + if (arg->index++) { + smart_str_appendc(arg->buffer, arg->delim); } - if (zconv) { - zval *rv = NULL; + if (arg->zconv) { + zval ztype, rv; - zend_call_method_with_1_params(zconv, NULL, NULL, "converttostring", &rv, zcopy); - convert_to_string(rv); - zcopy = rv; + ZVAL_LONG(&ztype, arg->type); + zend_call_method_with_2_params(arg->zconv, NULL, NULL, "converttostring", &rv, zparam, &ztype); + tmpstr = zval_get_string(&rv); + zval_ptr_dtor(&rv); goto append_string; + } else { - switch (Z_TYPE_P(zcopy)) { + again: + switch (Z_TYPE_P(zparam)) { + case IS_REFERENCE: + ZVAL_DEREF(zparam); + goto again; + case IS_NULL: - smart_str_appends(s, "NULL"); + smart_str_appends(arg->buffer, "NULL"); break; - case IS_BOOL: - smart_str_appends(s, Z_BVAL_P(zcopy) ? "t" : "f"); + case IS_TRUE: + smart_str_appends(arg->buffer, "t"); + break; + + case IS_FALSE: + smart_str_appends(arg->buffer, "f"); break; case IS_LONG: - smart_str_append_long(s, Z_LVAL_P(zcopy)); + smart_str_append_long(arg->buffer, Z_LVAL_P(zparam)); break; case IS_DOUBLE: - len = spprintf(&tmp, 0, "%F", Z_DVAL_P(zcopy)); - smart_str_appendl(s, tmp, len); + len = spprintf(&tmp, 0, "%F", Z_DVAL_P(zparam)); + smart_str_appendl(arg->buffer, tmp, len); efree(tmp); break; case IS_ARRAY: - j = 0; - smart_str_appendc(s, '{'); - zend_hash_apply_with_arguments(Z_ARRVAL_P(zcopy) TSRMLS_CC, apply_to_param_from_array, 5, p, &j, s, type, zconv); - smart_str_appendc(s, '}'); + subarg = *arg; + subarg.index = 0; + smart_str_appendc(arg->buffer, '{'); + zend_hash_apply_with_argument(Z_ARRVAL_P(zparam), apply_to_param_from_array, &subarg); + smart_str_appendc(arg->buffer, '}'); break; case IS_OBJECT: - if ((ztmp = object_param_to_string(p, zcopy, type TSRMLS_CC))) { - zcopy = ztmp; + if ((tmpstr = object_param_to_string(arg->params, zparam, arg->type))) { + goto append_string; } /* no break */ default: - SEPARATE_ZVAL(&zcopy); - convert_to_string(zcopy); + tmpstr = zval_get_string(zparam); append_string: - tmp = php_addslashes(Z_STRVAL_P(zcopy), Z_STRLEN_P(zcopy), &tmp_len, 0 TSRMLS_CC); - smart_str_appendc(s, '"'); - smart_str_appendl(s, tmp, tmp_len); - smart_str_appendc(s, '"'); - - if (zcopy != *zparam) { - zval_ptr_dtor(&zcopy); - } - efree(tmp); +#if PHP_VERSION_ID < 70300 + str = php_addslashes(tmpstr, 1); +#else + str = php_addslashes(tmpstr); + zend_string_release(tmpstr); +#endif + smart_str_appendc(arg->buffer, '"'); + smart_str_appendl(arg->buffer, str->val, str->len); + smart_str_appendc(arg->buffer, '"'); + zend_string_release(str); break; } } - ++(*i); + ++arg->index; return ZEND_HASH_APPLY_KEEP; } -static zval *array_param_to_string(php_pq_params_t *p, zval *zarr, Oid type TSRMLS_DC) +static zend_string *array_param_to_string(php_pq_params_t *p, zval *zarr, Oid type) { - zval *return_value, **zconv = NULL; smart_str s = {0}; - unsigned i = 0; + struct apply_to_param_from_array_arg arg = {NULL}; switch (type) { -#ifdef PHP_PQ_OID_JSON -# ifdef PHP_PQ_OID_JSONB +#if PHP_PQ_HAVE_PHP_JSON_H && defined(PHP_PQ_OID_JSON) +# ifdef PHP_PQ_OID_JSONB case PHP_PQ_OID_JSONB: -# endif +# endif case PHP_PQ_OID_JSON: - php_json_encode(&s, zarr, PHP_JSON_UNESCAPED_UNICODE TSRMLS_CC); - smart_str_0(&s); + php_json_encode(&s, zarr, PHP_JSON_UNESCAPED_UNICODE); break; #endif default: - zend_hash_index_find(&p->type.conv, PHP_PQ_TYPE_OF_ARRAY(type), (void *) &zconv); - - smart_str_appendc(&s, '{'); - zend_hash_apply_with_arguments(Z_ARRVAL_P(zarr) TSRMLS_CC, apply_to_param_from_array, 5, p, &i, &s, (Oid) PHP_PQ_TYPE_OF_ARRAY(type), zconv); - smart_str_appendc(&s, '}'); - smart_str_0(&s); + arg.params = p; + arg.buffer = &s; + arg.type = PHP_PQ_TYPE_OF_ARRAY(type); + arg.delim = PHP_PQ_DELIM_OF_ARRAY(type); + arg.zconv = zend_hash_index_find(&p->type.conv, PHP_PQ_TYPE_OF_ARRAY(type)); + smart_str_appendc(arg.buffer, '{'); + SEPARATE_ZVAL(zarr); + zend_hash_apply_with_argument(Z_ARRVAL_P(zarr), apply_to_param_from_array, &arg); + smart_str_appendc(arg.buffer, '}'); break; } - /* must not return NULL */ - MAKE_STD_ZVAL(return_value); - - if (s.c) { - RETVAL_STRINGL(s.c, s.len, 0); - } else { - RETVAL_EMPTY_STRING(); - } - - return return_value; + smart_str_0(&s); + return s.s; } -static void php_pq_params_set_param(php_pq_params_t *p, unsigned index, zval **zpp) +static void php_pq_params_set_param(php_pq_params_t *p, unsigned index, zval *zpp) { - zval **zconv = NULL; + zval *zconv = NULL; Oid type = p->type.count > index ? p->type.oids[index] : 0; - TSRMLS_DF(p); - if (type && SUCCESS == zend_hash_index_find(&p->type.conv, type, (void *) &zconv)) { - zval *rv = NULL; + if (type && (zconv = zend_hash_index_find(&p->type.conv, type))) { + zval ztype, rv; - zend_call_method_with_1_params(zconv, NULL, NULL, "converttostring", &rv, *zpp); - convert_to_string(rv); - p->param.strings[index] = Z_STRVAL_P(rv); - zend_hash_next_index_insert(&p->param.dtor, (void *) &rv, sizeof(zval *), NULL); + ZVAL_NULL(&rv); + ZVAL_LONG(&ztype, type); + zend_call_method_with_2_params(zconv, NULL, NULL, "converttostring", &rv, zpp, &ztype); + convert_to_string(&rv); + p->param.strings[index] = Z_STRVAL_P(&rv); + zend_hash_next_index_insert(&p->param.dtor, &rv); } else { - zval *tmp, *zcopy = *zpp; + zval tmp; + zend_string *str = NULL; + char tmp_str[64]; + size_t tmp_len = 0; + + again: + switch (Z_TYPE_P(zpp)) { + case IS_REFERENCE: + ZVAL_DEREF(zpp); + goto again; - switch (Z_TYPE_P(zcopy)) { case IS_NULL: p->param.strings[index] = NULL; return; - case IS_BOOL: - p->param.strings[index] = Z_BVAL_P(zcopy) ? "t" : "f"; + case IS_TRUE: + p->param.strings[index] = "t"; + break; + + case IS_FALSE: + p->param.strings[index] = "f"; return; case IS_DOUBLE: - SEPARATE_ZVAL(&zcopy); - Z_TYPE_P(zcopy) = IS_STRING; - Z_STRLEN_P(zcopy) = spprintf(&Z_STRVAL_P(zcopy), 0, "%F", Z_DVAL_PP(zpp)); + tmp_len = slprintf(tmp_str, sizeof(tmp_str), "%F", Z_DVAL_P(zpp)); + str = zend_string_init(tmp_str, tmp_len, 0); break; case IS_ARRAY: - zcopy = array_param_to_string(p, zcopy, type TSRMLS_CC); + str = array_param_to_string(p, zpp, type); break; case IS_OBJECT: - if ((tmp = object_param_to_string(p, zcopy, type TSRMLS_CC))) { - zcopy = tmp; + if ((str = object_param_to_string(p, zpp, type))) { break; } /* no break */ - default: - convert_to_string_ex(&zcopy); + str = zval_get_string(zpp); break; } - p->param.strings[index] = Z_STRVAL_P(zcopy); - - if (zcopy != *zpp) { - zend_hash_next_index_insert(&p->param.dtor, (void *) &zcopy, sizeof(zval *), NULL); + if (str) { + ZVAL_STR(&tmp, str); + p->param.strings[index] = Z_STRVAL(tmp); + zend_hash_next_index_insert(&p->param.dtor, &tmp); } } } -static int apply_to_params(void *zp TSRMLS_DC, int argc, va_list argv, zend_hash_key *key) +struct apply_to_params_arg { + php_pq_params_t *params; + unsigned index; +}; + +static int apply_to_params(zval *zp, void *arg_ptr) { - php_pq_params_t *p = (php_pq_params_t *) va_arg(argv, php_pq_params_t *); - unsigned *index = (unsigned *) va_arg(argv, unsigned *); + struct apply_to_params_arg *arg = arg_ptr; - php_pq_params_set_param(p, (*index)++, zp); + SEPARATE_ZVAL_IF_NOT_REF(zp); + php_pq_params_set_param(arg->params, arg->index++, zp); return ZEND_HASH_APPLY_KEEP; } unsigned php_pq_params_add_param(php_pq_params_t *p, zval *param) { p->param.strings = safe_erealloc(p->param.strings, ++p->param.count, sizeof(*p->param.strings), 0); - php_pq_params_set_param(p, p->param.count-1, ¶m); + php_pq_params_set_param(p, p->param.count-1, param); return p->type.count; } unsigned php_pq_params_set_params(php_pq_params_t *p, HashTable *params) { p->param.count = params ? zend_hash_num_elements(params) : 0; - TSRMLS_DF(p); if (p->param.strings) { efree(p->param.strings); @@ -323,9 +329,9 @@ unsigned php_pq_params_set_params(php_pq_params_t *p, HashTable *params) } zend_hash_clean(&p->param.dtor); if (p->param.count) { - unsigned index = 0; + struct apply_to_params_arg arg = {p, 0}; p->param.strings = ecalloc(p->param.count, sizeof(*p->param.strings)); - zend_hash_apply_with_arguments(params TSRMLS_CC, apply_to_params, 2, p, &index); + zend_hash_apply_with_argument(params, apply_to_params, &arg); } return p->param.count; } @@ -344,11 +350,10 @@ void php_pq_params_free(php_pq_params_t **p) } } -php_pq_params_t *php_pq_params_init(HashTable *conv, HashTable *oids, HashTable *params TSRMLS_DC) +php_pq_params_t *php_pq_params_init(HashTable *conv, HashTable *oids, HashTable *params) { php_pq_params_t *p = ecalloc(1, sizeof(*p)); - TSRMLS_CF(p); zend_hash_init(&p->type.conv, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_init(&p->param.dtor, 0, NULL, ZVAL_PTR_DTOR, 0);