Fixed array parser compatibility with arrays of boxes
[m6w6/ext-pq] / src / php_pq_misc.c
index ab90936428f20377d81c5ff84fdd915669c6ab07..a3db8bbcd52827c0f1258d4a841a77fa55975042 100644 (file)
 #include <php.h>
 #include <ext/date/php_date.h>
 #include <ext/standard/php_string.h>
-#if defined(HAVE_JSON) && !defined(COMPILE_DL_JSON)
-#      include <ext/json/php_json.h>
-#endif
 
 #include <Zend/zend_interfaces.h>
 
 #include <libpq/libpq-fs.h>
 
 #include "php_pq.h"
+#include "php_pqexc.h"
 #include "php_pq_misc.h"
+#undef PHP_PQ_TYPE
+#include "php_pq_type.h"
 
-char *rtrim(char *e)
+char *php_pq_rtrim(char *e)
 {
        size_t l = strlen(e);
 
@@ -38,7 +38,7 @@ char *rtrim(char *e)
        return e;
 }
 
-const char *strmode(long mode)
+const char *php_pq_strmode(long mode)
 {
        switch (mode & (INV_READ|INV_WRITE)) {
        case INV_READ|INV_WRITE:
@@ -52,7 +52,7 @@ const char *strmode(long mode)
        }
 }
 
-int compare_index(const void *lptr, const void *rptr TSRMLS_DC)
+int php_pq_compare_index(const void *lptr, const void *rptr TSRMLS_DC)
 {
        const Bucket *l = *(const Bucket **) lptr;
        const Bucket *r = *(const Bucket **) rptr;
@@ -81,13 +81,36 @@ static PHP_METHOD(pqdt, __toString)
        }
 }
 
