开发者

How reliable are basic_stringbuf::in_avail() and basic_stringbuf::str()?

I need to get all the contents from a stream, without actually extracting them (just like 开发者_如何学Gostringstream::str()). I've tried basic_stringbuf::str(), but it behaves incorrectly when the stream is empty. To avoid that case, I had a go at basic_stringbuf::in_avail(), but that hasn't worked out very well either.

In the following test case, in_avail() doesn't return the number of available elements on the stream, and str() returns more elements than what is currently there:

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

Compiling on g++ 4.4, the output is:

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

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

What am I doing wrong? What's the best way to do what I'm trying?

Thanks a lot.


in_avail is the number of characters ready to be read from the buffer, not the size of the buffer itself. It's really allowed to return any nonzero value here.

However, I can't answer what the best way is of what you're doing, because I don't know what you're doing. If you already have things as an unsigned char array, then you're going to want to do:

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

If you're just trying to read a whole stream into a vector, then I would do exactly what you're doing; I'd just replace you're stream2vector function with this, equivalent, simpler one:

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

I'm not entirely sure why you're specializing every operation here for unsigned char -- I would just use the default char versions, because unsigned char is allowed to be the same size as a short, which is probably not what you want (but I am not aware of any implementation that does this).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