2014-05-13 68 views
3

我有一個CONST向量躺在周圍,但需要一個函數來讀取它。問題是,函數需要一個istream。閱讀向量<char>作爲流

將向量中的數據傳遞給此函數的最有效方法是什麼?

我試過這種方法來防止複製流,但它不起作用,因爲我的向量是const並且pubsetbuf期望非const char *。

istringstream is; 
const vector<char>& data = GETDATA(); 
is.rdbuf()->pubsetbuf(&data[0], data.size()); 

由於流是隻讀的,我可以投射指針。那安全嗎? 或者更好的方法?

+0

是C++允許11? – luk32

+0

@ luk32沒有它的工作:( –

回答

3

考慮使用Boost.Iostreams

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

using namespace boost::iostreams; 
stream<array_source> bs(data.data(), data.size()); 
std::istream &is = bs; 
2

你可以寫你自己的流:

#include <algorithm> 
#include <ostream> 

// BasicSequenceInputBuffer 
// ============================================================================ 

template < typename Char, typename Traits = std::char_traits<Char> > 
class BasicSequenceInputBuffer 
: public std::basic_streambuf<Char, Traits> 
{ 
    // Types 
    // ===== 

    private: 
    typedef std::basic_streambuf<Char, Traits> Base; 

    public: 
    typedef typename Base::char_type char_type; 
    typedef typename Base::int_type int_type; 
    typedef typename Base::pos_type pos_type; 
    typedef typename Base::off_type off_type; 
    typedef typename Base::traits_type traits_type; 
    typedef const char_type* pointer; 
    typedef std::size_t size_type; 

    // Construction 
    // ============ 

    public: 
    BasicSequenceInputBuffer(pointer data, size_type size) { 
     // These casts are safe (no modification will take place): 
     char* begin = const_cast<char_type*>(data); 
     char* end = const_cast<char_type*>(data + size); 
     this->setg(begin, begin, end); 
    } 

    // Stream Buffer Interface 
    // ======================= 

    protected: 
    virtual std::streamsize showmanyc(); 
    virtual std::streamsize xsgetn(char_type*, std::streamsize); 
    virtual int_type pbackfail(int_type); 

    // Utilities 
    // ========= 

    protected: 
    int_type eof() { return traits_type::eof(); } 
    bool is_eof(int_type ch) { return ch == eof(); } 
}; 


// Get Area 
// ======== 

template <typename Char, typename Traits> 
std::streamsize 
BasicSequenceInputBuffer<Char, Traits>::showmanyc() { 
    return this->egptr() - this->gptr(); 
} 

template <typename Char, typename Traits> 
std::streamsize 
BasicSequenceInputBuffer<Char, Traits>::xsgetn(char_type* p, std::streamsize n) { 
    std::streamsize result = std::min(n, this->egptr() - this->gptr()); 
    std::copy(this->gptr(), this->gptr() + result, p); 
    this->gbump(result); 
    return result; 
} 

template <typename Char, typename Traits> 
typename BasicSequenceInputBuffer<Char, Traits>::int_type 
BasicSequenceInputBuffer<Char, Traits>::pbackfail(int_type ch) { 
    if(is_eof(ch)) { 
     if(this->eback() != this->gptr()) { 
      this->gbump(-1); 
      return traits_type::to_int_type(*this->gptr()); 
     } 
    } 
    return eof(); 
} 

typedef BasicSequenceInputBuffer<char> SequenceInputBuffer; 


// BasicSequenceInputStream 
//============================================================================= 

template < typename Char, typename Traits = std::char_traits<Char> > 
class BasicSequenceInputStream 
: public std::basic_istream<Char, Traits> 
{ 
    private: 
    typedef std::basic_istream<Char, Traits> Base; 

    public: 
    typedef typename Base::char_type char_type; 
    typedef typename Base::int_type int_type; 
    typedef typename Base::pos_type pos_type; 
    typedef typename Base::off_type off_type; 
    typedef typename Base::traits_type traits_type; 

    private: 
    typedef BasicSequenceInputBuffer<Char, Traits> buffer_type; 

    public: 
    typedef typename buffer_type::pointer pointer; 
    typedef typename buffer_type::size_type size_type; 

    // Construction 
    // ============ 

    public: 
    explicit BasicSequenceInputStream(pointer data, size_type size) 
    : Base(&m_buf), m_buf(data, size) 
    {} 

    private: 
    buffer_type m_buf; 
}; 

typedef BasicSequenceInputStream<char> SequenceInputStream; 


// Test 
// ==== 

#include <iostream> 
#include <vector> 

int main() 
{ 
    const std::string s = "Hello World"; 
    const std::vector<char> vector(s.begin(), s.end()); 
    SequenceInputStream stream(vector.data(), vector.size()); 

    std::string line; 
    std::getline(stream, line); 
    std::cout << line << '\n'; 
} 
+0

我很欣賞你在你的答案中付出的努力,但我想我會複製矢量。 –

+0

@NeilKirk注意:這裏沒有複製(序列的開始和結束是存儲在現有的流指針中)但是如果內存(大小)沒有問題,那麼普通副本是合理的並且足夠好。 –