xdrpp
RFC4506 XDR compiler and message library
iniparse.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 
3 /** \file iniparse.h
4  * \brief Parser for .ini style files.
5  *
6  * Accepts the following escape sequences in property values: \c '\\r'
7  * \c '\\n' \c '\\s' (for space) and \c '\\\\'. An example of how to
8  * use the parser is this:
9  * \code
10  * string foo, bar;
11  * bool baz;
12  *
13  * IniActions a;
14  * a["group1"].add("foo", &foo, "baz", &baz);
15  * a["group2"].add("bar", &bar);
16  *
17  * if (!ini_parse(a, "config.ini"))
18  * exit (1);
19  * \endcode
20  *
21  * This will parse an ini file like this:
22  *
23  * \code{.txt}
24  * [group1]
25  * foo = some string
26  * baz = true
27  * [group2]
28  * bar = \s a string starting with three spaces
29  * \endcode
30  */
31 
32 #ifndef _INIPARSE_H_
33 #define _INIPARSE_H_ 1
34 
35 #include <cstdint>
36 #include <functional>
37 #include <iostream>
38 #include <memory>
39 #include <stdexcept>
40 #include <string>
41 #include <unordered_map>
42 #include <vector>
43 
44 namespace xdr {
45 
46 using std::string;
47 
48 //! \cond
49 #define FROM_STRING(T) void from_string(const string &, T *);
50 FROM_STRING(string)
51 FROM_STRING(bool)
52 FROM_STRING(int)
53 FROM_STRING(long)
54 FROM_STRING(long long)
55 FROM_STRING(unsigned char)
56 FROM_STRING(unsigned short)
57 FROM_STRING(unsigned int)
58 FROM_STRING(unsigned long)
59 FROM_STRING(unsigned long long)
60 FROM_STRING(float)
61 FROM_STRING(double)
62 FROM_STRING(long double)
63 #undef FROM_STRING
64 //! \endcond
65 
66 //! Contents of a specific property.
67 class IniLine {
68  mutable bool error_ {false};
69 public:
70  int lineno_ {0};
71  string file_;
72 
73  string group_; //!< Name of the group containing property
74  string key_; //!< Key of the property.
75  string value_; //!< Value of the property.
76  //! Raw value of the property (with escape sequences unexpanded).
77  string rawvalue_;
78 
79  //! Print a message to `cerr` with the file ane line number prefixed.
80  std::ostream &warn() const {
81  return std::cerr << file_ << ':' << lineno_ << ": ";
82  }
83  //! Like IniLine::warn, but also sets the error flag to indicate failure.
84  std::ostream &fail() const { error_ = true; return warn(); }
85  //! Returns `true` if there has been a parsing error in the ini file.
86  bool error() const { return error_; }
87 
88  //! Transform the line into a vector of words.
89  std::vector<string> argv() const;
90  /** \brief Convert the line into a value of a type for which a
91  *`from_string` function has been defined. */
92  template<typename T> void convert(T *rp) const { from_string(value_, rp); }
93 };
94 
95 //! Set of callbacks to run when parsing properties within a particular group.
96 struct IniGroup {
97  using cb_t = std::function<void(const IniLine &li)>;
98  std::unordered_map<string, cb_t> cbs_;
99 
100  IniGroup &operator=(const IniGroup &&) = delete;
101  void parse(const IniLine &li);
102 
103  //! Add an explicit callback for a particular key.
104  IniGroup &add(const string &key, cb_t &&cb) {
105  if (!cbs_.emplace(key, std::move(cb)).second)
106  throw std::runtime_error("IniGroup::add: duplicate key " + key);
107  return *this;
108  }
109  IniGroup &add(const string &key, const cb_t &cb) {
110  if (!cbs_.emplace(key, cb).second)
111  throw std::runtime_error("IniGroup::add: duplicate key " + key);
112  return *this;
113  }
114  //! Construct a callback that places the parced value in `valp`.
115  template<typename T> IniGroup &add(const string &key, T *valp) {
116  add(key, [valp](const IniLine &li) { li.convert(valp); });
117  return *this;
118  }
119  //! A convenience allowing `add(field, callback, field, callback...)`.
120  template<typename T, typename ...Rest> IniGroup &
121  add(const string &key, T &&valp, const string &key2, Rest...rest) {
122  add(key, std::forward<T>(valp));
123  return add(key2, rest...);
124  }
125 };
126 
127 //! Holds the actions to execute on various properties in the ini file.
128 using IniActions = std::unordered_map<string, IniGroup>;
129 
130 /** \brief Run the ini parser.
131  *
132  * Afterwards ``a.error()`` will tell you if there was an error.
133  */
134 void ini_runparse(IniActions &a, IniLine &st, std::istream &s);
135 /** \brief Run the parser on a file.
136  *
137  * A simple wrapper around fba::ini_runparse that opens the file.
138  */
139 bool ini_parse(IniActions &a, string file);
140 
141 }
142 
143 #endif /* !_INIPARSE_H_ */
std::unordered_map< string, IniGroup > IniActions
Holds the actions to execute on various properties in the ini file.
Definition: iniparse.h:128
Most of the xdrpp library is encapsulated in the xdr namespace.
Definition: arpc.cc:4
string value_
Value of the property.
Definition: iniparse.h:75
IniGroup & add(const string &key, T &&valp, const string &key2, Rest...rest)
A convenience allowing add(field, callback, field, callback...).
Definition: iniparse.h:121
void ini_runparse(IniActions &a, IniLine &st, std::istream &s)
Run the ini parser.
Definition: iniparse.cc:171
bool ini_parse(IniActions &a, string file)
Run the parser on a file.
Definition: iniparse.cc:207
string rawvalue_
Raw value of the property (with escape sequences unexpanded).
Definition: iniparse.h:77
string group_
Name of the group containing property.
Definition: iniparse.h:73
void convert(T *rp) const
Convert the line into a value of a type for which a from_string function has been defined...
Definition: iniparse.h:92
bool error() const
Returns true if there has been a parsing error in the ini file.
Definition: iniparse.h:86
string key_
Key of the property.
Definition: iniparse.h:74
Set of callbacks to run when parsing properties within a particular group.
Definition: iniparse.h:96
IniGroup & add(const string &key, T *valp)
Construct a callback that places the parced value in valp.
Definition: iniparse.h:115
Contents of a specific property.
Definition: iniparse.h:67
std::ostream & warn() const
Print a message to cerr with the file ane line number prefixed.
Definition: iniparse.h:80
std::ostream & fail() const
Like IniLine::warn, but also sets the error flag to indicate failure.
Definition: iniparse.h:84
IniGroup & add(const string &key, cb_t &&cb)
Add an explicit callback for a particular key.
Definition: iniparse.h:104
std::vector< string > argv() const
Transform the line into a vector of words.
Definition: iniparse.cc:70