Implemented generating SNBT from tags
This commit is contained in:
parent
5b6fcd2d4c
commit
16369b68e3
|
@ -0,0 +1,30 @@
|
|||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace SharpNBT.Tests
|
||||
{
|
||||
public class StringifiedTest
|
||||
{
|
||||
private readonly ITestOutputHelper output;
|
||||
|
||||
|
||||
public StringifiedTest(ITestOutputHelper output)
|
||||
{
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BigOutput()
|
||||
{
|
||||
var tag = TestHelper.GetTag("bigtest.nbt", CompressionType.GZip);
|
||||
output.WriteLine(tag.Stringify(true));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HelloWorldOutput()
|
||||
{
|
||||
var tag = TestHelper.GetTag("hello_world.nbt", CompressionType.None);
|
||||
output.WriteLine(tag.Stringify(true));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace SharpNBT.SNBT
|
||||
{
|
||||
internal enum TokenType
|
||||
{
|
||||
None,
|
||||
CompoundBegin,
|
||||
CompoundEnd,
|
||||
Identifier,
|
||||
String,
|
||||
Separator,
|
||||
Comma,
|
||||
ByteArray,
|
||||
IntArray,
|
||||
LongArray,
|
||||
ListArray,
|
||||
EndArray,
|
||||
Float,
|
||||
Double,
|
||||
Byte,
|
||||
Short,
|
||||
Long,
|
||||
Int,
|
||||
WhiteSpace,
|
||||
Char
|
||||
}
|
||||
|
||||
internal sealed class LexerRule
|
||||
{
|
||||
internal delegate string PostProcessHandler(string input);
|
||||
|
||||
private readonly Regex regex;
|
||||
|
||||
public TokenType Type { get; }
|
||||
|
||||
public LexerRule(TokenType type, string pattern) : this(type, new Regex(pattern, RegexOptions.Multiline | RegexOptions.CultureInvariant))
|
||||
{
|
||||
}
|
||||
|
||||
public LexerRule(TokenType type, Regex regex)
|
||||
{
|
||||
Type = type;
|
||||
this.regex = regex ?? throw new ArgumentNullException(nameof(regex));
|
||||
}
|
||||
|
||||
public LexerRule(TokenType type, Regex regex, PostProcessHandler handler)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal class Lexer
|
||||
{
|
||||
private static readonly List<LexerRule> rules;
|
||||
|
||||
static Lexer()
|
||||
{
|
||||
rules = new List<LexerRule>
|
||||
{
|
||||
new LexerRule(TokenType.CompoundBegin, @"\{[\s]*"),
|
||||
new LexerRule(TokenType.CompoundEnd, @"[\s]*\}"),
|
||||
new LexerRule(TokenType.Identifier, "\".+?\"(?=:)"),
|
||||
new LexerRule(TokenType.Identifier, "'.+?'(?=:) "),
|
||||
new LexerRule(TokenType.Identifier, "A-Za-z0-9_-]+?(?=:) "),
|
||||
new LexerRule(TokenType.String, "\".*?\""),
|
||||
new LexerRule(TokenType.String, "'.*?'"),
|
||||
new LexerRule(TokenType.Separator, @"[\s]*:[\s]*"),
|
||||
new LexerRule(TokenType.Comma, @"[\s]*,[\s]*"),
|
||||
new LexerRule(TokenType.ByteArray, @"\[B;[\s]*?"),
|
||||
new LexerRule(TokenType.IntArray, @"\[I;[\s]*?"),
|
||||
new LexerRule(TokenType.LongArray, @"\[L;[\s]*?"),
|
||||
new LexerRule(TokenType.ListArray, @"\[[\s]*?"),
|
||||
new LexerRule(TokenType.EndArray, @"[\s]*\]"),
|
||||
new LexerRule(TokenType.Float, @"-?[0-9]*\.[0-9]+[Ff]"),
|
||||
new LexerRule(TokenType.Double, @"-?[0-9]*\.[0-9]+[Dd]?"),
|
||||
new LexerRule(TokenType.Byte, "-?([0-9]+)[Bb]"),
|
||||
new LexerRule(TokenType.Short, "-?([0-9]+)[Ss]"),
|
||||
new LexerRule(TokenType.Long, "-?([0-9]+)[Ll]"),
|
||||
new LexerRule(TokenType.Int, "-?([0-9]+)"),
|
||||
new LexerRule(TokenType.WhiteSpace, @"[\s]+"),
|
||||
new LexerRule(TokenType.String, @"[\S]+"),
|
||||
new LexerRule(TokenType.Char, ".")
|
||||
};
|
||||
}
|
||||
|
||||
public Lexer()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -57,5 +57,12 @@ namespace SharpNBT
|
|||
var word = Count == 1 ? Strings.WordElement : Strings.WordElements;
|
||||
return $"TAG_Byte_Array({PrettyName}): [{Count} {word}]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </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}[B;{string.Join(',', this)}]";
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace SharpNBT
|
||||
|
@ -69,5 +70,12 @@ namespace SharpNBT
|
|||
/// <returns>The tag represented as a <see cref="sbyte"/>.</returns>
|
||||
[CLSCompliant(false)]
|
||||
public static implicit operator sbyte(ByteTag tag) => unchecked((sbyte)tag.Value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </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";
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using JetBrains.Annotations;
|
||||
|
@ -112,5 +113,31 @@ namespace SharpNBT
|
|||
tag.PrettyPrinted(buffer, level + 1, indent);
|
||||
buffer.AppendLine(space + "}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </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 strings = new string[Count];
|
||||
for (var i = 0; i < strings.Length; i++)
|
||||
strings[i] = this[i].Stringify();
|
||||
|
||||
return $"{StringifyName}{{{string.Join(',', strings)}}}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <param name="topLevel">Flag indicating if this is the top-level tag that should be wrapped in braces.</param>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public string Stringify(bool topLevel)
|
||||
{
|
||||
var str = Stringify();
|
||||
return topLevel ? $"{{{str}}}" : str;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,5 +37,12 @@ namespace SharpNBT
|
|||
/// <param name="tag">The tag to convert.</param>
|
||||
/// <returns>The tag represented as a <see cref="double"/>.</returns>
|
||||
public static implicit operator double(DoubleTag tag) => tag.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </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";
|
||||
}
|
||||
}
|
|
@ -24,5 +24,12 @@ namespace SharpNBT
|
|||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public override string Stringify() => string.Empty;
|
||||
}
|
||||
}
|
|
@ -36,5 +36,12 @@ namespace SharpNBT
|
|||
/// <param name="tag">The tag to convert.</param>
|
||||
/// <returns>The tag represented as a <see cref="float"/>.</returns>
|
||||
public static implicit operator float(FloatTag tag) => tag.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </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";
|
||||
}
|
||||
}
|
|
@ -61,5 +61,12 @@ namespace SharpNBT
|
|||
var word = Count == 1 ? Strings.WordElement : Strings.WordElements;
|
||||
return $"TAG_Int_Array({PrettyName}): [{Count} {word}]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </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)}]";
|
||||
}
|
||||
}
|
|
@ -64,5 +64,12 @@ namespace SharpNBT
|
|||
/// <returns>The tag represented as a <see cref="uint"/>.</returns>
|
||||
[CLSCompliant(false)]
|
||||
public static implicit operator uint(IntTag tag) => unchecked((uint)tag.Value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </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}";
|
||||
}
|
||||
}
|
|
@ -85,5 +85,19 @@ namespace SharpNBT
|
|||
PrettyPrinted(buffer, 0, indent);
|
||||
return buffer.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </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 strings = new string[Count];
|
||||
for (var i = 0; i < strings.Length; i++)
|
||||
strings[i] = this[i].Stringify();
|
||||
|
||||
return $"{StringifyName}[{string.Join(',', strings)}]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -60,5 +60,12 @@ namespace SharpNBT
|
|||
var word = Count == 1 ? Strings.WordElement : Strings.WordElements;
|
||||
return $"TAG_Long_Array({PrettyName}): [{Count} {word}]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </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}[L;{string.Join(',', this)}]";
|
||||
}
|
||||
}
|
|
@ -64,5 +64,12 @@ namespace SharpNBT
|
|||
/// <returns>The tag represented as a <see cref="ulong"/>.</returns>
|
||||
[CLSCompliant(false)]
|
||||
public static implicit operator ulong(LongTag tag) => unchecked((ulong)tag.Value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </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";
|
||||
}
|
||||
}
|
|
@ -64,5 +64,12 @@ namespace SharpNBT
|
|||
/// <returns>The tag represented as a <see cref="ushort"/>.</returns>
|
||||
[CLSCompliant(false)]
|
||||
public static implicit operator ushort(ShortTag tag) => unchecked((ushort)tag.Value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </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";
|
||||
}
|
||||
}
|
|
@ -37,5 +37,12 @@ namespace SharpNBT
|
|||
/// <param name="tag">The tag to convert.</param>
|
||||
/// <returns>The tag represented as a <see cref="string"/>.</returns>
|
||||
public static implicit operator string(StringTag tag) => tag.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </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}\"";
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ using System.IO;
|
|||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
[assembly: CLSCompliant(true)]
|
||||
|
@ -208,6 +209,27 @@ namespace SharpNBT
|
|||
/// <param name="right">Second value to compare.</param>
|
||||
/// <returns>Result of comparison.</returns>
|
||||
public static bool operator !=(Tag left, Tag right) => !Equals(left, right);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <i>string</i> representation of this NBT tag (SNBT).
|
||||
/// </summary>
|
||||
/// <returns>This NBT tag in SNBT format.</returns>
|
||||
/// <seealso href="https://minecraft.fandom.com/wiki/NBT_format#SNBT_format"/>
|
||||
public abstract string Stringify();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name in a formatted properly for SNBT.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
protected internal string StringifyName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(Name))
|
||||
return string.Empty;
|
||||
return Regex.IsMatch(Name, @"^[A-Ba-z0-9_-]+$") ? $"{Name}: " : $"\"{Name}\": ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
Loading…
Reference in New Issue