source: nscp/include/settings/settings_ini.hpp @ 3eedfa6

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

fixed so we have a settings subsytem (ini files) which work on linux

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