1
0
Files
named-binary-tag/Nbt/NbtUtils.cs
2024-03-15 14:44:21 +01:00

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;
}
}