using System; using System.Linq; namespace BepInEx.Configuration { /// <summary> /// Section and key of a setting. Used as a unique key for identification within a <see cref="T:BepInEx.Configuration.ConfigFile" />. /// The same definition can be used in multiple config files, it will point to different settings then. /// </summary> /// <inheritdoc /> public class ConfigDefinition : IEquatable<ConfigDefinition> { /// <summary> /// Group of the setting. All settings within a config file are grouped by this. /// </summary> public string Section { get; } /// <summary> /// Name of the setting. /// </summary> public string Key { get; } /// <summary> /// Create a new definition. Definitions with same section and key are equal. /// </summary> /// <param name="section">Group of the setting, case sensitive.</param> /// <param name="key">Name of the setting, case sensitive.</param> public ConfigDefinition(string section, string key) { CheckInvalidConfigChars(section, nameof(section)); CheckInvalidConfigChars(key, nameof(key)); Key = key; Section = section; } private static readonly char[] _invalidConfigChars = { '=', '\n', '\t', '\\', '"', '\'', '[', ']' }; private static void CheckInvalidConfigChars(string val, string name) { if (val == null) throw new ArgumentNullException(name); if (val != val.Trim()) throw new ArgumentException("Cannot use whitespace characters at start or end of section and key names", name); if (val.Any(c => _invalidConfigChars.Contains(c))) throw new ArgumentException(@"Cannot use any of the following characters in section and key names: = \n \t \ "" ' [ ]", name); } /// <inheritdoc /> [Obsolete("description argument is no longer used, put it in a ConfigDescription instead")] public ConfigDefinition(string section, string key, string description) { Key = key ?? ""; Section = section ?? ""; } /// <summary> /// Check if the definitions are the same. /// </summary> /// <inheritdoc /> public bool Equals(ConfigDefinition other) { if (other == null) return false; return string.Equals(Key, other.Key) && string.Equals(Section, other.Section); } /// <summary> /// Check if the definitions are the same. /// </summary> public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; return Equals(obj as ConfigDefinition); } /// <inheritdoc /> public override int GetHashCode() { unchecked { int hashCode = Key != null ? Key.GetHashCode() : 0; hashCode = (hashCode * 397) ^ (Section != null ? Section.GetHashCode() : 0); return hashCode; } } /// <summary> /// Check if the definitions are the same. /// </summary> public static bool operator ==(ConfigDefinition left, ConfigDefinition right) => Equals(left, right); /// <summary> /// Check if the definitions are the same. /// </summary> public static bool operator !=(ConfigDefinition left, ConfigDefinition right) => !Equals(left, right); /// <inheritdoc /> public override string ToString() { return Section + "." + Key; } } }