]> granicus.if.org Git - php/commitdiff
- MFH Implement todo: SplFileObject: ability to set the CSV separator per object
authorMarcus Boerger <helly@php.net>
Sat, 15 Jul 2006 15:08:41 +0000 (15:08 +0000)
committerMarcus Boerger <helly@php.net>
Sat, 15 Jul 2006 15:08:41 +0000 (15:08 +0000)
NEWS
ext/spl/internal/splfileobject.inc
ext/spl/spl_directory.c
ext/spl/spl_directory.h
ext/standard/file.c
ext/standard/file.h

diff --git a/NEWS b/NEWS
index a4ae2ba9f80315d4bdecebf9dfafa547de704e73..ce0ed32d08bc8eec35b20f702e24f4c411cab02d 100644 (file)
--- 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+)
index 9d347b4b205da41e86d77c6cc3c1c48a989a58a4..08b2d091ddbbb58187e218c9bc90d0d978cbb0a4 100755 (executable)
@@ -4,7 +4,7 @@
  * @ingroup SPL
  * @brief class FileObject
  * @author  Marcus Boerger
- * @date    2003 - 2005
+ * @date    2003 - 2006
  *
  * SPL - Standard PHP Library
  */
 /** @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,13 +82,43 @@ 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
index 23a65a52abff1cfcbddd0a6ba6a5b90dfc862416..f84a515dc91fac77beb505e6851330ff95580b78 100755 (executable)
@@ -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)
index 2ab7513a1c772d87861569b9e8d7f45f4625c20a..e2f9de4e1582ae1372fd3f310979dd3fa4cc446f 100755 (executable)
@@ -82,6 +82,8 @@ struct _spl_filesystem_object {
                        long               current_line_num;
                        zval               zresource;
                        zend_function      *func_getCurr;
+                       char               delimiter;
+                       char               enclosure;
                } file;
        } u;
 };
index 744fa21d1ca9f50cf763b3d0364d4b5a70ff7b82..0bbb23f48c3a303aab3b08ec71f4dc9a257ec992 100644 (file)
@@ -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);
 
index 099a6ddbccc3d7570405b928337ffa642cf48cea..9d1836141d5b0375c84d4c568ca9c4f8d4bc2a71 100644 (file)
@@ -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