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 §ion) const; /*!< Check whether the INI file has a section with the specified name. */
void addSection(const String §ion); /*!< Add a section with the specified name to the INI file. */
void removeSection(const String §ion); /*!< 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 §ion) const; /*!< Check whether the @p section has a @p key. */
bool getKey(const String &key, const String §ion, String &value) const; /*!< Get the @p value of a @p key in a @p section. */
void setKey(const String &key, const String §ion, const String &value); /*!< Assign a @p value to a @p key in a @p section. */
void removeKey(const String &key, const String §ion); /*!< 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 §ion) 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 §ion);
const Section *getSection(const String §ion) const;
bool isValidChar(char c) const; /*!< Is given char allowed in section or key names*/
};
/** @} */
} // End of namespace Common
#endif
|