Hi Gustavo,

thanks for your detailed explanation.

Nevertheless it might be useful to document these inconsistent(from the
userland point of view) behavior. Please see my comments inline.

Am 28.08.2011 17:22, schrieb Gustavo Lopes:
> On Sun, 28 Aug 2011 14:29:28 +0100, Christian Kaps
> <christian.k...@mohiva.com> wrote:
> 
>> I have some problems with the stream API. The methods stream_tell and
>> stream_seek works not as expected in some cases.
>>
>> Before reading the next lines, please look at the short
>> gist(https://gist.github.com/1176641).
>>
>> First example:
>>
>> $fp = fopen('mfx://test1', 'w');
>> fwrite($fp, '12345678');
>> fseek($fp, -1, SEEK_CUR);
>> fclose($fp);
>> // stream_seek: $offset = 7
>>
>> If you call fseek with the arguments (-1, SEEK_CUR) then the $offset
>> parameter in the method stream_seek is 7. It seems that the internal API
>> takes the written bytes returned by fwrite and then it subtracts the
>> argument (-1) from it before passing it to stream_seek. For the
>> constants SEEK_SET and SEEK_END, the passed value is the same as defined
>> for the fseek call.
> 
> SEEK_CUR seeks are internally converted to SEEK_SET seeks. It's been
> this way since at least 2002:
> 
> http://svn.php.net/viewvc/php/php-src/trunk/main/streams.c?annotate=96547&pathrev=96547#l582
> 
> 
> The first thing you should know is that PHP keeps track internally of
> the position of the stream. That's why PHP knows how to convert SEEK_CUR
> -1 to SEEK_SET 7.
> 
> The seek type conversion is an arguable decision, but changing this has
> some risks. Consider that some some streams might not respond to
> SEEK_CUR seeks or that they do so defectively. The only advantages I see
> is that it could mitigate the problems of an inaccurate internal
> position (though this happens mostly with internal code that casts the
> stream into e.g. a FILE* and then manipulates the pointer); it would
> also save stream implementations that only support SEEK_CUR from having
> to reconvert the SEEK_SET to SEEK_CUR.
> 

This behavior should be documented. The possible values for the "whence"
parameter of the "stream_seek" method should only be SEEK_SET and
SEEK_END. And there should be a hint that the SEEK_CUR seeks are
internally converted to SEEK_SET seeks.

>> The second example:
>>
>> $fp = fopen('mfx://test2', 'w');
>> fwrite($fp, '12345678');
>> fread($fp, 2);
>> fseek($fp, 1, SEEK_CUR);
>> fclose($fp);
>>
>> For this example the stream_seek method gets never be called. The
>> difference here is that fread is called before fseek.
> 
> No bug here. This is by design. PHP doesn't read only two bytes from the
> stream, it reads an entire chunk. Once PHP has data buffered and you
> tell it to skip one byte, it can just advance its internal pointer on
> the buffered data; no need to actually call fseek.
> 
> 

It should be documented that, in some circumstances, the "stream_seek"
method isn't called in response to fseek.

>> The third example:
>>
>> $fp = fopen('mfx://test3', 'w');
>> fwrite($fp, '12345678');
>> fread($fp, 3);
>> ftell($fp);
>> fclose($fp);
>>
>> For this example the stream_tell method gets never be called. It is
>> documented(http://www.php.net/manual/en/streamwrapper.stream-tell.php)
>> that the stream_tell method is called in response to ftell(). But it
>> seems that this method is only be called internally by the stream API.
>>
>> There exists a Bug report at https://bugs.php.net/bug.php?id=30157
>>
>> In one of the comments Pierre says: There is no bug but a feature
>> request which seems to be very discutable.
>>
> 
> Again, as the comment on the bug report says, this is by design. PHP
> keeps track internally of the position, so it can just return the
> information it has.
> 
> But yes, the documentation is wrong in this respect. stream_tell is only
> called after a seek in order to determine where the seek ended up. In
> the C standard library, you're allowed to seek past the end of the file
> and then write, zeroing everything in between the end of the position
> sought to (or failing to write). In PHP, this convention doesn't apply;
> you're not always allowed to seek to any position.
> 

The documentation for "stream_tell" is wrong. This method gets only be
called internally.

What do you think about my suggestions?

Christian

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to