using System.Collections.Generic; using System; using System.Text; namespace NeXt.Vdf { /// /// A VdfValue that represents a table containing other VdfValues /// public sealed class VdfTable : VdfValue, IList { public VdfTable(string name) : base(name) { } public VdfTable(string name, IEnumerable values) : this(name) { if (values == null) { throw new ArgumentNullException("values"); } foreach(var val in values) { Add(val); } } private List values = new List(); private Dictionary valuelookup = new Dictionary(); public int IndexOf(VdfValue item) { return values.IndexOf(item); } public void Insert(int index, VdfValue item) { if(item == null) { throw new ArgumentNullException("item"); } if(index < 0 || index >= values.Count) { throw new ArgumentOutOfRangeException("index"); } if(string.IsNullOrEmpty(item.Name)) { throw new ArgumentException("item name cannot be empty or null"); } if (ContainsName(item.Name)) { throw new ArgumentException("a value with name " + item.Name + " already exists in the table"); } item.Parent = this; values.Insert(index, item); valuelookup.Add(item.Name, item); } public void InsertAfter(VdfValue item, VdfValue newitem) { if(!Contains(item)) { throw new ArgumentException("item needs to exist in this table", "item"); } if (string.IsNullOrEmpty(newitem.Name)) { throw new ArgumentException("newitem name cannot be empty or null"); } if (ContainsName(newitem.Name)) { throw new ArgumentException("a value with name " + newitem.Name + " already exists in the table"); } int i = -1; for(i = 0; i < values.Count; i++) { if(values[i] == item) { break; } } if(i >= 0 && i < values.Count) { if(i == values.Count -1) { Add(newitem); } else { Insert(i + 1, newitem); } } } public void RemoveAt(int index) { var val = values[index]; values.RemoveAt(index); valuelookup.Remove(val.Name); } public VdfValue this[int index] { get { return values[index]; } set { if(values[index].Name != value.Name) { valuelookup.Remove(values[index].Name); valuelookup.Add(value.Name, value); } else { valuelookup[value.Name] = value; } values[index] = value; } } public VdfValue this[string name] { get { return valuelookup[name]; } } public void Add(VdfValue item) { if (item == null) { throw new ArgumentNullException("item"); } if (string.IsNullOrEmpty(item.Name)) { throw new ArgumentException("item name cannot be empty or null"); } if (ContainsName(item.Name)) { throw new ArgumentException("a value with name " + item.Name + " already exists in the table"); } item.Parent = this; values.Add(item); valuelookup.Add(item.Name, item); } public void Clear() { values.Clear(); valuelookup.Clear(); } public bool Contains(VdfValue item) { if (item == null) { throw new ArgumentNullException("item"); } if (string.IsNullOrEmpty(item.Name)) { throw new ArgumentException("item name cannot be empty or null"); } return valuelookup.ContainsKey(item.Name) && (valuelookup[item.Name] == item); } public bool ContainsName(string name) { if (name == null) { throw new ArgumentNullException("name"); } if (string.IsNullOrEmpty(name)) { throw new ArgumentException("name cannot be empty"); } return valuelookup.ContainsKey(name); } public VdfValue GetByName(string name) { if(ContainsName(name)) { return valuelookup[name]; } return null; } public void CopyTo(VdfValue[] array, int arrayIndex) { values.CopyTo(array, arrayIndex); } public int Count { get { return values.Count; } } public bool Remove(VdfValue item) { if (item == null) { throw new ArgumentNullException("item"); } if (string.IsNullOrEmpty(item.Name)) { throw new ArgumentException("item name cannot be empty or null"); } if(Contains(item)) { valuelookup.Remove(item.Name); values.Remove(item); return true; } return false; } public IEnumerator GetEnumerator() { return values.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return values.GetEnumerator(); } bool ICollection.IsReadOnly { get { return false; } } public void Traverse(Func call) { if (call == null) { throw new ArgumentNullException("call"); } foreach (var value in values) { if (!call(value)) { break; } } } public void TraverseRecursive(Func call) { if (call == null) { throw new ArgumentNullException("call"); } foreach (var value in values) { if (value is VdfTable) { ((VdfTable)value).TraverseRecursive(call); } else { if (!call(value)) { break; } } } } } }