File: ini-file.h

package info (click to toggle)
scummvm 2.9.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 450,580 kB
  • sloc: cpp: 4,299,825; asm: 28,322; python: 12,901; sh: 11,302; java: 9,289; xml: 7,895; perl: 2,639; ansic: 2,465; yacc: 1,670; javascript: 1,020; makefile: 933; lex: 578; awk: 275; objc: 82; sed: 11; php: 1
file content (165 lines) | stat: -rw-r--r-- 6,785 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifndef COMMON_INI_FILE_H
#define COMMON_INI_FILE_H

#include "common/hash-str.h"
#include "common/list.h"
#include "common/path.h"
#include "common/str.h"

namespace Common {

/**
 * @defgroup common_ini_file INI files
 * @ingroup common
 *
 * @brief API for operations on INI configuration files.
 *
 *
 * @{
 */

class SeekableReadStream;
class WriteStream;

/**
 * This class allows for reading and writing INI-style config files.
 *
 * Lines starting with a '#' are ignored (i.e. treated as comments).
 * Some effort is made to preserve comments, though.
 *
 * This class makes no attempts to provide fast access to key/value pairs.
 * In particular, it stores all sections and key/value pairs in lists, not
 * in dictionaries/maps. This makes it very easy to read/write the data
 * from/to files, but of course is not appropriate for fast access.
 * The main reason is that this class is indeed geared toward doing precisely
 * that.
 */
class INIFile {
public:
	struct KeyValue {
		String key;     /*!< Key of the configuration entry, whitespace trimmed. */
		String value;   /*!< Value of the configuration entry, whitespace trimmed. */
		String comment; /*!< Comment within an INI file, including #s and newlines. */
	};

	typedef List<KeyValue> SectionKeyList; /*!< A list of all key/value pairs in this section. */

	/** A section in an INI file.
	 *
	 * Corresponds to the following:
	 * @code
	 * [mySection]
	 * key=value
	 * @endcode
	 * Comments are also stored, for convenience of users who prefer to edit
	 * INI files manually.
	 */
	struct Section {
		String name;         /*!< Name of the section, whitespace trimmed. */
		List<KeyValue> keys; /*!< List of all keys in this section. */
		String comment;      /*!< Comment within the section, including #s and newlines. */

		bool hasKey(const String &key) const; /*!< Check whether the section has a @p key. */
		const KeyValue* getKey(const String &key) const; /*!< Get the value assigned to a @p key. */
		void setKey(const String &key, const String &value); /*!< Assign a @p value to a @p key. */
		void removeKey(const String &key); /*!< Remove a @p key from this section. */
		const SectionKeyList getKeys() const { return keys; } /*!< Get a list of all keys in the section. */
	};

	typedef List<Section> SectionList; /*!< A list of all sections in this INI file. */

public:
	INIFile();
	~INIFile() {}

	// TODO: Maybe add a copy constructor etc.?

	/**
	 * Check whether the given string is a valid section or key name.
	 * For that, it must only consist of letters, numbers, dashes, and
	 * underscores. In particular, whitespace and "#", "=", "[", "]"
	 * are not valid.
	 */
	bool isValidName(const String &name) const;

	/** Reset everything stored in this INI file. */
	void	clear();

	bool	loadFromFile(const Path &filename); /*!< Load configuration from a file. */
	bool	loadFromFileOrDataFork(const Path &filename); /*!< Load configuration from a file in MacBinary format. */
	bool	loadFromSaveFile(const String &filename); /*!< Load configuration from a save file. */
	bool	loadFromStream(SeekableReadStream &stream); /*!< Load configuration from a @ref SeekableReadStream. */
	bool	saveToFile(const Path &filename); /*!< Save the current configuration to a file. */
	bool	saveToSaveFile(const String &filename); /*!< Save the current configuration to a save file. */
	bool	saveToStream(WriteStream &stream); /*!< Save the current configuration to a @ref WriteStream. */

	bool	hasSection(const String &section) const; /*!< Check whether the INI file has a section with the specified name. */
	void	addSection(const String &section); /*!< Add a section with the specified name to the INI file. */
	void	removeSection(const String &section); /*!< Remove the @p section from the INI file. */
	void	renameSection(const String &oldName, const String &newName); /*!< Rename the INI file from @p oldName to @p newName. */

	void	setDefaultSectionName(const String &name); /*!< Set initial section name for section-less INI files. */

	bool	hasKey(const String &key, const String &section) const; /*!< Check whether the @p section has a @p key. */
	bool	getKey(const String &key, const String &section, String &value) const; /*!< Get the @p value of a @p key in a @p section. */
	void	setKey(const String &key, const String &section, const String &value); /*!< Assign a @p value to a @p key in a @p section. */
	void	removeKey(const String &key, const String &section); /*!< Remove a @p key from this @p section. */

	const SectionList getSections() const { return _sections; } /*!< Get a list of sections in this INI file. */
	const SectionKeyList getKeys(const String &section) const; /*!< Get a list of keys in a @p section. */

	void listKeyValues(StringMap &kv); /*!< Get a list of all key/value pairs in this INI file. */

	void allowNonEnglishCharacters(); /*!< Allow non-English characters in this INI file. */
	void suppressValuelessLineWarning(); /*!< Disable warnings for lines that contain only keys. */

	/**
	 * Requires that every key/value line have a delimiter character.
	 * Otherwise, lines that don't contain a delimiter are interpreted as
	 * if the entire line is a key with an empty value. This can cause
	 * unexpected junk lines to reach engines. (bug #13920)
	 *
	 * It may be better if instead this were the default behavior for
	 * clients to disable if needed, but first we would need to identify
	 * everything that depends on the current behavior.
	 */
	void requireKeyValueDelimiter();

private:
	String		_defaultSectionName;
	SectionList _sections;
	bool _allowNonEnglishCharacters;
	bool _suppressValuelessLineWarning;
	bool _requireKeyValueDelimiter;

	Section *getSection(const String &section);
	const Section *getSection(const String &section) const;
	bool isValidChar(char c) const; /*!< Is given char allowed in section or key names*/
};

/** @} */

} // End of namespace Common

#endif