Как мне создать своего рода istream для вектора неподписанных символов - PullRequest
3 голосов
/ 04 июля 2010

как я могу создать istream из буфера unsigned char * или вектора.

В основном я хочу:

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

  x >> something;
}

тоже с помощью наддува ....

Ответы [ 4 ]

9 голосов
/ 04 июля 2010

Это можно сделать с помощью 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_;
};

, который можно использовать как:

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

и:

io << foo;
io >> bar;
2 голосов
/ 29 сентября 2012

Не устарелое решение с использованием 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);

или даже проще:

#include <boost/interprocess/streams/bufferstream.hpp>
using namespace boost::interprocess;

bufferstream input_stream(&my_vector[0], my_vector.size());
0 голосов
/ 04 июля 2010

Я бы порекомендовал:

  1. используйте std::string (причудливый вектор char с) вместо std::vector<unsigned char>, потому что это то, для чего оно. Затем вы можете использовать легкодоступный std::stringstream в заголовке <sstream>.

  2. Вы можете создать подкласс std::vector<unsigned char> и перегрузить operator>>() для того, что вам нужно.

    OR

    (сложнее, но теоретически лучше). Вы можете создать подкласс std::iostream для своего случая и сказать ему, что делать, когда вы используете operator>>() для него

Лично я бы пошел с 1, а если нужно, с 2а), потому что, честно говоря, я бы не знал, как подкласс iostream.

0 голосов
/ 04 июля 2010

Вы также можете взглянуть на std :: stringstream.

...