GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/configuration.h Lines: 24 38 63.2 %
Date: 2021-03-17 Branches: 29 108 26.9 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2019  The ManaPlus Developers
6
 *  Copyright (C) 2019-2021  Andrei Karas
7
 *
8
 *  This file is part of The ManaPlus Client.
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  any later version.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
#ifndef CONFIGURATION_H
25
#define CONFIGURATION_H
26
27
#include "utils/stringutils.h"
28
#ifdef ENABLE_PUGIXML
29
#include "utils/xmlwriter.h"
30
#else
31
#include "utils/xml.h"
32
#endif  // ENABLE_PUGIXML
33
34
#include "defaults.h"
35
#include "localconsts.h"
36
37
class ConfigListener;
38
class ConfigurationObject;
39
40
/**
41
 * Configuration list manager interface; responsible for
42
 * serializing/deserializing configuration choices in containers.
43
 *
44
 * \param T Type of the container elements to serialise
45
 * \param CONT Type of the container we (de)serialise
46
 */
47
template <class T, class CONT>
48
class ConfigurationListManager notfinal
49
{
50
    public:
51
1
        ConfigurationListManager()
52
        { }
53
54
        A_DELETE_COPY(ConfigurationListManager)
55
56
        /**
57
         * Writes a value into a configuration object
58
         *
59
         * \param value The value to write out
60
         * \param obj The configuation object to write to
61
         * \return obj, or otherwise NULL to indicate that this option should
62
         *         be skipped
63
         */
64
        virtual ConfigurationObject *writeConfigItem(const T &value,
65
                                                     ConfigurationObject
66
                                                     *const obj) const = 0;
67
68
        /**
69
         * Reads a value from a configuration object
70
         *
71
         * \param obj The configuration object to read from
72
         * \param container The container to insert the object to
73
         */
74
        virtual CONT readConfigItem(const ConfigurationObject *const obj,
75
                                    CONT container)
76
                                    const A_WARN_UNUSED = 0;
77
78
        virtual ~ConfigurationListManager()
79
        { }
80
};
81
82
/**
83
 * Configuration object, mapping values to names and possibly containing
84
 * lists of further configuration objects
85
 *
86
 * \ingroup CORE
87
 */
