refactoring and optimization
This commit is contained in:
parent
05126cee2a
commit
b50d5ebbd6
|
|
@ -42,7 +42,7 @@ public class TagBuilder
|
|||
/// <param name="name">The name of the node to add.</param>
|
||||
/// <param name="value">The value of the tag.</param>
|
||||
/// <returns>Returns this <see cref="TagBuilder"/> instance for chaining.</returns>
|
||||
public TagBuilder AddBool(string? name, bool value) => AddTag(new BoolTag(name, value));
|
||||
public TagBuilder AddBool(string? name, bool value) => AddTag(new ByteTag(name, value));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new unnamed <see cref="ByteTag"/> with the specified <paramref name="value"/> to the tree at the current depth.
|
||||
|
|
@ -58,7 +58,10 @@ public class TagBuilder
|
|||
/// <param name="value">The value of the tag.</param>
|
||||
/// <returns>Returns this <see cref="TagBuilder"/> instance for chaining.</returns>
|
||||
public TagBuilder AddByte(string? name, byte value) => AddTag(new ByteTag(name, value));
|
||||
|
||||
|
||||
/// <inheritdoc cref="AddByte(string,byte)"/>
|
||||
public TagBuilder AddByte(string? name, int value) => AddByte(name, unchecked((byte)(value & 0xFF)));
|
||||
|
||||
/// <inheritdoc cref="AddByte(string,byte)"/>
|
||||
[CLSCompliant(false)]
|
||||
public TagBuilder AddByte(string? name, sbyte value) => AddByte(name, unchecked((byte)value));
|
||||
|
|
@ -70,6 +73,9 @@ public class TagBuilder
|
|||
/// <returns>Returns this <see cref="TagBuilder"/> instance for chaining.</returns>
|
||||
public TagBuilder AddByte(byte value) => AddByte(null, value);
|
||||
|
||||
/// <inheritdoc cref="AddByte(sbyte)"/>
|
||||
public TagBuilder AddByte(int value) => AddByte(null, unchecked((byte)(value & 0xFF)));
|
||||
|
||||
/// <inheritdoc cref="AddByte(sbyte)"/>
|
||||
[CLSCompliant(false)]
|
||||
public TagBuilder AddByte(sbyte value) => AddByte(null, unchecked((byte)value));
|
||||
|
|
@ -82,6 +88,9 @@ public class TagBuilder
|
|||
/// <returns>Returns this <see cref="TagBuilder"/> instance for chaining.</returns>
|
||||
public TagBuilder AddShort(string? name, short value) => AddTag(new ShortTag(name, value));
|
||||
|
||||
/// <inheritdoc cref="AddShort(string,short)"/>
|
||||
public TagBuilder AddShort(string? name, int value) => AddShort(name, unchecked((short)(value & 0xFFFF)));
|
||||
|
||||
/// <inheritdoc cref="AddShort(string,short)"/>
|
||||
[CLSCompliant(false)]
|
||||
public TagBuilder AddShort(string? name, ushort value) => AddShort(name, unchecked((short)value));
|
||||
|
|
@ -93,6 +102,9 @@ public class TagBuilder
|
|||
/// <returns>Returns this <see cref="TagBuilder"/> instance for chaining.</returns>
|
||||
public TagBuilder AddShort(short value) => AddShort(null, value);
|
||||
|
||||
/// <inheritdoc cref="AddShort(short)"/>
|
||||
public TagBuilder AddShort(int value) => AddShort(null, unchecked((short)(value & 0xFFFF)));
|
||||
|
||||
/// <inheritdoc cref="AddShort(short)"/>
|
||||
[CLSCompliant(false)]
|
||||
public TagBuilder AddShort(ushort value) => AddShort(null, unchecked((short)value));
|
||||
|
|
@ -236,8 +248,7 @@ public class TagBuilder
|
|||
/// <inheritdoc cref="AddByteArray(byte[])"/>
|
||||
[CLSCompliant(false)]
|
||||
public TagBuilder AddByteArray(IEnumerable<sbyte> values) => AddByteArray(null, values.ToArray());
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new <see cref="IntArrayTag"/> with the specified <paramref name="values"/> to the tree at the current depth.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ public class TagWriter : TagIO
|
|||
public virtual void WriteByteArray(ByteArrayTag tag)
|
||||
{
|
||||
WriteTypeAndName(tag);
|
||||
WriteCount(tag);
|
||||
WriteCount(tag.Count);
|
||||
BaseStream.Write(tag.ToArray(), 0, tag.Count);
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ public class TagWriter : TagIO
|
|||
public virtual void WriteIntArray(IntArrayTag tag)
|
||||
{
|
||||
WriteTypeAndName(tag);
|
||||
WriteCount(tag);
|
||||
WriteCount(tag.Count);
|
||||
|
||||
var values = new Span<int>(tag.ToArray());
|
||||
if (UseVarInt)
|
||||
|
|
@ -155,7 +155,7 @@ public class TagWriter : TagIO
|
|||
{
|
||||
|
||||
WriteTypeAndName(tag);
|
||||
WriteCount(tag);
|
||||
WriteCount(tag.Count);
|
||||
|
||||
var values = new Span<long>(tag.ToArray());
|
||||
if (UseVarInt)
|
||||
|
|
@ -182,7 +182,7 @@ public class TagWriter : TagIO
|
|||
{
|
||||
WriteTypeAndName(tag);
|
||||
BaseStream.WriteByte((byte) tag.ChildType);
|
||||
WriteCount(tag);
|
||||
WriteCount(tag.Count);
|
||||
|
||||
foreach (var child in tag)
|
||||
WriteTag(child);
|
||||
|
|
@ -377,11 +377,11 @@ public class TagWriter : TagIO
|
|||
return bytes;
|
||||
}
|
||||
|
||||
private void WriteCount<T>(EnumerableTag<T> tag)
|
||||
private void WriteCount(int count)
|
||||
{
|
||||
if (UseVarInt)
|
||||
VarInt.Write(BaseStream, tag.Count, ZigZagEncoding);
|
||||
VarInt.Write(BaseStream, count, ZigZagEncoding);
|
||||
else
|
||||
BaseStream.Write(GetBytes(tag.Count), 0, sizeof(int));
|
||||
BaseStream.Write(GetBytes(count), 0, sizeof(int));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,142 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace SharpNBT;
|
||||
|
||||
public class ArrayTag
|
||||
/// <summary>
|
||||
/// Base class for NBT tags that contain a fixed-size array of numeric types.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">A value type that implements <see cref="INumber{TSelf}"/>.</typeparam>
|
||||
[PublicAPI][Serializable]
|
||||
public abstract class ArrayTag<T> : Tag, IReadOnlyList<T> where T : unmanaged, INumber<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a <see cref="Span{T}"/> over the tag data.
|
||||
/// </summary>
|
||||
public Span<T> Span => new(array);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="Memory{T}"/> over the tag data.
|
||||
/// </summary>
|
||||
public Memory<T> Memory => new(array);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <param name="value">The value of the tag.</param>
|
||||
// ReSharper disable InvalidXmlDocComment
|
||||
protected ArrayTag(TagType type, string? name, T[] value) : base(type, name)
|
||||
// ReSharper restore InvalidXmlDocComment
|
||||
{
|
||||
array = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected ArrayTag(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
var _ = info.GetInt32("count");
|
||||
var value = info.GetValue("values", typeof(T[])) as T[];
|
||||
array = value ?? Array.Empty<T>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
base.GetObjectData(info, context);
|
||||
info.AddValue("count", array.Length);
|
||||
info.AddValue("values", array);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
// ReSharper disable ForCanBeConvertedToForeach
|
||||
for (var i = 0; i < array.Length; i++)
|
||||
yield return array[i];
|
||||
// ReSharper restore ForCanBeConvertedToForeach
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
IEnumerator IEnumerable.GetEnumerator() => array.GetEnumerator();
|
||||
|
||||
/// <inheritdoc cref="IList{T}.CopyTo"/>
|
||||
// ReSharper disable once ParameterHidesMember
|
||||
public void CopyTo(T[] array, int arrayIndex) => this.array.CopyTo(array, arrayIndex);
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Count => array.Length;
|
||||
|
||||
/// <inheritdoc cref="IList{T}.IndexOf"/>
|
||||
public int IndexOf(T item)
|
||||
{
|
||||
for (var i = 0; i < array.Length; i++)
|
||||
{
|
||||
if (array[i] == item)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Span{T}.Slice(int,int)"/>
|
||||
/// <remarks>This method being defined provides Range indexers for the class.</remarks>
|
||||
public Span<T> Slice(int start, int length) => new(array, start, length);
|
||||
|
||||
/// <inheritdoc cref="IList{T}.this"/>
|
||||
public T this[int index]
|
||||
{
|
||||
get => array[index];
|
||||
set => array[index] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a reference to the underlying memory of this object that is be pinned using the <see langword="fixed"/>
|
||||
/// statement.
|
||||
/// </summary>
|
||||
/// <returns>A reference to the first value in the underlying array.</returns>
|
||||
public ref T GetPinnableReference() => ref array[0] ;
|
||||
|
||||
private protected string Stringify(char prefix, char? suffix)
|
||||
{
|
||||
var sb = new StringBuilder(32 + array.Length * 4);
|
||||
sb.Append($"{StringifyName}:[{prefix};");
|
||||
|
||||
for (var i = 0; i < array.Length; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
sb.Append(',');
|
||||
sb.Append(array[i]);
|
||||
if (suffix != null)
|
||||
sb.Append(suffix.Value);
|
||||
}
|
||||
sb.Append(']');
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicit conversion of a an <see cref="ArrayTag{T}"/> to an array of <see cref="T"/>.
|
||||
/// </summary>
|
||||
/// <param name="tag">The <see cref="ArrayTag{T}"/> to be converted.</param>
|
||||
/// <returns>The value of <paramref name="tag"/> as an array of <see cref="T"/>.</returns>
|
||||
public static implicit operator T[](ArrayTag<T> tag) => tag.array;
|
||||
|
||||
/// <summary>
|
||||
/// Implicit conversion of a an <see cref="ArrayTag{T}"/> to a <see cref="Span{T}"/>.
|
||||
/// </summary>
|
||||
/// <param name="tag">The <see cref="ArrayTag{T}"/> to be converted.</param>
|
||||
/// <returns>The value of <paramref name="tag"/> as a <see cref="Span{T}"/>.</returns>
|
||||
public static implicit operator Span<T>(ArrayTag<T> tag) => new(tag.array);
|
||||
|
||||
/// <summary>
|
||||
/// Implicit conversion of a an <see cref="ArrayTag{T}"/> to a <see cref="Memory{T}"/>.
|
||||
/// </summary>
|
||||
/// <param name="tag">The <see cref="ArrayTag{T}"/> to be converted.</param>
|
||||
/// <returns>The value of <paramref name="tag"/> as a <see cref="Memory{T}"/>.</returns>
|
||||
public static implicit operator Memory<T>(ArrayTag<T> tag) => new(tag.array);
|
||||
|
||||
private readonly T[] array;
|
||||
}
|
||||
|
|
@ -12,19 +12,19 @@ namespace SharpNBT;
|
|||
/// actually serialized as.
|
||||
/// </remarks>
|
||||
[PublicAPI][Serializable]
|
||||
[Obsolete("Use the IsBool and Bool properties of ByteTag. This class will be removed in a future release.")]
|
||||
public class BoolTag : Tag<bool>
|
||||
[Obsolete("Use the IsBool and Bool properties of ByteTag. This class will be removed in a future version.")]
|
||||
public class BoolTag : Tag
|
||||
{
|
||||
private const string TRUE = "true";
|
||||
private const string FALSE = "false";
|
||||
|
||||
public bool Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="SharpNBT.ByteTag"/> class with the specified <paramref name="value"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the tag, or <see langword="null"/> if tag has no name.</param>
|
||||
/// <param name="value">The value to assign to this tag.</param>
|
||||
public BoolTag(string? name, bool value) : base(TagType.Byte, name, value)
|
||||
public BoolTag(string? name, bool value) : base(TagType.Byte, name)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -37,7 +37,7 @@ public class BoolTag : Tag<bool>
|
|||
}
|
||||
|
||||
/// <inheritdoc cref="object.ToString"/>
|
||||
public override string ToString() => $"TAG_Bool({PrettyName}): {(Value ? TRUE : FALSE)}";
|
||||
public override string ToString() => $"TAG_Byte({PrettyName}): {(Value ? "true" : "false")}";
|
||||
|
||||
/// <summary>
|
||||
/// Implicit conversion of this tag to a <see cref="byte"/>.
|
||||
|
|
@ -51,6 +51,6 @@ public class BoolTag : Tag<bool>
|
|||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}{(Value ? TRUE : FALSE)}";
|
||||
public override string Stringify() => $"{StringifyName}:{(Value ? "true" : "false")}";
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
|
|
@ -13,8 +14,17 @@ namespace SharpNBT;
|
|||
/// the bits are equivalent for your values.
|
||||
/// </remarks>
|
||||
[PublicAPI][Serializable]
|
||||
public class ByteArrayTag : EnumerableTag<byte>
|
||||
public class ByteArrayTag : ArrayTag<byte>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ByteArrayTag"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the tag, or <see langword="null"/> if tag has no name.</param>
|
||||
/// <param name="capacity">The capacity of the array.</param>
|
||||
public ByteArrayTag(string? name, int capacity) : base(TagType.IntArray, name, new byte[capacity])
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ByteArrayTag"/>.
|
||||
/// </summary>
|
||||
|
|
@ -29,7 +39,7 @@ public class ByteArrayTag : EnumerableTag<byte>
|
|||
/// </summary>
|
||||
/// <param name="name">The name of the tag, or <see langword="null"/> if tag has no name.</param>
|
||||
/// <param name="values">A collection of values to include in this tag.</param>
|
||||
public ByteArrayTag(string? name, IEnumerable<byte> values) : base(TagType.ByteArray, name, values)
|
||||
public ByteArrayTag(string? name, IEnumerable<byte> values) : base(TagType.ByteArray, name, values.ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +48,7 @@ public class ByteArrayTag : EnumerableTag<byte>
|
|||
/// </summary>
|
||||
/// <param name="name">The name of the tag, or <see langword="null"/> if tag has no name.</param>
|
||||
/// <param name="values">A collection of values to include in this tag.</param>
|
||||
public ByteArrayTag(string? name, ReadOnlySpan<byte> values) : base(TagType.ByteArray, name, values)
|
||||
public ByteArrayTag(string? name, ReadOnlySpan<byte> values) : base(TagType.ByteArray, name, values.ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -63,11 +73,5 @@ public class ByteArrayTag : EnumerableTag<byte>
|
|||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify()
|
||||
{
|
||||
var values = new string[Count];
|
||||
for (var i = 0; i < Count; i++)
|
||||
values[i] = $"{this[i]}b";
|
||||
return $"{StringifyName}[B;{string.Join(',', values)}]";
|
||||
}
|
||||
public override string Stringify() => Stringify('B', 'b');
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ namespace SharpNBT;
|
|||
/// equivalent.
|
||||
/// </remarks>
|
||||
[PublicAPI][Serializable]
|
||||
public class ByteTag : Tag<byte>
|
||||
public class ByteTag : NumericTag<byte>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a flag indicating if this <see cref="ByteTag"/> was assigned a <see cref="bool"/> value.
|
||||
|
|
@ -95,9 +95,13 @@ public class ByteTag : Tag<byte>
|
|||
protected ByteTag(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc cref="object.ToString"/>
|
||||
public override string ToString() => $"TAG_Byte({PrettyName}): {Value}";
|
||||
public override string ToString()
|
||||
{
|
||||
object obj = IsBool ? Bool : Value;
|
||||
return $"TAG_Byte({PrettyName}): {obj}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicit conversion of this tag to a <see cref="byte"/>.
|
||||
|
|
@ -126,5 +130,5 @@ public class ByteTag : Tag<byte>
|
|||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}{Value}B";
|
||||
public override string Stringify() => $"{StringifyName}:{Value}B";
|
||||
}
|
||||
|
|
@ -122,7 +122,9 @@ public class CompoundTag : TagContainer
|
|||
for (var i = 0; i < strings.Length; i++)
|
||||
strings[i] = this[i].Stringify();
|
||||
|
||||
return $"{StringifyName}{{{string.Join(',', strings)}}}";
|
||||
// TODO: Use StringBuilder
|
||||
|
||||
return $"{StringifyName}:{{{string.Join(',', strings)}}}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace SharpNBT;
|
|||
/// A tag that contains a single IEEE-754 double-precision floating point number.
|
||||
/// </summary>
|
||||
[PublicAPI][Serializable]
|
||||
public class DoubleTag : Tag<double>
|
||||
public class DoubleTag : NumericTag<double>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DoubleTag"/> class with the specified <paramref name="value"/>.
|
||||
|
|
@ -43,5 +43,5 @@ public class DoubleTag : Tag<double>
|
|||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}{Value:0.0}D";
|
||||
public override string Stringify() => $"{StringifyName}:{Value:0.0}D";
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using JetBrains.Annotations;
|
||||
|
|
@ -72,7 +71,9 @@ public abstract class EnumerableTag<T> : Tag, IList<T>
|
|||
protected EnumerableTag(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
var dummy = info.GetInt32("count");
|
||||
internalList.AddRange((T[]) info.GetValue("values", typeof(T[])));
|
||||
var obj = info.GetValue("values", typeof(T[])) as T[];
|
||||
if (obj is IEnumerable<T> e)
|
||||
internalList.AddRange(e);
|
||||
}
|
||||
|
||||
/// <summary>Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo" /> with the data needed to serialize the target object.</summary>
|
||||
|
|
@ -101,7 +102,7 @@ public abstract class EnumerableTag<T> : Tag, IList<T>
|
|||
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only.</exception>
|
||||
/// <footer><a href="https://docs.microsoft.com/en-us/dotnet/api/System.Collections.Generic.ICollection-1.Add?view=netcore-5.0">`ICollection.Add` on docs.microsoft.com</a></footer>
|
||||
[SuppressMessage("ReSharper", "AnnotationConflictInHierarchy")]
|
||||
public virtual void Add([DisallowNull] T item) => internalList.Add(item);
|
||||
public virtual void Add(T item) => internalList.Add(item);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the elements of the specified collection to the <see cref="EnumerableTag{T}"/>.
|
||||
|
|
@ -121,7 +122,7 @@ public abstract class EnumerableTag<T> : Tag, IList<T>
|
|||
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1" /> is read-only.</exception>
|
||||
/// <footer><a href="https://docs.microsoft.com/en-us/dotnet/api/System.Collections.Generic.IList-1.Insert?view=netcore-5.0">`IList.Insert` on docs.microsoft.com</a></footer>
|
||||
[SuppressMessage("ReSharper", "AnnotationConflictInHierarchy")]
|
||||
public virtual void Insert(int index, [DisallowNull] T item) => internalList.Insert(index, item);
|
||||
public virtual void Insert(int index, T item) => internalList.Insert(index, item);
|
||||
|
||||
/// <summary>Gets or sets the element at the specified index.</summary>
|
||||
/// <param name="index">The zero-based index of the element to get or set.</param>
|
||||
|
|
@ -130,7 +131,6 @@ public abstract class EnumerableTag<T> : Tag, IList<T>
|
|||
/// <exception cref="T:System.NotSupportedException">The property is set and the <see cref="T:System.Collections.Generic.IList`1" /> is read-only.</exception>
|
||||
/// <returns>The element at the specified index.</returns>
|
||||
/// <footer><a href="https://docs.microsoft.com/en-us/dotnet/api/System.Collections.Generic.IList-1.Item?view=netcore-5.0">`IList.Item` on docs.microsoft.com</a></footer>
|
||||
[DisallowNull]
|
||||
public virtual T this[int index]
|
||||
{
|
||||
get => internalList[index];
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace SharpNBT;
|
|||
/// A tag that contains a single IEEE-754 single-precision floating point number.
|
||||
/// </summary>
|
||||
[PublicAPI][Serializable]
|
||||
public class FloatTag : Tag<float>
|
||||
public class FloatTag : NumericTag<float>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="FloatTag"/> class with the specified <paramref name="value"/>.
|
||||
|
|
@ -42,5 +42,5 @@ public class FloatTag : Tag<float>
|
|||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}{Value:0.0}F";
|
||||
public override string Stringify() => $"{StringifyName}:{Value:0.0}F";
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
|
|
@ -9,15 +10,17 @@ namespace SharpNBT;
|
|||
/// A tag that whose value is a contiguous sequence of 32-bit integers.
|
||||
/// </summary>
|
||||
[PublicAPI][Serializable]
|
||||
public class IntArrayTag : EnumerableTag<int>
|
||||
public class IntArrayTag : ArrayTag<int>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IntArrayTag"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the tag, or <see langword="null"/> if tag has no name.</param>
|
||||
public IntArrayTag(string? name) : base(TagType.IntArray, name)
|
||||
/// <param name="capacity">The capacity of the array.</param>
|
||||
public IntArrayTag(string? name, int capacity) : base(TagType.IntArray, name, new int[capacity])
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IntArrayTag"/> with the specified <paramref name="values"/>.
|
||||
/// </summary>
|
||||
|
|
@ -33,7 +36,7 @@ public class IntArrayTag : EnumerableTag<int>
|
|||
/// </summary>
|
||||
/// <param name="name">The name of the tag, or <see langword="null"/> if tag has no name.</param>
|
||||
/// <param name="values">A collection of values to include in this tag.</param>
|
||||
public IntArrayTag(string? name, IEnumerable<int> values) : base(TagType.IntArray, name, values)
|
||||
public IntArrayTag(string? name, IEnumerable<int> values) : base(TagType.IntArray, name, values.ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +45,7 @@ public class IntArrayTag : EnumerableTag<int>
|
|||
/// </summary>
|
||||
/// <param name="name">The name of the tag, or <see langword="null"/> if tag has no name.</param>
|
||||
/// <param name="values">A collection of values to include in this tag.</param>
|
||||
public IntArrayTag(string? name, ReadOnlySpan<int> values) : base(TagType.IntArray, name, values)
|
||||
public IntArrayTag(string? name, ReadOnlySpan<int> values) : base(TagType.IntArray, name, values.ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -67,5 +70,5 @@ public class IntArrayTag : EnumerableTag<int>
|
|||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}[I;{string.Join(',', this)}]";
|
||||
public override string Stringify() => Stringify('I', null);
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ namespace SharpNBT;
|
|||
/// A tag that contains a single 32-bit integer value.
|
||||
/// </summary>
|
||||
[PublicAPI][Serializable]
|
||||
public class IntTag : Tag<int>
|
||||
public class IntTag : NumericTag<int>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the value of this tag as an unsigned value.
|
||||
|
|
@ -70,5 +70,5 @@ public class IntTag : Tag<int>
|
|||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}{Value}";
|
||||
public override string Stringify() => $"{StringifyName}:{Value}";
|
||||
}
|
||||
|
|
@ -96,6 +96,8 @@ public class ListTag : TagContainer
|
|||
for (var i = 0; i < strings.Length; i++)
|
||||
strings[i] = this[i].Stringify();
|
||||
|
||||
return $"{StringifyName}[{string.Join(',', strings)}]";
|
||||
// TODO: Use StringBuilder
|
||||
|
||||
return $"{StringifyName}:[{string.Join(',', strings)}]";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
|
|
@ -9,13 +10,14 @@ namespace SharpNBT;
|
|||
/// A tag that whose value is a contiguous sequence of 64-bit integers.
|
||||
/// </summary>
|
||||
[PublicAPI][Serializable]
|
||||
public class LongArrayTag : EnumerableTag<long>
|
||||
public class LongArrayTag : ArrayTag<long>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LongArrayTag"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the tag, or <see langword="null"/> if tag has no name.</param>
|
||||
public LongArrayTag(string? name) : base(TagType.LongArray, name)
|
||||
/// <param name="capacity">The capacity of the array.</param>
|
||||
public LongArrayTag(string? name, int capacity) : base(TagType.LongArray, name, new long[capacity])
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
|
|
@ -23,7 +25,7 @@ public class LongArrayTag : EnumerableTag<long>
|
|||
/// </summary>
|
||||
/// <param name="name">The name of the tag, or <see langword="null"/> if tag has no name.</param>
|
||||
/// <param name="values">A collection of values to include in this tag.</param>
|
||||
public LongArrayTag(string? name, long[] values) : base(TagType.LongArray, name, values)
|
||||
public LongArrayTag(string? name, long[] values) : base(TagType.LongArray, name, values.ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +43,7 @@ public class LongArrayTag : EnumerableTag<long>
|
|||
/// </summary>
|
||||
/// <param name="name">The name of the tag, or <see langword="null"/> if tag has no name.</param>
|
||||
/// <param name="values">A collection of values to include in this tag.</param>
|
||||
public LongArrayTag(string? name, IEnumerable<long> values) : base(TagType.LongArray, name, values)
|
||||
public LongArrayTag(string? name, IEnumerable<long> values) : base(TagType.LongArray, name, values.ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +52,7 @@ public class LongArrayTag : EnumerableTag<long>
|
|||
/// </summary>
|
||||
/// <param name="name">The name of the tag, or <see langword="null"/> if tag has no name.</param>
|
||||
/// <param name="values">A collection of values to include in this tag.</param>
|
||||
public LongArrayTag(string? name, ReadOnlySpan<long> values) : base(TagType.LongArray, name, values)
|
||||
public LongArrayTag(string? name, ReadOnlySpan<long> values) : base(TagType.LongArray, name, values.ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -66,11 +68,5 @@ public class LongArrayTag : EnumerableTag<long>
|
|||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify()
|
||||
{
|
||||
var values = new string[Count];
|
||||
for (var i = 0; i < Count; i++)
|
||||
values[i] = $"{this[i]}l";
|
||||
return $"{StringifyName}[L;{string.Join(',', values)}]";
|
||||
}
|
||||
public override string Stringify() => Stringify('L', 'l');
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ namespace SharpNBT;
|
|||
/// A tag that contains a single 64-bit integer value.
|
||||
/// </summary>
|
||||
[PublicAPI][Serializable]
|
||||
public class LongTag : Tag<long>
|
||||
public class LongTag : NumericTag<long>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the value of this tag as an unsigned value.
|
||||
|
|
@ -70,5 +70,5 @@ public class LongTag : Tag<long>
|
|||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}{Value}L";
|
||||
public override string Stringify() => $"{StringifyName}:{Value}L";
|
||||
}
|
||||
|
|
@ -13,19 +13,32 @@ namespace SharpNBT;
|
|||
[PublicAPI][Serializable]
|
||||
public abstract class NumericTag<T> : Tag, IEquatable<NumericTag<T>>, IComparable<NumericTag<T>>, IComparable where T : unmanaged, INumber<T>
|
||||
{
|
||||
public T Value { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the tag.
|
||||
/// </summary>
|
||||
public T Value { get; [Obsolete("Numeric tag types will be made immutable in a future version.")] set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected NumericTag(TagType type, string? name, T value) : base(type, name)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected NumericTag(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
var value = info.GetValue("value", typeof(T));
|
||||
Value = value is null ? default : (T)value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
base.GetObjectData(info, context);
|
||||
info.AddValue("value", Value, typeof(T));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(NumericTag<T>? other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
|
|
@ -33,6 +46,7 @@ public abstract class NumericTag<T> : Tag, IEquatable<NumericTag<T>>, IComparabl
|
|||
return base.Equals(other) && Value.Equals(other.Value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
|
|
@ -41,8 +55,10 @@ public abstract class NumericTag<T> : Tag, IEquatable<NumericTag<T>>, IComparabl
|
|||
return Equals((NumericTag<T>)obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode() => base.GetHashCode();
|
||||
|
||||
/// <inheritdoc />
|
||||
public int CompareTo(NumericTag<T>? other)
|
||||
{
|
||||
if (ReferenceEquals(this, other)) return 0;
|
||||
|
|
@ -50,6 +66,7 @@ public abstract class NumericTag<T> : Tag, IEquatable<NumericTag<T>>, IComparabl
|
|||
return Value.CompareTo(other.Value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return 1;
|
||||
|
|
@ -57,27 +74,80 @@ public abstract class NumericTag<T> : Tag, IEquatable<NumericTag<T>>, IComparabl
|
|||
return obj is NumericTag<T> other ? CompareTo(other) : throw new ArgumentException($"Object must be of type {nameof(NumericTag<T>)}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares two values to determine equality.
|
||||
/// </summary>
|
||||
/// <param name="left">The value to compare with <paramref name="right" />.</param>
|
||||
/// <param name="right">The value to compare with <paramref name="left" />.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if <paramref name="left" /> is equal to <paramref name="right" />; otherwise,
|
||||
/// <see langword="false" />.
|
||||
/// </returns>
|
||||
public static bool operator ==(NumericTag<T>? left, NumericTag<T>? right) => Equals(left, right);
|
||||
|
||||
/// <summary>
|
||||
/// Compares two values to determine inequality.
|
||||
/// </summary>
|
||||
/// <param name="left">The value to compare with <paramref name="right" />.</param>
|
||||
/// <param name="right">The value to compare with <paramref name="left" />.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if <paramref name="left" /> is not equal to <paramref name="right" />; otherwise,
|
||||
/// <see langword="false" />.
|
||||
/// </returns>
|
||||
public static bool operator !=(NumericTag<T>? left, NumericTag<T>? right) => !Equals(left, right);
|
||||
|
||||
/// <summary>Compares two values to determine which is less.</summary>
|
||||
/// <param name="left">The value to compare with <paramref name="right" />.</param>
|
||||
/// <param name="right">The value to compare with <paramref name="left" />.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if <paramref name="left" /> is less than <paramref name="right" />; otherwise,
|
||||
/// <see langword="false" />.
|
||||
/// </returns>
|
||||
public static bool operator <(NumericTag<T>? left, NumericTag<T>? right)
|
||||
{
|
||||
return Comparer<NumericTag<T>>.Default.Compare(left, right) < 0;
|
||||
}
|
||||
|
||||
/// <summary>Compares two values to determine which is greater.</summary>
|
||||
/// <param name="left">The value to compare with <paramref name="right" />.</param>
|
||||
/// <param name="right">The value to compare with <paramref name="left" />.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if <paramref name="left" /> is greater than <paramref name="right" />; otherwise,
|
||||
/// <see langword="false" />.
|
||||
/// </returns>
|
||||
public static bool operator >(NumericTag<T>? left, NumericTag<T>? right)
|
||||
{
|
||||
return Comparer<NumericTag<T>>.Default.Compare(left, right) > 0;
|
||||
}
|
||||
|
||||
/// <summary>Compares two values to determine which is less or equal.</summary>
|
||||
/// <param name="left">The value to compare with <paramref name="right" />.</param>
|
||||
/// <param name="right">The value to compare with <paramref name="left" />.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if <paramref name="left" /> is less than or equal to <paramref name="right" />;
|
||||
/// otherwise, <see langword="false" />.
|
||||
/// </returns>
|
||||
public static bool operator <=(NumericTag<T>? left, NumericTag<T>? right)
|
||||
{
|
||||
return Comparer<NumericTag<T>>.Default.Compare(left, right) <= 0;
|
||||
}
|
||||
|
||||
/// <summary>Compares two values to determine which is greater or equal.</summary>
|
||||
/// <param name="left">The value to compare with <paramref name="right" />.</param>
|
||||
/// <param name="right">The value to compare with <paramref name="left" />.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if <paramref name="left" /> is greater than or equal to <paramref name="right" />;
|
||||
/// otherwise, <see langword="false" />.
|
||||
/// </returns>
|
||||
public static bool operator >=(NumericTag<T>? left, NumericTag<T>? right)
|
||||
{
|
||||
return Comparer<NumericTag<T>>.Default.Compare(left, right) >= 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicit conversion of a an <see cref="NumericTag{T}"/> to a <see cref="T"/>.
|
||||
/// </summary>
|
||||
/// <param name="tag">The <see cref="NumericTag{T}"/> to be converted.</param>
|
||||
/// <returns>The value of <paramref name="tag"/> as a <see cref="T"/>.</returns>
|
||||
public static implicit operator T(NumericTag<T> tag) => tag.Value;
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ namespace SharpNBT;
|
|||
/// A tag that contains a single 16-bit integer value.
|
||||
/// </summary>
|
||||
[PublicAPI][Serializable]
|
||||
public class ShortTag : Tag<short>
|
||||
public class ShortTag : NumericTag<short>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the value of this tag as an unsigned value.
|
||||
|
|
@ -76,5 +76,5 @@ public class ShortTag : Tag<short>
|
|||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}{Value}S";
|
||||
public override string Stringify() => $"{StringifyName}:{Value}S";
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.Serialization;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
|
|
@ -8,26 +9,36 @@ namespace SharpNBT;
|
|||
/// A tag the contains a UTF-8 string.
|
||||
/// </summary>
|
||||
[PublicAPI][Serializable]
|
||||
public class StringTag : Tag<string>
|
||||
public class StringTag : Tag, IEquatable<StringTag>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the tag.
|
||||
/// </summary>
|
||||
public string Value { get; [Obsolete("String tag type will be made immutable in a future version.")] set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="StringTag"/> class with the specified <paramref name="value"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the tag, or <see langword="null"/> if tag has no name.</param>
|
||||
/// <param name="value">The value to assign to this tag.</param>
|
||||
public StringTag(string? name, string? value) : base(TagType.String, name, value)
|
||||
public StringTag(string? name, string? value) : base(TagType.String, name)
|
||||
{
|
||||
Value = value ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Required constructor for ISerializable implementation.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> to describing this instance.</param>
|
||||
/// <param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext" />) for this serialization.</param>
|
||||
/// <inheritdoc />
|
||||
protected StringTag(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
Value = info.GetString("value") ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
base.GetObjectData(info, context);
|
||||
info.AddValue("value", Value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="object.ToString"/>
|
||||
public override string ToString() => $"TAG_String({PrettyName}): \"{Value}\"";
|
||||
|
||||
|
|
@ -43,5 +54,46 @@ public class StringTag : Tag<string>
|
|||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => $"{StringifyName}\"{Value}\"";
|
||||
public override string Stringify() => $"{StringifyName}:\"{Value}\""; // TODO: Does this get properly escaped?
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(StringTag? other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return base.Equals(other) && string.CompareOrdinal(Value, other.Value) == 0;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
return obj.GetType() == GetType() && Equals((StringTag)obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int GetHashCode() => base.GetHashCode(); // TODO: Add Value once immutable
|
||||
|
||||
/// <summary>
|
||||
/// Compares two values to determine equality.
|
||||
/// </summary>
|
||||
/// <param name="left">The value to compare with <paramref name="right" />.</param>
|
||||
/// <param name="right">The value to compare with <paramref name="left" />.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if <paramref name="left" /> is equal to <paramref name="right" />; otherwise,
|
||||
/// <see langword="false" />.
|
||||
/// </returns>
|
||||
public static bool operator ==(StringTag? left, StringTag? right) => Equals(left, right);
|
||||
|
||||
/// <summary>
|
||||
/// Compares two values to determine inequality.
|
||||
/// </summary>
|
||||
/// <param name="left">The value to compare with <paramref name="right" />.</param>
|
||||
/// <param name="right">The value to compare with <paramref name="left" />.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if <paramref name="left" /> is not equal to <paramref name="right" />; otherwise,
|
||||
/// <see langword="false" />.
|
||||
/// </returns>
|
||||
public static bool operator !=(StringTag? left, StringTag? right) => !Equals(left, right);
|
||||
}
|
||||
|
|
@ -32,7 +32,8 @@ public abstract class Tag : IEquatable<Tag>, ISerializable, ICloneable
|
|||
return new[]
|
||||
{
|
||||
typeof(TagType),
|
||||
typeof(Tag<>),
|
||||
typeof(NumericTag<>),
|
||||
typeof(ArrayTag<>),
|
||||
typeof(Tag[]),
|
||||
typeof(EnumerableTag<>),
|
||||
typeof(TagContainer),
|
||||
|
|
@ -81,15 +82,20 @@ public abstract class Tag : IEquatable<Tag>, ISerializable, ICloneable
|
|||
Type = type;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes this tag as a formatted string to the given <paramref name="buffer"/>.
|
||||
/// </summary>
|
||||
/// <param name="buffer">A <see cref="StringBuilder"/> instance to write to.</param>
|
||||
/// <param name="level">The current indent depth to write at.</param>
|
||||
/// <param name="indent">The string to use for indents.</param>
|
||||
protected internal abstract void PrettyPrinted(StringBuilder buffer, int level, string indent);
|
||||
|
||||
protected internal virtual void PrettyPrinted(StringBuilder buffer, int level, string indent)
|
||||
{
|
||||
for (var i = 0; i < level; i++)
|
||||
buffer.Append(indent);
|
||||
buffer.AppendLine(ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the object as a human-readable quoted string, or a default name to indicate it has no name when applicable.
|
||||
/// </summary>
|
||||
|
|
@ -234,113 +240,7 @@ public abstract class Tag : IEquatable<Tag>, ISerializable, ICloneable
|
|||
{
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
return string.Empty;
|
||||
return simpleNameMatcher.IsMatch(Name) ? $"{Name}: " : $"\"{Name}\": ";
|
||||
return simpleNameMatcher.IsMatch(Name) ? Name : $"\"{Name}\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract base class for <see cref="Tag"/> types that contain a single primitive value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the value the tag represents.</typeparam>
|
||||
[PublicAPI][Serializable]
|
||||
public abstract class Tag<T> : Tag, IEquatable<Tag<T>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the tag.
|
||||
/// </summary>
|
||||
public T Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Required constructor for ISerializable implementation.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> to describing this instance.</param>
|
||||
/// <param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext" />) for this serialization.</param>
|
||||
protected Tag(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
Value = (T)info.GetValue("value", typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo" /> with the data needed to serialize the target object.</summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> to populate with data.</param>
|
||||
/// <param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext" />) for this serialization.</param>
|
||||
/// <exception cref="T:System.Security.SecurityException">The caller does not have the required permission.</exception>
|
||||
public override void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
base.GetObjectData(info, context);
|
||||
info.AddValue("value", Value, typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DoubleTag"/> class with the specified <paramref name="value"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">A constant describing the NBT type for this tag.</param>
|
||||
/// <param name="name">The name of the tag, or <see langword="null"/> if tag has no name.</param>
|
||||
/// <param name="value">The value to assign to this tag.</param>
|
||||
protected Tag(TagType type, string? name, T value) : base(type, name)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Tag.PrettyPrinted(StringBuilder,int,string)"/>
|
||||
protected internal override void PrettyPrinted(StringBuilder buffer, int level, string indent)
|
||||
{
|
||||
for (var i = 0; i < level; i++)
|
||||
buffer.Append(indent);
|
||||
buffer.AppendLine(ToString());
|
||||
}
|
||||
|
||||
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
|
||||
/// <param name="other">An object to compare with this object.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if the current object is equal to the <paramref name="other" /> parameter; otherwise, <see langword="false" />.</returns>
|
||||
/// <footer><a href="https://docs.microsoft.com/en-us/dotnet/api/System.IEquatable-1.Equals?view=netstandard-2.1">`IEquatable.Equals` on docs.microsoft.com</a></footer>
|
||||
public bool Equals(Tag<T>? other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return base.Equals(other) && EqualityComparer<T>.Default.Equals(Value, other.Value);
|
||||
}
|
||||
|
||||
/// <summary>Determines whether the specified object is equal to the current object.</summary>
|
||||
/// <param name="obj">The object to compare with the current object.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if the specified object is equal to the current object; otherwise, <see langword="false" />.</returns>
|
||||
/// <footer><a href="https://docs.microsoft.com/en-us/dotnet/api/System.Object.Equals?view=netstandard-2.1">`Object.Equals` on docs.microsoft.com</a></footer>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != GetType()) return false;
|
||||
return Equals((Tag<T>)obj);
|
||||
}
|
||||
|
||||
/// <summary>Serves as the default hash function.</summary>
|
||||
/// <returns>A hash code for the current object.</returns>
|
||||
/// <footer><a href="https://docs.microsoft.com/en-us/dotnet/api/System.Object.GetHashCode?view=netstandard-2.1">`Object.GetHashCode` on docs.microsoft.com</a></footer>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
// ReSharper disable NonReadonlyMemberInGetHashCode
|
||||
return (base.GetHashCode() * 421) ^ EqualityComparer<T>.Default.GetHashCode(Value);
|
||||
// ReSharper restore NonReadonlyMemberInGetHashCode
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests for equality of this object with another <see cref="Tag"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="left">First value to compare.</param>
|
||||
/// <param name="right">Second value to compare.</param>
|
||||
/// <returns>Result of comparison.</returns>
|
||||
public static bool operator ==(Tag<T> left, Tag<T> right) => Equals(left, right);
|
||||
|
||||
/// <summary>
|
||||
/// Tests for inequality of this object with another <see cref="Tag"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="left">First value to compare.</param>
|
||||
/// <param name="right">Second value to compare.</param>
|
||||
/// <returns>Result of comparison.</returns>
|
||||
public static bool operator !=(Tag<T> left, Tag<T> right) => !Equals(left, right);
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ public enum TagType : byte
|
|||
/// <summary>
|
||||
/// Signifies the end of a <see cref="CompoundTag"/>.
|
||||
/// </summary>
|
||||
/// <remarks>Some implementation may also use as the child type for an empty list.</remarks>
|
||||
End = 0x00,
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
Loading…
Reference in New Issue