* @version 1.0
* @since PHP 5.1
*/
-class FileObject implements RecursiveIterator
+class FileObject implements RecursiveIterator, SeekableIterator
{
private $fp;
private $fname;
*/
function fgets()
{
+ $this->freeLine();
$this->lnum++;
$buf = fgets($this->fp, $this->max_len);
*/
function fgetcsv($delimiter = ';', $enclosure = '')
{
+ $this->freeLine();
$this->lnum++;
return fgetcsv($this->fp, $this->max_len, $delimiter, $enclosure);
}
*/
function fgetc()
{
- return fgetc($this->fp);
+ $this->freeLine();
+ $c = fgetc($this->fp);
+ if ($c == '\n') {
+ $this->lnum++;
+ }
}
/** Read and return remaining part of stream
*/
function fscanf($format /* , ... */)
{
+ $this->freeLine();
$this->lnum++;
return fscanf($this->fp, $format /* , ... */);
}
*/
function rewind()
{
- $this->line = NULL;
+ $this->freeLine();
$this->lnum = 0;
}
}
/**
- * @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;
}
*/
function next()
{
- $this->line = NULL;
+ $this->freeLine();
}
/**
*/
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();
}
{
return current();
}
+
+ /**
+ * @param $line_pos Seek to this line
+ */
+ function seek($line_pos)
+ {
+ $this->rewind();
+ while($this->lnum < $line_pos && !$this->eof())
+ {
+ $this->getCurrentLine();
+ }
+ }
}
?>
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) /* {{{ */
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);
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;
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));
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);
}
} /* }}} */
{
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);
} /* }}} */
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)
ZVAL_LONG(arg2, intern->max_line_len);
spl_file_object_free_line(intern TSRMLS_CC);
+ intern->current_line_num++;
FileFunctionCall(fgetcsv, arg2);
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';
ZVAL_LONG(arg2, intern->max_line_len);
spl_file_object_free_line(intern TSRMLS_CC);
+ intern->current_line_num++;
FileFunctionCall(fgetss, arg2);
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);
}