summaryrefslogtreecommitdiffstats
path: root/src/IniFile.h
blob: 216cd7eff3d757e256f65c9e94a60e2dac30a347 (plain) (blame)
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
// IniFile.cpp:  Implementation of the CIniFile class.
// Written by:   Adam Clauss
// Email: cabadam@tamu.edu
// You may use this class / code as you wish in your programs.  Feel free to distribute it, and
// email suggested changes to me.
//
// Rewritten by: Shane Hill
// Date:         2001-08-21
// Email:        Shane.Hill@dsto.defence.gov.au
// Reason:       Remove dependancy on MFC. Code should compile on any
//               platform. Tested on Windows / Linux / Irix
////////////////////////////////////////////////////////////////////////////////

/*
!! MODIFIED BY FAKETRUTH and madmaxoft!!
*/

#pragma once


#include "SettingsRepositoryInterface.h"

#define MAX_KEYNAME 128
#define MAX_VALUENAME 128
#define MAX_VALUEDATA 2048





// tolua_begin

class cIniFile : public cSettingsRepositoryInterface
{
  private:
	// tolua_end

	using Super = cSettingsRepositoryInterface;


	bool m_IsCaseInsensitive;

	AString m_Filename;

	struct key
	{
		std::vector<AString> m_Names;
		std::vector<AString> m_Values;
		std::vector<AString> m_Comments;
	};

	std::vector<key> m_Keys;
	std::vector<AString> m_Names;
	std::vector<AString> m_Comments;

	/** If the object is case-insensitive, returns s as lowercase; otherwise returns s as-is */
	AString CheckCase(const AString & s) const;

	/** Removes the UTF-8 BOMs (Byte order makers), if present. */
	void RemoveBom(AString & a_line) const;

	// tolua_begin

  public:
	// NOTE: This has to be present for ToLua++'s parser to output the noID constant into the API
	// We don't want to export the entire base class, so the constant needs to get pulled into this descendant
	enum
	{
		noID = Super::noID,
	};


	/** Creates a new instance with no data */
	cIniFile(void);

	// tolua_end

	virtual std::vector<std::pair<AString, AString>> GetValues(AString a_keyName) override;

	virtual bool KeyExists(const AString a_keyName) const override;

	// tolua_begin

	// Sets whether or not keynames and valuenames should be case sensitive.
	// The default is case insensitive.
	void CaseSensitive(void) { m_IsCaseInsensitive = false; }
	void CaseInsensitive(void) { m_IsCaseInsensitive = true; }

