LeechCraft  0.6.70-13729-g7046a9d2a7
Modular cross-platform feature rich live environment.
desktopparser.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * LeechCraft - modular cross-platform feature rich internet client.
3  * Copyright (C) 2006-2014 Georg Rudoy
4  *
5  * Boost Software License - Version 1.0 - August 17th, 2003
6  *
7  * Permission is hereby granted, free of charge, to any person or organization
8  * obtaining a copy of the software and accompanying documentation covered by
9  * this license (the "Software") to use, reproduce, display, distribute,
10  * execute, and transmit the Software, and to prepare derivative works of the
11  * Software, and to permit third-parties to whom the Software is furnished to
12  * do so, all subject to the following:
13  *
14  * The copyright notices in the Software and this entire statement, including
15  * the above license grant, this restriction and the following disclaimer,
16  * must be included in all copies of the Software, in whole or in part, and
17  * all derivative works of the Software, unless such copies or derivative
18  * works are solely in the form of machine-executable object code generated by
19  * a source language processor.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  **********************************************************************/
29 
30 #include "desktopparser.h"
31 #include <boost/spirit/include/qi.hpp>
32 #include <boost/spirit/include/phoenix.hpp>
33 #include <boost/fusion/adapted.hpp>
34 
35 namespace LC
36 {
37 namespace Util
38 {
39 namespace XDG
40 {
41  namespace
42  {
43  typedef boost::variant<std::string, std::vector<std::string>> FieldVal_t;
44  typedef boost::optional<std::string> Lang_t;
45  struct Field
46  {
47  std::string Name_;
48  Lang_t Lang_;
49  FieldVal_t Val_;
50  };
51  typedef std::vector<Field> Fields_t;
52 
53  struct Group
54  {
55  std::string Name_;
56  Fields_t Fields_;
57  };
58  typedef std::vector<Group> Groups_t;
59 
60  struct File
61  {
62  Groups_t Groups_;
63  };
64  }
65 }
66 }
67 }
68 
69 BOOST_FUSION_ADAPT_STRUCT (LC::Util::XDG::Field,
70  Name_,
71  Lang_,
72  Val_)
73 
74 BOOST_FUSION_ADAPT_STRUCT (LC::Util::XDG::Group,
75  Name_,
76  Fields_)
77 
78 BOOST_FUSION_ADAPT_STRUCT (LC::Util::XDG::File,
79  Groups_)
80 
81 namespace LC
82 {
83 namespace Util
84 {
85 namespace XDG
86 {
87  namespace
88  {
89  namespace ascii = boost::spirit::ascii;
90  namespace qi = boost::spirit::qi;
91  namespace phoenix = boost::phoenix;
92 
93  template<typename Iter>
94  struct Parser : qi::grammar<Iter, File ()>
95  {
96  qi::rule<Iter, File ()> Start_;
97  qi::rule<Iter, Group ()> Group_;
98  qi::rule<Iter, std::string ()> GroupName_;
99  qi::rule<Iter, std::string ()> Lang_;
100  qi::rule<Iter, void ()> KeyValSep_;
101  qi::rule<Iter, std::string ()> LineValSingle_;
102  qi::rule<Iter, FieldVal_t ()> LineVal_;
103  qi::rule<Iter, Field ()> Line_;
104  qi::rule<Iter, void ()> Comment_;
105 
106  Parser ()
107  : Parser::base_type (Start_)
108  {
109  auto eol = qi::lit ("\n");
110  Comment_ %= qi::lit ("#") >> *(qi::char_ - '\r' - '\n') >> eol;
111 
112  Lang_ %= '[' >> qi::lexeme [+(qi::char_ ("a-zA-Z0-9@_-"))] >> ']';
113 
114  KeyValSep_ %= *(qi::lit (' ')) >> '=' >> *(qi::lit (' '));
115 
116  LineValSingle_ %= qi::lexeme [+((qi::lit ("\\;") | (qi::char_ - ';' - '\r' - '\n')))];
117  LineVal_ %= ((LineValSingle_ % ';') >> -qi::lit (";")) | LineValSingle_;
118 
119  Line_ %= qi::lexeme [+(qi::char_ ("a-zA-Z0-9-"))] >>
120  -Lang_ >>
121  KeyValSep_ >>
122  -LineVal_ >>
123  eol;
124 
125  GroupName_ %= '[' >> qi::lexeme [+(qi::char_ ("a-zA-Z0-9 "))] >> ']';
126 
127  Group_ %= GroupName_ >> eol >>
128  *(Comment_ | Line_ | eol);
129 
130  Start_ %= *Comment_ >> +Group_;
131 
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);
136  }
137  };
138 
139  template<typename Iter>
140  File Parse (Iter begin, Iter end)
141  {
142  File res;
143  qi::parse (begin, end, Parser<Iter> (), res);
144  return res;
145  }
146 
147  QString ToUtf8 (const std::string& str)
148  {
149  return QString::fromUtf8 (str.c_str ());
150  }
151 
152  struct ValGetter : public boost::static_visitor<QStringList>
153  {
154  QStringList operator() (const std::string& str) const
155  {
156  return QStringList (ToUtf8 (str));
157  }
158 
159  QStringList operator() (const std::vector<std::string>& vec) const
160  {
161  QStringList result;
162  std::transform (vec.begin (), vec.end (), std::back_inserter (result), ToUtf8);
163  return result;
164  }
165  };
166  }
167 
168  auto DesktopParser::operator() (const QByteArray& data) -> Result_t
169  {
170  const auto& file = Parse (data.begin (), data.end ());
171 
172  Result_t result;
173  for (const auto& item : file.Groups_)
174  {
175  Group_t group;
176  for (const auto& field : item.Fields_)
177  {
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;
181  }
182  result [ToUtf8 (item.Name_)] = group;
183  }
184  return result;
185  }
186 }
187 }
188 }
std::string Name_
UTIL_XDG_API Result_t operator()(const QByteArray &data)
Parses the XDG data.
FieldVal_t Val_
Lang_t Lang_
Fields_t Fields_
BOOST_FUSION_ADAPT_STRUCT(Student, ID_, Name_) struct StudentInfo
Groups_t Groups_
Definition: constants.h:35