Skip to content
This repository was archived by the owner on Aug 10, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ obj/
/packages/
riderModule.iml
/_ReSharper.Caches/
Documentation/
Documentation/
.vs/
24 changes: 24 additions & 0 deletions SharpNBT/SNBT/Scanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,30 @@ public bool MoveNext(bool skipWhitespace, bool fail)
goto ReadChar;
return true;
}
public bool SkipSpace()
{
while (Position < Source.Length)
{
if (Position >= Source.Length)
{
return false;
}
if (Current == ' ') Position++;
}
return true;
}
public bool SkipWarp()
{
while (Position < Source.Length)
{
if (Position >= Source.Length)
{
return false;
}
if ("\t\n\r".Contains(Current)) Position++;
}
return true;
}

public void AssertChar(char c)
{
Expand Down
75 changes: 48 additions & 27 deletions SharpNBT/SNBT/StringNbt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ public static class StringNbt
/// <returns>The <see cref="CompoundTag"/> instance described in the source text.</returns>
/// <exception cref="ArgumentNullException">When <paramref name="source"/> is <see langword="null"/>.</exception>
/// <exception cref="SyntaxErrorException">When <paramref name="source"/> is invalid SNBT code.</exception>
public static CompoundTag Parse(string source)
public static CompoundTag Parse(string source,bool warp = false)
{
var bytes = Encoding.UTF8.GetBytes(source);
return Parse(bytes, Encoding.UTF8);
return Parse(bytes, Encoding.UTF8,warp);
}

/// <summary>
Expand All @@ -48,12 +48,12 @@ public static ListTag ParseList(string source)
/// <returns>The <see cref="CompoundTag"/> instance described in the source text.</returns>
/// <exception cref="ArgumentNullException">When <paramref name="source"/> is <see langword="null"/>.</exception>
/// <exception cref="SyntaxErrorException">When <paramref name="source"/> is invalid SNBT code.</exception>
public static CompoundTag Parse(ReadOnlySpan<byte> source, Encoding? encoding = null)
public static CompoundTag Parse(ReadOnlySpan<byte> source, Encoding? encoding = null,bool warp = false)
{
var scanner = new Scanner(source, encoding ?? Encoding.UTF8);
scanner.MoveNext(true, true);
scanner.AssertChar('{');
return ParseCompound(null, ref scanner);
return ParseCompound(null, ref scanner, warp);
}

/// <summary>
Expand All @@ -72,7 +72,7 @@ public static ListTag ParseList(ReadOnlySpan<byte> source, Encoding? encoding =
return ParseList(null, ref scanner);
}

private static CompoundTag ParseCompound(string? name, ref Scanner scanner)
private static CompoundTag ParseCompound(string? name, ref Scanner scanner,bool warp = false)
{
scanner.MoveNext(true, true);

Expand All @@ -92,26 +92,39 @@ private static CompoundTag ParseCompound(string? name, ref Scanner scanner)

// Move to and parse the tag value
scanner.MoveNext(true, true);
var tag = ParseTag(childName, ref scanner);
var tag = ParseTag(childName, ref scanner, warp);
result.Add(tag);
scanner.MoveNext(true, true);

// Comma encountered, read another tag.
if (scanner.Current == ',')
//���û��,��
if(warp)
{
scanner.MoveNext(true, true);
continue;
if (scanner.Current == '}')
{
// scanner.MoveNext(true, false);
break;
}
}

// Closing brace encountered, break loop.
if (scanner.Current == '}')
else
{
// scanner.MoveNext(true, false);
break;
// Comma encountered, read another tag.
if (scanner.Current == ',')
{
scanner.MoveNext(true, true);
continue;
}

// Closing brace encountered, break loop.
if (scanner.Current == '}')
{
// scanner.MoveNext(true, false);
break;
}

// Invalid character
scanner.SyntaxError($"Expected ',' or '}}', got '{scanner.Current}'.");
}

// Invalid character
scanner.SyntaxError($"Expected ',' or '}}', got '{scanner.Current}'.");

}

return result;
Expand Down Expand Up @@ -186,17 +199,17 @@ private static string ParseUnquotedString(ref Scanner scanner)
return string.Empty;
}

private static Tag ParseTag(string? name, ref Scanner scanner)
private static Tag ParseTag(string? name, ref Scanner scanner,bool warp = false)
{
return scanner.Current switch
{
'{' => ParseCompound(name, ref scanner),
'[' => ParseArray(name, ref scanner),
_ => ParseLiteral(name, ref scanner)
'{' => ParseCompound(name, ref scanner,warp),
'[' => ParseArray(name, ref scanner,warp),
_ => ParseLiteral(name, ref scanner,warp)
};
}

private static Tag ParseLiteral(string? name, ref Scanner scanner)
private static Tag ParseLiteral(string? name, ref Scanner scanner, bool warp = false)
{
// Read the input as a string
var value = ParseString(ref scanner, out var quoted);
Expand Down Expand Up @@ -282,15 +295,15 @@ private static bool TryParseNumber(string? name, string value, char suffix, out
return false;
}

private static Tag ParseArray(string? name, ref Scanner scanner)
private static Tag ParseArray(string? name, ref Scanner scanner, bool warp = false)
{
scanner.MoveNext(true, true);
if (scanner.Current == ']')
return new ListTag(name, TagType.End);

// No type-prefix, must be a ListTag
if (scanner.Peek() != ';')
return ParseList(name, ref scanner);
return ParseList(name, ref scanner,warp);

// This is an array of integral values
var prefix = scanner.Current;
Expand All @@ -304,16 +317,24 @@ private static Tag ParseArray(string? name, ref Scanner scanner)
};
}

