161 lines
4.9 KiB
C#
Executable File
161 lines
4.9 KiB
C#
Executable File
using System.Collections;
|
|
using System.Text;
|
|
using Nbt.Type;
|
|
|
|
namespace Nbt;
|
|
|
|
internal static class NbtUtils
|
|
{
|
|
public const char ESCAPE_CHAR = '\\';
|
|
public const char SINGLE_QUOTE_CHAR = '\'';
|
|
public const char DOUBLE_QUOTE_CHAR = '"';
|
|
|
|
public static readonly INbtRegistry Registry = new NbtRegistry();
|
|
|
|
static NbtUtils()
|
|
{
|
|
Registry.AddAll(NbtByteType.Value, NbtShortType.Value, NbtIntType.Value, NbtLongType.Value, NbtFloatType.Value, NbtDoubleType.Value, NbtStringType.Value, NbtListType.Value, NbtCompoundType.Value, NbtEndType.Value, NbtByteArrayType.Value, NbtIntArrayType.Value, NbtLongArrayType.Value);
|
|
}
|
|
|
|
public static INbtType GetTagType(NbtTagType tagType) => Registry.TryGet(tagType, out var value) ? value : throw new UnknownTagTypeException(tagType, $"Unknown tag type: {tagType}");
|
|
|
|
public static NbtTagType GetValueTagType<T>() => GetValueTagType(typeof(T));
|
|
|
|
public static NbtTagType GetValueTagType(System.Type type) =>
|
|
type == typeof(sbyte) ? NbtTagType.Byte :
|
|
type == typeof(short) ? NbtTagType.Short :
|
|
type == typeof(int) ? NbtTagType.Int :
|
|
type == typeof(long) ? NbtTagType.Long :
|
|
type == typeof(float) ? NbtTagType.Float :
|
|
type == typeof(double) ? NbtTagType.Double :
|
|
type == typeof(string) ? NbtTagType.String :
|
|
NbtTagType.Unknown;
|
|
|
|
public static NbtTagType GetArrayTagType<T>() => GetArrayTagType(typeof(T));
|
|
|
|
public static NbtTagType GetArrayTagType(System.Type type) =>
|
|
type == typeof(sbyte) ? NbtTagType.ByteArray :
|
|
type == typeof(int) ? NbtTagType.IntArray :
|
|
type == typeof(long) ? NbtTagType.LongArray :
|
|
NbtTagType.Unknown;
|
|
|
|
public static NbtTagType EnsureValueType<T>()
|
|
{
|
|
var type = typeof(T);
|
|
var tagType = GetValueTagType(type);
|
|
return tagType is NbtTagType.Unknown ? throw new UnknownTagTypeException(tagType, $"Unknown value type: {type.Name}") : tagType;
|
|
}
|
|
|
|
public static NbtTagType EnsureArrayType<T>()
|
|
{
|
|
var type = typeof(T);
|
|
var tagType = GetArrayTagType(type);
|
|
return tagType is NbtTagType.Unknown ? throw new UnknownTagTypeException(tagType, $"Unknown array type: {type.Name}") : tagType;
|
|
}
|
|
|
|
public static NbtTagType ToArrayType(this NbtTagType tagType) => tagType switch
|
|
{
|
|
NbtTagType.Byte => NbtTagType.ByteArray,
|
|
NbtTagType.Int => NbtTagType.IntArray,
|
|
NbtTagType.Long => NbtTagType.LongArray,
|
|
_ => NbtTagType.Unknown
|
|
};
|
|
|
|
public static NbtTagType ToValueType(this NbtTagType tagType) => tagType switch
|
|
{
|
|
NbtTagType.ByteArray => NbtTagType.Byte,
|
|
NbtTagType.IntArray => NbtTagType.Int,
|
|
NbtTagType.LongArray => NbtTagType.Long,
|
|
_ => NbtTagType.Unknown
|
|
};
|
|
|
|
public static string QuoteString(string s, bool onlyIfNeeded = false)
|
|
{
|
|
if (s.Length == 0)
|
|
{
|
|
return $"{DOUBLE_QUOTE_CHAR}{DOUBLE_QUOTE_CHAR}";
|
|
}
|
|
|
|
var sb = new StringBuilder();
|
|
var needQuotes = false;
|
|
var quoteChar = '\0';
|
|
|
|
foreach (var c in s)
|
|
{
|
|
needQuotes |= QuoteString(sb, c, ref quoteChar);
|
|
}
|
|
|
|
if (!onlyIfNeeded || needQuotes)
|
|
{
|
|
quoteChar = quoteChar == DOUBLE_QUOTE_CHAR ? SINGLE_QUOTE_CHAR : DOUBLE_QUOTE_CHAR;
|
|
|
|
sb.Insert(0, quoteChar);
|
|
sb.Append(quoteChar);
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static bool QuoteString(StringBuilder sb, char c, ref char quoteChar)
|
|
{
|
|
var needQuotes = false;
|
|
var escape = false;
|
|
|
|
switch (c)
|
|
{
|
|
case '\t':
|
|
escape = true;
|
|
c = 't';
|
|
break;
|
|
|
|
case '\r':
|
|
escape = true;
|
|
c = 'r';
|
|
break;
|
|
|
|
case '\n':
|
|
escape = true;
|
|
c = 'n';
|
|
break;
|
|
|
|
case ESCAPE_CHAR:
|
|
escape = true;
|
|
break;
|
|
|
|
case SINGLE_QUOTE_CHAR:
|
|
case DOUBLE_QUOTE_CHAR:
|
|
if (quoteChar == '\0')
|
|
{
|
|
quoteChar = c;
|
|
}
|
|
else if (c != quoteChar)
|
|
{
|
|
escape = true;
|
|
}
|
|
|
|
needQuotes = true;
|
|
break;
|
|
|
|
case '.':
|
|
case '_':
|
|
case '-':
|
|
case '+':
|
|
case >= 'a' and <= 'z' or >= 'A' and <= 'Z' or >= '0' and <= '9':
|
|
break;
|
|
|
|
default:
|
|
needQuotes = true;
|
|
break;
|
|
}
|
|
|
|
if (escape)
|
|
{
|
|
sb.Append(ESCAPE_CHAR);
|
|
}
|
|
|
|
sb.Append(c);
|
|
|
|
return needQuotes || escape;
|
|
}
|
|
}
|