2014-12-05 18 views
9

Próbuję zrozumieć połączenia boost::asio::streambuf::consume() i boost::asio::streambuf::commit(). W Dokumentach, mamy przykłady,Kiedy mogę wywołać metodę boost :: asio :: streambuf :: consume() i boost :: asio :: streambuf :: commit()?

boost::asio::streambuf b; 
std::ostream os(&b); 
os << "Hello, World!\n"; 

// try sending some data in input sequence 
size_t n = sock.send(b.data()); 

b.consume(n); // sent data is removed from input sequence 

i

boost::asio::streambuf b; 

// reserve 512 bytes in output sequence 
boost::asio::streambuf::mutable_buffers_type bufs = b.prepare(512); 

size_t n = sock.receive(bufs); 

// received data is "committed" from output sequence to input sequence 
b.commit(n); 

std::istream is(&b); 
std::string s; 
is >> s; 

rozumiem te dwa połączenia tak jak rozumiem co dokumentacja mówi o nich - call consume() aby usunąć znaki z sekwencji wejściowej wewnątrz boost::asio::streambuf i wywołanie commit() w celu przeniesienia znaków z sekwencji wyjściowej boost::asio::streambuf do sekwencji wejściowej. Słusznie.

Kiedy to mogę w rzeczywistości to je wywołać? Patrząc na źródło boost::asio::read_until() mamy

template <typename SyncReadStream, typename Allocator> 
std::size_t read_until(SyncReadStream& s, 
    boost::asio::basic_streambuf<Allocator>& b, char delim, 
    boost::system::error_code& ec) 
{ 
    std::size_t search_position = 0; 
    for (;;) 
    { 
    // Determine the range of the data to be searched. 
    typedef typename boost::asio::basic_streambuf< 
     Allocator>::const_buffers_type const_buffers_type; 
    typedef boost::asio::buffers_iterator<const_buffers_type> iterator; 
    const_buffers_type buffers = b.data(); 
    iterator begin = iterator::begin(buffers); 
    iterator start_pos = begin + search_position; 
    iterator end = iterator::end(buffers); 

    // Look for a match. 
    iterator iter = std::find(start_pos, end, delim); 
    if (iter != end) 
    { 
     // Found a match. We're done. 
     ec = boost::system::error_code(); 
     return iter - begin + 1; 
    } 
    else 
    { 
     // No match. Next search can start with the new data. 
     search_position = end - begin; 
    } 

    // Check if buffer is full. 
    if (b.size() == b.max_size()) 
    { 
     ec = error::not_found; 
     return 0; 
    } 

    // Need more data. 
    std::size_t bytes_to_read = read_size_helper(b, 65536); 
    b.commit(s.read_some(b.prepare(bytes_to_read), ec)); 
    if (ec) 
     return 0; 
    } 
} 

Widać, że, jak mówi dokumentacja, boost::asio::read_until() realizowany jest pod względem SyncReadStream „s read_some().

Do mnie, że mówi, że

  1. SyncReadStream::read_some() nie wymaga boost::asio::streambuf::commit()
  2. boost::asio::read_until() zwoła boost::asio::streambuf::commit()
  3. Żadna z nich wydają się być udokumentowane - ani w boost::asio::read_until() 'dokumentacji s, ani w SyncReadStream' s docs.
  4. Nie wiem, czy mam w ogóle dzwonić pod numer boost::asio::streambuf::commit()?

Z moim synchronicznego kodu na pewno nie wydaje się to potrzebne, a nie kiedy dzwonię wolne funkcje boost::asio::read() i boost::asio::read_until(). Mam go w swoim kodzie asynchronicznym w moich programach obsługi, głównie dlatego, że użyłem przykładów, których użyłem, ale nie jestem też pewny, czy go wywołać. Kiedy próbuję użyć boost::asio::streambuf z stringstream i std::string, wydaje się, że nie odgrywa roli - nic się nie zatrzyma ani nie utknie bez wywołania commit() na .

Czy ktoś może mi to załatwić?

+0

Chciałbym zobaczyć jakąś ostateczną dokumentację na ten temat. Nie mogę nic znaleźć. – EML

Odpowiedz

1

read_until używa read_some w swojej implementacji. Tak więc, read_some dzwoni streambuf::commit i read_until nie (bezpośrednio).

Zazwyczaj nie trzeba dzwonić pod numer commit i consume, ale jeśli chcesz coś zrobić z danymi bufora - może to być sposób na zrobienie tego. Na przykład, jeśli korzystasz z protokołu binarnego, którego nie można poprawnie sprawdzić przy pomocy read_until.

4

Asio definiuje liczbę auxiliary free functions (read_xxx), która akceptuje asio::streambuf i zależy im na i commit.

Z drugiej strony, jeśli chcesz używać asio::streambuf z lower-level functions które akceptują model MutableBufferSequence concept, trzeba zadzwonić streambuf::prepare(), która zwraca obiekty, które spotyka MutableBufferSequence koncepcję, przekazać ten obiekt jako bufor, a po funkcja wypełnia go - wywołaj commit().

W obu przypadkach, po czytałeś n bajtów danych z streambuf, trzeba zadzwonić consume(n) - w celu wykorzystania sekwencji wejściowej.