- Fixed SNBT bug that would not parse boolean values

- Implemented BoolTag type for convenience
- Implemented compiled regular expressions
This commit is contained in:
ForeverZer0 2021-09-18 18:46:43 -04:00
parent 7a1d6c0471
commit f27bebf6c9
9 changed files with 95 additions and 4 deletions

View File

@ -1,4 +1,5 @@
{ {
"bool test": true,
"test case": 90, "test case": 90,
noQuotes: "HELLO WORLD THIS IS A TEST STRING ÅÄÖ!", noQuotes: "HELLO WORLD THIS IS A TEST STRING ÅÄÖ!",
"test with \" escaped quote": 90, "test with \" escaped quote": 90,

View File

@ -30,6 +30,8 @@ namespace SharpNBT.Tests
.BeginCompound("egg").AddString("name", "Eggbert").AddFloat("value", 0.5f).EndCompound() .BeginCompound("egg").AddString("name", "Eggbert").AddFloat("value", 0.5f).EndCompound()
.BeginCompound("ham").AddString("name", "Hampus").AddFloat("value", 0.75f).EndCompound() .BeginCompound("ham").AddString("name", "Hampus").AddFloat("value", 0.75f).EndCompound()
.EndCompound() .EndCompound()
.AddBool("boolTest", true)
.AddBool("bool Test 2", false)
.AddInt("iniTest", 2147483647) .AddInt("iniTest", 2147483647)
.AddByte("byteTest", 127) .AddByte("byteTest", 127)
.AddString("stringTest", "HELLO WORLD THIS IS A TEST STRING \xc5\xc4\xd6!") .AddString("stringTest", "HELLO WORLD THIS IS A TEST STRING \xc5\xc4\xd6!")

View File

@ -24,7 +24,7 @@ namespace SharpNBT.SNBT
public LexerRule(TokenType type, string pattern, ResultHandler handler, bool skipped = false) public LexerRule(TokenType type, string pattern, ResultHandler handler, bool skipped = false)
{ {
Type = type; Type = type;
Pattern = new Regex(pattern); Pattern = new Regex(pattern, RegexOptions.Compiled);
IsSkipped = skipped; IsSkipped = skipped;
processResult = handler; processResult = handler;
} }

View File

@ -36,6 +36,7 @@ namespace SharpNBT.SNBT
lexer.AddRule(TokenType.EndArray, @"\]"); lexer.AddRule(TokenType.EndArray, @"\]");
lexer.AddRule(TokenType.Float, @"(-?[0-9]*\.[0-9]+)[Ff]", FirstGroupValue); lexer.AddRule(TokenType.Float, @"(-?[0-9]*\.[0-9]+)[Ff]", FirstGroupValue);
lexer.AddRule(TokenType.Double, @"(-?[0-9]*\.[0-9]+)[Dd]?", FirstGroupValue); lexer.AddRule(TokenType.Double, @"(-?[0-9]*\.[0-9]+)[Dd]?", FirstGroupValue);
lexer.AddRule(TokenType.Bool, "(true|false)", FirstGroupValue);
lexer.AddRule(TokenType.Byte, "(-?[0-9]+)[Bb]", FirstGroupValue); lexer.AddRule(TokenType.Byte, "(-?[0-9]+)[Bb]", FirstGroupValue);
lexer.AddRule(TokenType.Short, "(-?[0-9]+)[Ss]", FirstGroupValue); lexer.AddRule(TokenType.Short, "(-?[0-9]+)[Ss]", FirstGroupValue);
lexer.AddRule(TokenType.Long, "(-?[0-9]+)[Ll]", FirstGroupValue); lexer.AddRule(TokenType.Long, "(-?[0-9]+)[Ll]", FirstGroupValue);
@ -142,6 +143,7 @@ namespace SharpNBT.SNBT
TokenType.IntArray => ParseIntArray(name, queue), TokenType.IntArray => ParseIntArray(name, queue),
TokenType.LongArray => ParseLongArray(name, queue), TokenType.LongArray => ParseLongArray(name, queue),
TokenType.List => ParseList(name, queue), TokenType.List => ParseList(name, queue),
TokenType.Bool => new BoolTag(name, bool.Parse(token.Value)),
TokenType.Byte => new ByteTag(name, sbyte.Parse(token.Value)), TokenType.Byte => new ByteTag(name, sbyte.Parse(token.Value)),
TokenType.Short => new ShortTag(name, short.Parse(token.Value)), TokenType.Short => new ShortTag(name, short.Parse(token.Value)),
TokenType.Int => new IntTag(name, int.Parse(token.Value)), TokenType.Int => new IntTag(name, int.Parse(token.Value)),

View File

@ -70,6 +70,11 @@ namespace SharpNBT.SNBT
/// </summary> /// </summary>
Byte, Byte,
/// <summary>
/// A <see cref="BoolTag"/> value.
/// </summary>
Bool,
/// <summary> /// <summary>
/// A <see cref="ShortTag"/> value. /// A <see cref="ShortTag"/> value.
/// </summary> /// </summary>

View File

@ -13,7 +13,9 @@
<PackageTags>nbt;named binary tag;minecraft;serialization;java;bedrock;pocket edition;varint;varlong;zlib</PackageTags> <PackageTags>nbt;named binary tag;minecraft;serialization;java;bedrock;pocket edition;varint;varlong;zlib</PackageTags>
<Copyright>Copyright © Eric Freed 2021</Copyright> <Copyright>Copyright © Eric Freed 2021</Copyright>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageVersion>1.1.0</PackageVersion> <PackageVersion>1.2.0</PackageVersion>
<AssemblyVersion>1.2.0</AssemblyVersion>
<FileVersion>1.2.0</FileVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">

View File

@ -36,6 +36,21 @@ namespace SharpNBT
tree.Push(root); tree.Push(root);
} }
/// <summary>
/// Adds a new <see cref="ByteTag"/> with the specified <paramref name="name"/> and <paramref name="value"/> to the tree at the current depth.
/// </summary>
/// <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([CanBeNull] string name, bool value) => AddTag(new BoolTag(name, value));
/// <summary>
/// Adds a new unnamed <see cref="ByteTag"/> with the specified <paramref name="value"/> to the tree at the current depth.
/// </summary>
/// <param name="value">The value of the tag.</param>
/// <returns>Returns this <see cref="TagBuilder"/> instance for chaining.</returns>
public TagBuilder AddBool(bool value) => AddBool(null, value);
/// <summary> /// <summary>
/// Adds a new <see cref="ByteTag"/> with the specified <paramref name="name"/> and <paramref name="value"/> to the tree at the current depth. /// Adds a new <see cref="ByteTag"/> with the specified <paramref name="name"/> and <paramref name="value"/> to the tree at the current depth.
/// </summary> /// </summary>