88
class ConfigurationObject notfinal
89
{
90
    friend class Configuration;
91
92
    public:
93
        A_DELETE_COPY(ConfigurationObject)
94
95
        virtual ~ConfigurationObject();
96
97
        /**
98
         * Sets an option using a string value.
99
         *
100
         * \param key Option identifier.
101
         * \param value Value.
102
         */
103
        virtual void setValue(const std::string &key,
104
                              const std::string &value);
105
106
        void deleteKey(const std::string &key);
107
108
        /**
109
         * Gets a value as string.
110
         *
111
         * \param key Option identifier.
112
         * \param deflt Default option if not there or error.
113
         */
114
        std::string getValue(const std::string &key,
115
                             const std::string &deflt) const A_WARN_UNUSED;
116
117
        int getValue(const std::string &key,
118
                     const int deflt) const A_WARN_UNUSED;
119
120
        int getValueInt(const std::string &key,
121
                        const int deflt) const A_WARN_UNUSED;
122
123
        bool getValueBool(const std::string &key,
124
                          const bool deflt) const A_WARN_UNUSED;
125
126
        unsigned getValue(const std::string &key,
127
                          const unsigned deflt) const A_WARN_UNUSED;
128
129
        double getValue(const std::string &key,
130
                        const double deflt) const A_WARN_UNUSED;
131
132
        /**
133
         * Re-sets all data in the configuration
134
         */
135
        void clear();
136
137
        /**
138
         * Serialises a container into a list of configuration options
139
         *
140
         * \param name Name of the list the elements should be stored under
141
         * \param begin Iterator start
142
         * \param end Iterator end
143
         * \param manager An object capable of serialising T items
144
         */
145
        template <class IT, class T, class CONT>
146
215
        void setList(const std::string &name, IT begin, IT end,
147
                     ConfigurationListManager<T, CONT> *manager)
148
        {
149
215
            if (!manager)
150
                return;
151
152
215
            ConfigurationObject *nextobj = new ConfigurationObject;
153
215
            deleteList(name);
154
215
            ConfigurationList *list = &(mContainerOptions[name]);
155
156
430
            for (IT it = begin; it != end; it++)
157
            {
158
                ConfigurationObject *const wrobj
159
                    = manager->writeConfigItem(*it, nextobj);
160
                if (wrobj)
161
                {   // wrote something
162
                    nextobj = new ConfigurationObject;
163
                    list->push_back(wrobj);
164
                }
165
                else
166
                {
167
                    nextobj->clear();  // you never know...
168
                }
169
            }
170
171
215
            delete nextobj;
172
        }
173
174
       /**
175
        * Serialises a container into a list of configuration options
176
        *
177
        * \param name Name of the list the elements should be read from under
178
        * \param empty Initial (empty) container to write to
179
        * \param manager An object capable of deserialising items into CONT
180
        */
181
        template<class T, class CONT>
182
        CONT getList(const std::string &name, CONT empty,
183
                     ConfigurationListManager<T, CONT> *manager)
184
        {
185
            ConfigurationList *const list = &(mContainerOptions[name]);
186
            CONT container = empty;
187
188
            if (!manager)
189
                return container;
190
191
            for (ConfigurationList::const_iterator it = list->begin();
192
                 it != list->end();
193
                 ++ it)
194
            {
195
                container = manager->readConfigItem(*it, container);
196
            }
197
198
            return container;
199
        }
200
201
#ifdef DEBUG_CONFIG
202
        void enableKeyLogging()
203
        { mLogKeys = true; }
204
205
        void setIsMain(bool b)
206
        { mIsMain = b; }
207
#endif  // DEBUG_CONFIG
208
209
    protected:
210
        ConfigurationObject();
211
212
        virtual void initFromXML(XmlNodeConstPtrConst parentNode);
213
        virtual void writeToXML(XmlTextWriterPtr writer);
214
215
        void deleteList(const std::string &name);
216
217
        typedef std::map<std::string, std::string> Options;
218
        Options mOptions;
219
220
        typedef std::list<ConfigurationObject *> ConfigurationList;
221
        std::map<std::string, ConfigurationList> mContainerOptions;
222
223
#ifdef DEBUG_CONFIG
224
        bool mLogKeys;
225
        bool mIsMain;
226
#endif  // DEBUG_CONFIG
227
};
228
229
#define valTest(num) mStatsRe##num
230
231
/**
232
 * Configuration handler for reading (and writing).
233
 *
234
 * \ingroup CORE
235
 */
