diff options
-rw-r--r-- | NEWS | 1 | ||||
-rwxr-xr-x | ext/spl/internal/splfileobject.inc | 40 | ||||
-rwxr-xr-x | ext/spl/spl_directory.c | 114 | ||||
-rwxr-xr-x | ext/spl/spl_directory.h | 2 | ||||
-rw-r--r-- | ext/standard/file.c | 22 | ||||
-rw-r--r-- | ext/standard/file.h | 1 |
6 files changed, 160 insertions, 20 deletions
@@ -50,6 +50,7 @@ PHP NEWS . Added array functions to ArrayObject/ArrayIterator and made them faster. . Added support for reading csv and skipping empty lines in SplFileObject. . Added CachingIterator::TOSTRING_USE_INNER, calls inner iterator __toString. + . Added ability to set the CSV separator per SplFileObject. - Improved xmlReader: (Rob) . Added readInnerXml(), xmlReader::setSchema(). . Added readInnerXML(), readOuterXML(), readString(), setSchema(). (2.6.20+) diff --git a/ext/spl/internal/splfileobject.inc b/ext/spl/internal/splfileobject.inc index 9d347b4b20..08b2d091dd 100755 --- a/ext/spl/internal/splfileobject.inc +++ b/ext/spl/internal/splfileobject.inc @@ -4,7 +4,7 @@ * @ingroup SPL * @brief class FileObject * @author Marcus Boerger - * @date 2003 - 2005 + * @date 2003 - 2006 * * SPL - Standard PHP Library */ @@ -12,10 +12,10 @@ /** @ingroup SPL * @brief Object representation for any stream * @author Marcus Boerger - * @version 1.0 + * @version 1.1 * @since PHP 5.1 */ -class SplFileObject implements RecursiveIterator, SeekableIterator +class SplFileObject extends SplFileInfo implements RecursiveIterator, SeekableIterator { /** Flag: wheter to suppress new lines */ const DROP_NEW_LINE = 0x00000001; @@ -26,6 +26,8 @@ class SplFileObject implements RecursiveIterator, SeekableIterator private $lnum = 0; private $max_len = 0; private $flags = 0; + private $delimiter= ','; + private $enclosure= '"'; /** * Constructs a new file object @@ -80,14 +82,44 @@ class SplFileObject implements RecursiveIterator, SeekableIterator * @param enclosure end of * @return array containing read data */ - function fgetcsv($delimiter = ';', $enclosure = '') + function fgetcsv($delimiter = NULL, $enclosure = NULL) { $this->freeLine(); $this->lnum++; + switch(fun_num_args()) + { + case 0: + $delimiter = $this->delimiter; + case 1: + $enclosure = $this->enclosure; + default: + case 2: + break; + } return fgetcsv($this->fp, $this->max_len, $delimiter, $enclosure); } /** + * Set the delimiter and enclosure character used in fgetcsv + * + * @param delimiter new delimiter, defaults to ',' + * @param enclosure new enclosure, defaults to '"' + */ + function setCsvControl($delimiter = ';', $enclosure = '"') + { + $this->delimiter = $delimiter; + $this->enclosure = $enclosure; + } + + /** + * @return array(delimiter, enclosure) as used in fgetcsv + */ + function getCsvControl($delimiter = ',', $enclosure = '"') + { + return array($this->delimiter, $this->enclosure); + } + + /** * @param operation lock operation (LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB) * @retval $wouldblock whether the operation would block */ diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 23a65a52ab..f84a515dc9 100755 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -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); @@ -1441,17 +1444,25 @@ 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); + if (Z_TYPE_P(return_value) != IS_NULL) { + zval_dtor(return_value); + ZVAL_NULL(return_value); + } + php_fgetcsv(intern->u.file.stream, delimiter, enclosure, buf_len, buf, return_value TSRMLS_CC); + } + return ret; } /* }}} */ @@ -1469,7 +1480,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); } @@ -1794,9 +1805,86 @@ 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); + } +} +/* }}} */ + +/* {{{ proto void SplFileObject::setCsvControl([string delimiter = ',' [, string enclosure = '"']]) + Set the delimiter and enclosure character used in fgetcsv */ +SPL_METHOD(SplFileObject, setCsvControl) +{ + spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + char delimiter = ',', enclosure = '"'; + char *delim, *enclo; + int d_len, e_len; + + 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; + } + intern->u.file.delimiter = delimiter; + intern->u.file.enclosure = enclosure; + } +} +/* }}} */ + +/* {{{ proto array SplFileObject::getCsvControl() + Get the delimiter and enclosure character used in fgetcsv */ +SPL_METHOD(SplFileObject, getCsvControl) +{ + spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); + char delimiter[2], enclosure[2]; + + array_init(return_value); + + delimiter[0] = intern->u.file.delimiter; + delimiter[1] = '\0'; + enclosure[0] = intern->u.file.enclosure; + enclosure[1] = '\0'; + + add_next_index_string(return_value, delimiter, 1); + add_next_index_string(return_value, enclosure, 1); } /* }}} */ @@ -2057,6 +2145,8 @@ static zend_function_entry spl_SplFileObject_functions[] = { SPL_ME(SplFileObject, valid, NULL, ZEND_ACC_PUBLIC) SPL_ME(SplFileObject, fgets, NULL, ZEND_ACC_PUBLIC) SPL_ME(SplFileObject, fgetcsv, arginfo_file_object_fgetcsv, ZEND_ACC_PUBLIC) + SPL_ME(SplFileObject, setCsvControl, arginfo_file_object_fgetcsv, ZEND_ACC_PUBLIC) + SPL_ME(SplFileObject, getCsvControl, NULL, ZEND_ACC_PUBLIC) SPL_ME(SplFileObject, flock, arginfo_file_object_flock, ZEND_ACC_PUBLIC) SPL_ME(SplFileObject, fflush, NULL, ZEND_ACC_PUBLIC) SPL_ME(SplFileObject, ftell, NULL, ZEND_ACC_PUBLIC) 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 744fa21d1c..0bbb23f48c 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -1976,17 +1976,14 @@ PHP_FUNCTION(fputcsv) Get line from file pointer and parse for CSV fields */ 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; @@ -2048,6 +2045,23 @@ 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 099a6ddbcc..9d1836141d 100644 --- a/ext/standard/file.h +++ b/ext/standard/file.h @@ -74,6 +74,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 |