8

I'm trying to make use of a function which comes in a 3rd party lib and expects an input stream object in which binary file data is transported.

Signature looks like that:

doSomething(const std::string& ...,
          const std::string& ...,
          std::istream& aData,
          const std::string& ...,
          const std::map<std::string, std::string>* ...,
          long ...,
          bool ...);

Since I can't alter/change this 3rd party lib/function, I have to adapt in "my" code. In the calling place, I have a std::vector which contains the data which is expected to be passed in an istream object. Currently I copy the vector to the stream, by iterating over it and using the << operator to copy byte by byte.

I strongly suspect that there might be a more effective/convenient way but couldn't find anything useful up to now. Any help/your thoughts are greatly appreciated.

Best, JR

Rip-Off
  • 358
  • 1
  • 4
  • 14

2 Answers2

16

You can use a vector of characters as an underlying buffer for an input stream without copying the contents of the vector:

std::vector<unsigned char> my_vec;
my_vec.push_back('a');
my_vec.push_back('b');
my_vec.push_back('c');
my_vec.push_back('\n');

// make an imput stream from my_vec
std::stringstream is;
is.rdbuf()->pubsetbuf(reinterpret_cast<char*>(&my_vec[0]), my_vec.size());

// dump the input stream into stdout
std::cout << is.rdbuf();

@NeilKirk reports that the above method of using pubsetbuf is non-portable.

One portable way is to use boost::iostreams library. This is how to construct an input stream from a vector without copying its contents:

#include <iostream>
#include <vector>

#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>

int main() {
    std::vector<unsigned char> my_vec;
    my_vec.push_back('a');
    my_vec.push_back('b');
    my_vec.push_back('c');
    my_vec.push_back('\n');

    // Construct an input stream from the vector.
    boost::iostreams::array_source my_vec_source(reinterpret_cast<char*>(&my_vec[0]), my_vec.size());
    boost::iostreams::stream<boost::iostreams::array_source> is(my_vec_source);

    // Dump the input stream into stdout.
    std::cout << is.rdbuf();
}
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • The pointer to the vector data is easily invalidated. Nevertheless, the temporarity of the stringstream makes it reasonably safe. With that in mind, it's a good answer. – Zoomulator Aug 28 '14 at 08:00
  • This is not guaranteed to work, and doesn't on VS2015 – Neil Kirk Sep 24 '15 at 02:13
8
vector<unsigned char> values;
// ...

stringstream ioss;    
copy(values.begin(), values.end(),
     ostream_iterator<unsigned char>(ioss,","));

// doSomething(a, b, ioss, d, e, f, g);
Peter Wood
  • 23,859
  • 5
  • 60
  • 99
  • Thanks for pointing me to the right direction! `stringstream ss; copy(values.begin(), values.end(), ostream_iterator(ss,""));' works perfectly! – Rip-Off Feb 21 '12 at 14:46