using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Text.RegularExpressions; using System.Globalization; namespace ProxyCore { public class ConfigFile { protected ConfigFile() { } private string Filepath; /// /// Did we successfully load the config file? If not then it was probably missing. /// public bool DidLoad { get; private set; } /// /// Load a configuration file. /// /// Configuration name - for example "server". This should be your plugin name. /// internal void Load(string fileName) { fileName = "config." + fileName + ".txt"; _cfgData.Clear(); Filepath = fileName; OnCreated(); if(_cfgData.Count == 0) return; StreamReader f = null; try { f = new StreamReader(fileName); } catch(FileNotFoundException) { SaveNew(); return; } catch { return; } string l; while((l = f.ReadLine()) != null) { l = l.Trim(); if(string.IsNullOrEmpty(l) || l.StartsWith("#") || l.StartsWith(";") || l.StartsWith("//")) continue; Match m = _loadRegex.Match(l); if(!m.Success) continue; string Key = m.Groups[1].Value.ToLower(); if(!_cfgData.ContainsKey(Key)) continue; string Value = m.Groups[3].Value; if(Value.Contains('"') && _cfgData[Key].DefaultValue is string) Value = Value.Substring(1, Value.Length - 2); if(_cfgData[Key].DefaultValue is int) { int i; if(!int.TryParse(Value, out i)) continue; _cfgData[Key].Value = i; } else if(_cfgData[Key].DefaultValue is uint) { uint i; if(!uint.TryParse(Value, out i)) continue; _cfgData[Key].Value = i; } else if(_cfgData[Key].DefaultValue is long) { long i; if(!long.TryParse(Value, out i)) continue; _cfgData[Key].Value = i; } else if(_cfgData[Key].DefaultValue is ulong) { ulong i; if(!ulong.TryParse(Value, out i)) continue; _cfgData[Key].Value = i; } else if(_cfgData[Key].DefaultValue is string) { _cfgData[Key].Value = Value; } else if(_cfgData[Key].DefaultValue is float) { try { float i = Convert.ToSingle(Value, CultureInfo.InvariantCulture.NumberFormat); _cfgData[Key].Value = i; } catch { continue; } } else if(_cfgData[Key].DefaultValue is double) { try { double i = Convert.ToDouble(Value, CultureInfo.InvariantCulture.NumberFormat); _cfgData[Key].Value = i; } catch { continue; } } } f.Close(); } /// /// Regex pattern used to load a line from config file. /// Groups[1]: Name of setting /// Groups[3]: Value of setting (including "" if string) /// private static readonly Regex _loadRegex = new Regex("([\\w\\.]+)\\s*(=|:|-)\\s*((\".*\")|(-?\\d+\\.\\d+)|(-?\\d+))", RegexOptions.Compiled); /// /// Save a new configuration file with default values. If there is an existing config file, it will be replaced. /// public void SaveNew() { if(string.IsNullOrEmpty(Filepath) || _cfgData.Count == 0) return; StreamWriter f = null; try { f = new StreamWriter(Filepath, false); } catch { return; } foreach(KeyValuePair x in _cfgData) { f.WriteLine("###############################################################################"); f.WriteLine("#"); f.WriteLine("# " + x.Value.Key); if(!string.IsNullOrEmpty(x.Value.Desc)) { string[] oDesc = Utility.WrapColored(x.Value.Desc, 70, 0); for(int i = 0; i < oDesc.Length; i++) f.WriteLine("# " + oDesc[i]); } f.WriteLine("#"); f.WriteLine("###############################################################################"); f.WriteLine(""); f.WriteLine(x.Value.Key + " = " + ((x.Value.DefaultValue is string) ? ("\"" + x.Value.DefaultValue + "\"") : x.Value.DefaultValue.ToString().Replace(",", "."))); f.WriteLine(""); } f.Close(); } /// /// This will be called to populate config data with default values and descriptions. /// protected virtual void OnCreated() { } /// /// Create a new setting for the file. If setting with this name already exists then skip. /// /// Setting name. /// Default value for setting. Make sure to use type casting if not integer. /// Description to write in the file for this setting. protected void CreateSetting(string Key, object Value, string Desc) { if(_cfgData.ContainsKey(Key.ToLower().Trim())) return; CfgEntry e = new CfgEntry() { Key = Key, Value = Value, DefaultValue = Value, Desc = Desc }; _cfgData[Key.ToLower().Trim()] = e; } /// /// Read a 32 bit integer value from configuration file. /// /// Name of the option. /// Default value if config is missing this option or is invalid. /// public int GetInt32(string Key, int Default) { Key = Key.ToLower().Trim(); if(string.IsNullOrEmpty(Key) || !_cfgData.ContainsKey(Key) || !(_cfgData[Key].Value is int)) return Default; return (int)_cfgData[Key].Value; } /// /// Read a 32 bit unsigned integer value from configuration file. /// /// Name of the option. /// Default value if config is missing this option or is invalid. /// public uint GetUInt32(string Key, uint Default) { Key = Key.ToLower().Trim(); if(string.IsNullOrEmpty(Key) || !_cfgData.ContainsKey(Key) || !(_cfgData[Key].Value is uint)) return Default; return (uint)_cfgData[Key].Value; } /// /// Read a 64 bit integer value from configuration file. /// /// Name of the option. /// Default value if config is missing this option or is invalid. /// public long GetInt64(string Key, long Default) { Key = Key.ToLower().Trim(); if(string.IsNullOrEmpty(Key) || !_cfgData.ContainsKey(Key) || !(_cfgData[Key].Value is long)) return Default; return (long)_cfgData[Key].Value; } /// /// Read a 64 bit unsigned integer value from configuration file. /// /// Name of the option. /// Default value if config is missing this option or is invalid. /// public ulong GetUInt64(string Key, ulong Default) { Key = Key.ToLower().Trim(); if(string.IsNullOrEmpty(Key) || !_cfgData.ContainsKey(Key) || !(_cfgData[Key].Value is ulong)) return Default; return (ulong)_cfgData[Key].Value; } /// /// Read a float value from configuration file. /// /// Name of the option. /// Default value if config is missing this option or is invalid. /// public float GetFloat(string Key, float Default) { Key = Key.ToLower().Trim(); if(string.IsNullOrEmpty(Key) || !_cfgData.ContainsKey(Key) || !(_cfgData[Key].Value is float)) return Default; return (float)_cfgData[Key].Value; } /// /// Read a double value from configuration file. /// /// Name of the option. /// Default value if config is missing this option or is invalid. /// public double GetDouble(string Key, double Default) { Key = Key.ToLower().Trim(); if(string.IsNullOrEmpty(Key) || !_cfgData.ContainsKey(Key) || !(_cfgData[Key].Value is double)) return Default; return (double)_cfgData[Key].Value; } /// /// Read a string value from configuration file. /// /// Name of the option. /// Default value if config is missing this option or is invalid. /// public string GetString(string Key, string Default) { Key = Key.ToLower().Trim(); if(string.IsNullOrEmpty(Key) || !_cfgData.ContainsKey(Key) || !(_cfgData[Key].Value is string)) return Default; return (string)_cfgData[Key].Value; } private Dictionary _cfgData = new Dictionary(); private class CfgEntry { public string Key; public object Value; public object DefaultValue; public string Desc; } } }