diff --git a/.gitignore b/.gitignore index f2a0ca5..d1e7986 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ obj/ /packages/ riderModule.iml /_ReSharper.Caches/ -Documentation/ \ No newline at end of file +Documentation/ +.vs/ \ No newline at end of file diff --git a/SharpNBT/SNBT/Scanner.cs b/SharpNBT/SNBT/Scanner.cs index 0da765b..cc8c86f 100644 --- a/SharpNBT/SNBT/Scanner.cs +++ b/SharpNBT/SNBT/Scanner.cs @@ -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) { diff --git a/SharpNBT/SNBT/StringNbt.cs b/SharpNBT/SNBT/StringNbt.cs index b9b2383..162a29b 100644 --- a/SharpNBT/SNBT/StringNbt.cs +++ b/SharpNBT/SNBT/StringNbt.cs @@ -21,10 +21,10 @@ public static class StringNbt /// The instance described in the source text. /// When is . /// When is invalid SNBT code. - 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); } /// @@ -48,12 +48,12 @@ public static ListTag ParseList(string source) /// The instance described in the source text. /// When is . /// When is invalid SNBT code. - public static CompoundTag Parse(ReadOnlySpan source, Encoding? encoding = null) + public static CompoundTag Parse(ReadOnlySpan 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); } /// @@ -72,7 +72,7 @@ public static ListTag ParseList(ReadOnlySpan 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); @@ -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; @@ -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); @@ -282,7 +295,7 @@ 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 == ']') @@ -290,7 +303,7 @@ private static Tag ParseArray(string? name, ref Scanner scanner) // 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; @@ -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(); 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 == ',') { diff --git a/SharpNBT/Tags/BoolTag.cs b/SharpNBT/Tags/BoolTag.cs index 54528d1..c20b154 100644 --- a/SharpNBT/Tags/BoolTag.cs +++ b/SharpNBT/Tags/BoolTag.cs @@ -42,7 +42,8 @@ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = t /// public override string ToString() => $"TAG_Byte({PrettyName}): {(Value ? "true" : "false")}"; - + public override string ToWarppedString() => $"T{PrettyName}: {(Value ? "true" : "false")}"; + /// /// Implicit conversion of this tag to a . /// diff --git a/SharpNBT/Tags/ByteTag.cs b/SharpNBT/Tags/ByteTag.cs index 0d7ed7f..57e9cc5 100644 --- a/SharpNBT/Tags/ByteTag.cs +++ b/SharpNBT/Tags/ByteTag.cs @@ -12,14 +12,15 @@ namespace SharpNBT; /// recommended to use the property if your language supports a signed 8-bit value, otherwise simply ensure the bits are /// equivalent. /// -[PublicAPI][Serializable] +[PublicAPI] +[Serializable] public class ByteTag : NumericTag { /// /// Gets a flag indicating if this was assigned a value. /// public bool IsBool { get; private set; } - + /// public new byte Value { @@ -30,7 +31,7 @@ public class ByteTag : NumericTag IsBool = false; } } - + /// /// Gets or sets the value of this tag as an unsigned value. /// @@ -47,7 +48,7 @@ public sbyte SignedValue IsBool = false; } } - + /// /// Gets or sets the value of this tag as a boolean value. /// @@ -60,32 +61,28 @@ public bool Bool IsBool = true; } } - + /// /// Creates a new instance of the class with the specified . /// /// The name of the tag, or if tag has no name. /// The value to assign to this tag. - public ByteTag(string? name, byte value) : base(TagType.Byte, name, value) - { - } - + public ByteTag(string? name, byte value) + : base(TagType.Byte, name, value) { } + /// /// The use of is for convenience only. - 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))) { } + /// - 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) { } + /// [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)) { } /// public override string ToString() @@ -93,7 +90,20 @@ 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}"; + } + /// protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true) { @@ -109,21 +119,21 @@ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = t writer.WriteNumberValue(Value); } } - + /// /// Implicit conversion of this tag to a . /// /// The tag to convert. /// The tag represented as a . public static implicit operator byte(ByteTag tag) => tag.Value; - + /// /// Implicit conversion of this tag to a . /// /// The tag to convert. /// The tag represented as a . public static implicit operator bool(ByteTag tag) => tag.Bool; - + /// /// Implicit conversion of this tag to a . /// @@ -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); /// - public override string Stringify(bool named = true) => named ? $"{StringifyName}:{Value}B" : $"{Value}B"; -} \ No newline at end of file + public override string Stringify(bool named = true) => + named ? $"{StringifyName}:{Value}B" : $"{Value}B"; +} diff --git a/SharpNBT/Tags/CompoundTag.cs b/SharpNBT/Tags/CompoundTag.cs index 3087d6f..02a9349 100644 --- a/SharpNBT/Tags/CompoundTag.cs +++ b/SharpNBT/Tags/CompoundTag.cs @@ -10,32 +10,34 @@ namespace SharpNBT; /// -/// Top-level tag that acts as a container for other named tags. +/// Top-level tag that acts as a container for other named tags. /// /// /// This along with the class define the structure of the NBT format. Children are not order-dependent, nor is order guaranteed. The -/// closing does not require to be explicitly added, it will be added automatically during serialization. +/// closing does not require to be explicitly added, it will be added automatically during serialization. /// [PublicAPI] public class CompoundTag : Tag, IDictionary, ICollection { private readonly Dictionary dict; - + /// /// Creates a new instance of the class. /// /// The name of the tag, or if tag has no name. - public CompoundTag(string? name) : base(TagType.Compound, name) + public CompoundTag(string? name) + : base(TagType.Compound, name) { dict = new Dictionary(); } - + /// /// Creates a new instance of the class. /// /// The name of the tag, or if tag has no name. /// A collection objects that are children of this object. - public CompoundTag(string? name, IEnumerable values) : this(name) + public CompoundTag(string? name, IEnumerable values) + : this(name) { foreach (var value in values) { @@ -44,21 +46,26 @@ public CompoundTag(string? name, IEnumerable values) : this(name) } /// - void ICollection>.Add(KeyValuePair item) => Add(item.Value); + void ICollection>.Add(KeyValuePair item) => + Add(item.Value); /// - bool ICollection>.Contains(KeyValuePair item) => dict.Contains(item); - + bool ICollection>.Contains(KeyValuePair item) => + dict.Contains(item); + /// - void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + void ICollection>.CopyTo( + KeyValuePair[] array, + int arrayIndex + ) { foreach (var kvp in dict) array[arrayIndex++] = kvp; } - + /// bool ICollection>.IsReadOnly => false; - + /// bool ICollection.IsReadOnly => false; @@ -80,29 +87,30 @@ public void Clear() child.Parent = null; dict.Clear(); } - + /// public int Count => dict.Count; - + /// - IEnumerator> IEnumerable>.GetEnumerator() => dict.GetEnumerator(); + IEnumerator> IEnumerable>.GetEnumerator() => + dict.GetEnumerator(); /// IEnumerator IEnumerable.GetEnumerator() => dict.GetEnumerator(); /// public IEnumerator GetEnumerator() => dict.Values.GetEnumerator(); - + /// public void CopyTo(Tag[] array, int arrayIndex) { foreach (var value in dict.Values) array[arrayIndex++] = value; } - + /// public void Add(string key, Tag value) => dict.Add(key, ValidateChild(value)); - + /// public void Add(Tag value) => dict.Add(value.Name!, ValidateChild(value)); @@ -136,7 +144,8 @@ public bool Remove(Tag item) public bool TryGetValue(string key, out Tag value) => dict.TryGetValue(key, out value!); /// - public bool TryGetValue(string key, out TTag value) where TTag : Tag + public bool TryGetValue(string key, out TTag value) + where TTag : Tag { if (dict.TryGetValue(key, out var tag) && tag is TTag result) { @@ -147,13 +156,13 @@ public bool TryGetValue(string key, out TTag value) where TTag : Tag value = null!; return false; } - + /// public ICollection Keys => dict.Keys; /// public ICollection Values => dict.Values; - + /// public Tag this[string name] { @@ -161,11 +170,12 @@ public Tag this[string name] set => dict[name] = ValidateChild(value); } - public TTag Get(string name) where TTag : Tag + public TTag Get(string name) + where TTag : Tag { return (TTag)dict[name]; } - + /// protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true) { @@ -182,7 +192,7 @@ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = t child.WriteJson(writer, true); writer.WriteEndObject(); } - + /// Returns a string that represents the current object. /// A string that represents the current object. /// @@ -210,7 +220,8 @@ public string PrettyPrinted(string? indent = " ") /// The name of the tag to search for. /// to recursively search children, otherwise to only search direct descendants. /// The first tag found with , otherwise if none was found. - public TTag? Find(string name, bool recursive = false) where TTag : Tag + public TTag? Find(string name, bool recursive = false) + where TTag : Tag { foreach (var (key, value) in dict) { @@ -234,7 +245,7 @@ protected internal override void PrettyPrinted(StringBuilder buffer, int level, var space = new StringBuilder(); for (var i = 0; i < level; i++) space.Append(indent); - + buffer.AppendLine(space + ToString()); buffer.AppendLine(space + "{"); foreach (var tag in dict.Values) @@ -282,4 +293,28 @@ private Tag ValidateChild(Tag tag) tag.Parent = this; return tag; } -} \ No newline at end of file + + public string ToWarppedString(string indent = "\t") + { + var buffer = new StringBuilder(); + + WarppedPrinted(buffer, 0, indent ?? string.Empty); + return buffer.ToString(); + } + + protected internal override void WarppedPrinted(StringBuilder buffer, int level, string indent) + { + var space = new StringBuilder(); + for (var i = 0; i < level; i++) + space.Append(indent); + + if (String.IsNullOrWhiteSpace(Name)) + buffer.AppendLine($"{space}"); + else + buffer.AppendLine(space + Name + ":"); + buffer.AppendLine(space + "{"); + foreach (var tag in dict.Values) + tag.WarppedPrinted(buffer, level + 1, indent); + buffer.AppendLine(space + "}"); + } +} diff --git a/SharpNBT/Tags/DoubleTag.cs b/SharpNBT/Tags/DoubleTag.cs index 7a30ce4..86a3567 100644 --- a/SharpNBT/Tags/DoubleTag.cs +++ b/SharpNBT/Tags/DoubleTag.cs @@ -33,7 +33,8 @@ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = t /// public override string ToString() => $"TAG_Double({PrettyName}): {Value:0.0}"; - + public override string ToWarppedString() => $"{WarpedName}: {Value}d"; + /// /// Implicit conversion of this tag to a . /// diff --git a/SharpNBT/Tags/FloatTag.cs b/SharpNBT/Tags/FloatTag.cs index fcf4042..1684503 100644 --- a/SharpNBT/Tags/FloatTag.cs +++ b/SharpNBT/Tags/FloatTag.cs @@ -33,7 +33,8 @@ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = t /// public override string ToString() => $"TAG_Float({PrettyName}): {Value:0.0}"; - + public override string ToWarppedString() => $"{WarpedName}: {Value}f"; + /// /// Implicit conversion of this tag to a . /// diff --git a/SharpNBT/Tags/IntTag.cs b/SharpNBT/Tags/IntTag.cs index 9cffeb9..31b536e 100644 --- a/SharpNBT/Tags/IntTag.cs +++ b/SharpNBT/Tags/IntTag.cs @@ -53,7 +53,8 @@ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = t /// public override string ToString() => $"TAG_Int({PrettyName}): {Value}"; - + public override string ToWarppedString() => $"{WarpedName}: {Value}"; + /// /// Implicit conversion of this tag to a . /// diff --git a/SharpNBT/Tags/ListTag.cs b/SharpNBT/Tags/ListTag.cs index 653fb1f..eea0754 100644 --- a/SharpNBT/Tags/ListTag.cs +++ b/SharpNBT/Tags/ListTag.cs @@ -143,7 +143,14 @@ public override string ToString() var word = Count == 1 ? Strings.WordEntry : Strings.WordEntries; return $"TAG_List({PrettyName}): [{Count} {word}]"; } - + public override string ToWarppedString() + { + var word = Count == 1 ? Strings.WordEntry : Strings.WordEntries; + return $"{WarpedName}: "; + } + + + /// protected internal override void PrettyPrinted(StringBuilder buffer, int level, string indent) { @@ -157,6 +164,18 @@ protected internal override void PrettyPrinted(StringBuilder buffer, int level, tag.PrettyPrinted(buffer, level + 1, indent); buffer.AppendLine(space + "}"); } + protected internal override void WarppedPrinted(StringBuilder buffer, int level, string indent) + { + var space = new StringBuilder(); + for (var i = 0; i < level; i++) + space.Append(indent); + + buffer.AppendLine(space + ToWarppedString()); + buffer.AppendLine(space + "["); + foreach (var tag in this) + tag.WarppedPrinted(buffer, level + 1, indent); + buffer.AppendLine(space + "]"); + } /// /// Retrieves a "pretty-printed" multiline string representing the complete tree structure of the tag. @@ -169,6 +188,7 @@ public string PrettyPrinted(string indent = " ") PrettyPrinted(buffer, 0, indent); return buffer.ToString(); } + //public string WarppedPrinted /// /// Gets the string representation of this NBT tag (SNBT). diff --git a/SharpNBT/Tags/LongArrayTag.cs b/SharpNBT/Tags/LongArrayTag.cs index 521ee2a..50592ff 100644 --- a/SharpNBT/Tags/LongArrayTag.cs +++ b/SharpNBT/Tags/LongArrayTag.cs @@ -68,8 +68,13 @@ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = t public override string ToString() { var word = Count == 1 ? Strings.WordElement : Strings.WordElements; - return $"TAG_Long_Array({PrettyName}): [{Count} {word}]"; + return $"TAG_Long_Array({WarpedName}): [{Count} {word}]"; } + //public override string ToWarppedString() + //{ + // var word = Count == 1 ? Strings.WordElement : Strings.WordElements; + // return $"[{Count} {word}]"; + //} /// public override string Stringify(bool named = true) => Stringify(named, 'L', 'l'); diff --git a/SharpNBT/Tags/LongTag.cs b/SharpNBT/Tags/LongTag.cs index cd07e56..38ffdb7 100644 --- a/SharpNBT/Tags/LongTag.cs +++ b/SharpNBT/Tags/LongTag.cs @@ -53,7 +53,8 @@ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = t /// public override string ToString() => $"TAG_Long({PrettyName}): {Value}"; - + public override string ToWarppedString() => $"{WarpedName}: {Value}L"; + /// /// Implicit conversion of this tag to a . /// diff --git a/SharpNBT/Tags/ShortTag.cs b/SharpNBT/Tags/ShortTag.cs index 623f2e5..00a7904 100644 --- a/SharpNBT/Tags/ShortTag.cs +++ b/SharpNBT/Tags/ShortTag.cs @@ -59,7 +59,8 @@ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = t /// public override string ToString() => $"TAG_Short({PrettyName}): {Value}"; - + public override string ToWarppedString() => $"{WarpedName}: {Value}s"; + /// /// Implicit conversion of this tag to a . /// diff --git a/SharpNBT/Tags/StringTag.cs b/SharpNBT/Tags/StringTag.cs index dab72a9..bb66537 100644 --- a/SharpNBT/Tags/StringTag.cs +++ b/SharpNBT/Tags/StringTag.cs @@ -40,6 +40,7 @@ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = t /// public override string ToString() => $"TAG_String({PrettyName}): \"{Value}\""; + public override string ToWarppedString() => $"{WarpedName}: \"{Value}\""; /// /// Implicit conversion of this tag to a . diff --git a/SharpNBT/Tags/Tag.cs b/SharpNBT/Tags/Tag.cs index 52d77bb..0b04e85 100644 --- a/SharpNBT/Tags/Tag.cs +++ b/SharpNBT/Tags/Tag.cs @@ -62,7 +62,16 @@ protected internal virtual void PrettyPrinted(StringBuilder buffer, int level, s buffer.Append(indent); buffer.AppendLine(ToString()); } - + + protected internal virtual void WarppedPrinted(StringBuilder buffer, int level, string indent) + { + for (var i = 0; i < level; i++) + buffer.Append(indent); + buffer.AppendLine(ToWarppedString()); + } + public virtual string ToWarppedString() => ""; + protected internal string WarpedName => Name is null ? "" : $"{Name}"; + /// /// Gets the name of the object as a human-readable quoted string, or a default name to indicate it has no name when applicable. ///