mirror of
https://github.com/Dongyifengs/AssetStudio-Genshin-MoYi.git
synced 2025-05-07 03:49:19 +08:00
457 lines
10 KiB
C#
457 lines
10 KiB
C#
//#define USE_HEX_FLOAT
|
|
|
|
using System;
|
|
using System.Globalization;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace AssetStudio
|
|
{
|
|
public sealed class YAMLScalarNode : YAMLNode
|
|
{
|
|
public YAMLScalarNode()
|
|
{
|
|
}
|
|
|
|
public YAMLScalarNode(bool value) :
|
|
this(value, false)
|
|
{
|
|
}
|
|
|
|
public YAMLScalarNode(bool value, bool isHex)
|
|
{
|
|
SetValue(value);
|
|
Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain;
|
|
}
|
|
|
|
public YAMLScalarNode(byte value) :
|
|
this(value, false)
|
|
{
|
|
}
|
|
|
|
public YAMLScalarNode(byte value, bool isHex)
|
|
{
|
|
SetValue(value);
|
|
Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain;
|
|
}
|
|
|
|
public YAMLScalarNode(short value) :
|
|
this(value, false)
|
|
{
|
|
}
|
|
|
|
public YAMLScalarNode(short value, bool isHex)
|
|
{
|
|
SetValue(value);
|
|
Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain;
|
|
}
|
|
|
|
public YAMLScalarNode(ushort value) :
|
|
this(value, false)
|
|
{
|
|
}
|
|
|
|
public YAMLScalarNode(ushort value, bool isHex)
|
|
{
|
|
SetValue(value);
|
|
Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain;
|
|
}
|
|
|
|
public YAMLScalarNode(int value) :
|
|
this(value, false)
|
|
{
|
|
}
|
|
|
|
public YAMLScalarNode(int value, bool isHex)
|
|
{
|
|
SetValue(value);
|
|
Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain;
|
|
}
|
|
|
|
public YAMLScalarNode(uint value) :
|
|
this(value, false)
|
|
{
|
|
}
|
|
|
|
public YAMLScalarNode(uint value, bool isHex)
|
|
{
|
|
SetValue(value);
|
|
Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain;
|
|
}
|
|
|
|
public YAMLScalarNode(long value) :
|
|
this(value, false)
|
|
{
|
|
}
|
|
|
|
public YAMLScalarNode(long value, bool isHex)
|
|
{
|
|
SetValue(value);
|
|
Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain;
|
|
}
|
|
|
|
public YAMLScalarNode(ulong value) :
|
|
this(value, false)
|
|
{
|
|
}
|
|
|
|
public YAMLScalarNode(ulong value, bool isHex)
|
|
{
|
|
SetValue(value);
|
|
Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain;
|
|
}
|
|
|
|
public YAMLScalarNode(float value) :
|
|
this(value, false)
|
|
{
|
|
}
|
|
|
|
public YAMLScalarNode(float value, bool isHex)
|
|
{
|
|
SetValue(value);
|
|
Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain;
|
|
}
|
|
|
|
public YAMLScalarNode(double value) :
|
|
this(value, false)
|
|
{
|
|
}
|
|
|
|
public YAMLScalarNode(double value, bool isHex)
|
|
{
|
|
SetValue(value);
|
|
Style = isHex ? ScalarStyle.Hex : ScalarStyle.Plain;
|
|
}
|
|
|
|
public YAMLScalarNode(string value)
|
|
{
|
|
SetValue(value);
|
|
Style = GetStringStyle(value);
|
|
}
|
|
|
|
internal YAMLScalarNode(string value, bool _)
|
|
{
|
|
SetValue(value);
|
|
Style = ScalarStyle.Plain;
|
|
}
|
|
|
|
public void SetValue(bool value)
|
|
{
|
|
m_value = value ? 1u : 0u;
|
|
m_objectType = ScalarType.Boolean;
|
|
}
|
|
|
|
public void SetValue(byte value)
|
|
{
|
|
m_value = value;
|
|
m_objectType = ScalarType.Byte;
|
|
}
|
|
|
|
public void SetValue(short value)
|
|
{
|
|
m_value = unchecked((ushort)value);
|
|
m_objectType = ScalarType.Int16;
|
|
}
|
|
|
|
public void SetValue(ushort value)
|
|
{
|
|
m_value = value;
|
|
m_objectType = ScalarType.UInt16;
|
|
}
|
|
|
|
public void SetValue(int value)
|
|
{
|
|
m_value = unchecked((uint)value);
|
|
m_objectType = ScalarType.Int32;
|
|
}
|
|
|
|
public void SetValue(uint value)
|
|
{
|
|
m_value = value;
|
|
m_objectType = ScalarType.UInt32;
|
|
}
|
|
|
|
public void SetValue(long value)
|
|
{
|
|
m_value = unchecked((ulong)value);
|
|
m_objectType = ScalarType.Int64;
|
|
}
|
|
|
|
public void SetValue(ulong value)
|
|
{
|
|
m_value = value;
|
|
m_objectType = ScalarType.UInt64;
|
|
}
|
|
|
|
public void SetValue(float value)
|
|
{
|
|
#if USE_HEX_FLOAT
|
|
// It is more precise technic but output looks vague and less readable
|
|
uint hex = BitConverterExtensions.ToUInt32(value);
|
|
m_string = $"0x{hex.ToHexString()}({value.ToString(CultureInfo.InvariantCulture)})";
|
|
m_objectType = ScalarType.String;
|
|
#else
|
|
m_value = BitConverterExtensions.ToUInt32(value);
|
|
m_objectType = ScalarType.Single;
|
|
#endif
|
|
}
|
|
|
|
public void SetValue(double value)
|
|
{
|
|
#if USE_HEX_FLOAT
|
|
// It is more precise technic but output looks vague and less readable
|
|
ulong hex = BitConverterExtensions.ToUInt64(value);
|
|
m_string = $"0x{hex.ToHexString()}({value.ToString(CultureInfo.InvariantCulture)})";
|
|
m_objectType = ScalarType.String;
|
|
#else
|
|
m_value = BitConverterExtensions.ToUInt64(value);
|
|
m_objectType = ScalarType.Double;
|
|
#endif
|
|
}
|
|
|
|
public void SetValue(string value)
|
|
{
|
|
m_string = value;
|
|
m_objectType = ScalarType.String;
|
|
}
|
|
|
|
internal Emitter ToString(Emitter emitter)
|
|
{
|
|
if (Style == ScalarStyle.Hex)
|
|
{
|
|
switch (m_objectType)
|
|
{
|
|
case ScalarType.Byte:
|
|
return emitter.WriteHex((byte)m_value);
|
|
case ScalarType.Int16:
|
|
return emitter.WriteHex(unchecked((short)m_value));
|
|
case ScalarType.UInt16:
|
|
return emitter.WriteHex((ushort)m_value);
|
|
case ScalarType.Int32:
|
|
return emitter.WriteHex(unchecked((int)m_value));
|
|
case ScalarType.UInt32:
|
|
return emitter.WriteHex((uint)m_value);
|
|
case ScalarType.Int64:
|
|
return emitter.WriteHex(unchecked((long)m_value));
|
|
case ScalarType.UInt64:
|
|
return emitter.WriteHex(m_value);
|
|
case ScalarType.Single:
|
|
return emitter.WriteHex((uint)m_value);
|
|
case ScalarType.Double:
|
|
return emitter.WriteHex(m_value);
|
|
default:
|
|
throw new NotImplementedException(m_objectType.ToString());
|
|
}
|
|
}
|
|
|
|
switch (m_objectType)
|
|
{
|
|
case ScalarType.Boolean:
|
|
return emitter.Write(m_value);
|
|
case ScalarType.Byte:
|
|
return emitter.Write(m_value);
|
|
case ScalarType.Int16:
|
|
return emitter.Write(unchecked((short)m_value));
|
|
case ScalarType.UInt16:
|
|
return emitter.Write(m_value);
|
|
case ScalarType.Int32:
|
|
return emitter.Write(unchecked((int)m_value));
|
|
case ScalarType.UInt32:
|
|
return emitter.Write(m_value);
|
|
case ScalarType.Int64:
|
|
return emitter.Write(unchecked((long)m_value));
|
|
case ScalarType.UInt64:
|
|
return emitter.Write(m_value);
|
|
case ScalarType.Single:
|
|
return emitter.Write(BitConverterExtensions.ToSingle((uint)m_value));
|
|
case ScalarType.Double:
|
|
return emitter.Write(BitConverterExtensions.ToDouble(m_value));
|
|
case ScalarType.String:
|
|
return WriteString(emitter);
|
|
|
|
default:
|
|
throw new NotImplementedException(m_objectType.ToString());
|
|
}
|
|
}
|
|
|
|
internal override void Emit(Emitter emitter)
|
|
{
|
|
base.Emit(emitter);
|
|
|
|
switch (Style)
|
|
{
|
|
case ScalarStyle.Hex:
|
|
case ScalarStyle.Plain:
|
|
ToString(emitter);
|
|
break;
|
|
|
|
case ScalarStyle.SingleQuoted:
|
|
emitter.Write('\'');
|
|
ToString(emitter);
|
|
emitter.Write('\'');
|
|
break;
|
|
|
|
case ScalarStyle.DoubleQuoted:
|
|
emitter.Write('"');
|
|
ToString(emitter);
|
|
emitter.Write('"');
|
|
break;
|
|
|
|
default:
|
|
throw new Exception($"Unsupported scalar style {Style}");
|
|
}
|
|
}
|
|
|
|
private Emitter WriteString(Emitter emitter)
|
|
{
|
|
if (Style == ScalarStyle.Plain)
|
|
{
|
|
if (emitter.IsFormatKeys && emitter.IsKey)
|
|
{
|
|
emitter.WriteFormat(m_string);
|
|
}
|
|
else
|
|
{
|
|
emitter.Write(m_string);
|
|
}
|
|
}
|
|
else if (Style == ScalarStyle.SingleQuoted)
|
|
{
|
|
emitter.WriteDelayed();
|
|
for (int i = 0; i < m_string.Length; i++)
|
|
{
|
|
char c = m_string[i];
|
|
emitter.WriteRaw(c);
|
|
if (c == '\'')
|
|
{
|
|
emitter.WriteRaw(c);
|
|
}
|
|
else if (c == '\n')
|
|
{
|
|
emitter.WriteRaw("\n ");
|
|
}
|
|
}
|
|
}
|
|
else if (Style == ScalarStyle.DoubleQuoted)
|
|
{
|
|
emitter.WriteDelayed();
|
|
for (int i = 0; i < m_string.Length; i++)
|
|
{
|
|
char c = m_string[i];
|
|
switch (c)
|
|
{
|
|
case '\\':
|
|
emitter.WriteRaw('\\').WriteRaw('\\');
|
|
break;
|
|
case '\n':
|
|
emitter.WriteRaw('\\').WriteRaw('n');
|
|
break;
|
|
case '\r':
|
|
emitter.WriteRaw('\\').WriteRaw('r');
|
|
break;
|
|
case '\t':
|
|
emitter.WriteRaw('\\').WriteRaw('t');
|
|
break;
|
|
case '"':
|
|
emitter.WriteRaw('\\').WriteRaw('"');
|
|
break;
|
|
|
|
default:
|
|
emitter.WriteRaw(c);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new NotSupportedException(Style.ToString());
|
|
}
|
|
return emitter;
|
|
}
|
|
|
|
private static ScalarStyle GetStringStyle(string value)
|
|
{
|
|
if (s_illegal.IsMatch(value))
|
|
{
|
|
return value.Contains("\n ") ? ScalarStyle.DoubleQuoted : ScalarStyle.SingleQuoted;
|
|
}
|
|
return ScalarStyle.Plain;
|
|
}
|
|
|
|
public static YAMLScalarNode Empty { get; } = new YAMLScalarNode();
|
|
|
|
public override YAMLNodeType NodeType => YAMLNodeType.Scalar;
|
|
public override bool IsMultiline => false;
|
|
public override bool IsIndent => false;
|
|
|
|
public string Value
|
|
{
|
|
get
|
|
{
|
|
if (Style == ScalarStyle.Hex)
|
|
{
|
|
switch (m_objectType)
|
|
{
|
|
case ScalarType.Byte:
|
|
return unchecked((byte)m_value).ToHexString();
|
|
case ScalarType.Int16:
|
|
return unchecked((short)m_value).ToHexString();
|
|
case ScalarType.UInt16:
|
|
return unchecked((ushort)m_value).ToHexString();
|
|
case ScalarType.Int32:
|
|
return unchecked((int)m_value).ToHexString();
|
|
case ScalarType.UInt32:
|
|
return unchecked((uint)m_value).ToHexString();
|
|
case ScalarType.Int64:
|
|
return unchecked((long)m_value).ToHexString();
|
|
case ScalarType.UInt64:
|
|
return m_value.ToHexString();
|
|
case ScalarType.Single:
|
|
return BitConverterExtensions.ToSingle((uint)m_value).ToHexString();
|
|
case ScalarType.Double:
|
|
return BitConverterExtensions.ToDouble(m_value).ToHexString();
|
|
default:
|
|
throw new NotImplementedException(m_objectType.ToString());
|
|
}
|
|
}
|
|
|
|
switch (m_objectType)
|
|
{
|
|
case ScalarType.Boolean:
|
|
return m_value == 1 ? "true" : "false";
|
|
case ScalarType.Byte:
|
|
return m_value.ToString();
|
|
case ScalarType.Int16:
|
|
return unchecked((short)m_value).ToString();
|
|
case ScalarType.UInt16:
|
|
return m_value.ToString();
|
|
case ScalarType.Int32:
|
|
return unchecked((int)m_value).ToString();
|
|
case ScalarType.UInt32:
|
|
return m_value.ToString();
|
|
case ScalarType.Int64:
|
|
return unchecked((long)m_value).ToString();
|
|
case ScalarType.UInt64:
|
|
return m_value.ToString();
|
|
case ScalarType.Single:
|
|
return BitConverterExtensions.ToSingle((uint)m_value).ToString(CultureInfo.InvariantCulture);
|
|
case ScalarType.Double:
|
|
return BitConverterExtensions.ToDouble(m_value).ToString(CultureInfo.InvariantCulture);
|
|
case ScalarType.String:
|
|
return m_string;
|
|
|
|
default:
|
|
throw new NotImplementedException(m_objectType.ToString());
|
|
}
|
|
}
|
|
set => m_string = value;
|
|
}
|
|
public ScalarStyle Style { get; }
|
|
|
|
private static readonly Regex s_illegal = new Regex("(^\\s)|(^-\\s)|(^-$)|(^[\\:\\[\\]'\"*&!@#%{}?<>,\\`])|([:@]\\s)|([\\n\\r])|([:\\s]$)", RegexOptions.Compiled);
|
|
|
|
private ScalarType m_objectType = ScalarType.String;
|
|
private string m_string = string.Empty;
|
|
private ulong m_value = 0;
|
|
}
|
|
}
|