Topic: stream position when reaching eof


Author: James Kanze <kanze@alex.gabi-soft.de>
Date: Mon, 13 May 2002 17:35:33 GMT
Raw View
Olaf Groeger <Olaf.Groeger@gmx.de> writes:

|>  Unfortunatly it doesn't clear my view.

That is probably because the standard itself isn't as clear as it
could be.

|>  I agree with you that STLPort return the stream position -1 to
|>  indicate an invalid position. The question is whether it is
|>  allowed to do or whether it must return the position "value"
|>  regardless of validity as long as no error occurs.

|>  Should the STL be so intelligent to know that the position 1 is
|>  invalid ?

I don't think that that is the question. =20

The problem is more general.  There are really two questions.  Any
istream function (including read) is allowed to "look ahead" using
streambuf::sgetc.  The question is, what happens if streambuf::sgetc
returns EOF.  The stream is not necessarily in an error state,
although the eofbit should be set (not the case with the STLPort).
But what is the state of the streambuf in such a case?  Should tellg
be guaranteed to work in such a case?

More generally, is it required that streampos can represent the end of
file position?  I don't think so, although I would certainly expect
this to be the case for a quality implementation.

As a side remark, have you tried reporting this to SGI as an error?
Even if the standard allows it, I can imagine that they might want to
fix it.

|>  This has further consequences: Imagine the following scenario:
|>  - You have a file with one byte content.
|>  - you open it and read one byte.
|>  - now you reposition the stream according to the current position
|>    aStream.seekg( -1, std::ios::cur );

|>  STLPort refuses this seekg operation, gcc executes it. The point
|>  why STLPort refuses it is because the stream position is invalid
|>  (tellg =3D -1, according to the standard). gcc doesn't care that the
|>  current stream position (tellg =3D 1) is invalid, it executes the
|>  operation because the new stream position is valid. Unfortuntly,
|>  STLPort refuses the operation while the status flags show no error
|>  condition. A point from which i mean it is anyway an error.

This is part of the reason why I think a quality implementation *will*
support a streampos at end of file.  The reason why I think it may not
be required is that it may not be possible on certain systems.  But it
*is* possible on both Unix and Windows, the two systems targetted by
STLPort.

|>  btw, your proposal works as expected:
|>  >     std::char_traits::pos_type pos =3D aStream.tellg() ;
|>  >     aStream.seekg( 0, std::ios::beg ) ;
|>  >     //      Stream should be OK here...
|>  >     aStream.seekg( pos ) ;
|>  >     //      Stream should also be OK here, i.e.=20
|>  >     //      aStream.fail() should be false.

But does the next read return end of file, or the first character in
the file?  IMHO, it should return end of file.

--=20
James Kanze                                mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
                    Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Olaf Groeger <Olaf.Groeger@gmx.de>
Date: Fri, 10 May 2002 15:26:37 GMT
Raw View
Thank you for your answer, James.
Unfortunatly it doesn't clear my view. I agree with you that STLPort
return the stream position -1 to indicate an invalid position. The
question is whether it is allowed to do or whether it must return the
position "value" regardless of validity as long as no error occurs.
Should the STL be so intelligent to know that the position 1 is invalid ?
This has further consequences: Imagine the following scenario:
- You have a file with one byte content.
- you open it and read one byte.
- now you reposition the stream according to the current position
  aStream.seekg( -1, std::ios::cur );

STLPort refuses this seekg operation, gcc executes it. The point why
STLPort refuses it is because the stream position is invalid (tellg = -1,
according to the standard). gcc doesn't care that the current stream
position (tellg = 1) is invalid, it executes the operation because the
new stream position is valid. Unfortuntly, STLPort refuses the operation
while the status flags show no error condition. A point from which i mean
it is anyway an error.

Olaf

btw, your proposal works as expected:
>     std::char_traits::pos_type pos = aStream.tellg() ;
>     aStream.seekg( 0, std::ios::beg ) ;
>     //      Stream should be OK here...
>     aStream.seekg( pos ) ;
>     //      Stream should also be OK here, i.e.
>     //      aStream.fail() should be false.
>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Olaf Groeger <Olaf.Groeger@gmx.de>
Date: Tue, 7 May 2002 15:50:13 GMT
Raw View
Hello,

i have a question regarding the stream position after reading x bytes of a
x byte stream. Using STLPort 4.5 i get -1 as position, which means the
position is invalid as well as the status flags don't signal a fail
situation. Using gcc without STLPort i get x as position. To make it clear,
here is a test example:

e.g.:
1) create a 1-byte file test.dat
2) compile the following

#include <iostream>
#include <fstream>

