наследование проблемы ostream и streambuf с xsputn и переполнением
Я занимался исследованиями по созданию собственного ostream и вместе с тем streambuf для обработки буфера для моего ostream. У меня на самом деле большая часть работает, я могу вставить (
Я прошел через код, и я вижу, что поток вызывает do_put, а затем f_put который в конечном итоге пытается поместить символ float 1 за раз в буфер. Я могу заставить его вызвать мою реализацию переполнения виртуальной функции (int c), если я оставлю свой буфер без пространства и тем самым получу данные для float и int.
теперь вот проблема, мне нужно знать, когда поплавок будет помещен в буфер. Или, другими словами, Мне нужно знать, когда в последний раз будет вызываться переполнение для определенного значения. Этот причина xsputn работает для меня, потому что я поняла всю ценность и ее длина. Поэтому я могу скопировать его в буфер, а затем вызвать функцию, ожидающую заполнения буфера.
Я, по общему признанию, злоупотребляю дизайном ostream в том, что мне нужно кэшировать выходные данные, а затем отправлять их все сразу для каждого введенного значения (
в любом случае, чтобы быть ясным, я повторю, что я стреляю по-другому. Есть очень хороший шанс, что я просто поступаю неправильно. путь.
Я хочу использовать унаследованный ostream и streambuf, чтобы я мог вводить в него значения и позволять ему обрабатывать мое преобразование типов для меня, затем я хочу передать эту информацию другому объекту, которому я передаю дескриптор вниз к streambuf (для?). Этот объект имеет дорогостоящий ввод-вывод, поэтому я не хочу отправлять данные 1 char за раз.
извините заранее, если это непонятно. И спасибо, что уделили мне время.
1 ответов
это не слишком ясно, что вы делаете, хотя это звучит примерно
право. Просто чтобы быть уверенным: все ваши ostream
дает
удобство конструкторы для создания и установки вашего streambuf
,
деструктор и, возможно, реализация rdbuf
в
обрабатывать буферы нужного типа. Предположим, это правда.:
определение xsputn
в своем streambuf
- Это чисто оптимизации.
Ключевая функция, которую вы должны определить, -overflow
. Самый простой
реализация overflow
просто принимает один символ, и
выводит его в раковину. Все остальное-оптимизация:
вы можете, например, настроить буфер с помощью setp
, если вы делаете
это, значит ... --7--> будет вызываться только тогда, когда буфер
полный, или был запрошен флеш. В этом случае вам придется
выходной буфер также (используйте pbase
и pptr
получить
адреса.) (The streambuf
базовый класс инициализируется
указатели для создания буфера длины 0, поэтому overflow
будет
для каждого персонажа.) Другие функции, которые вы могли
хотеть переопределение в (очень) конкретных случаях:
imbue
: Если вам нужен язык по какой-то причине. (Помнить это
текущая кодировка символов является частью локали.)
setbuf
: разрешить клиентскому коду указывать буфер. (ИМХО, это
обычно не стоит беспокоиться, но у вас могут быть специальные
требования.)
seekoff
: поддержку стремления. Я никогда не использовал это в любом из
мой streambuf
S, поэтому я не могу дать никакой информации, кроме того, что
вы могли бы прочитать в норматив.
sync
: вызванный приток, должен вывести наружу все характеры в
буфер к раковине. Если вы никогда не позвоните setp
(так что нет
буфер), вы всегда синхронизированы, и это может быть no-op.
overflow
или uflow
может вызвать это, или оба могут вызвать некоторые
отдельная функция. (О единственной разнице между sync
и uflow
это uflow
будет вызываться только если есть
буфер, и он никогда не будет вызываться, если буфер пуст.
sync
будет вызываться при клиентский код сбрасывает поток.)
при написании собственных потоков, если производительность не диктует
в противном случае, я буду держать его простым, и только переопределить overflow
.
Если производительность диктует буфер, я обычно помещаю код в
очистите буфер в отдельный write(address, length)
функция и реализация overflow
и sync
вдоль линии
из:
int MyStreambuf::overflow( int ch )
{
if ( pbase() == NULL ) {
// save one char for next overflow:
setp( buffer, buffer + bufferSize - 1 );
if ( ch != EOF ) {
ch = sputc( ch );
} else {
ch = 0;
}
} else {
char* end = pptr();
if ( ch != EOF ) {
*end ++ = ch;
}
if ( write( pbase(), end - pbase() ) == failed ) {
ch = EOF;
} else if ( ch == EOF ) {
ch = 0;
}
setp( buffer, buffer + bufferSize - 1 );
}
return ch;
}
int sync()
{
return (pptr() == pbase()
|| write( pbase(), pptr() - pbase() ) != failed)
? 0
: -1;
}
в общем, я не буду заморачиваться с xsputn
, а если ваш клиент
код выводит много длинных строк, это может быть полезный.
Что-то вроде этого должно сделать трюк:
streamsize xsputn(char const* p, streamsize n)
{
streamsize results = 0;
if ( pptr() == pbase()
|| write( pbase(), pptr() - pbase() ) != failed ) {
if ( write(p, n) != failed ) {
results = n;
}
}
setp( buffer, buffer + bufferSize - 1 );
return results;
}