Насколько надежны basic_stringbuf :: in_avail () и basic_stringbuf :: str ()? - PullRequest
0 голосов
/ 31 августа 2010

Мне нужно получить все содержимое из потока, фактически не извлекая его (как stringstream::str()). Я пробовал basic_stringbuf::str(), но он ведет себя неправильно, когда поток пуст. Чтобы избежать этого, я попытался набрать basic_stringbuf::in_avail(), но это тоже не сработало.

В следующем тестовом примере in_avail() не возвращает количество доступных элементов в потоке, а str() возвращает больше элементов, чем то, что есть в данный момент:

#include <iostream>
#include <iterator>
#include <vector>
#include <sstream>

// extracts everything from the stream
std::vector<unsigned char> stream2vector(std::basic_istream<unsigned char>& stream)
{
    std::vector<unsigned char> retreivedData;
    std::istreambuf_iterator<unsigned char> it(stream);
    const std::istreambuf_iterator<unsigned char> endOfStream;
    retreivedData.insert(retreivedData.begin(), it, endOfStream);
    return retreivedData;
}

int main() {
    std::basic_stringbuf<unsigned char> buf;
    std::basic_iostream<unsigned char> stream(&buf);
    unsigned char array[5] = { 1, 2, 3, 4, 5 };
    stream.write(array, 5);


    std::cout << "rdbuf()->in_avail(): " << buf.in_avail() << "\n";
    std::vector<unsigned char> d1 = stream2vector(stream);
    std::cout << "d1.size(): " << d1.size() << "\n";

    std::cout << "\n";
    // d2 should be empty
    std::vector<unsigned char> d2 = stream2vector(stream);
    std::cout << "d2.size(): " << d2.size() << "\n";
    std::basic_string<unsigned char> s = buf.str();
    std::cout << "buf.str().size(): " << buf.str().size() << "\n";
}

Компиляция на g ++ 4.4, вывод:

rdbuf()->in_avail(): 1 // expected: 5
d1.size(): 5 // as expected

d2.size(): 0 // as expected
buf.str().size(): 5 // expected: 0

Что я делаю не так? Какой лучший способ сделать то, что я пытаюсь?

Большое спасибо.

1 Ответ

0 голосов
/ 31 августа 2010

in_avail - это количество символов, готовых для чтения из буфера, а не размер самого буфера. Здесь действительно разрешено возвращать любое ненулевое значение.

Однако я не могу ответить, как лучше всего поступать, потому что я не знаю, что ты делаешь. Если у вас уже есть вещи в виде массива unsigned char, то вы захотите сделать:

std::vector<unsigned char> data(array, array + sizeof(array)/sizeof(unsigned char));

Если вы просто пытаетесь прочитать весь поток в векторе, то я бы сделал именно то, что вы делаете; Я бы просто заменил вашу функцию stream2vector на эту, эквивалентную, более простую:

// extracts everything from the stream
std::vector<unsigned char> stream2vector(std::basic_istream<unsigned char>& stream)
{
    std::istreambuf_iterator<unsigned char> it(stream);
    const std::istreambuf_iterator<unsigned char> endOfStream;
    return std::vector<unsigned char>(it, endOfStream);
}

Я не совсем уверен, почему вы специализируете здесь каждую операцию для unsigned char - я бы просто использовал версии char по умолчанию, потому что unsigned char может быть такого же размера, как short , что, вероятно, не то, что вы хотите (но я не знаю ни одной реализации, которая делает это).

...