summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Boerger <helly@php.net>2005-05-03 22:18:19 +0000
committerMarcus Boerger <helly@php.net>2005-05-03 22:18:19 +0000
commit177ea26dc1d6942b292072110e7199ba19656a95 (patch)
tree81f43eebfe2d2c0f83a7c382496c443e271aad66
parent287864a611ccf1023221ddbcb598abe1fbdfea72 (diff)
downloadphp-git-177ea26dc1d6942b292072110e7199ba19656a95.tar.gz
- Make line counting work with FileObject::fgetc()
- Add a test for FileObject::fgetc() - Update docs
-rwxr-xr-xext/spl/internal/fileobject.inc68
-rwxr-xr-xext/spl/spl_directory.c39
-rwxr-xr-xext/spl/tests/fileobject_002.phpt122
3 files changed, 206 insertions, 23 deletions
diff --git a/ext/spl/internal/fileobject.inc b/ext/spl/internal/fileobject.inc
index 152b6e4ece..6cabf97cdd 100755
--- a/ext/spl/internal/fileobject.inc
+++ b/ext/spl/internal/fileobject.inc
@@ -15,7 +15,7 @@
* @version 1.0
* @since PHP 5.1
*/
-class FileObject implements RecursiveIterator
+class FileObject implements RecursiveIterator, SeekableIterator
{
private $fp;
private $fname;
@@ -65,6 +65,7 @@ class FileObject implements RecursiveIterator
*/
function fgets()
{
+ $this->freeLine();
$this->lnum++;
$buf = fgets($this->fp, $this->max_len);
@@ -77,6 +78,7 @@ class FileObject implements RecursiveIterator
*/
function fgetcsv($delimiter = ';', $enclosure = '')
{
+ $this->freeLine();
$this->lnum++;
return fgetcsv($this->fp, $this->max_len, $delimiter, $enclosure);
}
@@ -122,7 +124,11 @@ class FileObject implements RecursiveIterator
*/
function fgetc()
{
- return fgetc($this->fp);
+ $this->freeLine();
+ $c = fgetc($this->fp);
+ if ($c == '\n') {
+ $this->lnum++;
+ }
}
/** Read and return remaining part of stream
@@ -146,6 +152,7 @@ class FileObject implements RecursiveIterator
*/
function fscanf($format /* , ... */)
{
+ $this->freeLine();
$this->lnum++;
return fscanf($this->fp, $format /* , ... */);
}
@@ -228,7 +235,7 @@ class FileObject implements RecursiveIterator
*/
function rewind()
{
- $this->line = NULL;
+ $this->freeLine();
$this->lnum = 0;
}
@@ -254,15 +261,13 @@ class FileObject implements RecursiveIterator
}
/**
- * @note Fill current line buffer if not done yet.
* @return line number
+ * @note fgetc() will increase the line number when reaing a new line char.
+ * This has the effect key() called on a read a new line will already
+ * return the increased line number.
*/
function key()
{
- if (is_null($this->line))
- {
- $line = getCurrentLine();
- }
return $this->lnum;
}
@@ -270,7 +275,7 @@ class FileObject implements RecursiveIterator
*/
function next()
{
- $this->line = NULL;
+ $this->freeLine();
}
/**
@@ -278,16 +283,41 @@ class FileObject implements RecursiveIterator
*/
private function readLine()
{
- $this->lnum++;
- return fgets($this->fp, $this->max_len);
+ if ($this->eof())
+ {
+ $this->freeLine();
+ throw new RuntimeException("Cannot read from file " . $this->fname);
+ }
+ if ($this->line) {
+ $this->lnum++;
+ }
+ $this->freeLine();
+ $this->line = fgets($this->fp, $this->max_len);
+ return $this->line;
+ }
+
+ /**
+ * Free the current line buffer and increment the line counter
+ */
+ private function freeLine()
+ {
+ if ($this->line) {
+ $this->line = NULL;
+ }
}
/*
- * @note if you overload this function key() and current() will increment
- * $this->lnum.
+ * @note If you DO overload this function key() and current() will increment
+ * $this->lnum automatically. If not then function reaLine() will do
+ * that for you.
*/
function getCurrentLine()
{
+ $this->freeLine();
+ if ($this->eof())
+ {
+ throw new RuntimeException("Cannot read from file " . $this->fname);
+ }
$this->readLine();
}
@@ -298,6 +328,18 @@ class FileObject implements RecursiveIterator
{
return current();
}
+
+ /**
+ * @param $line_pos Seek to this line
+ */
+ function seek($line_pos)
+ {
+ $this->rewind();
+ while($this->lnum < $line_pos && !$this->eof())
+ {
+ $this->getCurrentLine();
+ }
+ }
}
?>
diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index c2fd725c46..4a942687fc 100755
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -872,19 +872,14 @@ static zend_function_entry spl_ce_dir_tree_class_functions[] = {
static void spl_file_object_free_line(spl_file_object *intern TSRMLS_DC) /* {{{ */
{
- long line_add = 0;
-
if (intern->current_line) {
efree(intern->current_line);
intern->current_line = NULL;
- line_add = 1;
}
if (intern->current_zval) {
zval_ptr_dtor(&intern->current_zval);
intern->current_zval = NULL;
- line_add = 1;
}
- intern->current_line_num += line_add;
} /* }}} */
static void spl_file_object_free_storage(void *object TSRMLS_DC) /* {{{ */
@@ -944,7 +939,10 @@ static int spl_file_object_read(spl_file_object *intern, int silent TSRMLS_DC) /
char *buf;
size_t line_len;
int len;
+ long line_add = (intern->current_line || intern->current_zval) ? 1 : 0;
+ spl_file_object_free_line(intern TSRMLS_CC);
+
if (php_stream_eof(intern->stream)) {
if (!silent) {
zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot read from file %s", intern->file_name);
@@ -954,8 +952,6 @@ static int spl_file_object_read(spl_file_object *intern, int silent TSRMLS_DC) /
buf = php_stream_get_line(intern->stream, NULL, intern->max_line_len, &line_len);
- spl_file_object_free_line(intern TSRMLS_CC);
-
if (!buf) {
intern->current_line = estrdup("");
intern->current_line_len = 0;
@@ -973,18 +969,28 @@ static int spl_file_object_read(spl_file_object *intern, int silent TSRMLS_DC) /
intern->current_line = buf;
intern->current_line_len = line_len;
}
+ intern->current_line_num += line_add;
return SUCCESS;
} /* }}} */
-static void spl_file_object_read_line(zval * this_ptr, spl_file_object *intern, int silent TSRMLS_DC) /* {{{ */
+static int spl_file_object_read_line(zval * this_ptr, spl_file_object *intern, int silent TSRMLS_DC) /* {{{ */
{
zval *retval;
/* if overloaded call the function, otherwise do it directly */
if (intern->func_getCurr->common.scope != spl_ce_FileObject) {
+ if (php_stream_eof(intern->stream)) {
+ if (!silent) {
+ zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "Cannot read from file %s", intern->file_name);
+ }
+ return FAILURE;
+ }
zend_call_method_with_0_params(&getThis(), Z_OBJCE_P(getThis()), &intern->func_getCurr, "getCurrentLine", &retval);
if (retval) {
+ if (intern->current_line || intern->current_zval) {
+ intern->current_line_num++;
+ }
spl_file_object_free_line(intern TSRMLS_CC);
if (Z_TYPE_P(retval) == IS_STRING) {
intern->current_line = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
@@ -994,9 +1000,12 @@ static void spl_file_object_read_line(zval * this_ptr, spl_file_object *intern,
ZVAL_ZVAL(intern->current_zval, retval, 1, 0);
}
zval_ptr_dtor(&retval);
+ return SUCCESS;
+ } else {
+ return FAILURE;
}
} else {
- spl_file_object_read(intern, silent TSRMLS_CC);
+ return spl_file_object_read(intern, silent TSRMLS_CC);
}
} /* }}} */
@@ -1134,9 +1143,10 @@ SPL_METHOD(FileObject, key)
{
spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+/* Do not read the next line to support correct counting with fgetc()
if (!intern->current_line) {
spl_file_object_read_line(getThis(), intern, 1 TSRMLS_CC);
- }
+ } */
RETURN_LONG(intern->current_line_num);
} /* }}} */
@@ -1147,6 +1157,7 @@ SPL_METHOD(FileObject, next)
spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
spl_file_object_free_line(intern TSRMLS_CC);
+ intern->current_line_num++;
} /* }}} */
/* {{{ proto void FileObject::setFlags(int flags)
@@ -1279,6 +1290,7 @@ SPL_METHOD(FileObject, fgetcsv)
ZVAL_LONG(arg2, intern->max_line_len);
spl_file_object_free_line(intern TSRMLS_CC);
+ intern->current_line_num++;
FileFunctionCall(fgetcsv, arg2);
@@ -1338,11 +1350,16 @@ SPL_METHOD(FileObject, fgetc)
char buf[2];
int result;
+ spl_file_object_free_line(intern TSRMLS_CC);
+
result = php_stream_getc(intern->stream);
if (result == EOF) {
RETVAL_FALSE;
} else {
+ if (result == '\n') {
+ intern->current_line_num++;
+ }
buf[0] = result;
buf[1] = '\0';
@@ -1360,6 +1377,7 @@ SPL_METHOD(FileObject, fgetss)
ZVAL_LONG(arg2, intern->max_line_len);
spl_file_object_free_line(intern TSRMLS_CC);
+ intern->current_line_num++;
FileFunctionCall(fgetss, arg2);
@@ -1382,6 +1400,7 @@ SPL_METHOD(FileObject, fscanf)
spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
spl_file_object_free_line(intern TSRMLS_CC);
+ intern->current_line_num++;
FileFunctionCall(fscanf, NULL);
}
diff --git a/ext/spl/tests/fileobject_002.phpt b/ext/spl/tests/fileobject_002.phpt
new file mode 100755
index 0000000000..f85b020503
--- /dev/null
+++ b/ext/spl/tests/fileobject_002.phpt
@@ -0,0 +1,122 @@
+--TEST--
+SPL: FileObject::fgetc
+--FILE--
+<?php
+
+function test($name)
+{
+ echo "===$name===\n";
+
+ $o = new FileObject(dirname(__FILE__) . '/' . $name);
+
+ var_dump($o->key());
+ while(($c = $o->fgetc()) !== false)
+ {
+ var_dump($o->key(), $c, $o->eof());
+ }
+ echo "===EOF?===\n";
+ var_dump($o->eof());
+ var_dump($o->key());
+ var_dump($o->eof());
+}
+
+test('fileobject_001a.txt');
+test('fileobject_001b.txt');
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+===fileobject_001a.txt===
+int(0)
+int(0)
+string(1) "0"
+bool(false)
+int(1)
+string(1) "
+"
+bool(false)
+int(1)
+string(1) "1"
+bool(false)
+int(2)
+string(1) "
+"
+bool(false)
+int(2)
+string(1) "2"
+bool(false)
+int(3)
+string(1) "
+"
+bool(false)
+int(3)
+string(1) "3"
+bool(false)
+int(4)
+string(1) "
+"
+bool(false)
+int(4)
+string(1) "4"
+bool(false)
+int(5)
+string(1) "
+"
+bool(false)
+int(5)
+string(1) "5"
+bool(false)
+int(6)
+string(1) "
+"
+bool(false)
+===EOF?===
+bool(true)
+int(6)
+bool(true)
+===fileobject_001b.txt===
+int(0)
+int(0)
+string(1) "0"
+bool(false)
+int(1)
+string(1) "
+"
+bool(false)
+int(1)
+string(1) "1"
+bool(false)
+int(2)
+string(1) "
+"
+bool(false)
+int(2)
+string(1) "2"
+bool(false)
+int(3)
+string(1) "
+"
+bool(false)
+int(3)
+string(1) "3"
+bool(false)
+int(4)
+string(1) "
+"
+bool(false)
+int(4)
+string(1) "4"
+bool(false)
+int(5)
+string(1) "
+"
+bool(false)
+int(5)
+string(1) "5"
+bool(false)
+===EOF?===
+bool(true)
+int(5)
+bool(true)
+===DONE===