/* Parses a rfc822 style file, returning the headers in a map and the body in a string. Copyright 2003, 2004 Walter Landry This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "boost/spirit.hpp" #include "boost/filesystem/operations.hpp" #include "arx_error.hpp" #include #include #include #include "Parsed_Name.hpp" #include "valid_package_name.hpp" #include "tree_root.hpp" using namespace std; using namespace boost; using namespace boost::spirit; namespace fs=boost::filesystem; using fs::path; /* Make a spirit parser to break up the contents of the header file. This is where most of the logic is. */ struct header_functor { header_functor(map &Headers, string &Body, const string &Endline) : headers(Headers), body(Body), endline(Endline) {} template void operator()(IteratorT first, IteratorT second) const { if(headers[body].empty()) headers[body]=string(first,second); else headers[body]+=endline + string(first,second); } map &headers; string &body; const string &endline; }; struct rfc822_grammar : public grammar { map &headers; string &body; const string &endline; rfc822_grammar(map &Headers, string &Body, const string &Endline) : headers(Headers), body(Body), endline(Endline) {} template struct definition { definition(rfc822_grammar const & self) { r=*header_rule >> *space_p >> (*anychar_p)[assign(self.body)]; header_rule=(*(graph_p-':'))[assign(self.body)] >> ch_p(':') >> *blank_p >> (*print_p)[header_functor(self.headers,self.body,self.endline)] >> *(ch_p('\n') >> blank_p >> *blank_p >> (*print_p)[header_functor(self.headers,self.body,self.endline)]) >> ch_p('\n'); } rule r, header_rule; rule const& start() const { return r; } }; }; /* The actual function call is quite small. */ void parse_rfc822(const path &log_name, map &headers, string &body, const string endline="\n") { file_iterator<> start(log_name.native_file_string().c_str()); if (!start) { throw arx_error("Can't open the log file\n\t" + log_name.native_file_string()); } file_iterator<> finish = start.make_end(); rfc822_grammar g(headers,body,endline); if(!parse(start,finish,g).full) { throw arx_error("Malformed patch log\n\t" + log_name.native_file_string()); } }