56
SharpNBT/Tags/BoolTag.cs Normal file
View File

@ -0,0 +1,56 @@
using System;
using System.Runtime.Serialization;
using JetBrains.Annotations;
namespace SharpNBT
{
/// <summary>
/// A tag that contains a single 8-bit integer value.
/// </summary>
/// <remarks>
/// This tag type does not exist in the NBT specification, and is included for convenience to differentiate it from the <see cref="ByteTag"/> that it is
/// actually serialized as.
/// </remarks>
[PublicAPI][Serializable]
public class BoolTag : Tag<bool>
{
private const string TRUE = "true";
private const string FALSE = "false";
/// <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([CanBeNull] string name, bool value) : base(TagType.Byte, name, value)
{
}
/// <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 BoolTag(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
/// <inheritdoc cref="object.ToString"/>
public override string ToString() => $"TAG_Bool({PrettyName}): {(Value ? TRUE : FALSE)}";
/// <summary>
/// Implicit conversion of this tag to a <see cref="byte"/>.
/// </summary>
/// <param name="tag">The tag to convert.</param>
/// <returns>The tag represented as a <see cref="byte"/>.</returns>
public static implicit operator bool(BoolTag 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 ? TRUE : FALSE)}";
}
}

View File

@ -19,6 +19,14 @@ namespace SharpNBT
[PublicAPI][Serializable] [PublicAPI][Serializable]
public abstract class Tag : IEquatable<Tag>, ISerializable, ICloneable public abstract class Tag : IEquatable<Tag>, ISerializable, ICloneable
{ {
private static Regex simpleNameMatcher;
static Tag()
{
simpleNameMatcher = new Regex(@"^[A-Ba-z0-9_-]+$", RegexOptions.Compiled);
}
private static IEnumerable<Type> GetKnownTypes() private static IEnumerable<Type> GetKnownTypes()
{ {
return new[] return new[]
@ -229,7 +237,7 @@ namespace SharpNBT
{ {
if (string.IsNullOrEmpty(Name)) if (string.IsNullOrEmpty(Name))
return string.Empty; return string.Empty;
return Regex.IsMatch(Name, @"^[A-Ba-z0-9_-]+$") ? $"{Name}: " : $"\"{Name}\": "; return simpleNameMatcher.IsMatch(Name) ? $"{Name}: " : $"\"{Name}\": ";
} }
} }
} }