private static ListTag ParseList(string? name, ref Scanner scanner)
private static ListTag ParseList(string? name, ref Scanner scanner, bool warp = false)
{
var list = new List<Tag>();
while (true)
{
var child = ParseTag(null, ref scanner);
var child = ParseTag(null, ref scanner, warp);
list.Add(child);

scanner.MoveNext(true, true);

if(warp)
{
if (scanner.Current == ']')
{
break;
}
continue;
}
// Comma encountered, read another tag.
if (scanner.Current == ',')
{
Expand Down
3 changes: 2 additions & 1 deletion SharpNBT/Tags/BoolTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = t

/// <inheritdoc cref="object.ToString"/>
public override string ToString() => $"TAG_Byte({PrettyName}): {(Value ? "true" : "false")}";

public override string ToWarppedString() => $"T{PrettyName}: {(Value ? "true" : "false")}";

/// <summary>
/// Implicit conversion of this tag to a <see cref="byte"/>.
/// </summary>
Expand Down
63 changes: 37 additions & 26 deletions SharpNBT/Tags/ByteTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ namespace SharpNBT;
/// recommended to use the <see cref="SignedValue"/> property if your language supports a signed 8-bit value, otherwise simply ensure the bits are
/// equivalent.
/// </remarks>
[PublicAPI][Serializable]
[PublicAPI]
[Serializable]
public class ByteTag : NumericTag<byte>
{
/// <summary>
/// Gets a flag indicating if this <see cref="ByteTag"/> was assigned a <see cref="bool"/> value.
/// </summary>
public bool IsBool { get; private set; }

/// <inheritdoc cref="Tag{T}.Value"/>
public new byte Value
{
Expand All @@ -30,7 +31,7 @@ public class ByteTag : NumericTag<byte>
IsBool = false;
}
}

/// <summary>
/// Gets or sets the value of this tag as an unsigned value.
/// </summary>
Expand All @@ -47,7 +48,7 @@ public sbyte SignedValue
IsBool = false;
}
}

/// <summary>
/// Gets or sets the value of this tag as a boolean value.
/// </summary>
Expand All @@ -60,40 +61,49 @@ public bool Bool
IsBool = true;
}
}

/// <summary>
/// Creates a new instance of the <see cref="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 ByteTag(string? name, byte value) : base(TagType.Byte, name, value)
{
}

public ByteTag(string? name, byte value)
: base(TagType.Byte, name, value) { }

/// <inheritdoc cref="ByteTag(string,byte)"/>
/// <remarks>The use of <see cref="int"/> is for convenience only.</remarks>
public ByteTag(string? name, int value) : base(TagType.Byte, name, unchecked((byte) (value & 0xFF)))
{
}

public ByteTag(string? name, int value)
: base(TagType.Byte, name, unchecked((byte)(value & 0xFF))) { }

/// <inheritdoc cref="ByteTag(string,byte)"/>
public ByteTag(string? name, bool value) : base(TagType.Byte, name, value ? (byte) 1 : (byte) 0)
{
}

public ByteTag(string? name, bool value)
: base(TagType.Byte, name, value ? (byte)1 : (byte)0) { }

/// <inheritdoc cref="ByteTag(string,byte)"/>
[CLSCompliant(false)]
public ByteTag(string? name, sbyte value) : base(TagType.Byte, name, unchecked((byte) value))
{
}
public ByteTag(string? name, sbyte value)
: base(TagType.Byte, name, unchecked((byte)value)) { }

/// <inheritdoc cref="object.ToString"/>
public override string ToString()
{
object obj = IsBool ? Bool : Value;
return $"TAG_Byte({PrettyName}): {obj}";
}


public override string ToWarppedString()
{
object str;
if (IsBool)
if (Bool)
str = "true";
else
str = "false";
else
str = Value + "b";
return $"{WarpedName}: {str}";
}

/// <inheritdoc />
protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
{
Expand All @@ -109,21 +119,21 @@ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = t
writer.WriteNumberValue(Value);
}
}

/// <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 byte(ByteTag tag) => tag.Value;

/// <summary>
/// Implicit conversion of this tag to a <see cref="bool"/>.
/// </summary>
/// <param name="tag">The tag to convert.</param>
/// <returns>The tag represented as a <see cref="byte"/>.</returns>
public static implicit operator bool(ByteTag tag) => tag.Bool;

/// <summary>
/// Implicit conversion of this tag to a <see cref="sbyte"/>.
/// </summary>
Expand All @@ -133,5 +143,6 @@ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = t
public static implicit operator sbyte(ByteTag tag) => unchecked((sbyte)tag.Value);

/// <inheritdoc />
public override string Stringify(bool named = true) => named ? $"{StringifyName}:{Value}B" : $"{Value}B";
}
public override string Stringify(bool named = true) =>
named ? $"{StringifyName}:{Value}B" : $"{Value}B";
}
Loading