int main(void)
{
// open a one character file
std::ifstream aStream("test.dat", std::ios::in | std::ios::binary);
std::cout << "Status good() after stream open: " << aStream.good() <<
std::endl;
std::cout << "Status fail() after stream open: " << aStream.fail() <<
std::endl;
std::cout << "Status bad() after stream open: " << aStream.bad() <<
std::endl;
std::cout << "Status eof() after stream open: " << aStream.eof() <<
std::endl;
std::cout << "Status rdstate() after stream open: " << aStream.rdstate()
<< std::endl << std::endl;

aStream.seekg(0, std::ios::beg);

// read one character so we get to the end of the stream
char ch = '\0';
aStream.read(&ch, 1);
std::cout << "Buffer is: " << ch << std::endl;
std::cout << "Status good() after first read: " << aStream.good() <<
std::endl;
std::cout << "Status fail() after first read: " << aStream.fail() <<
std::endl;
std::cout << "Status bad() after first read: " << aStream.bad() <<
std::endl;
std::cout << "Status eof() after first read: " << aStream.eof() <<
std::endl;
std::cout << "Status rdstate() after first read: " << aStream.rdstate() <<
std::endl << std::endl;

// read the position
std::cout << "position: " << aStream.tellg() << std::endl;

aStream.close();
return 0;
}


using gcc without STLPort the output is:
$ ./seekg_gcc
Status good() after stream open: 1
Status fail() after stream open: 0
Status bad() after stream open: 0
Status eof() after stream open: 0
Status rdstate() after stream open: 0

Buffer is: Q
Status good() after first read: 1
Status fail() after first read: 0
Status bad() after first read: 0
Status eof() after first read: 0
Status rdstate() after first read: 0

position: 1



using vc6 with STLPort 4.5 the output is
C:\Temp>seekg_1
Status good() after stream open: 1
Status fail() after stream open: 0
Status bad() after stream open: 0
Status eof() after stream open: 0
Status rdstate() after stream open: 0

Buffer is: Q
Status good() after first read: 1
Status fail() after first read: 0
Status bad() after first read: 0
Status eof() after first read: 0
Status rdstate() after first read: 0

position: -1

so, what is the correct result ?

Olaf

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: James Kanze <kanze@alex.gabi-soft.de>
Date: Wed, 8 May 2002 16:08:21 GMT
Raw View
Olaf Groeger <Olaf.Groeger@gmx.de> writes:

|>  i have a question regarding the stream position after reading x
|>  bytes of a x byte stream. Using STLPort 4.5 i get -1 as position,
|>  which means the position is invalid as well as the status flags
|>  don't signal a fail situation.

This is a tricky question, and hits on some ambiguities in the
standard.  To begin with, of course, the stream position isn't an
integral value, so any comparisons or output involving using it as a
numerical value are on weak footing.  For example, the standard
requires that streampos(streamoff(p)) =3D=3D p (where p is a streampos),
but it also requires that streampos contain more state than streamoff,
which means that this requirement is, by definition, impossible to
meet.  Add to this that there is nothing in the standard requiring
that streampos(i) =3D=3D streampos(streamoff(i)) (where i is an integral
value).

I think that the intent is that streamoff be an integral type,
although the standard certainly doesn't say so; nor does it require
streamoff to be comparable.  (The return type of istream::tellg,
streampos, can in no case be an integral value.)  If streamoff is NOT
an integral value, then even things like:

    std::cout << aStream.tellg() << '\n' ;

may not compile, since there is not necessarily an operator<< for
either streampos nor streamoff.  (Streamoff is required to convert to
streamsize, which is required to be a signed integral type, but to go
from a streampos to a streamsize would require two user defined
conversions.)  In any case, what is displayed is implementation
defined, and can be totally arbitrary.

The case of -1 is, however, special.  In 27.4.3, it says that
streampos(streamoff(-1)) is used as an error indicator.  I'm not sure
what this exactly guarantees, however, since I've never seen anyone
write something like std::char_traits<char>::pos_type(
std::char_traits<char>::off_type(-1)) in order to compare the value.
So I don't think that the -1 in the output means anything according
the standard.

Independantly of what the standard says, if outputting the results of
tellg works, and the value is -1, I would suspect that it is meant to
be an invalid position, since doing otherwise, while conform, would
require a pretty tortuous implementation, with many disadvantages, and
no possible gain that I can see.  Unless the STLPort is doing
something really strange (which I doubt), this looks like an error.

What you really want to test, of course, is what the standard does
guarantee; that you can use the return value as an argument to seekg,
and return to where you were.  Try the following:

    std::char_traits::pos_type pos =3D aStream.tellg() ;
    aStream.seekg( 0, std::ios::beg ) ;
    //      Stream should be OK here...
    aStream.seekg( pos ) ;
    //      Stream should also be OK here, i.e.=20
    //      aStream.fail() should be false.

--=20
James Kanze                                mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
                    Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]