mirror of
https://github.com/AssetRipper/AssetRipper.git
synced 2025-12-11 20:15:29 +01:00
* Export MonoBehaviour byte arrays as scalars rather than sequences * Do not serialize yaml scalars, especially not for byte arrays * Eliminate unnecessary state for yaml scalars * Create a new type hierarchy for yaml scalars * Implement hexidecimal emission of floating point scalars * Implement hexidecimal emission of numeric lists * Resolves #1422 * Resolves #1409 * Resolves #1381 * Related to #927 * Related to #695
143 lines
2.8 KiB
C#
143 lines
2.8 KiB
C#
using System.Text.RegularExpressions;
|
|
|
|
namespace AssetRipper.Yaml;
|
|
|
|
public abstract partial class YamlScalarNode
|
|
{
|
|
private sealed partial class StringNode : YamlScalarNode
|
|
{
|
|
public StringNode(string value)
|
|
{
|
|
Value = value;
|
|
Style = GetStringStyle(value);
|
|
}
|
|
|
|
public StringNode(string value, ScalarStyle style)
|
|
{
|
|
Value = value;
|
|
Style = style;
|
|
}
|
|
|
|
private protected override void EmitCore(Emitter emitter)
|
|
{
|
|
WriteString(emitter);
|
|
}
|
|
|
|
public override string Value { get; }
|
|
public override ScalarStyle Style { get; }
|
|
|
|
private void WriteString(Emitter emitter)
|
|
{
|
|
switch (Style)
|
|
{
|
|
case ScalarStyle.Plain:
|
|
if (emitter.IsFormatKeys && emitter.IsKey)
|
|
{
|
|
emitter.WriteFormat(Value);
|
|
}
|
|
else
|
|
{
|
|
emitter.Write(Value);
|
|
}
|
|
break;
|
|
case ScalarStyle.SingleQuoted:
|
|
{
|
|
emitter.WriteDelayed();
|
|
for (int i = 0; i < Value.Length; i++)
|
|
{
|
|
char c = Value[i];
|
|
emitter.WriteRaw(c);
|
|
switch (c)
|
|
{
|
|
case '\'':
|
|
emitter.WriteRaw(c);
|
|
break;
|
|
case '\n':
|
|
emitter.WriteRaw("\n ");
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case ScalarStyle.DoubleQuoted:
|
|
{
|
|
emitter.WriteDelayed();
|
|
for (int i = 0; i < Value.Length; i++)
|
|
{
|
|
char c = Value[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:
|
|
if (char.IsControl(c))
|
|
{
|
|
emitter.WriteRawUnicode(c);
|
|
}
|
|
else
|
|
{
|
|
emitter.WriteRaw(c);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
throw new NotSupportedException(Style.ToString());
|
|
}
|
|
}
|
|
|
|
private static ScalarStyle GetStringStyle(string value)
|
|
{
|
|
if (string.IsNullOrEmpty(value))
|
|
{
|
|
return ScalarStyle.Plain;
|
|
}
|
|
else if (ContainsControlCharacter(value))
|
|
{
|
|
return ScalarStyle.DoubleQuoted;
|
|
}
|
|
else if (IllegalStringsRegex().IsMatch(value))
|
|
{
|
|
return value.Contains("\n ") ? ScalarStyle.DoubleQuoted : ScalarStyle.SingleQuoted;
|
|
}
|
|
|
|
return ScalarStyle.Plain;
|
|
}
|
|
|
|
private static bool ContainsControlCharacter(ReadOnlySpan<char> span)
|
|
{
|
|
foreach (char c in span)
|
|
{
|
|
if (char.IsControl(c))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
[GeneratedRegex("""(^\s)|(^-\s)|(^-$)|(^[\:\[\]'"*&!@#%{}?<>,\`])|([:@]\s)|([\n\r])|([:\s]$)""", RegexOptions.Compiled)]
|
|
private static partial Regex IllegalStringsRegex();
|
|
}
|
|
}
|