From d795e0b9bb5be027e86fe2be89f029a866c1c9ec Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Sat, 15 Jul 2006 14:31:51 +0000 Subject: [PATCH] - Implement todo: SplFileObject: ability to set the CSV separator per object --- ext/spl/spl_directory.c | 56 +++++++++++++++++++++++++++++++---------- ext/spl/spl_directory.h | 2 ++ ext/standard/file.c | 21 +++++++++++++--- ext/standard/file.h | 1 + 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 207d955930..298e99b826 100755 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -207,7 +207,7 @@ static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_inclu if (!intern->file_name_len || !intern->u.file.stream) { if (!EG(exception)) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot open file '%s'", intern->file_name); + zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot open file '%s'", intern->file_name_len ? intern->file_name : ""); } intern->file_name = NULL; /* until here it is not a copy */ intern->u.file.open_mode = NULL; @@ -232,6 +232,9 @@ static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_inclu /* avoid reference counting in debug mode, thus do it manually */ ZVAL_RESOURCE(&intern->u.file.zresource, php_stream_get_resource_id(intern->u.file.stream)); intern->u.file.zresource.refcount = 1; + + intern->u.file.delimiter = ','; + intern->u.file.enclosure = '"'; zend_hash_find(&intern->std.ce->function_table, "getcurrentline", sizeof("getcurrentline"), (void **) &intern->u.file.func_getCurr); @@ -1435,17 +1438,21 @@ static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function spl_filesystem_file_call(intern, func_ptr, pass_num_args, return_value, arg2 TSRMLS_CC); \ } -static void spl_filesystem_file_read_csv(zval * this_ptr, spl_filesystem_object *intern, int pass_num_args, zval *return_value TSRMLS_DC) /* {{{ */ +static int spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, zval *return_value TSRMLS_DC) /* {{{ */ { - zval *arg2 = NULL; - MAKE_STD_ZVAL(arg2); - ZVAL_LONG(arg2, intern->u.file.max_line_len); - - spl_filesystem_file_free_line(intern TSRMLS_CC); - - FileFunctionCall(fgetcsv, pass_num_args, arg2); + int ret = SUCCESS; + + do { + ret = spl_filesystem_file_read(intern, 1 TSRMLS_CC); + } while (ret == SUCCESS && !intern->u.file.current_line_len && (intern->flags & SPL_FILE_OBJECT_SKIP_EMPTY)); + + if (ret == SUCCESS) { + size_t buf_len = intern->u.file.current_line_len; + char *buf = estrndup(intern->u.file.current_line, buf_len); - zval_ptr_dtor(&arg2); + php_fgetcsv(intern->u.file.stream, delimiter, enclosure, buf_len, buf, return_value TSRMLS_CC); + } + return ret; } /* }}} */ @@ -1463,7 +1470,7 @@ static int spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_obje } if (intern->flags & SPL_FILE_OBJECT_READ_CSV) { MAKE_STD_ZVAL(retval); - spl_filesystem_file_read_csv(this_ptr, intern, 0, retval TSRMLS_CC); + return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, retval TSRMLS_CC); } else { zend_call_method_with_0_params(&this_ptr, Z_OBJCE_P(getThis()), &intern->u.file.func_getCurr, "getCurrentLine", &retval); } @@ -1790,9 +1797,32 @@ SPL_METHOD(SplFileObject, func_name) \ SPL_METHOD(SplFileObject, fgetcsv) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure; + char *delim, *enclo; + int d_len, e_len; - spl_filesystem_file_read_csv(getThis(), intern, ZEND_NUM_ARGS(), return_value TSRMLS_CC); - intern->u.file.current_line_num++; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &delim, &d_len, &enclo, &e_len) == SUCCESS) { + switch(ZEND_NUM_ARGS()) + { + case 2: + if (e_len != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character"); + RETURN_FALSE; + } + enclosure = enclo[0]; + /* no break */ + case 1: + if (d_len != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "delimiter must be a character"); + RETURN_FALSE; + } + delimiter = delim[0]; + /* no break */ + case 0: + break; + } + spl_filesystem_file_read_csv(intern, delimiter, enclosure, return_value TSRMLS_CC); + } } /* }}} */ diff --git a/ext/spl/spl_directory.h b/ext/spl/spl_directory.h index 2ab7513a1c..e2f9de4e15 100755 --- a/ext/spl/spl_directory.h +++ b/ext/spl/spl_directory.h @@ -82,6 +82,8 @@ struct _spl_filesystem_object { long current_line_num; zval zresource; zend_function *func_getCurr; + char delimiter; + char enclosure; } file; } u; }; diff --git a/ext/standard/file.c b/ext/standard/file.c index 8d6e79cf77..f98b62a2e0 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -2054,17 +2054,14 @@ PHP_FUNCTION(fputcsv) /* UTODO: Accept unicode contents */ PHP_FUNCTION(fgetcsv) { - char *temp, *tptr, *bptr, *line_end, *limit; char delimiter = ','; /* allow this to be set as parameter */ char enclosure = '"'; /* allow this to be set as parameter */ - const char escape_char = '\\'; /* first section exactly as php_fgetss */ long len = 0; - size_t buf_len, temp_len, line_end_len; + size_t buf_len; char *buf; php_stream *stream; - int inc_len; { zval *fd, **len_zv = NULL; @@ -2126,6 +2123,22 @@ PHP_FUNCTION(fgetcsv) RETURN_FALSE; } } + + php_fgetcsv(stream, delimiter, enclosure, buf_len, buf, return_value TSRMLS_CC); +} +/* }}} */ + +PHPAPI void php_fgetcsv(php_stream *stream, /* {{{ */ + char delimiter, char enclosure, + size_t buf_len, char *buf, + zval *return_value TSRMLS_DC) +{ + char *temp, *tptr, *bptr, *line_end, *limit; + const char escape_char = '\\'; + + size_t temp_len, line_end_len; + int inc_len; + /* initialize internal state */ php_mblen(NULL, 0); diff --git a/ext/standard/file.h b/ext/standard/file.h index a88e360836..c87dc1854b 100644 --- a/ext/standard/file.h +++ b/ext/standard/file.h @@ -75,6 +75,7 @@ PHPAPI int php_set_sock_blocking(int socketd, int block TSRMLS_DC); PHPAPI int php_copy_file(char *src, char *dest TSRMLS_DC); PHPAPI int php_mkdir_ex(char *dir, long mode, int options TSRMLS_DC); PHPAPI int php_mkdir(char *dir, long mode TSRMLS_DC); +PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, size_t buf_len, char *buf, zval *return_value TSRMLS_DC); #define META_DEF_BUFSIZE 8192 -- 2.40.0