Line data Source code
1 : // Copyright (c) 2006-2022 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/advgetopt
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 : #pragma once
20 :
21 : /** \file
22 : * \brief Declaration of the conf_file class used to read a configuration file.
23 : *
24 : * The library offers a way to read a configuration file parameters without
25 : * doing anything more than that. The getopt class uses it to read and verify
26 : * the parameters. It also uses it to read files of configuration options.
27 : */
28 :
29 : // self
30 : //
31 : #include "advgetopt/variables.h"
32 :
33 :
34 : // C++ lib
35 : //
36 : #include <fstream>
37 : #include <functional>
38 : #include <map>
39 : #include <memory>
40 : #include <set>
41 :
42 :
43 :
44 : namespace advgetopt
45 : {
46 :
47 :
48 :
49 : enum class callback_action_t
50 : {
51 : created,
52 : updated,
53 : erased
54 : };
55 :
56 :
57 : enum class line_continuation_t
58 : {
59 : line_continuation_single_line, // no continuation support
60 : line_continuation_rfc_822, // like email/HTTP, whitespace at start of next line
61 : line_continuation_msdos, // '&' at end of line
62 : line_continuation_unix, // '\' at end of line
63 : line_continuation_fortran, // '&' at start of next line
64 : line_continuation_semicolon // ';' ends the _line_
65 : };
66 :
67 :
68 : typedef std::uint_fast16_t assignment_operator_t;
69 :
70 : constexpr assignment_operator_t ASSIGNMENT_OPERATOR_EQUAL = 0x0001; // a = b
71 : constexpr assignment_operator_t ASSIGNMENT_OPERATOR_COLON = 0x0002; // a: b
72 : constexpr assignment_operator_t ASSIGNMENT_OPERATOR_SPACE = 0x0004; // a b
73 :
74 : constexpr assignment_operator_t ASSIGNMENT_OPERATOR_MASK = 0x0007;
75 :
76 :
77 : typedef std::uint_fast16_t comment_t;
78 :
79 : constexpr comment_t COMMENT_NONE = 0x0000; // no support for comments
80 : constexpr comment_t COMMENT_INI = 0x0001; // ; comment
81 : constexpr comment_t COMMENT_SHELL = 0x0002; // # comment
82 : constexpr comment_t COMMENT_CPP = 0x0004; // // comment
83 :
84 : constexpr comment_t COMMENT_SAVE = 0x8000; // save comments along parameters
85 :
86 : constexpr comment_t COMMENT_MASK = 0x0007;
87 :
88 :
89 : typedef std::uint_fast16_t section_operator_t;
90 :
91 : constexpr section_operator_t SECTION_OPERATOR_NONE = 0x0000; // no support
92 : constexpr section_operator_t SECTION_OPERATOR_C = 0x0001; // a.b
93 : constexpr section_operator_t SECTION_OPERATOR_CPP = 0x0002; // a::b
94 : constexpr section_operator_t SECTION_OPERATOR_BLOCK = 0x0004; // a { ... }
95 : constexpr section_operator_t SECTION_OPERATOR_INI_FILE = 0x0008; // [a]
96 :
97 : constexpr section_operator_t SECTION_OPERATOR_ONE_SECTION = 0x8000; // accept at most 1 section
98 :
99 : constexpr section_operator_t SECTION_OPERATOR_MASK = 0x000F;
100 :
101 :
102 : typedef std::uint_fast16_t name_separator_t;
103 :
104 : constexpr name_separator_t NAME_SEPARATOR_UNDERSCORES = 0x0001; // output underscore ('_') instead of dashes
105 : constexpr name_separator_t NAME_SEPARATOR_DASHES = 0x0002; // output dashes ('-')
106 :
107 :
108 28927 : class conf_file_setup
109 : {
110 : public:
111 : conf_file_setup(
112 : std::string const & filename
113 : , line_continuation_t line_continuation = line_continuation_t::line_continuation_unix
114 : , assignment_operator_t assignment_operator = ASSIGNMENT_OPERATOR_EQUAL
115 : , comment_t comment = COMMENT_INI | COMMENT_SHELL
116 : , section_operator_t section_operator = SECTION_OPERATOR_INI_FILE
117 : , name_separator_t name_separator = NAME_SEPARATOR_UNDERSCORES);
118 :
119 : bool is_valid() const;
120 : std::string const & get_original_filename() const;
121 : std::string const & get_filename() const;
122 : line_continuation_t get_line_continuation() const;
123 : assignment_operator_t get_assignment_operator() const;
124 : comment_t get_comment() const;
125 : section_operator_t get_section_operator() const;
126 : std::string get_config_url() const;
127 : name_separator_t get_name_separator() const;
128 :
129 : private:
130 : std::string f_original_filename = std::string();
131 : std::string f_filename = std::string();
132 : line_continuation_t f_line_continuation = line_continuation_t::line_continuation_unix;
133 : assignment_operator_t f_assignment_operator = ASSIGNMENT_OPERATOR_EQUAL;
134 : comment_t f_comment = COMMENT_INI | COMMENT_SHELL;
135 : section_operator_t f_section_operator = SECTION_OPERATOR_INI_FILE;
136 : mutable std::string f_url = std::string();
137 : name_separator_t f_name_separator = NAME_SEPARATOR_UNDERSCORES;
138 : };
139 :
140 :
141 617 : class parameter_value
142 : {
143 : public:
144 : parameter_value();
145 : parameter_value(parameter_value const & rhs);
146 : parameter_value(std::string const & value);
147 :
148 : parameter_value & operator = (parameter_value const & rhs);
149 : parameter_value & operator = (std::string const & value);
150 : operator std::string () const;
151 :
152 : void set_value(std::string const & value);
153 : void set_comment(std::string const & comment);
154 :
155 : std::string const & get_value() const;
156 : std::string const & get_comment() const;
157 :
158 : private:
159 : std::string f_value = std::string();
160 : std::string f_comment = std::string();
161 : };
162 :
163 :
164 347 : class conf_file
165 : : public std::enable_shared_from_this<conf_file>
166 : {
167 : public:
168 : typedef std::shared_ptr<conf_file> pointer_t;
169 : typedef std::set<std::string> sections_t;
170 : typedef std::map<std::string, parameter_value> parameters_t;
171 : typedef std::function<void(
172 : pointer_t conf_file
173 : , callback_action_t action
174 : , std::string const & parameter_name
175 : , std::string const & value)> callback_t;
176 : typedef int callback_id_t;
177 :
178 : static pointer_t get_conf_file(conf_file_setup const & setup);
179 :
180 : bool save_configuration(
181 : std::string backup_extension = std::string(".bak")
182 : , bool replace_backup = false
183 : , bool prepend_warning = true
184 : , std::string output_filename = std::string());
185 :
186 : conf_file_setup const & get_setup() const;
187 : callback_id_t add_callback(
188 : callback_t const & c
189 : , std::string const & parameter_name = std::string());
190 : void remove_callback(callback_id_t id);
191 :
192 : int get_errno() const;
193 :
194 : int section_to_variables(
195 : std::string const & section_name
196 : , variables::pointer_t var);
197 : void set_variables(variables::pointer_t variables);
198 : variables::pointer_t get_variables() const;
199 : sections_t get_sections() const;
200 : parameters_t get_parameters() const;
201 : bool has_parameter(std::string name) const;
202 : std::string get_parameter(std::string name) const;
203 : bool set_parameter(
204 : std::string section
205 : , std::string name
206 : , std::string const & value
207 : , std::string const & comment = std::string());
208 : bool erase_parameter(std::string name);
209 : bool was_modified() const;
210 :
211 : bool is_assignment_operator(int c) const;
212 : bool is_comment(char const * s) const;
213 :
214 : private:
215 16 : struct callback_entry_t
216 : {
217 2 : callback_entry_t(
218 : callback_id_t id
219 : , callback_t const & c
220 : , std::string const & name)
221 2 : : f_id(id)
222 : , f_callback(c)
223 2 : , f_parameter_name(name)
224 : {
225 2 : }
226 :
227 : callback_id_t f_id = 0;
228 : callback_t f_callback = callback_t();
229 : std::string f_parameter_name = std::string();
230 : };
231 : typedef std::vector<callback_entry_t>
232 : callback_vector_t;
233 :
234 : conf_file(conf_file_setup const & setup);
235 :
236 : int getc(std::ifstream & stream);
237 : void ungetc(int c);
238 : bool get_line(std::ifstream & stream, std::string & line);
239 : void read_configuration();
240 : void value_changed(
241 : callback_action_t action
242 : , std::string const & parameter_name
243 : , std::string const & value);
244 :
245 : conf_file_setup const f_setup;
246 :
247 : int f_unget_char = '\0';
248 : int f_line = 0;
249 : int f_errno = 0;
250 : bool f_reading = false;
251 :
252 : bool f_modified = false;
253 : sections_t f_sections = sections_t();
254 : variables::pointer_t f_variables = variables::pointer_t();
255 : parameters_t f_parameters = parameters_t();
256 : callback_vector_t f_callbacks = callback_vector_t();
257 : callback_id_t f_next_callback_id = 0;
258 : };
259 :
260 :
261 : bool iswspace(int c);
262 :
263 :
264 : } // namespace advgetopt
265 : // vim: ts=4 sw=4 et
|