In [filebuf.virtuals]:
pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;
Effects: Let
width
denotea_codecvt.encoding()
. Ifis_open() == false
, oroff != 0 && width <= 0
, then the positioning operation fails. Otherwise, ifway != basic_ios::cur
oroff != 0
, and if the last operation was output, then update the output sequence and write any unshift sequence. Next, seek to the new position: ifwidth > 0
, callfseek(file, width * off, whence)
, otherwise callfseek(file, 0, whence)
.
It does not mention that this function updates the input sequence. As a contrast, seekpos
does update the input sequence:
pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override;
Alters the file position, if possible, to correspond to the position stored in
sp
(as described below). Altering the file position performs as follows:
if
(om & ios_base::out) != 0
, then update the output sequence and write any unshift sequence;set the file position to
sp
as if by a call tofsetpos
;if
(om & ios_base::in) != 0
, then update the input sequence;
So is seekoff
guaranteed to update the input sequence?
For a concrete example, consider:
#include <fstream>
#include <iostream>
int main()
{
std::fstream f("test.txt"); // test.txt contains "test"
char ch;
f >> ch;
f.rdbuf()->pubseekoff(0, std::ios_base::beg);
f >> ch;
std::cout << ch;
}
Is the program guaranteed to output t
?
I can see your point friend, and indeed this may be a source of some confusion not only for yourself.
Short answer:
Yes, seekoff
will update the the input sequence just as seekpos
will. Both seekoff
and seekpos
behave the same regarding which sequence is being updated by the call, input or output (or both).
Long explanation:
Not by way of convention alone, but according to the standard itself, the behavior of both seekoff
and seekpos
is defined to be dependent of the ios_base::openmode which
argument. As can be seen in another class template, stringbuf
, derived from the same parent as filebuf
, the override for seekoff
explicitly states that for (which & ios_base::in) == ios_base::in
the call will position the input sequence; for (which & ios_base::out) == ios_base::out
the call will position the output sequence; for (which & (ios_base::in | ios_base::out)) == (ios_base::in | ios_base::out)
and way ==
either ios_base::beg
or ios_base::end
the call will position both the input and the output sequences.
But when working directly in front of the standard, one need not expect things to just present themselves. See here under the parent class streambuf
:
pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;
Effects: Alters the stream positions within one or more of the controlled sequences in a way that is defined separately for each class derived from
basic_streambuf
...
So, by looking more carefully in the standard for the quote you have provided yourself regarding seekpos
of filebuf
:
pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override;
Alters the file position, if possible, to correspond to the position stored in
sp
(as described below). Altering the file position performs as follows:
if
(om & ios_base::out) != 0
, then update the output sequence and write any unshift sequence;set the file position to
sp
as if by a call tofsetpos
;if
(om & ios_base::in) != 0
, then update the input sequence;
the following line says:
where
om
is the open mode passed to the last call to open(). ...
So this means that you cannot specify in the call itself which sequence you want to update. As in, the standard here says that the implementation should plainly ignore (!) the om
argument.
Another bit we need not miss is in the quote you have provided regarding seekoff
, where it says:
Next, seek to the new position: if
width > 0
, callfseek(file, width * off, whence)
, otherwise callfseek(file, 0, whence)
.
So underlying it's just a call to fseek
. But on which particular FILE object? Are there separate ones for input and output? I believe the answer we're looking for appears in spec under filebuf:
§ 27.9.1.1
- The class basic_filebuf associates both the input sequence and the output sequence with a file.
- The restrictions on reading and writing a sequence controlled by an object of class basic_filebuf are the same as for reading and writing with the Standard C library FILEs.
- In particular:
- If the file is not open for reading the input sequence cannot be read.
- If the file is not open for writing the output sequence cannot be written.
- A joint file position is maintained for both the input sequence and the output sequence.
As in, both seekoff
and seekpos
behaves the same regarding which sequence is being updated by the call, input or output (or both), and it is determined only by what was passed to open()
.
Also, just encountered this from about 5 years ago I see: fstream seekg(), seekp(), and write()
Edit, for further clarification:
Note the spec for seekoff
says:
if the last operation was output, then update the output sequence and write any unshift sequence.
seekpos
also says:
update the output sequence and write any unshift sequence;
It is the remarks section for seekoff
that defines what “Write any unshift sequence” means. And as such it should be equivalent for both methods. But then both specify further: seekoff
says it calls fseek
and seekpos
says it calls fsetpos
(identical to fseek
in this regard).
The reason for this, and for even mentioning the last operation was output bit, is found when considering that point 2 from section § 27.9.1.1 brought above is explained here in the C11 standard, ISO/IEC 9899:2011:
§7.21.5.3 The
fopen
function¶7 When a file is opened with update mode ('+' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the
fflush
function or to a file positioning function (fseek
,fsetpos
, orrewind
), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
So to answer your comment below, whether seekoff
will update the input sequence is regardless of whether the last operation was input. If the last operation wasn't input, then there's the technicality with the unshift sequence discussed above. But part of the idea for the whole stream
classes is to encapsulate i/o in a way that doesn't bother you with such maintenance chores.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With