Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i create a istream from a uint8_t vector?

Tags:

c++

I am in the process of adding the ability to get data over the network to code that used to only read local files. The network library I am using sends and receives data in the form of a vector<uint8_t>. I'd like to be able to reuse the code that processes the data after reading the file, but that code expects a std::istream, is there a way to have an istream read the vector data? It's the same data so I feel like there should be a way, but i haven't been able to find or figure out code for how to do it.

current code:

    std::ifstream stream("data.img", std::ios::in | std::ios::binary | std::ios::ate);

    if (!stream.is_open())
    {
        throw std::invalid_argument("Could not open file.");
    }
    // the arg for processData is std::istream
    processData(stream);

network framework:

    vector<uint8_t> data = networkMessage.data;

    // need some way to create istream from data
    std::istream stream = ?

    processData(stream);
    stream.close();

Is there a way to do this, or am I barking up the wrong tree?

like image 443
S. Casey Avatar asked Aug 16 '17 20:08

S. Casey


2 Answers

Well C++ does actually have a class for this - istrstream, and you could use it like this:

    vector<uint8_t> data = ...;

    // need some way to create istream from data
    std::istrstream stream(reinterpret_cast<const char*>(data.data()), data.size());

    processData(stream);

As far as I can tell this doesn't copy the data, unlike the other answers. However it was also deprecated in C++98 because it's hard to know who is responsible for freeing the buffer, so you may want to write your own equivalent.

like image 176
Timmmm Avatar answered Nov 09 '22 05:11

Timmmm


std::basic_istream gets its data from an associated std::basic_streambuf derived class. The STL provides such classes for file I/O and string I/O, but not for memory I/O or network I/O.

You could easily write (or find a 3rd party) memory-based streambuf class that uses the std::vector as its underlying buffer, and then you can construct an std::istream that uses that memory streambuf. For example (using the imemstream class from this answer):

std::vector<uint8_t> &data = networkMessage.data;
imemstream stream(reinterpret_cast<const char*>(data.data()), data.size());
processData(stream);
like image 21
Remy Lebeau Avatar answered Nov 09 '22 06:11

Remy Lebeau