diff --git a/Apewer/Models/IniFile.cs b/Apewer/Models/IniFile.cs new file mode 100644 index 0000000..ef36a5a --- /dev/null +++ b/Apewer/Models/IniFile.cs @@ -0,0 +1,196 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; + +namespace Apewer.Models +{ + + /// INI 文件。 + [Serializable] + public sealed class IniFile : IEnumerable, IToJson + { + + List _sections = new List(); + + #region Constructors + + /// + public IniFile() { } + + /// + public IniFile(IEnumerable sections) + { + if (sections == null) throw new ArgumentNullException(nameof(sections)); + sections.ForEach(Add); + } + + #endregion + + #region CRUD + + /// 节的数量。 + public int Count { get => _sections.Count; } + + /// 添加节。 + public void Add(IniSection section) + { + if (section == null) return; + _sections.Add(section); + } + + /// 添加节。 + public void Add(string name, TextField[] fields) => _sections.Add(new IniSection(name, fields)); + + /// 获取节。 + public IniSection Get(string sectionName) + { + var emptyName = sectionName.IsEmpty(); + foreach (var section in _sections) + { + if (emptyName) + { + if (section.Name.IsEmpty()) return section; + } + else + { + if (section.Name == sectionName) return section; + } + } + return null; + } + + /// 移除节。 + public void Remove(IniSection section) + { + while (_sections.Contains(section)) _sections.Remove(section); + } + + /// 移除节。 + public void Remove(string sectionName) + { + var emptyName = sectionName.IsEmpty(); + foreach (var section in _sections) + { + if (emptyName) + { + _sections = _sections.FindAll(x => x.Name.IsEmpty()); + } + else + { + _sections = _sections.FindAll(x => x.Name == sectionName); + } + } + } + + #endregion + + #region IEnumerable + + /// + public IEnumerator GetEnumerator() => new Enumerator(i => i < _sections.Count ? new Class(_sections[i]) : null); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + #endregion + + #region IToJson + + /// + public Json ToJson() + { + var json = Json.NewArray(); + _sections.ForEach(section => json.AddItem(section.ToJson())); + return json; + } + + #endregion + + #region ToString + + const string CRLF = "\r\n"; + + /// + public override string ToString() => ToString(CRLF); + + /// + public string ToString(string seperator) + { + if (seperator.IsEmpty()) seperator = CRLF; + + var sb = new StringBuilder(); + + var noName = 0; + foreach (var section in _sections) + { + if (section == null) continue; + + if (section.Name.IsEmpty()) + { + var count = section.Count; + for (var i = 0; i < count; i++) + { + var field = section.GetField(i); + if (Append(sb, field)) + { + sb.Append(seperator); + noName += 1; + } + } + } + + } + if (noName > 1) sb.Append(seperator); + + foreach (var section in _sections) + { + if (section == null) continue; + + if (section.Name.NotEmpty()) + { + sb.Append("["); + sb.Append(section.Name); + sb.Append("]"); + sb.Append(seperator); + + foreach (var field in section) + { + if (Append(sb, field)) + { + sb.Append(seperator); + } + } + } + sb.Append(seperator); + } + + return sb.ToString(); + } + + static bool Append(StringBuilder sb, TextField field) + { + var nameEmpty = field.Name.IsEmpty(); + var valueEmpty = field.Value.IsEmpty(); + if (nameEmpty && valueEmpty) return false; + + if (!nameEmpty) + { + sb.Append(field.Name); + sb.Append(" ="); + } + + if (!valueEmpty) + { + if (nameEmpty) sb.Append("; "); + else sb.Append(" "); + sb.Append(field.Value); + } + + return true; + } + + #endregion + + } + +} diff --git a/Apewer/Models/IniSection.cs b/Apewer/Models/IniSection.cs new file mode 100644 index 0000000..df39f3b --- /dev/null +++ b/Apewer/Models/IniSection.cs @@ -0,0 +1,196 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using static System.Collections.Specialized.BitVector32; + +namespace Apewer.Models +{ + + /// INI 节。 + [Serializable] + public sealed class IniSection : ICollection, IEnumerable, IToJson + { + + private List _fields = new List(); + + /// 节的名称(不含方括号)。 + public string Name { get; set; } + + /// + public override string ToString() => $"Name = \"{Name}\", Count = {_fields.Count}"; + + #region ICollection + + /// + public int Count { get => _fields.Count; } + + /// 集合是只读的。 + /// 此值始终为 FALSE。 + public bool IsReadOnly { get => false; } + + /// 添加字段。 + /// + public void Add(TextField item) + { + if (item == null) throw new ArgumentNullException(nameof(item)); + _fields.Add(item); + } + + /// 清空字段。 + public void Clear() => _fields.Clear(); + + /// 检查此集合是否包含指定的字段。 + public bool Contains(TextField item) => _fields.Contains(item); + + /// 复制字段到数组中。 + /// + /// + /// + public void CopyTo(TextField[] array, int arrayIndex) + { + if (array == null) throw new ArgumentNullException(nameof(array)); + if (arrayIndex < 0) throw new ArgumentOutOfRangeException(nameof(arrayIndex)); + if (array.Length - arrayIndex < _fields.Count) throw new ArgumentException("目标数组长度不足。"); + + _fields.CopyTo(array, arrayIndex); + } + + /// 移除字段。 + public bool Remove(TextField item) + { + var removed = false; + while (_fields.Contains(item)) + { + _fields.Remove(item); + removed = true; + } + return removed; + } + + #endregion + + #region Enumerable + + /// + public IEnumerator GetEnumerator() => new Enumerator(i => i < _fields.Count ? new Class(_fields[i]) : null); + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + #endregion + + #region IToJson + + /// + public Json ToJson() + { + var fields = Json.NewObject(); + foreach (var field in _fields) + { + fields.SetProperty(field.Name, field.Value); + } + + var json = Json.NewObject(); + json.SetProperty("name", Name); + json.SetProperty("fields", fields); + + return json; + } + + #endregion + + /// 检查此集合是否包含指定的字段。 + /// 字段名称。 + public bool Contains(string name) + { + var count = _fields.Count; + for (var i = 0; i < count; i++) + { + if (_fields[0].Name == name) return true; + } + return false; + } + + /// 获取字段。 + /// " + public TextField GetField(int index) + { + if (index < 0 || index >= _fields.Count) throw new ArgumentOutOfRangeException(nameof(index)); + return _fields[index]; + } + + /// + public string GetValue(string name) + { + if (name.IsEmpty()) throw new ArgumentNullException(nameof(name)); + + foreach (var field in _fields) + { + if (field.Name == name) return field.Value; + } + return null; + } + + /// + public void SetValue(string name, string value) + { + if (name.IsEmpty()) throw new ArgumentNullException(nameof(name)); + + var count = _fields.Count; + var setted = false; + for (var i = 0; i < count; i++) + { + if (_fields[i].Name == name) + { + _fields[i].Value = value; + setted = true; + } + } + + if (!setted) + { + var field = new TextField(name, value); + _fields.Add(field); + } + } + + /// 获取或设置字段。 + public string this[string name] { get => GetValue(name); set => SetValue(name, value); } + + /// + public IniSection() { } + + /// + public IniSection(string name) : this() + { + this.Name = name; + } + + /// + /// + public IniSection(string name, IEnumerable fields) : this(name) + { + if (fields == null) throw new ArgumentNullException(nameof(fields)); + _fields.AddRange(fields.Map(x => x == null ? null : new TextField(x.Name, x.Value)).FindAll(x => x != null)); + } + + /// + /// + public IniSection(IEnumerable fields) : this(null, fields) { } + + /// + /// + public IniSection(string name, IEnumerable> fields) : this(name) + { + if (fields == null) throw new ArgumentNullException(nameof(fields)); + _fields.AddRange(fields.Map(x => new TextField(x))); + } + + /// + /// + public IniSection(IEnumerable> fields) : this(null, fields) { } + + } + +} diff --git a/Apewer/Models/TextField.cs b/Apewer/Models/TextField.cs new file mode 100644 index 0000000..2f2009c --- /dev/null +++ b/Apewer/Models/TextField.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Apewer.Models +{ + + /// 文本字段。 + [Serializable] + public sealed class TextField + { + + /// 名称。 + public string Name { get; set; } + + /// 值。 + public string Value { get; set; } + + /// 文本字段。 + public TextField() { } + + /// 创建文本字段。 + public TextField(string name, string value) + { + this.Name = name; + this.Value = value; + } + + /// 创建文本字段。 + public TextField(KeyValuePair pair) + { + this.Name = pair.Key; + this.Value = pair.Value; + } + + /// + public override string ToString() => $"{Name} = {Value}"; + + /// + public override bool Equals(object obj) + { + if (obj != null && obj is TextField field) return field.Name == Name && field.Value == Value; + return false; + } + + /// + public override int GetHashCode() => (Name ?? "").GetHashCode() ^ (Value ?? "").GetHashCode(); + + /// + public static implicit operator KeyValuePair(TextField field) => field == null ? default : new KeyValuePair(field.Name, field.Value); + + /// + public static implicit operator TextField(KeyValuePair pair) => new KeyValuePair(pair.Key, pair.Value); + + } + +}