+ZEND_BEGIN_ARG_INFO_EX(ai_pqdt_create_from_format, 0, 0, 2)
+       ZEND_ARG_INFO(0, format)
+       ZEND_ARG_INFO(0, datetime)
+       ZEND_ARG_INFO(0, timezone)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqdt, createFromFormat)
+{
+       zend_error_handling zeh;
+       char *fmt_str, *dt_str;
+       int fmt_len, dt_len;
+       zval *ztz = 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, "ss|O", &fmt_str, &fmt_len, &dt_str, &dt_len, &ztz, php_date_get_timezone_ce());
+       zend_restore_error_handling(&zeh TSRMLS_CC);
+
+       if (SUCCESS == rv) {
+               php_pqdt_from_string(return_value, fmt_str, dt_str, dt_len, "Y-m-d H:i:s.uO", ztz TSRMLS_CC);
+       }
+}
+
 static zend_function_entry php_pqdt_methods[] = {
+       PHP_ME(pqdt, createFromFormat, ai_pqdt_create_from_format, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
        PHP_ME(pqdt, __toString, ai_pqdt_to_string, ZEND_ACC_PUBLIC)
        PHP_MALIAS(pqdt, jsonSerialize, __toString, ai_pqdt_to_string, ZEND_ACC_PUBLIC)
        {0}
 };
 
-zval *php_pqdt_from_string(char *dt_str, size_t dt_len, char *fmt, zval *zv TSRMLS_DC)
+zval *php_pqdt_from_string(zval *zv, char *input_fmt, char *dt_str, size_t dt_len, char *output_fmt, zval *ztimezone TSRMLS_DC)
 {
        php_date_obj *dobj;
 
@@ -97,11 +120,11 @@ zval *php_pqdt_from_string(char *dt_str, size_t dt_len, char *fmt, zval *zv TSRM
 
        php_date_instantiate(php_pqdt_class_entry, zv TSRMLS_CC);
        dobj = zend_object_store_get_object(zv TSRMLS_CC);
-       if (!php_date_initialize(dobj, dt_str, dt_len, NULL, NULL, 1 TSRMLS_CC)) {
+       if (!php_date_initialize(dobj, dt_str, dt_len, input_fmt, ztimezone, 1 TSRMLS_CC)) {
                zval_dtor(zv);
                ZVAL_NULL(zv);
-       } else if (fmt) {
-               zend_update_property_string(php_pqdt_class_entry, zv, ZEND_STRL("format"), fmt TSRMLS_CC);
+       } else if (output_fmt) {
+               zend_update_property_string(php_pqdt_class_entry, zv, ZEND_STRL("format"), output_fmt TSRMLS_CC);
        }
 
        return zv;
@@ -142,12 +165,14 @@ zend_class_entry *php_pqconv_class_entry;
 ZEND_BEGIN_ARG_INFO_EX(ai_pqconv_convert_types, 0, 0, 0)
 ZEND_END_ARG_INFO();
 
-ZEND_BEGIN_ARG_INFO_EX(ai_pqconv_convert_from_string, 0, 0, 1)
+ZEND_BEGIN_ARG_INFO_EX(ai_pqconv_convert_from_string, 0, 0, 2)
        ZEND_ARG_INFO(0, data)
+       ZEND_ARG_INFO(0, type)
 ZEND_END_ARG_INFO();
 
-ZEND_BEGIN_ARG_INFO_EX(ai_pqconv_convert_to_string, 0, 0, 1)
+ZEND_BEGIN_ARG_INFO_EX(ai_pqconv_convert_to_string, 0, 0, 2)
        ZEND_ARG_INFO(0, data)
+       ZEND_ARG_INFO(0, type)
 ZEND_END_ARG_INFO();
 
 zend_function_entry php_pqconv_methods[] = {
@@ -212,7 +237,7 @@ static char caa(ArrayParserState *a, const char *any, unsigned advance)
        return 0;
 }
 
-static STATUS add_element(ArrayParserState *a, const char *start)
+static ZEND_RESULT_CODE add_element(ArrayParserState *a, const char *start)
 {
        zval *zelem;
        size_t el_len = a->ptr - start;
@@ -242,9 +267,9 @@ static STATUS add_element(ArrayParserState *a, const char *start)
        return zend_hash_next_index_insert(&a->list->ht, &zelem, sizeof(zval *), NULL);
 }
 
-static STATUS parse_array(ArrayParserState *a);
+static ZEND_RESULT_CODE parse_array(ArrayParserState *a);
 
-static STATUS parse_element(ArrayParserState *a)
+static ZEND_RESULT_CODE parse_element(ArrayParserState *a, char delim)
 {
        const char *el;
        TSRMLS_FETCH_FROM_CTX(a->ts);
@@ -261,6 +286,10 @@ static STATUS parse_element(ArrayParserState *a)
 
        for (el = a->ptr; a->ptr < a->end; ++a->ptr) {
                switch (*a->ptr) {
+               case '\\':
+                       a->escaped = !a->escaped;
+                       break;
+
                case '"':
                        if (a->escaped) {
                                a->escaped = 0;
@@ -277,20 +306,18 @@ static STATUS parse_element(ArrayParserState *a)
                        }
                        break;
 
-               case ',':
+               default:
+                       if (delim != *a->ptr) {
+                               a->escaped = 0;
+                               break;
+                       }
+                       /* no break */
                case '}':
                        if (!a->quotes) {
                                return add_element(a, el);
                        }
                        break;
 
-               case '\\':
-                       a->escaped = !a->escaped;
-                       break;
-
-               default:
-                       a->escaped = 0;
-                       break;
                }
        }
 
@@ -298,12 +325,13 @@ static STATUS parse_element(ArrayParserState *a)
        return FAILURE;
 }
 
-static STATUS parse_elements(ArrayParserState *a)
+static ZEND_RESULT_CODE parse_elements(ArrayParserState *a)
 {
+       char delims[] = {'}', PHP_PQ_DELIM_OF_ARRAY(a->typ), 0};
        TSRMLS_FETCH_FROM_CTX(a->ts);
 
-       while (SUCCESS == parse_element(a)) {
-               switch (caa(a, ",}", 0)) {
+       while (SUCCESS == parse_element(a, delims[1])) {
+               switch (caa(a, delims, 0)) {
                case 0:
                        return FAILURE;
 
@@ -322,7 +350,7 @@ static STATUS parse_elements(ArrayParserState *a)
        return FAILURE;
 }
 
-static STATUS parse_array(ArrayParserState *a)
+static ZEND_RESULT_CODE parse_array(ArrayParserState *a)
 {
        HashTableList *list;