summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Boerger <helly@php.net>2006-07-15 15:08:41 +0000
committerMarcus Boerger <helly@php.net>2006-07-15 15:08:41 +0000
commit9c30e20bd672b7c8ef53257705e9010dd29b656f (patch)
tree003ea112037c0fc8241f19c4af80df7cc5c88c5b
parentbb3c702162f2f67a2e7187dae621aed071c8b5f3 (diff)
downloadphp-git-9c30e20bd672b7c8ef53257705e9010dd29b656f.tar.gz
- MFH Implement todo: SplFileObject: ability to set the CSV separator per object
-rw-r--r--NEWS1
-rwxr-xr-xext/spl/internal/splfileobject.inc40
-rwxr-xr-xext/spl/spl_directory.c114
-rwxr-xr-xext/spl/spl_directory.h2
-rw-r--r--ext/standard/file.c22
-rw-r--r--ext/standard/file.h1
6 files changed, 160 insertions, 20 deletions
diff --git a/NEWS b/NEWS
index a4ae2ba9f8..ce0ed32d08 100644
--- a/NEWS
+++ b/NEWS
@@ -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