From 0bd3a87e85b4716c386563ecc6811f4b45b54f8b Mon Sep 17 00:00:00 2001 From: Alex Malyshev Date: Fri, 6 Sep 2013 13:31:30 -0700 Subject: [PATCH] Implement str_getcsv, and fix some fgetcsv related issues str_getcsv is now just a wrapper around fgetcsv Differential Revision: D958124 --- hphp/runtime/base/file.cpp | 19 +++++++------ hphp/runtime/ext/ext_file.cpp | 13 ++++++--- hphp/system/php.txt | 1 + hphp/system/php/misc/str_getcsv.php | 32 ++++++++++++++++++++++ .../{bad => good}/ext-standard-file/bug53848.php | 2 +- .../ext-standard-file/bug53848.php.expectf | 0 .../ext-standard-file/fgetcsv_error.php | 2 +- .../ext-standard-file/fgetcsv_error.php.expectf | 0 .../stream_get_contents_001.php | 2 +- .../stream_get_contents_001.php.expectf | 2 +- .../ext-standard-strings/str_getcsv_001.php | 2 +- .../str_getcsv_001.php.expectf | 0 12 files changed, 58 insertions(+), 17 deletions(-) create mode 100644 hphp/system/php/misc/str_getcsv.php rename hphp/test/zend/{bad => good}/ext-standard-file/bug53848.php (98%) rename hphp/test/zend/{bad => good}/ext-standard-file/bug53848.php.expectf (100%) rename hphp/test/zend/{bad => good}/ext-standard-file/fgetcsv_error.php (98%) rename hphp/test/zend/{bad => good}/ext-standard-file/fgetcsv_error.php.expectf (100%) rename hphp/test/zend/{bad => good}/ext-standard-strings/str_getcsv_001.php (99%) rename hphp/test/zend/{bad => good}/ext-standard-strings/str_getcsv_001.php.expectf (100%) diff --git a/hphp/runtime/base/file.cpp b/hphp/runtime/base/file.cpp index 050631e8d90..c31a2f6885a 100644 --- a/hphp/runtime/base/file.cpp +++ b/hphp/runtime/base/file.cpp @@ -623,11 +623,14 @@ Array File::readCSV(int64_t length /* = 0 */, char delimiter_char /* = ',' */, tptr = temp; - /* 1. Strip any leading space */ - for (; bptr < limit; ++bptr) { - if (!isspace((int)*(unsigned char *)bptr) || *bptr == delimiter_char) { - break; - } + /* 1. Strip any leading space before an enclosure */ + + const char *tmp = bptr; + while ((*tmp != delimiter_char) && isspace((int)*(unsigned char *)tmp)) { + ++tmp; + } + if (*tmp == enclosure_char) { + bptr = tmp; } if (first_field && bptr == line_end) { @@ -724,10 +727,10 @@ Array File::readCSV(int64_t length /* = 0 */, char delimiter_char /* = ',' */, state = 0; break; default: - if (*bptr == escape_char) { - state = 1; - } else if (*bptr == enclosure_char) { + if (*bptr == enclosure_char) { state = 2; + } else if (*bptr == escape_char) { + state = 1; } bptr++; break; diff --git a/hphp/runtime/ext/ext_file.cpp b/hphp/runtime/ext/ext_file.cpp index 67fef149c9c..def59a3b584 100644 --- a/hphp/runtime/ext/ext_file.cpp +++ b/hphp/runtime/ext/ext_file.cpp @@ -50,13 +50,18 @@ #include #include -#define CHECK_HANDLE(handle, f) \ +#define CHECK_HANDLE_BASE(handle, f, ret) \ File *f = handle.getTyped(true, true); \ - if (f == NULL || f->isClosed()) { \ + if (f == nullptr || f->isClosed()) { \ raise_warning("Not a valid stream resource"); \ - return false; \ + return (ret); \ } \ +#define CHECK_HANDLE(handle, f) \ + CHECK_HANDLE_BASE(handle, f, false) +#define CHECK_HANDLE_RET_NULL(handle, f) \ + CHECK_HANDLE_BASE(handle, f, null_variant) + #define CHECK_SYSTEM(exp) \ if ((exp) != 0) { \ Logger::Verbose("%s/%d: %s", __FUNCTION__, __LINE__, \ @@ -381,7 +386,7 @@ Variant f_fgetcsv(CResRef handle, int64_t length /* = 0 */, throw_invalid_argument("escape: %s", enclosure.data()); return false; } - CHECK_HANDLE(handle, f); + CHECK_HANDLE_RET_NULL(handle, f); Array ret = f->readCSV(length, delimiter.charAt(0), enclosure.charAt(0), escape.charAt(0)); if (!ret.isNull()) { diff --git a/hphp/system/php.txt b/hphp/system/php.txt index 4bb25091d8d..1d2f3828dc6 100644 --- a/hphp/system/php.txt +++ b/hphp/system/php.txt @@ -73,6 +73,7 @@ hphp/system/php/json/JsonSerializable.php hphp/system/php/lang/ErrorException.php hphp/system/php/misc/highlight.php hphp/system/php/misc/php_strip_whitespace.php +hphp/system/php/misc/str_getcsv.php hphp/system/php/pdo/PDOException.php hphp/system/php/redis/Redis.php hphp/system/php/redis/RedisSessionModule.php diff --git a/hphp/system/php/misc/str_getcsv.php b/hphp/system/php/misc/str_getcsv.php new file mode 100644 index 00000000000..6f1165c5204 --- /dev/null +++ b/hphp/system/php/misc/str_getcsv.php @@ -0,0 +1,32 @@ + 1) { + $args[$i] = substr($args[$i], 0, 1); + } + } + + $temp = tmpfile(); + fwrite($temp, $input); + fseek($temp, 0); + $ret = fgetcsv($temp, 0, $args[0], $args[1], $args[2]); + fclose($temp); + return $ret !== false ? $ret : array(null); +} diff --git a/hphp/test/zend/bad/ext-standard-file/bug53848.php b/hphp/test/zend/good/ext-standard-file/bug53848.php similarity index 98% rename from hphp/test/zend/bad/ext-standard-file/bug53848.php rename to hphp/test/zend/good/ext-standard-file/bug53848.php index 474095b226b..21971be9299 100644 --- a/hphp/test/zend/bad/ext-standard-file/bug53848.php +++ b/hphp/test/zend/good/ext-standard-file/bug53848.php @@ -6,4 +6,4 @@ $fp = fopen($file, "r"); while ($l = fgetcsv($fp)) var_dump($l); fclose($fp); @unlink($file); -?> \ No newline at end of file +?> diff --git a/hphp/test/zend/bad/ext-standard-file/bug53848.php.expectf b/hphp/test/zend/good/ext-standard-file/bug53848.php.expectf similarity index 100% rename from hphp/test/zend/bad/ext-standard-file/bug53848.php.expectf rename to hphp/test/zend/good/ext-standard-file/bug53848.php.expectf diff --git a/hphp/test/zend/bad/ext-standard-file/fgetcsv_error.php b/hphp/test/zend/good/ext-standard-file/fgetcsv_error.php similarity index 98% rename from hphp/test/zend/bad/ext-standard-file/fgetcsv_error.php rename to hphp/test/zend/good/ext-standard-file/fgetcsv_error.php index af9a32f943e..6cd8419bc44 100644 --- a/hphp/test/zend/bad/ext-standard-file/fgetcsv_error.php +++ b/hphp/test/zend/good/ext-standard-file/fgetcsv_error.php @@ -36,4 +36,4 @@ for($loop_counter = 1; $loop_counter <= count($invalid_args); $loop_counter++) { var_dump( fgetcsv($invalid_args[$loop_counter - 1], $len, $delim, $enclosure, $escape) ); // all args specified } -echo "Done\n"; \ No newline at end of file +echo "Done\n"; diff --git a/hphp/test/zend/bad/ext-standard-file/fgetcsv_error.php.expectf b/hphp/test/zend/good/ext-standard-file/fgetcsv_error.php.expectf similarity index 100% rename from hphp/test/zend/bad/ext-standard-file/fgetcsv_error.php.expectf rename to hphp/test/zend/good/ext-standard-file/fgetcsv_error.php.expectf diff --git a/hphp/test/zend/good/ext-standard-streams/stream_get_contents_001.php b/hphp/test/zend/good/ext-standard-streams/stream_get_contents_001.php index aca5864368c..d973c0d8691 100644 --- a/hphp/test/zend/good/ext-standard-streams/stream_get_contents_001.php +++ b/hphp/test/zend/good/ext-standard-streams/stream_get_contents_001.php @@ -11,4 +11,4 @@ echo stream_get_contents($tmp, 2, -1), "--\n"; @unlink($tmp); -?> \ No newline at end of file +?> diff --git a/hphp/test/zend/good/ext-standard-streams/stream_get_contents_001.php.expectf b/hphp/test/zend/good/ext-standard-streams/stream_get_contents_001.php.expectf index 19547967e3e..6b5a5b938c8 100644 --- a/hphp/test/zend/good/ext-standard-streams/stream_get_contents_001.php.expectf +++ b/hphp/test/zend/good/ext-standard-streams/stream_get_contents_001.php.expectf @@ -1,4 +1,4 @@ -- -- 45-- --- \ No newline at end of file +-- diff --git a/hphp/test/zend/bad/ext-standard-strings/str_getcsv_001.php b/hphp/test/zend/good/ext-standard-strings/str_getcsv_001.php similarity index 99% rename from hphp/test/zend/bad/ext-standard-strings/str_getcsv_001.php rename to hphp/test/zend/good/ext-standard-strings/str_getcsv_001.php index 82ffa1bb765..cf6c1b5a6c1 100644 --- a/hphp/test/zend/bad/ext-standard-strings/str_getcsv_001.php +++ b/hphp/test/zend/good/ext-standard-strings/str_getcsv_001.php @@ -26,4 +26,4 @@ print "-----\n"; var_dump(str_getcsv('')); print "-----\n"; -?> \ No newline at end of file +?> diff --git a/hphp/test/zend/bad/ext-standard-strings/str_getcsv_001.php.expectf b/hphp/test/zend/good/ext-standard-strings/str_getcsv_001.php.expectf similarity index 100% rename from hphp/test/zend/bad/ext-standard-strings/str_getcsv_001.php.expectf rename to hphp/test/zend/good/ext-standard-strings/str_getcsv_001.php.expectf -- 2.11.4.GIT