]> git.stg.codes - ssmd.git/blob - src/settingsfileparser.cpp
Fix build on osx.
[ssmd.git] / src / settingsfileparser.cpp
1 #include <fstream>
2 #include <numeric>
3 #include <map>
4 #include <string>
5
6 #include <boost/spirit/include/qi.hpp>
7 #include <boost/fusion/include/std_pair.hpp>
8
9 #include "settings.h"
10
11 namespace qi = boost::spirit::qi;
12
13 namespace {
14
15 typedef std::map<std::string, std::string> PairsType;
16 typedef std::map<std::string, PairsType> SectionsType;
17
18 template <typename Iterator>
19 struct IniGrammar
20   : qi::grammar<Iterator, SectionsType()>
21 {
22     IniGrammar()
23       : IniGrammar::base_type(query)
24     {
25         query          = +(section | (comment >> eol) | (space >> eol));
26         section        =  sectionHeader >> -sectionContent;
27         sectionHeader  =  '[' >> space >> key >> space >> ']' >> eol;
28         sectionContent = +((line | comment | space) >> eol);
29         comment        =  (qi::char_(';') | '#') >> *qi::print;
30         line           =  space >> key >> space >> -('=' >> space >> value >> space);
31         key            =  qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
32         value          = +qi::print;
33         space          = *qi::char_("\t ");
34         eol            =  qi::lit("\r\n") | '\r' | '\n';
35     }
36
37     qi::rule<Iterator, SectionsType()> query;
38     qi::rule<Iterator, std::pair<std::string, PairsType>()> section;
39     qi::rule<Iterator, PairsType()> sectionContent;
40     qi::rule<Iterator, std::pair<std::string, std::string>()> line;
41     qi::rule<Iterator, std::string()> key, value, sectionHeader;
42     qi::rule<Iterator> comment, space, eol;
43 };
44
45 inline
46 bool fieldExists(const SectionsType & data, const std::string & sectionName, const std::string & fieldName) throw()
47 {
48     const SectionsType::const_iterator sectionIterator(data.find(sectionName));
49     if (sectionIterator == data.end())
50         return false;
51     return sectionIterator->second.find(fieldName) != sectionIterator->second.end();
52 }
53
54 inline
55 bool fieldValue(const SectionsType & data, const std::string & sectionName, const std::string & fieldName, std::string & value) throw()
56 {
57     const SectionsType::const_iterator sectionIterator(data.find(sectionName));
58     if (sectionIterator == data.end())
59         return false;
60     const PairsType::const_iterator pairIterator(sectionIterator->second.find(fieldName));
61     if (pairIterator == sectionIterator->second.end())
62         return false;
63     value = pairIterator->second;
64     return true;
65 }
66
67 }
68
69 using SSMD::SettingsParser;
70
71 void SettingsParser::parseFile(const std::string & fileName)
72 {
73     std::ifstream in(fileName.c_str());
74     if (!in)
75         throw std::runtime_error("Can't open file");
76
77     std::string text;
78     while(!in.eof()) {
79         std::string s;
80         std::getline(in, s);
81         text += s + "\n";
82     }
83
84     std::string::iterator begin = text.begin();
85     std::string::iterator end = text.end();
86
87     SectionsType data;
88     IniGrammar<std::string::iterator> parser; //  Our parser
89
90     if (!qi::parse(begin, end, parser, data)) {
91         throw std::runtime_error("Parse error");
92     }
93
94     std::string res;
95     _settings._isDaemon = fieldExists(data, "general", "daemon");
96     _settings._isDebug = fieldExists(data, "general", "debug");
97     if (fieldValue(data, "general", "log_file", res))
98         _settings._logFile = res;
99     if (fieldValue(data, "general", "pid_file", res))
100         _settings._PIDFile = res;
101     if (fieldValue(data, "sync", "switch_interval", res))
102         _settings._switchSyncInterval = boost::lexical_cast<time_t>(res);
103     if (fieldValue(data, "sync", "info_interval", res))
104         _settings._infoSyncInterval = boost::lexical_cast<time_t>(res);
105     if (fieldValue(data, "sync", "up_profile_id", res))
106         _settings._upProfileId = boost::lexical_cast<unsigned>(res);
107     if (fieldValue(data, "sync", "down_profile_id", res))
108         _settings._downProfileId = boost::lexical_cast<unsigned>(res);
109     if (fieldValue(data, "sync", "max_acl_per_pdu", res))
110         _settings._maxACLPerPDU = boost::lexical_cast<size_t>(res);
111     if (fieldValue(data, "sync", "data_url", res))
112         _settings._dataURL = res;
113     if (fieldValue(data, "sync", "script_base", res))
114         _settings._scriptBase = res;
115     _settings._dumpScripts = fieldExists(data, "sync", "dump_scripts");
116 }