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