我正在尝试构建一个解析器,它根据初始位字段的内容决定是否解析字段:
rule<Iterator, locals<uint32_t> > r =
big_dword [_a = _1]
>> (((_a & 0x01) >> big_dword) | attr(100))
>> (((_a & 0x10) >> big_dword) | attr(0))
>> (((_a & 0x80) >> big_qword) | attr(0))
;
也就是说,如果设置了LSB,它只会尝试提取第一个字段,如果没有,它会将默认值100作为属性等公开,依此类推其他字段。
(来自:spirit-general列表)
答案 0 :(得分:3)
好的,你让我猜实际的问题。
但是我用一些'告诉'后备值编写了一些测试用例。我使用业力来格式化解析结果。为了更好的衡量(真的检查我自己的理智),我提供了little-endian和big-endian测试结果。
希望这会有所帮助:
#include <boost/fusion/adapted.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
template <typename dword_t, typename qword_t, typename Cases>
void test(const dword_t& dword, const qword_t& qword, const Cases& cases)
{
typedef boost::tuple<uint32_t,uint32_t,uint32_t,uint64_t> attr_t;
typedef const char* Iterator;
int count = 0;
for (auto testcase : cases)
{
Iterator f = reinterpret_cast<const char*>(&*testcase.begin());
Iterator l = reinterpret_cast<const char*>(&*testcase.end());
Iterator b = f;
qi::rule<Iterator, attr_t(), qi::locals<uint32_t> > r;
r %= dword [ qi::_a = qi::_1 ]
>> (( qi::eps(qi::_a & 0x01ul) > dword) | qi::attr(0x0123ul ))
>> (( qi::eps(qi::_a & 0x10ul) > dword) | qi::attr(0x0234ul ))
>> (( qi::eps(qi::_a & 0x80ul) > qword) | qi::attr(0x0345ull))
;
attr_t data;
bool ok = qi::parse(f,l,r,data);
std::cout << std::dec << "testcase " << count++ << "\t"
<< "success: " << std::boolalpha << ok << "\t"
<< "parsed: " << std::distance(b, f) << (f==l?"(complete)\n":"(incomplete)\n")
<< "\t" << std::hex << data << "\n";
}
}
typedef std::vector<uint32_t> Input;
int main()
{
std::cout << "little endian: ";
test(qi::dword, qi::qword, std::list<Input> {
{ 0x11110000u, 0x22220000u, 0x44440000u, 0x88880000u, 0x99990000u, },
{ 0x11110001u, 0x22220000u, 0x44440000u, 0x88880000u, 0x99990000u, },
{ 0x11110010u, 0x22220000u, 0x44440000u, 0x88880000u, 0x99990000u, },
{ 0x11110080u, 0x22220000u, 0x44440000u, 0x88880000u, 0x99990000u, },
{ 0x11110011u, 0x22220000u, 0x44440000u, 0x88880000u, 0x99990000u, },
{ 0x11110081u, 0x22220000u, 0x44440000u, 0x88880000u, 0x99990000u, },
{ 0x11110091u, 0x22220000u, 0x44440000u, 0x88880000u, 0x99990000u, },
});
std::cout << "\nbig endian: ";
test(qi::big_dword, qi::big_qword, std::list<Input> {
{ 0x00001111u, 0x00002222u, 0x00004444u, 0x00008888u, 0x00009999u, },
{ 0x01001111u, 0x00002222u, 0x00004444u, 0x00008888u, 0x00009999u, },
{ 0x10001111u, 0x00002222u, 0x00004444u, 0x00008888u, 0x00009999u, },
{ 0x80001111u, 0x00002222u, 0x00004444u, 0x00008888u, 0x00009999u, },
{ 0x11001111u, 0x00002222u, 0x00004444u, 0x00008888u, 0x00009999u, },
{ 0x81001111u, 0x00002222u, 0x00004444u, 0x00008888u, 0x00009999u, },
{ 0x91001111u, 0x00002222u, 0x00004444u, 0x00008888u, 0x00009999u, },
});
}
little endian: testcase 0 success: true parsed: 4(incomplete)
(11110000 123 234 345)
testcase 1 success: true parsed: 8(incomplete)
(11110001 22220000 234 345)
testcase 2 success: true parsed: 8(incomplete)
(11110010 123 22220000 345)
testcase 3 success: true parsed: 12(incomplete)
(11110080 123 234 4444000022220000)
testcase 4 success: true parsed: 12(incomplete)
(11110011 22220000 44440000 345)
testcase 5 success: true parsed: 16(incomplete)
(11110081 22220000 234 8888000044440000)
testcase 6 success: true parsed: 20(complete)
(11110091 22220000 44440000 9999000088880000)
big endian: testcase 0 success: true parsed: 4(incomplete)
(11110000 123 234 345)
testcase 1 success: true parsed: 8(incomplete)
(11110001 22220000 234 345)
testcase 2 success: true parsed: 8(incomplete)
(11110010 123 22220000 345)
testcase 3 success: true parsed: 12(incomplete)
(11110080 123 234 2222000044440000)
testcase 4 success: true parsed: 12(incomplete)
(11110011 22220000 44440000 345)
testcase 5 success: true parsed: 16(incomplete)
(11110081 22220000 234 4444000088880000)
testcase 6 success: true parsed: 20(complete)
(11110091 22220000 44440000 8888000099990000)