2017-01-26 88 views
1

我正在使用boost::asio::async_read_until從TCP套接字讀取\n -ended行。讓我請記得,async_read_until簽名如下:Boost ASIO ForwardIterator for streambuf

http://www.boost.org/doc/libs/1_63_0/doc/html/boost_asio/reference.html#boost_asio.reference.async_read_until

void-or-deduced async_read_until(
    AsyncReadStream & s, 
    boost::asio::basic_streambuf<Allocator> & b, 
    char delim, 
    ReadHandler handler); 

這裏

boost::asio::streambuf b; 

是存儲接收到的數據自動調整大小的對象。

據我所知,它在內部由緩衝區序列組成,boost :: asio緩衝區列表。但是,沒有簡單的方法來獲取ForwardIterator來遍歷由多個連續區域組成的內部緩衝區。

我發現下面的使用模式:

std::istream stream(&b); 
std::istream_iterator<char> end; 
std::istream_iterator<char> begin(stream); 

然而,這裏endbegin是InputIterators。

與此同時,boost::spirit::phrase_parse(begin, end, grammar, space, obj)解析器可以用於解析從停飛線獲得需要beginend是ForwardIterators:

http://www.boost.org/doc/libs/1_63_0/libs/spirit/doc/html/spirit/support/multi_pass.html

這是必需的回溯。但是,這些數據實際上已經存儲在boost::asio::streambuf b對象的內存緩衝區中,沒有什麼能夠防止迭代器被多次取消引用。

+0

我可以編寫自己的迭代器(逐個遍歷BufferSequenced元素)並使用b.data()遍歷它。但是,我認爲應該有標準的方法... – 0x2207

+0

@Nim你可以簡單地多次調整一個streambuf_iterator(與boost :: spirit :: istream_iterator調整istream_iterator的方式完全相同)。但即使這樣也是不必要的。 Boost Asio的緩衝迭代器符合要求,請參閱我的答案。 – sehe

回答

3

升壓具有buffers_begin()buffers_end(),你可以在的data()streambuf使用:

Live On Coliru

#include <boost/asio.hpp> 
#include <boost/spirit/include/qi.hpp> 

namespace a = boost::asio; 
namespace qi = boost::spirit::qi; 

#include <iostream> 
int main() 
{ 
    a::streambuf input; 
    std::ostream(&input) << "123, 4, 5; 78, 8, 9;\n888, 8, 8;"; 

    auto f = a::buffers_begin(input.data()), l = a::buffers_end(input.data()); 
    //std::copy(f, l, std::ostream_iterator<char>(std::cout)); 

    std::vector<std::vector<int> > parsed; 
    bool ok = qi::phrase_parse(f, l, *(qi::int_ % ',' >> ';'), qi::space, parsed); 

    if (ok) { 
     std::cout << "parsed: \n"; 
     for (auto& row : parsed) { 
      for (auto& v : row) { std::cout << v << " "; } 
      std::cout << ";\n"; 
     } 
    } 
    else 
     std::cout << "parse failed\n"; 

    if (f!=l) 
     std::cout << "remaining unparsed input: '" << std::string(f,l) << "'\n"; 
} 

打印(如預期):

parsed: 
123 4 5 ; 
78 8 9 ; 
888 8 8 ; 

注意別忘了consume()輸入的解析部分!

+0

哦酷 - 我沒有意識到'buffers_begin()'et-al爲此返回了一個合適的迭代器!我會刪除我的評論.. – Nim

+0

謝謝。答案是有道理的。我確定buffers_begin/end()在序列的緩衝區上迭代。 – 0x2207