This repository has been archived by the owner on Feb 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIniFile.cs
180 lines (159 loc) · 7.43 KB
/
IniFile.cs
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
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
namespace MewsToolbox
{
public class IniFile
{
private Dictionary<string, Dictionary<string, string>> iniContent;
private string FilePath;
public IFormatProvider Culture;
/// <summary>
/// Creates a new Ini file handler for the file at the given path. /!\ THE FILE MUST EXIST FIRST. IT WILL NOT BE CREATED AUTOMATICALLY IF MISSING
/// </summary>
/// <param name="filePath">The path to the file. Make sure the given path is valid!</param>
public IniFile(string filePath)
{
FilePath = filePath;
Culture = new CultureInfo("en-US");
var fileContent = File.ReadAllLines(FilePath);
iniContent = new Dictionary<string, Dictionary<string, string>>();
ParseFile(fileContent);
}
/// <summary>
/// Get a section as a string-string dictionary
/// </summary>
/// <param name="section">The section to get</param>
/// <returns>The section as a string-string dictionary</returns>
public Dictionary<string, string> this[string section]
{
get { return iniContent[section]; }
}
private void ParseFile(string[] content)
{
string section = "";
foreach (string line in content)
{
if (line.StartsWith(";") || string.IsNullOrWhiteSpace(line)) continue; // This is either a comment or an empty line, we don't count it.
else if (line.StartsWith("[") && line.EndsWith("]")) // This is a section, we want to create a new sub dictionary
{
string sectionName = line.Substring(1, line.Length - 2);
if (string.IsNullOrWhiteSpace(sectionName)) continue; // We don't want to handle an empty value
iniContent.Add(sectionName, new Dictionary<string, string>());
section = sectionName;
}
else
{
if (string.IsNullOrWhiteSpace(section)) continue; // No empty values
if (!line.Contains("=")) continue;
var substrings = line.Split('=');
iniContent[section].Add(substrings[0], substrings[1]);
}
}
}
private string MakeString()
{
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, Dictionary<string, string>> pair in iniContent)
{
sb.AppendLine("[" + pair.Key + "]");
foreach (KeyValuePair<string, string> valuePair in pair.Value)
{
sb.AppendLine(valuePair.Key + "=" + valuePair.Value.ToString(Culture));
}
sb.AppendLine();
}
return sb.ToString();
}
/// <summary>
/// Saves the file
/// </summary>
public void SaveFile() => SaveFile(FilePath);
/// <summary>
/// Saves the file at a certain path
/// </summary>
/// <param name="filePath">The path to save the file to</param>
public void SaveFile(string filePath)
{
File.WriteAllText(filePath, MakeString());
}
/// <summary>
/// Reloads the file if any external changes were made
/// </summary>
public void ReloadFile()
{
iniContent = new Dictionary<string, Dictionary<string, string>>();
ParseFile(File.ReadAllLines(FilePath));
}
/// <summary>
/// Safely get a value from the config file. It will automatically be cast to the requested type. If an error occurs or the config entry is missing, it can be created automatically.
/// </summary>
/// <typeparam name="T">The type to cast the config entry to. Currently supported: string, bool, int, float, double, decimal</typeparam>
/// <param name="section">The config section to get the value from</param>
/// <param name="setting">The config entry to get the value from</param>
/// <param name="defaultValue">The value returned if the entry was not found or a cast isn't supported. In the first case, this value can be used to make a new config entry</param>
/// <param name="setIfDoesntExist">If set to true, the config file will be updated with the new value. Default: true</param>
/// <returns>The setting you're looking for, or defaultValue if the value is not found</returns>
public T GetValueOrDefaultTo<T>(string section, string setting, T defaultValue, bool setIfDoesntExist = true, bool saveIfDoesntExist = true)
{
try
{
var value = iniContent[section][setting];
switch (Type.GetTypeCode(typeof(T)))
{
case TypeCode.String:
return (T)(object)value;
case TypeCode.Boolean:
return (T)(object)bool.Parse(value);
case TypeCode.Int32:
return (T)(object)int.Parse(value);
case TypeCode.Single:
return (T)(object)float.Parse(value, Culture);
case TypeCode.Double:
return (T)(object)double.Parse(value, Culture);
case TypeCode.Decimal:
return (T)(object)decimal.Parse(value, Culture);
default:
return defaultValue;
}
}
catch
{
if (setIfDoesntExist)
SetValue(section, setting, defaultValue, saveIfDoesntExist);
return defaultValue;
}
}
/// <summary>
/// Sets a value in the config
/// </summary>
/// <typeparam name="T">The type of the value</typeparam>
/// <param name="section">The section to save the value to</param>
/// <param name="setting">The config entry to save the value to</param>
/// <param name="value">The value to save</param>
/// <param name="immediatelySave">If set to true, immediately save the config file afterwards.</param>
public void SetValue<T>(string section, string setting, T value, bool immediatelySave = true)
{
if (!iniContent.ContainsKey(section))
iniContent.Add(section, new Dictionary<string, string>());
if (!iniContent[section].ContainsKey(setting))
iniContent[section].Add(setting, value.ToString());
if (immediatelySave) SaveFile();
}
/// <summary>
/// Checks if a section exists
/// </summary>
/// <param name="section">The section to check</param>
/// <returns>True if the section exists, False otherwise</returns>
public bool Exists(string section) => iniContent.ContainsKey(section);
/// <summary>
/// Checks if a setting exists
/// </summary>
/// <param name="section">The section to check</param>
/// <param name="setting">The setting to check</param>
/// <returns>True if both the section and the setting exist, False otherwise</returns>
public bool Exists(string section, string setting) => iniContent.ContainsKey(section) && iniContent[section].ContainsKey(setting);
}
}