X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-pq;a=blobdiff_plain;f=src%2Fphp_pq_misc.c;h=44e9f357f1301a2c3a2b41902d7937a2144f7ddb;hp=72fa07bac306736800ec53ec4b762584ccb8d462;hb=e830226915242b6831e11009503a462d7971b965;hpb=9e37136f3b7f6d2d2d35b5626cd56dab0d5acce3 diff --git a/src/php_pq_misc.c b/src/php_pq_misc.c index 72fa07b..44e9f35 100644 --- a/src/php_pq_misc.c +++ b/src/php_pq_misc.c @@ -248,6 +248,7 @@ typedef struct _ArrayParserState { #ifdef ZTS void ***ts; #endif + Oid typ; unsigned quotes:1; unsigned escaped:1; } ArrayParserState; @@ -271,31 +272,28 @@ static char caa(ArrayParserState *a, const char *any, unsigned advance) static STATUS add_element(ArrayParserState *a, const char *start) { zval *zelem; + size_t el_len = a->ptr - start; + char *el_str = estrndup(start, el_len); TSRMLS_FETCH_FROM_CTX(a->ts); - MAKE_STD_ZVAL(zelem); if (a->quotes) { - ZVAL_STRINGL(zelem, start, a->ptr - start, 1); - php_stripslashes(Z_STRVAL_P(zelem), &Z_STRLEN_P(zelem) TSRMLS_CC); + int tmp_len; + + php_stripslashes(el_str, &tmp_len TSRMLS_CC); + el_len = tmp_len; } else if ((a->ptr - start == 4) && !strncmp(start, "NULL", 4)) { + efree(el_str); + el_str = NULL; + el_len = 0; + } + + if (!el_str) { + MAKE_STD_ZVAL(zelem); ZVAL_NULL(zelem); } else { - long lval = 0; - double dval = 0; - - switch (is_numeric_string(start, a->ptr - start, &lval, &dval, 0)) { - case IS_LONG: - ZVAL_LONG(zelem, lval); - break; + zelem = php_pq_typed_zval(el_str, el_len, a->typ TSRMLS_CC); - case IS_DOUBLE: - ZVAL_DOUBLE(zelem, dval); - break; - - default: - ZVAL_STRINGL(zelem, start, a->ptr - start, 1); - break; - } + efree(el_str); } return zend_hash_next_index_insert(&a->list->ht, &zelem, sizeof(zval *), NULL); @@ -420,12 +418,13 @@ static STATUS parse_array(ArrayParserState *a) return SUCCESS; } -HashTable *php_pq_parse_array(const char *val_str, size_t val_len TSRMLS_DC) +HashTable *php_pq_parse_array(const char *val_str, size_t val_len, Oid typ TSRMLS_DC) { HashTable *ht = NULL; ArrayParserState a = {0}; TSRMLS_SET_CTX(a.ts); + a.typ = typ; a.ptr = val_str; a.end = val_str + val_len; @@ -451,6 +450,71 @@ HashTable *php_pq_parse_array(const char *val_str, size_t val_len TSRMLS_DC) return ht; } +zval *php_pq_typed_zval(char *val, size_t len, Oid typ TSRMLS_DC) +{ + zval *zv; + + MAKE_STD_ZVAL(zv); + + switch (typ) { +#ifdef HAVE_PHP_PQ_TYPE_H +# undef PHP_PQ_TYPE +# include "php_pq_type.h" + case PHP_PQ_OID_BOOL: + ZVAL_BOOL(zv, *val == 't'); + break; +#if SIZEOF_LONG >= 8 + case PHP_PQ_OID_INT8: + case PHP_PQ_OID_TID: +#endif + case PHP_PQ_OID_INT4: + case PHP_PQ_OID_INT2: + case PHP_PQ_OID_XID: + case PHP_PQ_OID_OID: + ZVAL_LONG(zv, zend_atol(val, len)); + break; + + case PHP_PQ_OID_FLOAT4: + case PHP_PQ_OID_FLOAT8: + ZVAL_DOUBLE(zv, zend_strtod(val, NULL)); + break; + + case PHP_PQ_OID_DATE: + php_pqdt_from_string(val, len, "Y-m-d", zv TSRMLS_CC); + break; + + case PHP_PQ_OID_ABSTIME: + php_pqdt_from_string(val, len, "Y-m-d H:i:s", zv TSRMLS_CC); + break; + + case PHP_PQ_OID_TIMESTAMP: + php_pqdt_from_string(val, len, "Y-m-d H:i:s.u", zv TSRMLS_CC); + break; + + case PHP_PQ_OID_TIMESTAMPTZ: + php_pqdt_from_string(val, len, "Y-m-d H:i:s.uO", zv TSRMLS_CC); + break; + + default: + if (PHP_PQ_TYPE_IS_ARRAY(typ) && (Z_ARRVAL_P(zv) = php_pq_parse_array(val, len, PHP_PQ_TYPE_OF_ARRAY(typ) TSRMLS_CC))) { + Z_TYPE_P(zv) = IS_ARRAY; + } else { + ZVAL_STRINGL(zv, val, len, 1); + } + break; +#else + case 16: /* BOOL */ + ZVAL_BOOL(zv, *val == 't'); + break; + + default: + ZVAL_STRINGL(zv, val, len, 1); +#endif + } + + return zv; +} + /* * Local variables: * tab-width: 4