31 #include <boost/spirit/include/qi.hpp> 32 #include <boost/spirit/include/phoenix.hpp> 33 #include <boost/fusion/adapted.hpp> 43 typedef boost::variant<std::string, std::vector<std::string>> FieldVal_t;
44 typedef boost::optional<std::string> Lang_t;
51 typedef std::vector<Field> Fields_t;
58 typedef std::vector<Group> Groups_t;
71 (LeechCraft::Util::XDG::Lang_t,
Lang_)
72 (LeechCraft::Util::XDG::FieldVal_t,
Val_));
76 (LeechCraft::Util::XDG::Fields_t,
Fields_));
79 (LeechCraft::Util::XDG::Groups_t,
Groups_));
89 namespace ascii = boost::spirit::ascii;
90 namespace qi = boost::spirit::qi;
91 namespace phoenix = boost::phoenix;
93 template<
typename Iter>
94 struct Parser : qi::grammar<Iter, File ()>
99 qi::rule<Iter, std::string ()>
Lang_;
107 : Parser::base_type (Start_)
109 auto eol = qi::lit (
"\n");
110 Comment_ %= qi::lit (
"#") >> *(qi::char_ -
'\r' -
'\n') >> eol;
112 Lang_ %=
'[' >> qi::lexeme [+(qi::char_ (
"a-zA-Z0-9@_-"))] >>
']';
114 KeyValSep_ %= *(qi::lit (
' ')) >>
'=' >> *(qi::lit (
' '));
116 LineValSingle_ %= qi::lexeme [+((qi::lit (
"\\;") | (qi::char_ -
';' -
'\r' -
'\n')))];
117 LineVal_ %= ((LineValSingle_ %
';') >> -qi::lit (
";")) | LineValSingle_;
119 Line_ %= qi::lexeme [+(qi::char_ (
"a-zA-Z0-9-"))] >>
125 GroupName_ %=
'[' >> qi::lexeme [+(qi::char_ (
"a-zA-Z0-9 "))] >>
']';
127 Group_ %= GroupName_ >> eol >>
128 *(Comment_ | Line_ | eol);
130 Start_ %= *Comment_ >> +
Group_;
132 qi::on_error<qi::fail> (
Start_,
133 std::cout << phoenix::val (
"Error! Expecting") << qi::_4
134 << phoenix::val (
" here: \"") << phoenix::construct<std::string> (qi::_3, qi::_2)
135 << phoenix::val (
"\"") << std::endl);
139 template<
typename Iter>
140 File Parse (Iter begin, Iter end)
143 qi::parse (begin, end, Parser<Iter> (), res);
147 QString ToUtf8 (
const std::string& str)
149 return QString::fromUtf8 (str.c_str ());
152 struct ValGetter :
public boost::static_visitor<QStringList>
154 QStringList operator() (
const std::string& str)
const 156 return QStringList (ToUtf8 (str));
159 QStringList operator() (
const std::vector<std::string>& vec)
const 162 std::transform (vec.begin (), vec.end (), std::back_inserter (result), ToUtf8);
170 const auto& file = Parse (data.begin (), data.end ());
173 for (
const auto& item : file.Groups_)
176 for (
const auto& field : item.Fields_)
178 const auto& values = boost::apply_visitor (ValGetter (), field.Val_);
179 const auto& lang = field.Lang_ ? ToUtf8 (*field.Lang_) : QString ();
180 group [ToUtf8 (field.Name_)] [lang] = values;
182 result [ToUtf8 (item.Name_)] = group;
UTIL_XDG_API Result_t operator()(const QByteArray &data)
Parses the XDG data.
qi::rule< Iter, File()> Start_
qi::rule< Iter, void()> KeyValSep_
qi::rule< Iter, std::string()> LineValSingle_
qi::rule< Iter, Field()> Line_
qi::rule< Iter, Group()> Group_
BOOST_FUSION_ADAPT_STRUCT(LeechCraft::Util::XDG::Field,(std::string, Name_)(LeechCraft::Util::XDG::Lang_t, Lang_)(LeechCraft::Util::XDG::FieldVal_t, Val_))
qi::rule< Iter, void()> Comment_
qi::rule< Iter, std::string()> GroupName_
QHash< QString, LangValue_t > Group_t
Mapping from a field name to the list of language-dependent values of that field. ...
QHash< QString, Group_t > Result_t
Mapping from a group name to the group itself.
qi::rule< Iter, FieldVal_t()> LineVal_