better checks for json support
[m6w6/ext-pq] / src / php_pq_params.c
index ffe5e70ba7b06b6d13fd72134c462c4a456b6c79..0cc370d36a6654db5261d6edc8602a0deec6eec8 100644 (file)
@@ -17,7 +17,9 @@
 #include <php.h>
 #include <ext/standard/php_string.h>
 #include <ext/standard/php_smart_str.h>
-#include <ext/json/php_json.h>
+#if PHP_PQ_HAVE_PHP_JSON_H
+#include <php_json.h> /* we've added the include directory to INCLUDES */
+#endif
 
 #include <Zend/zend_interfaces.h>
 
@@ -86,7 +88,7 @@ static zval *object_param_to_string(php_pq_params_t *p, zval *zobj, Oid type TSR
        smart_str str = {0};
 
        switch (type) {
-#ifdef PHP_PQ_OID_JSON
+#if HAVE_JSON && defined(PHP_PQ_OID_JSON)
 #      ifdef PHP_PQ_OID_JSONB
        case PHP_PQ_OID_JSONB:
 #      endif
@@ -113,9 +115,9 @@ static zval *object_param_to_string(php_pq_params_t *p, zval *zobj, Oid type TSR
                break;
 
        default:
-               SEPARATE_ZVAL(&zobj);
-               convert_to_string(zobj);
-               return_value = zobj;
+               MAKE_STD_ZVAL(return_value);
+               MAKE_COPY_ZVAL(&zobj, return_value);
+               convert_to_string(return_value);
                break;
        }
 
@@ -127,57 +129,73 @@ static zval *object_param_to_string(php_pq_params_t *p, zval *zobj, Oid type TSR
        return return_value;
 }
 
-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;
+       zval **zconv;
+};
+
+static int apply_to_param_from_array(void *ptr, void *arg_ptr TSRMLS_DC)
 {
-       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;
+       zval *ztmp, **zparam = ptr, *zcopy = *zparam;
        char *tmp;
        size_t len;
        int tmp_len;
 
-       if ((*i)++) {
-               smart_str_appendc(s, ',');
+       if (arg->index++) {
+               smart_str_appendc(arg->buffer, ',');
        }
 
-       if (zconv) {
-               zval *rv = NULL;
+       if (arg->zconv) {
+               zval *ztype, *rv = NULL;
+
+               MAKE_STD_ZVAL(ztype);
+               ZVAL_LONG(ztype, arg->type);
+               zend_call_method_with_2_params(arg->zconv, NULL, NULL, "converttostring", &rv, zcopy, ztype);
+               zval_ptr_dtor(&ztype);
+
+               if (rv) {
+                       convert_to_string(rv);
+                       zcopy = rv;
+               } else {
+                       return ZEND_HASH_APPLY_STOP;
+               }
 
-               zend_call_method_with_1_params(zconv, NULL, NULL, "converttostring", &rv, zcopy);
-               convert_to_string(rv);
-               zcopy = rv;
                goto append_string;
+
        } else {
                switch (Z_TYPE_P(zcopy)) {
                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");
+                       smart_str_appends(arg->buffer, Z_BVAL_P(zcopy) ? "t" : "f");
                        break;
 
                case IS_LONG:
-                       smart_str_append_long(s, Z_LVAL_P(zcopy));
+                       smart_str_append_long(arg->buffer, Z_LVAL_P(zcopy));
                        break;
 
                case IS_DOUBLE:
                        len = spprintf(&tmp, 0, "%F", Z_DVAL_P(zcopy));
-                       smart_str_appendl(s, tmp, len);
+                       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(zcopy), apply_to_param_from_array, &subarg TSRMLS_CC);
+                       smart_str_appendc(arg->buffer, '}');
                        break;
 
                case IS_OBJECT:
-                       if ((ztmp = object_param_to_string(p, zcopy, type TSRMLS_CC))) {
+                       if ((ztmp = object_param_to_string(arg->params, zcopy, arg->type TSRMLS_CC))) {
                                zcopy = ztmp;
                        }
                        /* no break */
@@ -187,9 +205,9 @@ static int apply_to_param_from_array(void *ptr TSRMLS_DC, int argc, va_list argv
 
                        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, '"');
+                       smart_str_appendc(arg->buffer, '"');
+                       smart_str_appendl(arg->buffer, tmp, tmp_len);
+                       smart_str_appendc(arg->buffer, '"');
 
                        if (zcopy != *zparam) {
                                zval_ptr_dtor(&zcopy);
@@ -198,18 +216,18 @@ static int apply_to_param_from_array(void *ptr TSRMLS_DC, int argc, va_list argv
                        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)
 {
-       zval *return_value, **zconv = NULL;
+       zval *zcopy, *return_value;
        smart_str s = {0};
-       unsigned i = 0;
+       struct apply_to_param_from_array_arg arg = {NULL};
 
        switch (type) {
-#ifdef PHP_PQ_OID_JSON
+#if HAVE_JSON && defined(PHP_PQ_OID_JSON)
 #      ifdef PHP_PQ_OID_JSONB
        case PHP_PQ_OID_JSONB:
 #      endif
@@ -220,11 +238,16 @@ static zval *array_param_to_string(php_pq_params_t *p, zval *zarr, Oid type TSRM
 #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, '}');
+               arg.params = p;
+               arg.buffer = &s;
+               arg.type = PHP_PQ_TYPE_OF_ARRAY(type);
+               zend_hash_index_find(&p->type.conv, PHP_PQ_TYPE_OF_ARRAY(type), (void *) &arg.zconv);
+               smart_str_appendc(arg.buffer, '{');
+               MAKE_STD_ZVAL(zcopy);
+               MAKE_COPY_ZVAL(&zarr, zcopy);
+               zend_hash_apply_with_argument(Z_ARRVAL_P(zcopy), apply_to_param_from_array, &arg TSRMLS_CC);
+               zval_ptr_dtor(&zcopy);
+               smart_str_appendc(arg.buffer, '}');
                smart_str_0(&s);
                break;
        }
@@ -248,12 +271,17 @@ static void php_pq_params_set_param(php_pq_params_t *p, unsigned index, zval **z
        TSRMLS_DF(p);
 
        if (type && SUCCESS == zend_hash_index_find(&p->type.conv, type, (void *) &zconv)) {
-               zval *rv = NULL;
-
-               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 *ztype, *rv = NULL;
+
+               MAKE_STD_ZVAL(ztype);
+               ZVAL_LONG(ztype, type);
+               zend_call_method_with_2_params(zconv, NULL, NULL, "converttostring", &rv, *zpp, ztype);
+               zval_ptr_dtor(&ztype);
+               if (rv) {
+                       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);
+               }
        } else {
                zval *tmp, *zcopy = *zpp;
 
@@ -267,13 +295,18 @@ static void php_pq_params_set_param(php_pq_params_t *p, unsigned index, zval **z
                        return;
 
                case IS_DOUBLE:
-                       SEPARATE_ZVAL(&zcopy);
+                       MAKE_STD_ZVAL(zcopy);
+                       MAKE_COPY_ZVAL(zpp, zcopy);
                        Z_TYPE_P(zcopy) = IS_STRING;
                        Z_STRLEN_P(zcopy) = spprintf(&Z_STRVAL_P(zcopy), 0, "%F", Z_DVAL_PP(zpp));
                        break;
 
                case IS_ARRAY:
-                       zcopy = array_param_to_string(p, zcopy, type TSRMLS_CC);
+                       MAKE_STD_ZVAL(zcopy);
+                       MAKE_COPY_ZVAL(zpp, zcopy);
+                       tmp = array_param_to_string(p, zcopy, type TSRMLS_CC);
+                       zval_ptr_dtor(&zcopy);
+                       zcopy = tmp;
                        break;
 
                case IS_OBJECT:
@@ -296,12 +329,17 @@ static void php_pq_params_set_param(php_pq_params_t *p, unsigned index, zval **z
        }
 }
 
-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(void *zp, void *arg_ptr TSRMLS_DC)
 {
-       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((zval **) zp);
+       php_pq_params_set_param(arg->params, arg->index++, zp);
        return ZEND_HASH_APPLY_KEEP;
 }
 
@@ -323,9 +361,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 TSRMLS_CC);
        }
        return p->param.count;
 }