mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
- Add fputcsv() (David Sklar)
This commit is contained in:
parent
5177691e4a
commit
32e478b9fc
4 changed files with 212 additions and 0 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
107
ext/standard/tests/file/fputcsv.phpt
Executable file
107
ext/standard/tests/file/fputcsv.phpt
Executable file
|
@ -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===
|
Loading…
Add table
Add a link
Reference in a new issue