Implemented a stack getting naming strategy during serialization
This commit is contained in:
parent
7bb273b262
commit
bf700464fa
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpNBT.Tests
|
||||
{
|
||||
public class CompressionTest : IDisposable
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadUncompressed()
|
||||
{
|
||||
using var stream = NbtStream.OpenRead("./Data/hello_world.nbt");
|
||||
var compound = stream.ReadTag<CompoundTag>();
|
||||
Assert.Equal("hello world", compound.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadCompressed()
|
||||
{
|
||||
using var stream = NbtStream.OpenRead("./Data/bigtest.nbt");
|
||||
var compound = stream.ReadTag<CompoundTag>();
|
||||
Assert.Equal("Level", compound.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ namespace SharpNBT
|
|||
/// <returns>The deserialized <see cref="ByteTag"/> instance.</returns>
|
||||
public new ByteTag ReadByte()
|
||||
{
|
||||
var name = named ? ReadPrefixedString() : null;
|
||||
var name = nameStack.Peek() ? ReadPrefixedString() : null;
|
||||
return new ByteTag(name, (byte)BaseStream.ReadByte());
|
||||
}
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ namespace SharpNBT
|
|||
/// <returns>The deserialized <see cref="ShortTag"/> instance.</returns>
|
||||
public ShortTag ReadShort()
|
||||
{
|
||||
var name = named ? ReadPrefixedString() : null;
|
||||
var name = nameStack.Peek() ? ReadPrefixedString() : null;
|
||||
return new ShortTag(name, BitConverter.ToInt16(ReadNumber(sizeof(short))));
|
||||
}
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ namespace SharpNBT
|
|||
/// <returns>The deserialized <see cref="IntTag"/> instance.</returns>
|
||||
public IntTag ReadInt()
|
||||
{
|
||||
var name = named ? ReadPrefixedString() : null;
|
||||
var name = nameStack.Peek() ? ReadPrefixedString() : null;
|
||||
return new IntTag(name, BitConverter.ToInt32(ReadNumber(sizeof(int))));
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ namespace SharpNBT
|
|||
/// <returns>The deserialized <see cref="LongTag"/> instance.</returns>
|
||||
public LongTag ReadLong()
|
||||
{
|
||||
var name = named ? ReadPrefixedString() : null;
|
||||
var name = nameStack.Peek() ? ReadPrefixedString() : null;
|
||||
return new LongTag(name, BitConverter.ToInt64(ReadNumber(sizeof(long))));
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ namespace SharpNBT
|
|||
/// <returns>The deserialized <see cref="FloatTag"/> instance.</returns>
|
||||
public FloatTag ReadFloat()
|
||||
{
|
||||
var name = named ? ReadPrefixedString() : null;
|
||||
var name = nameStack.Peek() ? ReadPrefixedString() : null;
|
||||
return new FloatTag(name, BitConverter.ToSingle(ReadNumber(sizeof(float))));
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ namespace SharpNBT
|
|||
/// <returns>The deserialized <see cref="DoubleTag"/> instance.</returns>
|
||||
public DoubleTag ReadDouble()
|
||||
{
|
||||
var name = named ? ReadPrefixedString() : null;
|
||||
var name = nameStack.Peek() ? ReadPrefixedString() : null;
|
||||
return new DoubleTag( name, BitConverter.ToDouble(ReadNumber(sizeof(double))));
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ namespace SharpNBT
|
|||
/// <returns>The deserialized <see cref="StringTag"/> instance.</returns>
|
||||
public StringTag ReadString()
|
||||
{
|
||||
var name = named ? ReadPrefixedString() : null;
|
||||
var name = nameStack.Peek() ? ReadPrefixedString() : null;
|
||||
var value = ReadPrefixedString();
|
||||
return new StringTag(name, value);
|
||||
}
|
||||
|
|
@ -93,7 +93,7 @@ namespace SharpNBT
|
|||
/// <returns>The deserialized <see cref="ByteArrayTag"/> instance.</returns>
|
||||
public ByteArrayTag ReadByteArray()
|
||||
{
|
||||
var name = named ? ReadPrefixedString() : null;
|
||||
var name = nameStack.Peek() ? ReadPrefixedString() : null;
|
||||
var count = BitConverter.ToInt32(ReadNumber(sizeof(int)));
|
||||
var buffer = new byte[count];
|
||||
BaseStream.Read(buffer, 0, count);
|
||||
|
|
@ -109,7 +109,7 @@ namespace SharpNBT
|
|||
{
|
||||
const int INT_SIZE = sizeof(int);
|
||||
|
||||
var name = named ? ReadPrefixedString() : null;
|
||||
var name = nameStack.Peek() ? ReadPrefixedString() : null;
|
||||
var count = BitConverter.ToInt32(ReadNumber(sizeof(int)));
|
||||
var buffer = new byte[count * INT_SIZE];
|
||||
BaseStream.Read(buffer, 0, count * INT_SIZE);
|
||||
|
|
@ -143,7 +143,7 @@ namespace SharpNBT
|
|||
{
|
||||
const int LONG_SIZE = sizeof(long);
|
||||
|
||||
var name = named ? ReadPrefixedString() : null;
|
||||
var name = nameStack.Peek() ? ReadPrefixedString() : null;
|
||||
var count = BitConverter.ToInt32(ReadNumber(sizeof(int)));
|
||||
var buffer = new byte[count * LONG_SIZE];
|
||||
BaseStream.Read(buffer, 0, count * LONG_SIZE);
|
||||
|
|
@ -177,19 +177,18 @@ namespace SharpNBT
|
|||
/// <returns>The deserialized <see cref="ListTag"/> instance.</returns>
|
||||
public ListTag ReadList()
|
||||
{
|
||||
var name = named ? ReadPrefixedString() : null;
|
||||
var name = nameStack.Peek() ? ReadPrefixedString() : null;
|
||||
var childType = ReadType();
|
||||
var count = BitConverter.ToInt32(ReadNumber(sizeof(int)));
|
||||
var list = new ListTag(name, childType);
|
||||
|
||||
var previous = named;
|
||||
named = false;
|
||||
nameStack.Push(false);
|
||||
while (count-- > 0)
|
||||
{
|
||||
list.Add(ReadTag(childType));
|
||||
}
|
||||
named = previous;
|
||||
|
||||
nameStack.Pop();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
|
@ -200,10 +199,9 @@ namespace SharpNBT
|
|||
/// <returns>The deserialized <see cref="CompoundTag"/> instance.</returns>
|
||||
public CompoundTag ReadCompound()
|
||||
{
|
||||
var name = named ? ReadPrefixedString() : null;
|
||||
var name = nameStack.Peek() ? ReadPrefixedString() : null;
|
||||
var compound = new CompoundTag(name);
|
||||
var previous = named;
|
||||
named = true;
|
||||
nameStack.Push(true);
|
||||
while (true)
|
||||
{
|
||||
var type = ReadType();
|
||||
|
|
@ -211,8 +209,7 @@ namespace SharpNBT
|
|||
break;
|
||||
compound.Add(ReadTag(type));
|
||||
}
|
||||
|
||||
named = previous;
|
||||
nameStack.Pop();
|
||||
|
||||
return compound;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,6 @@ namespace SharpNBT
|
|||
{
|
||||
public partial class NbtStream
|
||||
{
|
||||
|
||||
private bool named = true;
|
||||
|
||||
public void WriteType(Tag tag)
|
||||
{
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
|
|
@ -18,7 +15,7 @@ namespace SharpNBT
|
|||
public void WriteByte(ByteTag tag)
|
||||
{
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
if (named)
|
||||
if (nameStack.Peek())
|
||||
WriteString(tag.Name);
|
||||
BaseStream.WriteByte(tag.Value);
|
||||
}
|
||||
|
|
@ -26,7 +23,7 @@ namespace SharpNBT
|
|||
public void WriteShort(ShortTag tag)
|
||||
{
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
if (named)
|
||||
if (nameStack.Peek())
|
||||
WriteString(tag.Name);
|
||||
WriteNumber(BitConverter.GetBytes(tag.Value));
|
||||
}
|
||||
|
|
@ -34,7 +31,7 @@ namespace SharpNBT
|
|||
public void WriteInt(IntTag tag)
|
||||
{
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
if (named)
|
||||
if (nameStack.Peek())
|
||||
WriteString(tag.Name);
|
||||
WriteNumber(BitConverter.GetBytes(tag.Value));
|
||||
}
|
||||
|
|
@ -42,7 +39,7 @@ namespace SharpNBT
|
|||
public void WriteLong(LongTag tag)
|
||||
{
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
if (named)
|
||||
if (nameStack.Peek())
|
||||
WriteString(tag.Name);
|
||||
WriteNumber(BitConverter.GetBytes(tag.Value));
|
||||
}
|
||||
|
|
@ -50,7 +47,7 @@ namespace SharpNBT
|
|||
public void WriteFloat(FloatTag tag)
|
||||
{
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
if (named)
|
||||
if (nameStack.Peek())
|
||||
WriteString(tag.Name);
|
||||
WriteNumber(BitConverter.GetBytes(tag.Value));
|
||||
}
|
||||
|
|
@ -58,7 +55,7 @@ namespace SharpNBT
|
|||
public void WriteDouble(DoubleTag tag)
|
||||
{
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
if (named)
|
||||
if (nameStack.Peek())
|
||||
WriteString(tag.Name);
|
||||
WriteNumber(BitConverter.GetBytes(tag.Value));
|
||||
}
|
||||
|
|
@ -66,7 +63,7 @@ namespace SharpNBT
|
|||
public void WriteString(StringTag tag)
|
||||
{
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
if (named)
|
||||
if (nameStack.Peek())
|
||||
WriteString(tag.Name);
|
||||
WriteString(tag.Value);
|
||||
}
|
||||
|
|
@ -74,7 +71,7 @@ namespace SharpNBT
|
|||
public void WriteByteArray(ByteArrayTag tag)
|
||||
{
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
if (named)
|
||||
if (nameStack.Peek())
|
||||
WriteString(tag.Name);
|
||||
|
||||
WriteNumber(BitConverter.GetBytes(tag.Count));
|
||||
|
|
@ -86,7 +83,7 @@ namespace SharpNBT
|
|||
const int INT_SIZE = sizeof(int);
|
||||
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
if (named)
|
||||
if (nameStack.Peek())
|
||||
WriteString(tag.Name);
|
||||
|
||||
WriteNumber(BitConverter.GetBytes(tag.Count));
|
||||
|
|
@ -121,7 +118,7 @@ namespace SharpNBT
|
|||
const int LONG_SIZE = sizeof(long);
|
||||
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
if (named)
|
||||
if (nameStack.Peek())
|
||||
WriteString(tag.Name);
|
||||
|
||||
WriteNumber(BitConverter.GetBytes(tag.Count));
|
||||
|
|
@ -154,29 +151,31 @@ namespace SharpNBT
|
|||
public void WriteList(ListTag tag)
|
||||
{
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
if (named)
|
||||
if (nameStack.Peek())
|
||||
WriteString(tag.Name);
|
||||
|
||||
BaseStream.WriteByte((byte) tag.ChildType);
|
||||
WriteNumber(BitConverter.GetBytes(tag.Count));
|
||||
|
||||
named = false;
|
||||
nameStack.Push(false);
|
||||
foreach (var child in tag)
|
||||
WriteTag(child);
|
||||
named = true;
|
||||
nameStack.Pop();
|
||||
}
|
||||
|
||||
public void WriteCompound(CompoundTag tag)
|
||||
{
|
||||
BaseStream.WriteByte((byte) tag.Type);
|
||||
if (named)
|
||||
if (nameStack.Peek())
|
||||
WriteString(tag.Name);
|
||||
|
||||
nameStack.Push(true);
|
||||
foreach (var child in tag)
|
||||
{
|
||||
child.Parent = tag;
|
||||
WriteTag(child);
|
||||
}
|
||||
nameStack.Pop();
|
||||
|
||||
WriteEndTag();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,21 +13,15 @@ namespace SharpNBT
|
|||
public partial class NbtStream : Stream
|
||||
{
|
||||
protected readonly Stream BaseStream;
|
||||
private readonly Stack<Tag> topLevel;
|
||||
|
||||
// /// <summary>
|
||||
// /// Opens a <see cref="NbtStream"/> on the specified <paramref name="path"/> with read/write access.
|
||||
// /// </summary>
|
||||
// /// <param name="path">The path to a file to open.</param>
|
||||
// /// <param name="mode">
|
||||
// /// A value that specified whether a file is created if one does not exist, and determines
|
||||
// /// whether the contents of an existing file are retained or overwritten.
|
||||
// /// </param>
|
||||
// /// <returns>A <see cref="NbtStream"/> opened in the specified mode and path, with read/write access.</returns>
|
||||
// public static NbtStream Open(string path, FileMode mode) => new(File.Open(path, mode));
|
||||
//
|
||||
// public static NbtStream Open(string path, FileMode mode, FileAccess access) => new(File.Open(path, mode, access));
|
||||
private readonly Stack<bool> nameStack;
|
||||
|
||||
/// <summary>
|
||||
/// Opens a <see cref="NbtStream"/> on the specified <paramref name="path"/> with read access.
|
||||
/// <para/>
|
||||
/// GZip compressed files will be detected and handled automatically.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to a file to open.</param>
|
||||
///<returns>A <see cref="NbtStream"/> opened on the specified path with read access.</returns>
|
||||
public static NbtStream OpenRead(string path)
|
||||
{
|
||||
var compressed = false;
|
||||
|
|
@ -42,6 +36,14 @@ namespace SharpNBT
|
|||
return compressed ? new NbtStream(File.OpenRead(path), CompressionMode.Decompress) : new NbtStream(File.OpenRead(path));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens a <see cref="NbtStream"/> on the specified <paramref name="path"/> with write access.
|
||||
/// <para/>
|
||||
/// GZip compressed files will be detected and handled automatically.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to a file to open.</param>
|
||||
/// <param name="level">Specify a compression strategy to emphasise either size or speed, or no compression at all.</param>
|
||||
/// <returns>A <see cref="NbtStream"/> opened on the specified path with write access.</returns>
|
||||
public static NbtStream OpenWrite(string path, CompressionLevel level = CompressionLevel.NoCompression)
|
||||
{
|
||||
if (level != CompressionLevel.NoCompression)
|
||||
|
|
@ -55,17 +57,14 @@ namespace SharpNBT
|
|||
public NbtStream(Stream stream, bool leaveOpen = false)
|
||||
{
|
||||
BaseStream = stream ?? throw new ArgumentNullException(nameof(stream));
|
||||
topLevel = new Stack<Tag>();
|
||||
nameStack = new Stack<bool>();
|
||||
nameStack.Push(true);
|
||||
}
|
||||
|
||||
public NbtStream(Stream stream, CompressionMode compression, bool leaveOpen = false) : this(new GZipStream(stream, compression, leaveOpen), leaveOpen)
|
||||
{
|
||||
}
|
||||
|
||||
public NbtStream([NotNull] byte[] buffer) : this(new MemoryStream(buffer), false)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Clears all buffers for this stream and causes any buffered data to be written to the underlying device.</summary>
|
||||
/// <exception cref="T:System.IO.IOException">An I/O error occurs.</exception>
|
||||
/// <footer><a href="https://docs.microsoft.com/en-us/dotnet/api/System.IO.Stream.Flush?view=netcore-5.0">`Stream.Flush` on docs.microsoft.com</a></footer>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,16 @@
|
|||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<Title>SharpNBT</Title>
|
||||
<Authors>ForeverZer0</Authors>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<Description>A pure CLS-compliant C# implementation of the Named Binary Tag (NBT) format specification commonly used with Minecraft applications, allowing easy reading/writing streams and serialization to other formats.</Description>
|
||||
<PackageProjectUrl>https://github.com/ForeverZer0/SharpNBT</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/ForeverZer0/SharpNBT</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageTags>nbt;named binary tag;minecraft;serialization</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="icon.png" Pack="true" Visible="true" PackagePath=""/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -34,6 +34,11 @@ namespace SharpNBT
|
|||
[CanBeNull]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialized a new instance of the <see cref="Tag"/> class.
|
||||
/// </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>
|
||||
protected Tag(TagType type, [CanBeNull] string name)
|
||||
{
|
||||
Type = type;
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 204 KiB |
Loading…
Reference in New Issue