summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Boerger <helly@php.net>2004-09-26 21:55:22 +0000
committerMarcus Boerger <helly@php.net>2004-09-26 21:55:22 +0000
commit32e478b9fc0c677ada30e9dc13b6983d7154550d (patch)
treede953310662f7a6856ec49b1e145b7b1044d8a6e
parent5177691e4a671fc313b1296d09b1d9a4cced568c (diff)
downloadphp-git-32e478b9fc0c677ada30e9dc13b6983d7154550d.tar.gz
- Add fputcsv() (David Sklar)
-rw-r--r--ext/standard/basic_functions.c1
-rw-r--r--ext/standard/file.c103
-rw-r--r--ext/standard/file.h1
-rwxr-xr-xext/standard/tests/file/fputcsv.phpt107
4 files changed, 212 insertions, 0 deletions
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index c9449ee492..dd4299a9a3 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -602,6 +602,7 @@ function_entry basic_functions[] = {
PHP_FE(stream_copy_to_stream, NULL)
PHP_FE(stream_get_contents, NULL)
PHP_FE(fgetcsv, NULL)
+ PHP_FE(fputcsv, NULL)
PHP_FE(flock, third_arg_force_ref)
PHP_FE(get_meta_tags, NULL)
PHP_FE(stream_set_write_buffer, NULL)
diff --git a/ext/standard/file.c b/ext/standard/file.c
index f8e08ade00..835f26893e 100644
--- a/ext/standard/file.c
+++ b/ext/standard/file.c
@@ -35,6 +35,7 @@
#include "php_open_temporary_file.h"
#include "ext/standard/basic_functions.h"
#include "php_ini.h"
+#include "php_smart_str.h"
#include <stdio.h>
#include <stdlib.h>
@@ -1715,6 +1716,108 @@ quit_loop:
return ptr;
}
+#define FPUTCSV_FLD_CHK(c) php_memnstr(Z_STRVAL_PP(field), c, 1, Z_STRVAL_PP(field) + Z_STRLEN_PP(field))
+
+/* {{{ proto int fputcsv(resource fp, array fields [, string delimiter [, string enclosure]])
+ Format line as CSV and write to file pointer */
+PHP_FUNCTION(fputcsv)
+{
+ char delimiter = ','; /* allow this to be set as parameter */
+ char enclosure = '"'; /* allow this to be set as parameter */
+ php_stream *stream;
+ int ret;
+ zval *fp = NULL, *fields = NULL, **field = NULL;
+ char *delimiter_str = NULL, *enclosure_str = NULL;
+ int delimiter_str_len, enclosure_str_len;
+ HashPosition pos;
+ int count, i = 0;
+ char enc_double[3];
+ smart_str csvline = {0};
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|ass",
+ &fp, &fields, &delimiter_str, &delimiter_str_len,
+ &enclosure_str, &enclosure_str_len) == FAILURE) {
+ return;
+ }
+
+ if (delimiter_str != NULL) {
+ /* Make sure that there is at least one character in string */
+ if (delimiter_str_len < 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "delimiter must be a character");
+ RETURN_FALSE;
+ } else if (delimiter_str_len > 1) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "delimiter must be a single character");
+ }
+
+ /* use first character from string */
+ delimiter = *delimiter_str;
+ }
+
+ if (enclosure_str != NULL) {
+ if (enclosure_str_len < 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character");
+ RETURN_FALSE;
+ } else if (enclosure_str_len > 1) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "enclosure must be a single character");
+ }
+ /* use first character from string */
+ enclosure = *enclosure_str;
+ }
+
+ PHP_STREAM_TO_ZVAL(stream, &fp);
+
+ enc_double[0] = enclosure;
+ enc_double[1] = enclosure;
+ enc_double[2] = '\0';
+ count = zend_hash_num_elements(Z_ARRVAL_P(fields));
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(fields), &pos);
+ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(fields), (void **) &field, &pos) == SUCCESS) {
+ if (Z_TYPE_PP(field) != IS_STRING) {
+ SEPARATE_ZVAL(field);
+ convert_to_string(*field);
+ }
+ /* enclose a field that contains a delimiter, an enclosure character, or a newline */
+ if (FPUTCSV_FLD_CHK(&delimiter) || FPUTCSV_FLD_CHK(&enclosure) || FPUTCSV_FLD_CHK("\n") ||
+ FPUTCSV_FLD_CHK("\r") || FPUTCSV_FLD_CHK(" ") || FPUTCSV_FLD_CHK("\t")
+ ) {
+ zval enclosed_field;
+ smart_str_appendl(&csvline, &enclosure, 1);
+
+ php_char_to_str_ex(Z_STRVAL_PP(field), Z_STRLEN_PP(field),
+ enclosure, enc_double, 2, &enclosed_field, 0, NULL);
+ smart_str_appendl(&csvline, Z_STRVAL(enclosed_field), Z_STRLEN(enclosed_field));
+ zval_dtor(&enclosed_field);
+
+ smart_str_appendl(&csvline, &enclosure, 1);
+ } else {
+ smart_str_appendl(&csvline, Z_STRVAL_PP(field), Z_STRLEN_PP(field));
+ }
+
+ if (++i != count) {
+ smart_str_appendl(&csvline, &delimiter, 1);
+ }
+ zend_hash_move_forward_ex(Z_ARRVAL_P(fields), &pos);
+ }
+
+ smart_str_appendc(&csvline, '\n');
+ smart_str_0(&csvline);
+
+ if (!PG(magic_quotes_runtime)) {
+ ret = php_stream_write(stream, csvline.c, csvline.len);
+ } else {
+ char *buffer = estrndup(csvline.c, csvline.len);
+ int len = csvline.len;
+ php_stripslashes(buffer, &len TSRMLS_CC);
+ ret = php_stream_write(stream, buffer, len);
+ efree(buffer);
+ }
+
+ smart_str_free(&csvline);
+
+ RETURN_LONG(ret);
+}
+/* }}} */
+
/* {{{ proto array fgetcsv(resource fp [,int length [, string delimiter [, string enclosure]]])
Get line from file pointer and parse for CSV fields */
PHP_FUNCTION(fgetcsv)
diff --git a/ext/standard/file.h b/ext/standard/file.h
index dfcf79561c..3f76cbf211 100644
--- a/ext/standard/file.h
+++ b/ext/standard/file.h
@@ -39,6 +39,7 @@ PHPAPI PHP_FUNCTION(fgets);
PHP_FUNCTION(fscanf);
PHPAPI PHP_FUNCTION(fgetss);
PHP_FUNCTION(fgetcsv);
+PHP_FUNCTION(fputcsv);
PHPAPI PHP_FUNCTION(fwrite);
PHPAPI PHP_FUNCTION(fflush);
PHPAPI PHP_FUNCTION(rewind);
diff --git a/ext/standard/tests/file/fputcsv.phpt b/ext/standard/tests/file/fputcsv.phpt
new file mode 100755
index 0000000000..6d919563e9
--- /dev/null
+++ b/ext/standard/tests/file/fputcsv.phpt
@@ -0,0 +1,107 @@
+--TEST--
+various fputcsv() functionality tests
+--INI--
+magic_quotes_runtime=0
+--FILE--
+<?php
+
+$list = array (
+ 0 => 'aaa,bbb',
+ 1 => 'aaa,"bbb"',
+ 2 => '"aaa","bbb"',
+ 3 => 'aaa,bbb',
+ 4 => '"aaa",bbb',
+ 5 => '"aaa", "bbb"',
+ 6 => ',',
+ 7 => 'aaa,',
+ 8 => ',"aaa"',
+ 9 => '"",""',
+ 10 => '"""""",',
+ 11 => '""""",aaa',
+ 12 => 'aaa,bbb ',
+ 13 => 'aaa,"bbb "',
+ 14 => 'aaa"aaa","bbb"bbb',
+ 15 => 'aaa"aaa""",bbb',
+ 16 => 'aaa,"\\"bbb,ccc',
+ 17 => 'aaa"\\"a","bbb"',
+ 18 => '"\\"","aaa"',
+ 19 => '"\\""",aaa',
+);
+
+$file = dirname(__FILE__) . 'fgetcsv.csv';
+@unlink($file);
+
+$fp = fopen($file, "w");
+foreach ($list as $v) {
+ fputcsv($fp, split(',', $v));
+}
+fclose($fp);
+
+$res = file($file);
+foreach($res as &$val)
+{
+ $val = substr($val, 0, -1);
+}
+echo '$list = ';var_export($res);echo ";\n";
+
+$fp = fopen($file, "r");
+$res = array();
+while($l=fgetcsv($fp))
+{
+ $res[] = join(',',$l);
+}
+fclose($fp);
+
+echo '$list = ';var_export($res);echo ";\n";
+
+@unlink($file);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+$list = array (
+ 0 => 'aaa,bbb',
+ 1 => 'aaa,"""bbb"""',
+ 2 => '"""aaa""","""bbb"""',
+ 3 => 'aaa,bbb',
+ 4 => '"""aaa""",bbb',
+ 5 => '"""aaa"""," ""bbb"""',
+ 6 => ',',
+ 7 => 'aaa,',
+ 8 => ',"""aaa"""',
+ 9 => '"""""",""""""',
+ 10 => '"""""""""""""",',
+ 11 => '"""""""""""",aaa',
+ 12 => 'aaa,"bbb "',
+ 13 => 'aaa,"""bbb """',
+ 14 => '"aaa""aaa""","""bbb""bbb"',
+ 15 => '"aaa""aaa""""""",bbb',
+ 16 => 'aaa,"""\\""bbb",ccc',
+ 17 => '"aaa""\\""a""","""bbb"""',
+ 18 => '"""\\""""","""aaa"""',
+ 19 => '"""\\""""""",aaa',
+);
+$list = array (
+ 0 => 'aaa,bbb',
+ 1 => 'aaa,"bbb"',
+ 2 => '"aaa","bbb"',
+ 3 => 'aaa,bbb',
+ 4 => '"aaa",bbb',
+ 5 => '"aaa", "bbb"',
+ 6 => ',',
+ 7 => 'aaa,',
+ 8 => ',"aaa"',
+ 9 => '"",""',
+ 10 => '"""""",',
+ 11 => '""""",aaa',
+ 12 => 'aaa,bbb ',
+ 13 => 'aaa,"bbb "',
+ 14 => 'aaa"aaa","bbb"bbb',
+ 15 => 'aaa"aaa""",bbb',
+ 16 => 'aaa,"\\"bbb,ccc',
+ 17 => 'aaa"\\"a","bbb"',
+ 18 => '"\\"","aaa"',
+ 19 => '"\\""",aaa',
+);
+===DONE===