#include <sstream>
#include <istream>
#include <iostream>
void fill_testdata(std::ostream& os);
struct FormatData {
std::string signature, header; // e.g. 4 + 16 = 20 bytes - could be different, of course
std::string payload; // 16bit length prefixed
};
FormatData parse(std::istream& is);
int main() {
std::stringstream ss;
fill_testdata(ss);
try {
FormatData data = parse(ss);
std::cout << "actual payload bytes: " << data.payload.length() << "\n";
std::cout << "payload: '" << data.payload << "'\n";
} catch(std::runtime_error const& e) {
std::cout << "Error: " << e.what() << "\n";
}
}
// some testdata
void fill_testdata(std::ostream& os)
{
char data[] = {
'S' , 'I' , 'G' , 'N' , '\x00' , // 0..4
'\x00', '\x00', '\x00', '\x00', '\x00' , // 5..9
'\x00', '\x00', '\x00', '\x00', '\x00' , // 10..14
'\x00', '\x00', '\x00', '\x00', '\x00' , // 15..19
'\x0b', '\x00', 'H' , 'e' , 'l' , // 20..24
'l' , 'o' , ' ' , 'w' , 'o' , // 25..29
'r' , 'l' , 'd' , '!' , // 30..33
};
os.write(data, sizeof(data));
}
//#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
BOOST_FUSION_ADAPT_STRUCT(FormatData, signature, header, payload)
template <typename It>
struct FileFormat : qi::grammar<It, FormatData()> {
FileFormat() : FileFormat::base_type(start) {
using namespace qi;
signature = string("SIGN"); // 4 byte signature, just for example
header = repeat(16) [byte_]; // 16 byte header, same
payload %= omit[little_word[_len=_1]] >> repeat(_len) [byte_];
start = signature >> header >> payload;
//BOOST_SPIRIT_DEBUG_NODES((start)(signature)(header)(payload))
}
private:
qi::rule<It, FormatData()> start;
qi::rule<It, std::string()> signature, header;
qi::_a_type _len;
qi::rule<It, std::string(), qi::locals<uint16_t> > payload;
};
FormatData parse(std::istream& is) {
using it = boost::spirit::istream_iterator;
FormatData data;
it f(is >> std::noskipws), l;
bool ok = parse(f, l, FileFormat<it>{}, data);
if (!ok)
throw std::runtime_error("parse failure\n");
return data;
}
I2luY2x1ZGUgPHNzdHJlYW0+CiNpbmNsdWRlIDxpc3RyZWFtPgojaW5jbHVkZSA8aW9zdHJlYW0+Cgp2b2lkIGZpbGxfdGVzdGRhdGEoc3RkOjpvc3RyZWFtJiBvcyk7CgpzdHJ1Y3QgRm9ybWF0RGF0YSB7CiAgICBzdGQ6OnN0cmluZyBzaWduYXR1cmUsIGhlYWRlcjsgLy8gZS5nLiA0ICsgMTYgPSAyMCBieXRlcyAtIGNvdWxkIGJlIGRpZmZlcmVudCwgb2YgY291cnNlCiAgICBzdGQ6OnN0cmluZyBwYXlsb2FkOyAgICAgICAgICAgLy8gMTZiaXQgbGVuZ3RoIHByZWZpeGVkCn07CgpGb3JtYXREYXRhIHBhcnNlKHN0ZDo6aXN0cmVhbSYgaXMpOwoKaW50IG1haW4oKSB7CiAgICBzdGQ6OnN0cmluZ3N0cmVhbSBzczsKICAgIGZpbGxfdGVzdGRhdGEoc3MpOwoKICAgIHRyeSB7CiAgICAgICAgRm9ybWF0RGF0YSBkYXRhID0gcGFyc2Uoc3MpOwoKICAgICAgICBzdGQ6OmNvdXQgPDwgImFjdHVhbCBwYXlsb2FkIGJ5dGVzOiAiIDw8IGRhdGEucGF5bG9hZC5sZW5ndGgoKSA8PCAiXG4iOwogICAgICAgIHN0ZDo6Y291dCA8PCAicGF5bG9hZDogJyIgPDwgZGF0YS5wYXlsb2FkIDw8ICInXG4iOwogICAgfSBjYXRjaChzdGQ6OnJ1bnRpbWVfZXJyb3IgY29uc3QmIGUpIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgIkVycm9yOiAiIDw8IGUud2hhdCgpIDw8ICJcbiI7CiAgICB9Cn0KCi8vIHNvbWUgdGVzdGRhdGEKdm9pZCBmaWxsX3Rlc3RkYXRhKHN0ZDo6b3N0cmVhbSYgb3MpCnsKICAgIGNoYXIgZGF0YVtdID0geyAKICAgICAgICAnUycgICAsICdJJyAgICwgJ0cnICAgLCAnTicgICAsICdceDAwJyAgICwgLy8gMC4uNAogICAgICAgICdceDAwJywgJ1x4MDAnLCAnXHgwMCcsICdceDAwJywgJ1x4MDAnICAgLCAvLyA1Li45CiAgICAgICAgJ1x4MDAnLCAnXHgwMCcsICdceDAwJywgJ1x4MDAnLCAnXHgwMCcgICAsIC8vIDEwLi4xNAogICAgICAgICdceDAwJywgJ1x4MDAnLCAnXHgwMCcsICdceDAwJywgJ1x4MDAnICAgLCAvLyAxNS4uMTkKICAgICAgICAnXHgwYicsICdceDAwJywgJ0gnICAgLCAnZScgICAsICdsJyAgICAgICwgLy8gMjAuLjI0CiAgICAgICAgJ2wnICAgLCAnbycgICAsICcgJyAgICwgJ3cnICAgLCAnbycgICAgICAsIC8vIDI1Li4yOQogICAgICAgICdyJyAgICwgJ2wnICAgLCAnZCcgICAsICchJyAgICwgLy8gMzAuLjMzCiAgICB9OwogICAgb3Mud3JpdGUoZGF0YSwgc2l6ZW9mKGRhdGEpKTsKfQoKLy8jZGVmaW5lIEJPT1NUX1NQSVJJVF9ERUJVRwojaW5jbHVkZSA8Ym9vc3QvZnVzaW9uL2FkYXB0ZWQvc3RydWN0LmhwcD4KI2luY2x1ZGUgPGJvb3N0L3NwaXJpdC9pbmNsdWRlL3FpLmhwcD4KI2luY2x1ZGUgPGJvb3N0L3NwaXJpdC9pbmNsdWRlL3Bob2VuaXguaHBwPgpuYW1lc3BhY2UgcWkgPSBib29zdDo6c3Bpcml0OjpxaTsKCkJPT1NUX0ZVU0lPTl9BREFQVF9TVFJVQ1QoRm9ybWF0RGF0YSwgc2lnbmF0dXJlLCBoZWFkZXIsIHBheWxvYWQpCgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSXQ+CnN0cnVjdCBGaWxlRm9ybWF0IDogcWk6OmdyYW1tYXI8SXQsIEZvcm1hdERhdGEoKT4gewogICAgRmlsZUZvcm1hdCgpIDogRmlsZUZvcm1hdDo6YmFzZV90eXBlKHN0YXJ0KSB7CiAgICAgICAgdXNpbmcgbmFtZXNwYWNlIHFpOwoKICAgICAgICBzaWduYXR1cmUgID0gc3RyaW5nKCJTSUdOIik7ICAgICAvLyA0IGJ5dGUgc2lnbmF0dXJlLCBqdXN0IGZvciBleGFtcGxlCiAgICAgICAgaGVhZGVyICAgICA9IHJlcGVhdCgxNikgW2J5dGVfXTsgLy8gMTYgYnl0ZSBoZWFkZXIsIHNhbWUKCiAgICAgICAgcGF5bG9hZCAgICU9IG9taXRbbGl0dGxlX3dvcmRbX2xlbj1fMV1dID4+IHJlcGVhdChfbGVuKSBbYnl0ZV9dOwogICAgICAgIHN0YXJ0ICAgICAgPSBzaWduYXR1cmUgPj4gaGVhZGVyID4+IHBheWxvYWQ7CgogICAgICAgIC8vQk9PU1RfU1BJUklUX0RFQlVHX05PREVTKChzdGFydCkoc2lnbmF0dXJlKShoZWFkZXIpKHBheWxvYWQpKQogICAgfQogIHByaXZhdGU6CiAgICBxaTo6cnVsZTxJdCwgRm9ybWF0RGF0YSgpPiBzdGFydDsKICAgIHFpOjpydWxlPEl0LCBzdGQ6OnN0cmluZygpPiBzaWduYXR1cmUsIGhlYWRlcjsKCiAgICBxaTo6X2FfdHlwZSBfbGVuOwogICAgcWk6OnJ1bGU8SXQsIHN0ZDo6c3RyaW5nKCksIHFpOjpsb2NhbHM8dWludDE2X3Q+ID4gcGF5bG9hZDsKfTsKCkZvcm1hdERhdGEgcGFyc2Uoc3RkOjppc3RyZWFtJiBpcykgewogICAgdXNpbmcgaXQgPSBib29zdDo6c3Bpcml0Ojppc3RyZWFtX2l0ZXJhdG9yOwoKICAgIEZvcm1hdERhdGEgZGF0YTsKICAgIGl0IGYoaXMgPj4gc3RkOjpub3NraXB3cyksIGw7CiAgICBib29sIG9rID0gcGFyc2UoZiwgbCwgRmlsZUZvcm1hdDxpdD57fSwgZGF0YSk7CgogICAgaWYgKCFvaykKICAgICAgICB0aHJvdyBzdGQ6OnJ1bnRpbWVfZXJyb3IoInBhcnNlIGZhaWx1cmVcbiIpOwoKICAgIHJldHVybiBkYXRhOwp9Cg==