LibZNI/NBT/CompoundTag.cs

283 lines
7.2 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using LibAC.NBT.API;
namespace LibAC.NBT
{
public class CompoundTag : Tag, IDictionary<string, Tag>
{
private readonly Dictionary<string, Tag> _value = new Dictionary<string, Tag>();
public CompoundTag() { }
public override void ReadValue(ByteLayer data)
{
_value.Clear();
while (true)
{
Tag tag = Tag.ReadNamedTag(data);
if (tag.GetType() == 0)
{
return;
}
tag.SetParentTagType(TagType.Compound);
this[tag.GetKey()] = tag;
}
}
public override void WriteValue(ByteLayer data)
{
foreach (var tag in _value.Values)
{
Tag.WriteNamedTag(tag, data);
}
data.WriteByte((byte)TagType.End);
}
public void Put(string name, Tag tag)
{
_value[name] = tag;
tag.SetKey(name);
tag.UpdateParent(this);
}
public Tag? Get(string name)
{
return ContainsKey(name) ? _value[name] : null;
}
public override TagType GetTagType()
{
return TagType.Compound;
}
public override object GetValue()
{
return null;
}
public override void SetValue(object val) { }
public override void PrettyPrint(int indent, bool recurse)
{
Console.WriteLine($"{new string('\t', indent)}{Tag.GetCanonicalName(GetTagType())}: [{_value.Count} entries]");
Console.WriteLine($"{new string('\t', indent)}");
if (recurse)
{
foreach (var tag in _value.Values)
{
tag.PrettyPrint(indent + 1, true);
}
}
}
public void EndPrettyPrint(int indent)
{
Console.WriteLine($"{new string('\t', indent)}");
}
public override void WriteStringifiedValue(StringBuilder builder, int indent, bool isList)
{
builder.Append($"{(isList ? new string('\t', indent - 1) : "")}{{\n");
bool firstEntry = true;
foreach (var tag in _value.Values)
{
if (!firstEntry)
{
builder.Append(",\n");
}
firstEntry = false;
Tag.WriteStringifiedNamedTag(tag, builder, indent);
}
builder.Append($"\n{new string('\t', indent - 1)}}}");
}
public bool TryGetValue(string key, out Tag value)
{
return _value.TryGetValue(key, out value);
}
public Tag? this[string key]
{
get => _value.ContainsKey(key) ? _value[key] : null;
set
{
if (value != null)
{
_value[key] = value;
value.UpdateParent(this);
}
}
}
public void Add(string key, Tag value)
{
_value.Add(key, value);
value.UpdateParent(this);
}
public void Add(KeyValuePair<string, Tag> item)
{
_value.Add(item.Key, item.Value);
item.Value.UpdateParent(this);
}
public void Clear()
{
UnsetParent();
_value.Clear();
}
public bool Contains(KeyValuePair<string, Tag> item)
{
return _value.ContainsKey(item.Key);
}
public void CopyTo(KeyValuePair<string, Tag>[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public bool Remove(KeyValuePair<string, Tag> item)
{
return _value.Remove(item.Key);
}
public void UnsetParent()
{
foreach (var entry in _value)
{
entry.Value.SetParentTagType(TagType.End);
entry.Value.UpdateParent(null);
}
}
public bool ContainsKey(string key)
{
return _value.ContainsKey(key);
}
public bool ContainsValue(Tag value)
{
return _value.ContainsValue(value);
}
public void ForEach(Action<string, Tag> action)
{
foreach (var entry in _value)
{
action(entry.Key, entry.Value);
}
}
public int Count => _value.Count;
public bool IsReadOnly { get; }
public bool IsEmpty => _value.Count == 0;
public bool IsNotEmpty => _value.Count > 0;
public ICollection<string> Keys => _value.Keys;
public ICollection<Tag> Values => _value.Values;
public override void ReadStringifiedValue(StringReader reader)
{
reader.Expect('{');
while (reader.Peek() != '}')
{
Tag tag = Tag.ReadStringifiedNamedTag(reader);
Put(tag.GetKey(), tag);
if (reader.Peek() == ',') reader.Next();
}
reader.Expect('}');
}
public void AddAll(IDictionary<string, Tag> other)
{
foreach (var entry in other)
{
_value[entry.Key] = entry.Value;
entry.Value.UpdateParent(this);
}
}
public bool Remove(string key)
{
if (_value.ContainsKey(key))
{
_value[key].UpdateParent(null);
return _value.Remove(key);
}
return false;
}
public void RemoveWhere(Predicate<KeyValuePair<string, Tag>> predicate)
{
var toRemove = new List<string>();
foreach (var entry in _value)
{
if (predicate(entry))
{
toRemove.Add(entry.Key);
}
}
foreach (var key in toRemove)
{
_value[key].UpdateParent(null);
_value.Remove(key);
}
}
public void UpdateAll(Action<string, Tag> update)
{
foreach (var entry in _value)
{
update(entry.Key, entry.Value);
}
}
public Tag PutIfAbsent(string key, Func<Tag> ifAbsent)
{
if (!_value.ContainsKey(key))
{
var tag = ifAbsent();
tag.UpdateParent(this);
_value[key] = tag;
return tag;
}
return _value[key];
}
public void AddEntries(IEnumerable<KeyValuePair<string, Tag>> newEntries)
{
foreach (var entry in newEntries)
{
_value.Add(entry.Key, entry.Value);
entry.Value.UpdateParent(this);
}
}
public IEnumerator<KeyValuePair<string, Tag>> GetEnumerator()
{
return _value.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _value.GetEnumerator();
}
}
}