Когда вызов basic_filebuf::pbackfail разрешен/определен для успеха

При реализации basic_filebuf я наткнулся на basic_filebuf::pbackfail и не совсем понимаю его определение.

С cplusplus.com

Moves the current input position on position back to point to the previous character and, if supported, makes c available as that next character to be read.

If the implementation does not support writing to putback positions, c shall either match the character at the putback position or be the end-of-file value (traits_type::eof()). Otherwise, the function fails. [...]

If the get pointer (gptr) is at the beginning of the character sequence before the call, the function may either fail or make additional putback positions available and succeed, depending on the library implementation.

Или из cppreference:

1) The caller is requesting that the get area is backed up by one character (pbackfail() is called with no arguments), in which case, this function re-reads the file starting one byte earlier and decrements basic_streambuf::gptr(), e.g. by calling gbump(-1).
2) The caller attempts to putback a different character from the one retrieved earlier (pbackfail() is called with the character that needs to be put back), in which case
a) First, checks if there is a putback position, and if there isn't, backs up the get area by re-reading the file starting one byte earlier.
a) Then checks what character is in the putback position. If the character held there is already equal to c, as determined by Traits::eq(to_char_type(c), gptr()[-1]), then simply decrements basic_streambuf::gptr().
b) Otherwise, if the buffer is allowed to modify its own get area, decrements basic_streambuf::gptr() and writes c to the location pointed to gptr() after adjustment.

Таким образом, по сути, оба говорят, что позиция ввода уменьшается (если только она не находится в начале файла) и, возможно, возвращается символ. Таким образом, следующее должно быть успешным (предположим, что файл подготовлен в соответствии с комментариями, используя классы std для сравнения поведения):

std::fstream f(..., in | out | binary);
f.get() // == 'a'
f.get() // == 'b'
f.sync(); // or f.seekg(0)
f.putback('b');
f.putback('a');
f.putback(); // may fail

Однако в libc++ первый возврат уже терпит неудачу, и, проверив исходный код, я обнаружил, что pbackfail охраняется if (__file_ && this->eback() < this->gptr()), иначе говоря, «если есть открытый файл и есть место в начале текущего буфера чтения».

Очистка/синхронизация/поиск очищает буфер чтения, что объясняет сбой возврата. При использовании небуферизованного ввода-вывода в буфере чтения будет только одно символьное пространство, поэтому (по крайней мере) второй ввод не удастся даже без сброса. Или второй get может пересечь «границу» буфера, что означает, что «b» будет первым символом в текущем буфере, что также приведет к сбою второго ввода.

Вопрос: Как именно указывается путбэк? Кажется, что это действительно только сразу после получения, хотя и cppreference, и cplusplus, кажется, подразумевают, что позиция чтения уменьшается в любом случае. Если они правы, является ли libc++ несоответствующей или я что-то упустил?


person Flamefire    schedule 04.12.2019    source источник


Ответы (1)


Вопрос: Как именно указывается путбэк?

Он указан в разделе istream.unformatted.

Однако это относится к sputbackc, и вы, вероятно, захотите прочитать общие требования к буферу потока.

person Marshall Clow    schedule 04.12.2019
comment
Это в основном говорит то же самое the input sequence is backed up one character .... Так является ли указанное выше ошибкой в ​​​​libc++? (2-й вопрос) - person Flamefire; 04.12.2019