Tutorial :How do i make a some sort of istream for a vector of unsigned chars



Question:

how can i create an istream from a buffer unsigned char* or vector.

basically i want :

void Func(vector<unsigned char> data)  {    someSortOfIstream x (data);      x >> something;  }  

using boost too....


Solution:1

I would recommend:

  1. use a std::string (a fancy vector of chars) instead of a std::vector<unsigned char>, because that's what it's for. You can then use the readily available std::stringstream in the <sstream> header.

  2. You can subclass a std::vector<unsigned char> and overload the operator>>() for what you need it.

    OR

    (harder but theoretically better) You can subclass std::iostream for your case and tell it what to do when you use operator>>() on it

Personnally I'd go with 1, and if you must, with 2a) because frankly, I'd have no idea how to subclass an iostream.


Solution:2

This can be done using Boost.IOStreams:

#include <iosfwd>                          // streamsize  #include <boost/iostreams/categories.hpp>  // seekable_device_tag   #include <boost/iostreams/positioning.hpp> // stream_offset    template<typename Container>  class container_device   {  public:      typedef typename Container::value_type char_type;      typedef boost::iostreams::seekable_device_tag category;        container_device(Container& container)         : container_(container), pos_(0) {}        /// Read up to n characters from the underlying data source into the       /// buffer s, returning the number of characters read; return -1 to       /// indicate EOF      std::streamsize read(char_type* s, std::streamsize n)      {          std::streamsize amt =               static_cast<std::streamsize>(container_.size() - pos_);          std::streamsize result = (std::min)(n, amt);          if (result != 0) {              std::copy(container_.begin() + pos_,                         container_.begin() + pos_ + result, s);              pos_ += result;              return result;          }           else {              return -1;  // EOF          }      }        /// Write up to n characters to the underlying data sink into the       /// buffer s, returning the number of characters written      std::streamsize write(const char_type* s, std::streamsize n)      {          std::streamsize result = 0;          if (pos_ != container_.size()) {              std::streamsize amt =                   static_cast<std::streamsize>(container_.size() - pos_);              std::streamsize result = (std::min)(n, amt);              std::copy(s, s + result, container_.begin() + pos_);              pos_ += result;          }          if (result < n) {              container_.insert(container_.end(), s, s + n);              pos_ = container_.size();          }          return n;      }        /// Seek to position off and return the new stream position. The       /// argument 'way' indicates how off is interpreted:      ///    - std::ios_base::beg indicates an offset from the sequence       ///      beginning       ///    - std::ios_base::cur indicates an offset from the current       ///      character position       ///    - std::ios_base::end indicates an offset from the sequence end      boost::iostreams::stream_offset seek(          boost::iostreams::stream_offset off, std::ios_base::seekdir way)      {          // Determine new value of pos_          boost::iostreams::stream_offset next;          if (way == std::ios_base::beg) {              next = off;          }           else if (way == std::ios_base::cur) {              next = pos_ + off;          }           else if (way == std::ios_base::end) {              next = container_.size() + off - 1;          }            // Check for errors          if (next < ((boost::iostreams::stream_offset)0)            || next >= ((boost::iostreams::stream_offset)container_.size()))              throw std::ios_base::failure("bad seek offset");            pos_ = (size_type)next;          return pos_;      }        Container& container() { return container_; }    private:      typedef typename Container::size_type size_type;      Container& container_;      size_type pos_;  };  

which can be used as:

std::vector<char> data;  boost::iostreams::stream<container_device<std::vector<char> > > io(data);  

and:

io << foo;  io >> bar;  


Solution:3

A non deprecated solution using Boost:

#include <boost/iostreams/stream.hpp>  #include <boost/iostreams/device/array.hpp>  using namespace boost::iostreams;    basic_array_source<char> input_source(&my_vector[0], my_vector.size());  stream<basic_array_source<char> > input_stream(input_source);  

or even simpler:

#include <boost/interprocess/streams/bufferstream.hpp>  using namespace boost::interprocess;    bufferstream input_stream(&my_vector[0], my_vector.size());  


Solution:4

You could also take a look at std::stringstream.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »