Line data Source code
1 : /*
2 : * License:
3 : * Copyright (c) 2006-2021 Made to Order Software Corp. All Rights Reserved
4 : *
5 : * https://snapwebsites.org/project/advgetopt
6 : * contact@m2osw.com
7 : *
8 : * This program is free software; you can redistribute it and/or modify
9 : * it under the terms of the GNU General Public License as published by
10 : * the Free Software Foundation; either version 2 of the License, or
11 : * (at your option) any later version.
12 : *
13 : * This program is distributed in the hope that it will be useful,
14 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : * GNU General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU General Public License along
19 : * with this program; if not, write to the Free Software Foundation, Inc.,
20 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 : *
22 : * Authors:
23 : * Alexis Wilke alexis@m2osw.com
24 : * Doug Barbieri doug@m2osw.com
25 : */
26 : #pragma once
27 :
28 : /** \file
29 : * \brief Declaration of the conf_file class used to read a configuration file.
30 : *
31 : * The library offers a way to read a configuration file parameters without
32 : * doing anything more than that. The getopt class uses it to read and verify
33 : * the parameters. It also uses it to read files of configuration options.
34 : */
35 :
36 : // C++ lib
37 : //
38 : #include <fstream>
39 : #include <functional>
40 : #include <map>
41 : #include <memory>
42 : #include <set>
43 :
44 :
45 :
46 : namespace advgetopt
47 : {
48 :
49 :
50 :
51 : enum class callback_action_t
52 : {
53 : created,
54 : updated,
55 : erased
56 : };
57 :
58 :
59 : enum class line_continuation_t
60 : {
61 : line_continuation_single_line, // no continuation support
62 : line_continuation_rfc_822, // like email/HTTP, whitespace at start of next line
63 : line_continuation_msdos, // '&' at end of line
64 : line_continuation_unix, // '\' at end of line
65 : line_continuation_fortran, // '&' at start of next line
66 : line_continuation_semicolon // ';' ends the _line_
67 : };
68 :
69 :
70 : typedef std::uint_fast16_t assignment_operator_t;
71 :
72 : constexpr assignment_operator_t ASSIGNMENT_OPERATOR_EQUAL = 0x0001; // a = b
73 : constexpr assignment_operator_t ASSIGNMENT_OPERATOR_COLON = 0x0002; // a: b
74 : constexpr assignment_operator_t ASSIGNMENT_OPERATOR_SPACE = 0x0004; // a b
75 :
76 : constexpr assignment_operator_t ASSIGNMENT_OPERATOR_MASK = 0x0007;
77 :
78 :
79 : typedef std::uint_fast16_t comment_t;
80 :
81 : constexpr comment_t COMMENT_NONE = 0x0000; // no support for comments
82 : constexpr comment_t COMMENT_INI = 0x0001; // ; comment
83 : constexpr comment_t COMMENT_SHELL = 0x0002; // # comment
84 : constexpr comment_t COMMENT_CPP = 0x0004; // // comment
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 28829 : class conf_file_setup
103 : {
104 : public:
105 : conf_file_setup(
106 : std::string const & filename
107 : , line_continuation_t line_continuation = line_continuation_t::line_continuation_unix
108 : , assignment_operator_t assignment_operator = ASSIGNMENT_OPERATOR_EQUAL
109 : , comment_t comment = COMMENT_INI | COMMENT_SHELL
110 : , section_operator_t section_operator = SECTION_OPERATOR_INI_FILE);
111 :
112 : bool is_valid() const;
113 : std::string const & get_original_filename() const;
114 : std::string const & get_filename() const;
115 : line_continuation_t get_line_continuation() const;
116 : assignment_operator_t get_assignment_operator() const;
117 : comment_t get_comment() const;
118 : section_operator_t get_section_operator() const;
119 : std::string get_config_url() const;
120 :
121 : private:
122 : std::string f_original_filename = std::string();
123 : std::string f_filename = std::string();
124 : line_continuation_t f_line_continuation = line_continuation_t::line_continuation_unix;
125 : assignment_operator_t f_assignment_operator = ASSIGNMENT_OPERATOR_EQUAL;
126 : comment_t f_comment = COMMENT_INI | COMMENT_SHELL;
127 : section_operator_t f_section_operator = SECTION_OPERATOR_INI_FILE;
128 : mutable std::string f_url = std::string();
129 : };
130 :
131 :
132 300 : class conf_file
133 : : public std::enable_shared_from_this<conf_file>
134 : {
135 : public:
136 : typedef std::shared_ptr<conf_file> pointer_t;
137 : typedef std::set<std::string> sections_t;
138 : typedef std::map<std::string, std::string> parameters_t;
139 : typedef std::function<void(
140 : pointer_t conf_file
141 : , callback_action_t action
142 : , std::string const & parameter_name
143 : , std::string const & value)> callback_t;
144 : typedef int callback_id_t;
145 :
146 : static pointer_t get_conf_file(conf_file_setup const & setup);
147 :
148 : bool save_configuration(bool create_backup = true);
149 :
150 : conf_file_setup const & get_setup() const;
151 : callback_id_t add_callback(
152 : callback_t const & c
153 : , std::string const & parameter_name = std::string());
154 : void remove_callback(callback_id_t id);
155 :
156 : int get_errno() const;
157 :
158 : sections_t get_sections() const;
159 : parameters_t get_parameters() const;
160 : bool has_parameter(std::string name) const;
161 : std::string get_parameter(std::string name) const;
162 : bool set_parameter(std::string section, std::string name, std::string const & value);
163 : bool erase_parameter(std::string name);
164 : bool was_modified() const;
165 :
166 : bool is_assignment_operator(int c) const;
167 : bool is_comment(char const * s) const;
168 :
169 : private:
170 16 : struct callback_entry_t
171 : {
172 2 : callback_entry_t(
173 : callback_id_t id
174 : , callback_t const & c
175 : , std::string const & name)
176 2 : : f_id(id)
177 : , f_callback(c)
178 2 : , f_parameter_name(name)
179 : {
180 2 : }
181 :
182 : callback_id_t f_id = 0;
183 : callback_t f_callback = callback_t();
184 : std::string f_parameter_name = std::string();
185 : };
186 : typedef std::vector<callback_entry_t>
187 : callback_vector_t;
188 :
189 : conf_file(conf_file_setup const & setup);
190 :
191 : int getc(std::ifstream & stream);
192 : void ungetc(int c);
193 : bool get_line(std::ifstream & stream, std::string & line);
194 : void read_configuration();
195 : void value_changed(
196 : callback_action_t action
197 : , std::string const & parameter_name
198 : , std::string const & value);
199 :
200 : conf_file_setup const f_setup;
201 :
202 : int f_unget_char = '\0';
203 : int f_line = 0;
204 : int f_errno = 0;
205 : bool f_reading = false;
206 :
207 : bool f_modified = false;
208 : sections_t f_sections = sections_t();
209 : parameters_t f_parameters = parameters_t();
210 : callback_vector_t f_callbacks = callback_vector_t();
211 : callback_id_t f_next_callback_id = 0;
212 : };
213 :
214 :
215 : bool iswspace(int c);
216 :
217 :
218 : } // namespace advgetopt
219 : // vim: ts=4 sw=4 et
|