236
class Configuration final : public ConfigurationObject
237
{
238
    public:
239
        Configuration();
240
241
        A_DELETE_COPY(Configuration)
242
243
        ~Configuration() override final;
244
245
        /**
246
         * Reads config file and parse all options into memory.
247
         *
248
         * @param filename path to config file
249
         * @param useResManager Make use of the resource manager.
250
         */
251
        void init(const std::string &filename,
252
                  const UseVirtFs useResManager,
253
                  const SkipError skipError);
254
255
        void reInit();
256
257
        void unload();
258
259
        DefaultsData &getDefaultValues()
260
1228
        { return mDefaultsData; }
261
262
        /**
263
         * Writes the current settings back to the config file.
264
         */
265
        void write();
266
267
        /**
268
         * Adds a listener to the listen list of the specified config option.
269
         */
270
        void addListener(const std::string &key,
271
                         ConfigListener *const listener);
272
273
        /**
274
         * Removes a listener from the listen list of the specified config
275
         * option.
276
         */
277
        void removeListener(const std::string &key,
278
                            ConfigListener *const listener);
279
280
        void removeListeners(ConfigListener *const listener);
281
282
#ifdef ENABLE_CHECKS
283
        void checkListeners(ConfigListener *const listener,
284
                            const char *const file,
285
                            const unsigned line);
286
#endif  // ENABLE_CHECKS
287
288
        void setValue(const std::string &key,
289
                      const std::string &value) override;
290
291
        void incValue(const std::string &key);
292
293
        void setSilent(const std::string &key,
294
                       const std::string &value);
295
296
1804
        inline void setValue(const std::string &key,
297
                             const char *const value)
298

7216
        { if (value != nullptr) setValue(key, std::string(value)); }
299
300
2
        inline void setSilent(const std::string &key,
301
                              const char *const value)
302

8
        { if (value != nullptr) setSilent(key, std::string(value)); }
303
304
302
        inline void setValue(const std::string &key,
305
                             const float value)
306
604
        { setValue(key, toString(value)); }
307
308
1
        inline void setValue(const std::string &key,
309
                             const double value)
310
2
        { setValue(key, toString(value)); }
311
312
19795
        inline void setValue(const std::string &key,
313
                             const int value)
314
39590
        { setValue(key, toString(value)); }
315
316
        inline void setValueInt(const std::string &key,
317
                                const int value)
318
        { setValue(key, toString(value)); }
319
320
215
        inline void setValue(const std::string &key,
321
                             const unsigned value)
322
430
        { setValue(key, toString(value)); }
323
324
        inline void setValue(const std::string &key,
325
                             const bool value)
326
















1637
        { setValue(key, value ? "1" : "0"); }
327
328
        inline void setSilent(const std::string &key,
329
                              const bool value)
330

2
        { setSilent(key, value ? "1" : "0"); }
331
332
        int resetIntValue(const std::string &key);
333
334
        bool resetBoolValue(const std::string &key);
335
336
        const std::string &getConfigPath() const noexcept2 A_WARN_UNUSED
337
        { return mConfigPath; }
338
339
        /**
340
         * returns a value corresponding to the given key.
341
         * The default value returned in based on fallbacks registry.
342
         * @see defaults.h
343
         */
344
        int getIntValue(const std::string &key) const A_WARN_UNUSED_NON_TESTS;
345
346
        float getFloatValue(const std::string &key) const
347
                            A_WARN_UNUSED_NON_TESTS;
348
349
        std::string getStringValue(const std::string &key) const
350
                                   A_WARN_UNUSED_NON_TESTS;
351
352
        bool getBoolValue(const std::string &key) const
353
                          A_WARN_UNUSED_NON_TESTS;
354
355
        std::string getDirectory() const noexcept2 A_WARN_UNUSED
356
        { return mDirectory; }
357
358
        void removeOldKeys();
359
360
        std::string getFileName() const noexcept2 A_WARN_UNUSED
361
2456
        { return mFilename; }
362
363
        void writeUpdated();
364
365
        /**
366
         * Clean up the default values member.
367
         */
368
        void cleanDefaults();
369
370
    private:
371
        typedef std::list<ConfigListener*> Listeners;
372
        typedef Listeners::iterator ListenerIterator;
373
        typedef std::map<std::string, Listeners> ListenerMap;
374
        typedef ListenerMap::iterator ListenerMapIterator;
375
        ListenerMap mListenerMap;
376
377
        // Location of config file
378
        std::string mConfigPath;
379
        /// Defaults of value for a given key
380
        DefaultsData mDefaultsData;
381
        std::string mDirectory;
382
        std::string mFilename;
383
        UseVirtFs mUseResManager;
384
        bool mUpdated;
385
};
386
387
extern Configuration branding;
388
extern Configuration config;
389
extern Configuration serverConfig;
390
extern Configuration paths;
391
extern Configuration features;
392
393
#endif  // CONFIGURATION_H