	/** Reads the contents of the specified ini file
	If the file doesn't exist and a_AllowExampleRedirect is true, tries to read <basename>.example.ini, and
	writes its contents as <basename>.ini, if successful.
	Returns true if successful, false otherwise. */
	bool ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect = true);

	/** Writes data stored in class to the specified ini file.
	Returns true on success, false on failure. */
	bool WriteFile(const AString & a_FileName) const;

	virtual bool Flush() override { return WriteFile(m_Filename); }

	/** Deletes all stored ini data (but doesn't touch the file) */
	void Clear(void);

	/** Returns true iff the specified value exists. */
	bool HasValue(const AString & a_KeyName, const AString & a_ValueName) const override;

	/** Returns index of specified key, or noID if not found */
	int FindKey(const AString & keyname) const;

	/** Returns index of specified value, in the specified key, or noID if not found */
	int FindValue(const int keyID, const AString & valuename) const;

	/** Returns number of keys currently in the ini */
	int GetNumKeys(void) const { return static_cast<int>(m_Keys.size()); }

	/** Add a key name */
	int AddKeyName(const AString & keyname) override;

	// Returns key names by index.
	AString GetKeyName(const int keyID) const;

	// Returns number of values stored for specified key.
	int GetNumValues(const AString & keyname) const;
	int GetNumValues(const int keyID) const;

	// Returns value name by index for a given keyname or keyID.
	AString GetValueName(const AString & keyname, const int valueID) const;
	AString GetValueName(const int keyID, const int valueID) const;

	// Gets value of [keyname] valuename =.
	// Overloaded to return string, int, and double.
	// Returns defValue if key / value not found.
	AString GetValue(const AString & keyname, const AString & valuename, const AString & defValue = "") const override;
	AString GetValue(const int keyID, const int valueID, const AString & defValue = "") const;
	double GetValueF(const AString & keyname, const AString & valuename, const double defValue = 0) const;
	int GetValueI(const AString & keyname, const AString & valuename, const int defValue = 0) const;
	bool GetValueB(const AString & keyname, const AString & valuename, const bool defValue = false) const
	{
		return (GetValueI(keyname, valuename, defValue ? 1 : 0) != 0);
	}

	// Gets the value; if not found, write the default to the INI file
	AString GetValueSet(const AString & keyname, const AString & valuename, const AString & defValue = "") override;
	double GetValueSetF(const AString & keyname, const AString & valuename, const double defValue = 0.0);
	int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0) override;
	Int64 GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue = 0) override;
	bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false) override
	{
		return (GetValueSetI(keyname, valuename, defValue ? 1 : 0) != 0);
	}

	// Adds a new value to the specified key.
	// If a value of the same name already exists, creates another one (non-standard INI file)
	void AddValue(const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) override;
	void AddValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value);
	void AddValueB(const AString & a_KeyName, const AString & a_ValueName, const bool a_Value)
	{
		return AddValueI(a_KeyName, a_ValueName, a_Value ? 1 : 0);
	}
	void AddValueF(const AString & a_KeyName, const AString & a_ValueName, const double a_Value);

	// Overwrites the value of [keyname].valuename
	// Specify the optional parameter as false (0) if you do not want the value created if it doesn't exist.
	// Returns true if value set, false otherwise.
	// Overloaded to accept string, int, and double.
	bool SetValue(const int keyID, const int valueID, const AString & value);
	bool SetValue(
		const AString & a_KeyName,
		const AString & a_ValueName,
		const AString & a_Value,
		const bool a_CreateIfNotExists = true
	) override;
	bool SetValueI(
		const AString & a_KeyName,
		const AString & a_ValueName,
		const int a_Value,
		const bool a_CreateIfNotExists = true
	) override;
	bool SetValueI(
		const AString & a_Keyname,
		const AString & a_ValueName,
		const Int64 a_Value,
		const bool a_CreateIfNotExists = true
	);
	bool SetValueB(
		const AString & a_KeyName,
		const AString & a_ValueName,
		const bool a_Value,
		const bool a_CreateIfNotExists = true
	)
	{
		return SetValueI(a_KeyName, a_ValueName, int(a_Value), a_CreateIfNotExists);
	}
	bool SetValueF(
		const AString & a_KeyName,
		const AString & a_ValueName,
		const double a_Value,
		const bool a_CreateIfNotExists = true
	);

	// Deletes specified value.
	// Returns true if value existed and deleted, false otherwise.
	bool DeleteValueByID(const int keyID, const int valueID);
	bool DeleteValue(const AString & keyname, const AString & valuename) override;

	// Deletes specified key and all values contained within.
	// Returns true if key existed and deleted, false otherwise.
	bool DeleteKey(const AString & keyname);

	// Header comment functions.
	// Header comments are those comments before the first key.

	/** Returns the number of header comments */
	int GetNumHeaderComments(void) { return static_cast<int>(m_Comments.size()); }

	/** Adds a header comment */
	void AddHeaderComment(const AString & comment);

	/** Returns a header comment, or empty string if out of range */
	AString GetHeaderComment(const int commentID) const;

	/** Deletes a header comment. Returns true if successful */
	bool DeleteHeaderComment(int commentID);

	/** Deletes all header comments */
	void DeleteHeaderComments(void) { m_Comments.clear(); }


	// Key comment functions.
	// Key comments are those comments within a key. Any comments
	// defined within value names will be added to this list. Therefore,
	// these comments will be moved to the top of the key definition when
	// the CIniFile::WriteFile() is called.

	/** Get number of key comments */
	int GetNumKeyComments(const int keyID) const;

	/** Get number of key comments */
	int GetNumKeyComments(const AString & keyname) const;

	/** Add a key comment */
	bool AddKeyComment(const int keyID, const AString & comment);

	/** Add a key comment */
	bool AddKeyComment(const AString & keyname, const AString & comment) override;

	/** Return a key comment */
	AString GetKeyComment(const int keyID, const int commentID) const;
	AString GetKeyComment(const AString & keyname, const int commentID) const override;

	// Delete a key comment.
	bool DeleteKeyComment(const int keyID, const int commentID);
	bool DeleteKeyComment(const AString & keyname, const int commentID) override;

	// Delete all comments for a key.
	bool DeleteKeyComments(const int keyID);
	bool DeleteKeyComments(const AString & keyname);
};

// tolua_end





/** Reads the list of ports from the INI file, possibly upgrading from IPv4 / IPv6-specific values into new
version-agnostic value. Reads the list of ports from a_PortsValueName. If that value doesn't exist or is empty, the list
is combined from values in a_OldIPv4ValueName and a_OldIPv6ValueName; in this case the old values are removed from the
INI file. If there is none of the three values or they are all empty, the default is used and stored in the Ports value.
*/
AStringVector ReadUpgradeIniPorts(
	cSettingsRepositoryInterface & a_Settings,
	const AString & a_KeyName,
	const AString & a_PortsValueName,
	const AString & a_OldIPv4ValueName,
	const AString & a_OldIPv6ValueName,
	const AString & a_DefaultValue
);