gpt4 book ai didi

c++ - boost 灵气 : binding to struct with vector of tuples

转载 作者:行者123 更新时间:2023-12-02 10:04:58 28 4
gpt4 key购买 nike

Boost Spirit Qi 解析当然是 C++ 的一个独特应用,它具有陡峭的学习曲线。在这种情况下,我试图解析一个字符串,该字符串包含一个 struct 的语法正确的 C++ 列表初始化。包含 std::vectorstd::tuple<std::string, short> .这是 struct 的声明:

typedef std::vector<std::tuple<std::string, int>> label_t;

struct BulkDataParmas
{
std::string strUUID;
short subcam;
long long pts_beg;
long long pts_len;
long long pts_gap;
label_t labels;
};

这是我将这种结构绑定(bind)到 Qi 属性的失败尝试。注释掉的 start如果我也注释掉 vector,则按预期工作 struct 的成员. (我也试过 std::pair 而不是 std::tuple )。
BOOST_FUSION_ADAPT_STRUCT
(
BulkDataParmas,
(std::string, strUUID)
(short, subcam)
(long long, pts_beg)
(long long, pts_len)
(long long, pts_gap)
(label_t, labels)
)



template <typename Iterator>
struct load_parser : boost::spirit::qi::grammar<Iterator, BulkDataParmas(), boost::spirit::ascii::space_type>
{
load_parser() : load_parser::base_type(start)
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
using qi::attr;
using qi::short_;
using qi::int_;
using qi::long_long;
using qi::lit;
using qi::xdigit;
using qi::lexeme;
using ascii::char_;
using boost::proto::deep_copy;

auto hex2_ = deep_copy(xdigit >> xdigit >> xdigit >> xdigit);
auto hex4_ = deep_copy(hex2_ >> hex2_);
auto hex6_ = deep_copy(hex4_ >> hex2_);
auto fmt_ = deep_copy('"' >> hex4_ >> char_('-') >> hex2_ >> char_('-') >> hex2_ >> char_('-') >> hex2_ >> char_('-') >> hex6_ >> '"');
uuid = qi::as_string[fmt_];

quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];

label = '{' >> quoted_string >> ',' >> int_ >> '}';

start = '{' >> uuid >> ',' >> short_ >> ',' >> long_long >> ',' >> long_long >> ',' >> long_long >> ',' >> '{' >> -(label >> *(',' >> label)) >>'}' >> '}';
// start = '{' >> uuid >> ',' >> short_ >> ',' >> long_long >> ',' >> long_long >> ',' >> long_long >> '}';
}

private:

boost::spirit::qi::rule<Iterator, std::string()> uuid;
boost::spirit::qi::rule<Iterator, std::string()> quoted_string;
boost::spirit::qi::rule<Iterator, std::string(), boost::spirit::ascii::space_type> label;
boost::spirit::qi::rule<Iterator, BulkDataParmas(), boost::spirit::ascii::space_type> start;
};

这是一个要解析的示例字符串:
"{ \"68965363-2d87-46d4-b05d-f293f2c8403b\", 0, 1583798400000000, 86400000000, 600000000, { { \"motorbike\", 5 }, { \"aeroplane\", 6 } } };"

最佳答案

