source: nscp/include/settings/settings_ini.hpp @ d05c3f0

0.4.00.4.10.4.2
Last change on this file since d05c3f0 was d05c3f0, checked in by Michael Medin <michael@…>, 4 years ago

Next major "milestone" we now have one working plugin (CheckHelpers) which loads and works both on Linux and Windows.
This is (as always) a broken build which many many features disabled and non functional...

  • Property mode set to 100644
File size: 8.2 KB
Line 
1#pragma once
2
3#include <string>
4#include <map>
5
6#include <boost/filesystem/path.hpp>
7#include <boost/filesystem/operations.hpp>
8
9#include <settings/Settings.h>
10#include <simpleini/simpleini.h>
11#include <error.hpp>
12
13namespace Settings {
14        class INISettings : public Settings::SettingsInterfaceImpl {
15        private:
16                boost::filesystem::wpath filename_;
17                bool is_loaded_;
18                CSimpleIni ini;
19
20        public:
21                INISettings(Settings::SettingsCore *core, std::wstring context) : ini(false, false, false), is_loaded_(false), Settings::SettingsInterfaceImpl(core, context) {}
22                //////////////////////////////////////////////////////////////////////////
23                /// Create a new settings interface of "this kind"
24                ///
25                /// @param context the context to use
26                /// @return the newly created settings interface
27                ///
28                /// @author mickem
29                virtual SettingsInterfaceImpl* create_new_context(std::wstring context) {
30                        return new INISettings(get_core(), context);
31                }
32                //////////////////////////////////////////////////////////////////////////
33                /// Get a string value if it does not exist exception will be thrown
34                ///
35                /// @param path the path to look up
36                /// @param key the key to lookup
37                /// @return the string value
38                ///
39                /// @author mickem
40                virtual std::wstring get_real_string(SettingsCore::key_path_type key) {
41                        load_data();
42                        const wchar_t *val = ini.GetValue(key.first.c_str(), key.second.c_str(), NULL);
43                        if (val == NULL)
44                                throw KeyNotFoundException(key);
45                        return val;
46                }
47                //////////////////////////////////////////////////////////////////////////
48                /// Get an integer value if it does not exist exception will be thrown
49                ///
50                /// @param path the path to look up
51                /// @param key the key to lookup
52                /// @return the int value
53                ///
54                /// @author mickem
55                virtual int get_real_int(SettingsCore::key_path_type key) {
56                        std::wstring str = get_real_string(key);
57                        return strEx::stoi(str);
58                }
59                //////////////////////////////////////////////////////////////////////////
60                /// Get a boolean value if it does not exist exception will be thrown
61                ///
62                /// @param path the path to look up
63                /// @param key the key to lookup
64                /// @return the boolean value
65                ///
66                /// @author mickem
67                virtual bool get_real_bool(SettingsCore::key_path_type key) {
68                        std::wstring str = get_real_string(key);
69                        return SettingsInterfaceImpl::string_to_bool(str);
70                }
71                //////////////////////////////////////////////////////////////////////////
72                /// Check if a key exists
73                ///
74                /// @param path the path to look up
75                /// @param key the key to lookup
76                /// @return true/false if the key exists.
77                ///
78                /// @author mickem
79                virtual bool has_real_key(SettingsCore::key_path_type key) {
80                        return false;
81                }
82                //////////////////////////////////////////////////////////////////////////
83                /// Get the type this settings store represent.
84                ///
85                /// @return the type of settings store
86                ///
87                /// @author mickem
88                virtual SettingsCore::settings_type get_type() {
89                        return SettingsCore::ini_file;
90                }
91                //////////////////////////////////////////////////////////////////////////
92                /// Is this the active settings store
93                ///
94                /// @return
95                ///
96                /// @author mickem
97                virtual bool is_active() {
98                        return true;
99                }
100                //////////////////////////////////////////////////////////////////////////
101                /// Write a value to the resulting context.
102                ///
103                /// @param key The key to write to
104                /// @param value The value to write
105                ///
106                /// @author mickem
107                virtual void set_real_value(SettingsCore::key_path_type key, conainer value) {
108                        try {
109                                const SettingsCore::key_description desc = get_core()->get_registred_key(key.first, key.second);
110                                std::wstring comment = _T("; ");
111                                if (!desc.title.empty())
112                                        comment += desc.title + _T(" - ");
113                                if (!desc.description.empty())
114                                        comment += desc.description;
115                                strEx::replace(comment, _T("\n"), _T(" "));
116                                get_core()->get_logger()->quick_debug(_T("saving: ") + key.first + _T("//") + key.second);
117                                ini.SetValue(key.first.c_str(), key.second.c_str(), value.get_string().c_str(), comment.c_str());
118                        } catch (KeyNotFoundException e) {
119                                ini.SetValue(key.first.c_str(), key.second.c_str(), value.get_string().c_str());
120                        } catch (SettingsException e) {
121                                get_core()->get_logger()->err(__FILEW__, __LINE__, std::wstring(_T("Failed to write key: ") + e.getError()));
122                        } catch (...) {
123                                get_core()->get_logger()->err(__FILEW__, __LINE__, std::wstring(_T("Unknown filure when writing key: ") + key.first + _T(".") + key.second));
124                        }
125                }
126                //////////////////////////////////////////////////////////////////////////
127                /// Get all (sub) sections (given a path).
128                /// If the path is empty all root sections will be returned
129                ///
130                /// @param path The path to get sections from (if empty root sections will be returned)
131                /// @param list The list to append nodes to
132                /// @return a list of sections
133                ///
134                /// @author mickem
135                virtual void get_real_sections(std::wstring path, string_list &list) {
136                        get_core()->get_logger()->debug(__FILEW__, __LINE__, std::wstring(_T("Get sections for: ")) + path);
137                        CSimpleIni::TNamesDepend lst;
138                        ini.GetAllSections(lst);
139                        if (path.empty()) {
140                                for (CSimpleIni::TNamesDepend::const_iterator cit = lst.begin(); cit != lst.end(); ++cit) {
141                                        std::wstring mapped = (*cit).pItem;
142                                        if (mapped.length() > 1) {
143                                                std::wstring::size_type pos = mapped.find(L'/', 1);
144                                                if (pos != std::wstring::npos)
145                                                        mapped = mapped.substr(0,pos);
146                                        }
147                                        list.push_back(mapped);
148                                }
149                        } else {
150                                for (CSimpleIni::TNamesDepend::const_iterator cit = lst.begin(); cit != lst.end(); ++cit) {
151                                        std::wstring mapped = (*cit).pItem;
152                                        std::wstring::size_type mapped_len = mapped.length();
153                                        std::wstring::size_type path_len = path.length();
154                                        if (mapped_len > path_len+1 && mapped.substr(0,path_len) == path) {
155                                                std::wstring::size_type pos = mapped.find(L'/', path_len+1);
156                                                if (pos == std::wstring::npos)
157                                                        mapped = mapped.substr(path_len+1);
158                                                else
159                                                        mapped = mapped.substr(path_len+1, pos-path_len-1);
160                                                list.push_back(mapped);
161                                        }
162                                }
163                        }
164                }
165                //////////////////////////////////////////////////////////////////////////
166                /// Get all keys given a path/section.
167                /// If the path is empty all root sections will be returned
168                ///
169                /// @param path The path to get sections from (if empty root sections will be returned)
170                /// @param list The list to append nodes to
171                /// @return a list of sections
172                ///
173                /// @author mickem
174                virtual void get_real_keys(std::wstring path, string_list &list) {
175                        load_data();
176                        get_core()->get_logger()->debug(__FILEW__, __LINE__, std::wstring(_T("Looking for: ")) + path);
177                        CSimpleIni::TNamesDepend lst;
178                        ini.GetAllKeys(path.c_str(), lst);
179                        for (CSimpleIni::TNamesDepend::const_iterator cit = lst.begin(); cit != lst.end(); ++cit) {
180                                list.push_back((*cit).pItem);
181                        }
182                }
183                //////////////////////////////////////////////////////////////////////////
184                /// Save the settings store
185                ///
186                /// @author mickem
187                virtual void save() {
188                        SettingsInterfaceImpl::save();
189                        SI_Error rc = ini.SaveFile(get_file_name().string().c_str());
190                        if (rc < 0)
191                                throw_SI_error(rc, _T("Failed to save file"));
192                }
193                virtual SettingsCore::key_type get_key_type(std::wstring path, std::wstring key) {
194                        return SettingsCore::key_string;
195                }
196        private:
197                void load_data() {
198                        if (is_loaded_)
199                                return;
200                        if (!file_exists()) {
201                                is_loaded_ = true;
202                                return;
203                        }
204                        SI_Error rc = ini.LoadFile(get_file_name().string().c_str());
205                        if (rc < 0)
206                                throw_SI_error(rc, _T("Failed to load file"));
207                        is_loaded_ = true;
208                }
209                void throw_SI_error(SI_Error err, std::wstring msg) {
210                        std::wstring error_str = _T("unknown error");
211                        if (err == SI_NOMEM)
212                                error_str = _T("Out of memmory");
213                        if (err == SI_FAIL)
214                                error_str = _T("General failure");
215                        if (err == SI_FILE)
216                                error_str = _T("I/O error: ") + error::lookup::last_error();
217                        throw SettingsException(msg + _T(": ") + get_context() + _T(" - ") + error_str);
218                }
219                boost::filesystem::wpath get_file_name() {
220                        if (filename_.empty()) {
221                                filename_ = get_core()->get_base() / boost::filesystem::wpath(get_core()->get_boot_string(get_context(), _T("file"), _T("nsclient.ini")));
222                                get_core()->get_logger()->debug(__FILEW__, __LINE__, _T("Reading INI settings from: ") + filename_.string());
223                        }
224                        return filename_;
225                }
226                bool file_exists() {
227                        return boost::filesystem::is_regular(get_file_name());
228                }
229        };
230}
Note: See TracBrowser for help on using the repository browser.