Compound and List tags now assign/unassign parent on insertion/deletion
This commit is contained in:
parent
11f3c4d70c
commit
bcd41b37f0
|
@ -306,7 +306,7 @@ public class TagWriter : TagIO
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void WriteTypeAndName(Tag tag)
|
||||
{
|
||||
if (tag.Parent is ListTag)
|
||||
if (tag.Parent is ListTag || string.IsNullOrEmpty(tag.Name))
|
||||
return;
|
||||
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
|
|
|
@ -39,12 +39,12 @@ public class CompoundTag : Tag, IDictionary<string, Tag>, ICollection<Tag>
|
|||
{
|
||||
foreach (var value in values)
|
||||
{
|
||||
dict.Add(value.Name!, AssertName(value));
|
||||
dict.Add(value.Name!, ValidateChild(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
void ICollection<KeyValuePair<string, Tag>>.Add(KeyValuePair<string, Tag> item) => dict.Add(item.Key, item.Value);
|
||||
void ICollection<KeyValuePair<string, Tag>>.Add(KeyValuePair<string, Tag> item) => Add(item.Value);
|
||||
|
||||
/// <inheritdoc />
|
||||
bool ICollection<KeyValuePair<string, Tag>>.Contains(KeyValuePair<string, Tag> item) => dict.Contains(item);
|
||||
|
@ -61,12 +61,25 @@ public class CompoundTag : Tag, IDictionary<string, Tag>, ICollection<Tag>
|
|||
|
||||
/// <inheritdoc />
|
||||
bool ICollection<Tag>.IsReadOnly => false;
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
bool ICollection<KeyValuePair<string, Tag>>.Remove(KeyValuePair<string, Tag> item) => dict.Remove(item.Key);
|
||||
bool ICollection<KeyValuePair<string, Tag>>.Remove(KeyValuePair<string, Tag> item)
|
||||
{
|
||||
if (dict.Remove(item.Key))
|
||||
{
|
||||
item.Value.Parent = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICollection{T}.Clear"/>
|
||||
public void Clear() => dict.Clear();
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var child in dict.Values)
|
||||
child.Parent = null;
|
||||
dict.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICollection{T}.Clear"/>
|
||||
public int Count => dict.Count;
|
||||
|
@ -88,10 +101,10 @@ public class CompoundTag : Tag, IDictionary<string, Tag>, ICollection<Tag>
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Add(string key, Tag value) => dict.Add(key, AssertName(value));
|
||||
public void Add(string key, Tag value) => dict.Add(key, ValidateChild(value));
|
||||
|
||||
/// <inheritdoc cref="ICollection{T}.Add"/>
|
||||
public void Add(Tag value) => dict.Add(value.Name!, AssertName(value));
|
||||
public void Add(Tag value) => dict.Add(value.Name!, ValidateChild(value));
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool ContainsKey(string key) => dict.ContainsKey(key);
|
||||
|
@ -100,10 +113,24 @@ public class CompoundTag : Tag, IDictionary<string, Tag>, ICollection<Tag>
|
|||
public bool Contains(Tag tag) => !string.IsNullOrEmpty(tag.Name) && dict.ContainsKey(tag.Name);
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Remove(string key) => dict.Remove(key);
|
||||
public bool Remove(string key)
|
||||
{
|
||||
if (dict.TryGetValue(key, out var tag))
|
||||
tag.Parent = null;
|
||||
return dict.Remove(key);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Remove(Tag item) => !string.IsNullOrWhiteSpace(item.Name) && dict.Remove(item.Name);
|
||||
public bool Remove(Tag item)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(item.Name) && dict.Remove(item.Name))
|
||||
{
|
||||
item.Parent = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetValue(string key, out Tag value) => dict.TryGetValue(key, out value!);
|
||||
|
@ -131,7 +158,7 @@ public class CompoundTag : Tag, IDictionary<string, Tag>, ICollection<Tag>
|
|||
public Tag this[string name]
|
||||
{
|
||||
get => dict[name];
|
||||
set => dict[name] = value;
|
||||
set => dict[name] = ValidateChild(value);
|
||||
}
|
||||
|
||||
public TTag Get<TTag>(string name) where TTag : Tag
|
||||
|
@ -249,10 +276,11 @@ public class CompoundTag : Tag, IDictionary<string, Tag>, ICollection<Tag>
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Tag AssertName(Tag tag)
|
||||
private Tag ValidateChild(Tag tag)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tag.Name))
|
||||
throw new FormatException(Strings.ChildrenMustBeNamed);
|
||||
tag.Parent = this;
|
||||
return tag;
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ public class ListTag : Tag, IList<Tag>
|
|||
/// <summary>
|
||||
/// Gets the NBT type of this tag's children.
|
||||
/// </summary>
|
||||
public TagType ChildType { get; private set; }
|
||||
public TagType ChildType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="ListTag"/> class.
|
||||
|
@ -54,7 +54,7 @@ public class ListTag : Tag, IList<Tag>
|
|||
public ListTag(string? name, TagType childType, IEnumerable<Tag> children) : this(name, childType)
|
||||
{
|
||||
foreach (var item in children)
|
||||
list.Add(AssertType(item));
|
||||
list.Add(ValidateChild(item));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -64,12 +64,12 @@ public class ListTag : Tag, IList<Tag>
|
|||
IEnumerator IEnumerable.GetEnumerator() => list.GetEnumerator();
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Add(Tag item) => list.Add(AssertType(item));
|
||||
public void Add(Tag item) => list.Add(ValidateChild(item));
|
||||
|
||||
public void AddRange(IEnumerable<Tag> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
list.Add(AssertType(item));
|
||||
list.Add(ValidateChild(item));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -82,7 +82,16 @@ public class ListTag : Tag, IList<Tag>
|
|||
public void CopyTo(Tag[] array, int arrayIndex) => list.CopyTo(array, arrayIndex);
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Remove(Tag item) => list.Remove(item);
|
||||
public bool Remove(Tag item)
|
||||
{
|
||||
if (list.Remove(item))
|
||||
{
|
||||
item.Parent = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Count => list.Count;
|
||||
|
@ -94,16 +103,21 @@ public class ListTag : Tag, IList<Tag>
|
|||
public int IndexOf(Tag item) => list.IndexOf(item);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Insert(int index, Tag item) => list.Insert(index, AssertType(item));
|
||||
public void Insert(int index, Tag item) => list.Insert(index, ValidateChild(item));
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RemoveAt(int index) => list.RemoveAt(index);
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
var item = list[index];
|
||||
item.Parent = null;
|
||||
list.RemoveAt(index);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Tag this[int index]
|
||||
{
|
||||
get => list[index];
|
||||
set => list[index] = AssertType(value);
|
||||
set => list[index] = ValidateChild(value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -173,14 +187,13 @@ public class ListTag : Tag, IList<Tag>
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private Tag AssertType(Tag tag)
|
||||
private Tag ValidateChild(Tag tag)
|
||||
{
|
||||
if (tag.Type != ChildType)
|
||||
throw new ArrayTypeMismatchException(Strings.ChildWrongType);
|
||||
tag.Parent = this;
|
||||
return tag;
|
||||
}
|
||||
|
||||
private readonly List<Tag> list;
|
||||
|
||||
|
||||
}
|
|
@ -31,7 +31,7 @@ public abstract class Tag : IEquatable<Tag>, ICloneable
|
|||
/// <summary>
|
||||
/// Gets the parent <see cref="Tag"/> this object is a child of.
|
||||
/// </summary>
|
||||
[Obsolete("Parent property will be removed in a future version.")]
|
||||
[Obsolete("Parent property may be removed in a future version.")]
|
||||
public Tag? Parent { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -181,7 +181,7 @@ public abstract class Tag : IEquatable<Tag>, ICloneable
|
|||
// Serialize then deserialize to make a deep-copy
|
||||
using var stream = new MemoryStream();
|
||||
|
||||
// Might as well not worry about swapping bits, just use native endian
|
||||
// Use native endian
|
||||
var opts = BitConverter.IsLittleEndian ? FormatOptions.LittleEndian : FormatOptions.BigEndian;
|
||||
using var writer = new TagWriter(stream, opts, true);
|
||||
using var reader = new TagReader(stream, opts, true);
|
||||
|
@ -192,6 +192,7 @@ public abstract class Tag : IEquatable<Tag>, ICloneable
|
|||
return reader.ReadTag(!string.IsNullOrWhiteSpace(Name));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tests for equality of this object with another <see cref="Tag"/> instance.
|
||||
/// </summary>
|
||||
|
|
Loading…
Reference in New Issue