prevent multipass iterators from consuming on incomplete parse
Stephan Menzel <[email protected]> Wed, 22 May 2019 11:06:00 +0100
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <CAEQ568uM86n-QFiKMtyN0brPfr0a0XtdNzLq_1aQnNn160-p4A@mail.gmail.com> |
Hello all,
I'm working on a spirit based redis client (
https://github.com/MrMoose/mredis/blob/master/RESP.cpp) and make heavy use
of multi-pass iterators, which I have now discovered a problem with. I seek
advice on how to solve this.
Basically, I have a number of grammars that parse specific message types
and then an alternative message type:
template <typename InputIterator>
struct message_parser : qi::grammar<InputIterator, RedisMessage()> {
message_parser() : message_parser::base_type(m_start, "message") {
m_start %= m_simple_string | m_integer | m_array | m_null_result |
m_bulk_string | m_error;
}
integer_parser<InputIterator> m_integer;
simple_string_parser<InputIterator> m_simple_string;
bulk_string_parser<InputIterator> m_bulk_string;
null_parser<InputIterator> m_null_result;
array_parser<InputIterator> m_array;
error_parser<InputIterator> m_error;
qi::rule<InputIterator, RedisMessage()> m_start;
};
Each parser parses one message. I parse those messages directly from an
asio streambuf object and use multipass iterators to do this:
boost::spirit::multi_pass<stream_iterator_type> first =
boost::spirit::make_default_multi_pass(stream_iterator_type(n_input_stream));
const boost::spirit::multi_pass<stream_iterator_type> last =
boost::spirit::make_default_multi_pass(stream_iterator_type());
const bool retval = qi::parse(first, last, s_response_parser,
n_response);
Now I ran into problems with large messages and after extensive debugging I
found that the multipass iterator will consume the input when it parses
part of a message but not the entire message.
Like when the stream contains the beginning of a large message but it is
incomplete and I need to continue reading. parse() will fail and I see
remaining bytes in the buffers but those parts of the message that were
parsed are already missing.
I suppose this page explains the background:
https://www.boost.org/doc/libs/1_70_0/libs/spirit/doc/html/spirit/support/multi_pass.html
Sadly, I don't really understand what this means to me and my use case. How
can I prevent this from happening? I have tried adding flush_multi_pass at
the end of each seperate message but that didn't help.
What I need is for the stream to be "unconsumed", untouched, when the
overall parse command fails and no complete message could be parsed. Is
this possible?
Thanks for any input!
Stephan
_______________________________________________
Spirit-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spirit-general