наследование проблемы 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: поддержку стремления. Я никогда не использовал это в любом из мой streambufS, поэтому я не могу дать никакой информации, кроме того, что вы могли бы прочитать в норматив.

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;
}