除了你提到的两件事(这是正确的),我建议

  • 一些简化:
    uuid = '"' >> qi::raw [
    hex_<4>{} >> qi::repeat(3)['-' >> hex_<2>{}] >> '-' >> hex_<6>{}
    ] >> '"';

    请注意,这会删除所有子表达式 as-string 和 deepcopy,而不是使用整数解析器:
    template<int N> using hex_ = boost::spirit::qi::int_parser<std::intmax_t, 16, 2*N, 2*N>;
    raw[]解析器将很好地公开匹配的源字符串。
  • 接下来,
    quoted_string = '"' >> *~qi::char_('"') >> '"';

    在这里我建议使用 *接受空字符串(这经常
    引用字符串的“点”,所以我们可以明确地嵌入
    空格或有意为空的字符串)。此外,使用 ~charset成为
    更高效。

    还删除了lexeme[]因为无论如何都已经声明了规则而没有 skipper 。
  • 整理起来:
    label = '{' >> quoted_string >> ',' >> qi::int_ >> '}';

    start = qi::skip(ascii::space) [ '{'
    >> uuid >> ','
    >> qi::auto_ >> ','
    >> qi::auto_ >> ','
    >> qi::auto_ >> ','
    >> qi::auto_ >> ','
    >> '{' >> -(label % ',') >> '}'
    >> '}' >> ';'
    ];

    请注意,我合并了 skipper 的选择。所以你不必在 phrase_parse 中繁琐地传递正确的东西. skipper 通常不是调用者应该能够改变的东西。
  • 现在让我们也对改编进行现代化改造:
    BOOST_FUSION_ADAPT_STRUCT(BulkDataParams, strUUID, subcam, pts_beg, pts_len, pts_gap, labels)

    之后,您可以以现代方式重新拼写类型,而不会冒任何兼容性问题的风险。请注意,这也是首选 qi::auto_ 的原因。在那里的开始规则中,所以你不会得到痛苦的惊喜,例如解析器结果以预期的方式隐式转换为目标类型。
    struct BulkDataParams {
    std::string strUUID;
    int16_t subcam;
    int64_t pts_beg;
    int64_t pts_len;
    int64_t pts_gap;
    label_t labels;
    };
  • 现在让我们输入调试输出和测试体:

    Live On Wandbox
    #define BOOST_SPIRIT_DEBUG
    #include <boost/spirit/include/qi.hpp>
    #include <boost/fusion/adapted/std_tuple.hpp>
    #include <iostream>
    #include <iomanip>

    using label_t = std::vector<std::tuple<std::string, int>>;

    namespace std {
    std::ostream& operator<<(std::ostream& os, label_t::value_type const& t) {
    auto const& [k,v] = t;
    return os << "[" << std::quoted(k) << "," << v << "]";
    }

    std::ostream& operator<<(std::ostream& os, label_t const& m) {
    os << "{";
    for (auto&& el:m) os << el << ",";
    return os << "}";
    }
    }

    struct BulkDataParams {
    std::string strUUID;
    int16_t subcam;
    int64_t pts_beg;
    int64_t pts_len;
    int64_t pts_gap;
    label_t labels;
    };

    BOOST_FUSION_ADAPT_STRUCT(BulkDataParams, strUUID, subcam, pts_beg, pts_len, pts_gap, labels)

    template <typename Iterator> struct load_parser : boost::spirit::qi::grammar<Iterator, BulkDataParams()> {
    load_parser() : load_parser::base_type(start) {
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;

    uuid = '"' >> qi::raw [
    hex_<4>{} >> qi::repeat(3)['-' >> hex_<2>{}] >> '-' >> hex_<6>{}
    ] >> '"';

    quoted_string = '"' >> *~qi::char_('"') >> '"';

    label = '{' >> quoted_string >> ',' >> qi::int_ >> '}';

    start = qi::skip(ascii::space) [ '{'
    >> uuid >> ','
    >> qi::auto_ >> ','
    >> qi::auto_ >> ','
    >> qi::auto_ >> ','
    >> qi::auto_ >> ','
    >> '{' >> -(label % ',') >> '}'
    >> '}' >> ';'
    ];

    BOOST_SPIRIT_DEBUG_NODES(
    (uuid) (quoted_string) (label) (start)
    )
    }

    template<int N> using hex_ = boost::spirit::qi::int_parser<std::intmax_t, 16, 2*N, 2*N>;

    private:
    boost::spirit::qi::rule<Iterator, std::string()> uuid;
    boost::spirit::qi::rule<Iterator, std::string()> quoted_string;
    boost::spirit::qi::rule<Iterator, label_t::value_type(), boost::spirit::ascii::space_type> label;
    boost::spirit::qi::rule<Iterator, BulkDataParams()> start;
    };

    int main() {

    for (std::string const input : {
    R"({ "68965363-2d87-46d4-b05d-f293f2c8403b", 0, 1583798400000000, 86400000000, 600000000, { { "motorbike", 5 }, { "aeroplane", 6 } } };)",
    })
    {
    auto f = begin(input), l = end(input);
    BulkDataParams bdp;
    load_parser<std::string::const_iterator> p;
    if (parse(f, l, p, bdp)) {
    std::cout << "Parsed: " << boost::fusion::as_vector(bdp) << "\n";
    } else {
    std::cout << "Parse Failed\n";
    }

    if (f != l) {
    std::cout << "Remaining unparsed: " << std::quoted(std::string(f,l)) << "\n";
    }
    }
    }

    常规输出:

    Parsed: (68965363-2d87-46d4-b05d-f293f2c8403b 0 1583798400000000 86400000000 600000000 {["motorbike",5],["aeroplane",6],})



    调试输出:
    <start>
    <try>{ "68965363-2d87-46d</try>
    <uuid>
    <try>"68965363-2d87-46d4-</try>
    <success>, 0, 158379840000000</success>
    <attributes>[[6, 8, 9, 6, 5, 3, 6, 3, -, 2, d, 8, 7, -, 4, 6, d, 4, -, b, 0, 5, d, -, f, 2, 9, 3, f, 2, c, 8, 4, 0, 3, b]]</attributes>
    </uuid>
    <label>
    <try> { "motorbike", 5 },</try>
    <quoted_string>
    <try>"motorbike", 5 }, { </try>
    <success>, 5 }, { "aeroplane"</success>
    <attributes>[[m, o, t, o, r, b, i, k, e]]</attributes>
    </quoted_string>
    <success>, { "aeroplane", 6 }</success>
    <attributes>[[[m, o, t, o, r, b, i, k, e], 5]]</attributes>
    </label>
    <label>
    <try> { "aeroplane", 6 } </try>
    <quoted_string>
    <try>"aeroplane", 6 } } }</try>
    <success>, 6 } } };</success>
    <attributes>[[a, e, r, o, p, l, a, n, e]]</attributes>
    </quoted_string>
    <success> } };</success>
    <attributes>[[[a, e, r, o, p, l, a, n, e], 6]]</attributes>
    </label>
    <success></success>
    <attributes>[[[6, 8, 9, 6, 5, 3, 6, 3, -, 2, d, 8, 7, -, 4, 6, d, 4, -, b, 0, 5, d, -, f, 2, 9, 3, f, 2, c, 8, 4, 0, 3, b], 0, 1583798400000000, 86400000000, 600000000, [[[m, o, t, o, r, b, i, k, e], 5], [[a, e, r, o, p, l, a, n, e], 6]]]]</attributes>
    </start>
  • 关于c++ - boost 灵气 : binding to struct with vector of tuples,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60660550/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com