This commit is contained in:
Razmoth
2023-09-22 20:31:55 +04:00
parent d594f90fec
commit 6ebeaeee3f
48 changed files with 5886 additions and 81 deletions

View File

@@ -0,0 +1,231 @@
using System;
using System.IO;
using System.Text;
namespace AssetStudio
{
internal class Emitter
{
public Emitter(TextWriter writer, bool formatKeys)
{
if (writer == null)
{
throw new ArgumentNullException(nameof(writer));
}
m_stream = writer;
IsFormatKeys = formatKeys;
if (formatKeys)
{
m_sb = new StringBuilder();
}
}
public Emitter IncreaseIndent()
{
m_indent++;
return this;
}
public Emitter DecreaseIndent()
{
if (m_indent == 0)
{
throw new Exception($"Increase/decrease indent mismatch");
}
m_indent--;
return this;
}
public Emitter Write(char value)
{
WriteDelayed();
m_stream.Write(value);
return this;
}
public Emitter WriteRaw(char value)
{
m_stream.Write(value);
return this;
}
public Emitter Write(byte value)
{
WriteDelayed();
m_stream.Write(value);
return this;
}
public Emitter Write(ushort value)
{
WriteDelayed();
m_stream.Write(value);
return this;
}
public Emitter Write(short value)
{
WriteDelayed();
m_stream.Write(value);
return this;
}
public Emitter Write(uint value)
{
WriteDelayed();
m_stream.Write(value);
return this;
}
public Emitter Write(int value)
{
WriteDelayed();
m_stream.Write(value);
return this;
}
public Emitter Write(ulong value)
{
WriteDelayed();
m_stream.Write(value);
return this;
}
public Emitter Write(long value)
{
WriteDelayed();
m_stream.Write(value);
return this;
}
public Emitter Write(float value)
{
WriteDelayed();
m_stream.Write(value);
return this;
}
public Emitter Write(double value)
{
WriteDelayed();
m_stream.Write(value);
return this;
}
public Emitter Write(string value)
{
if (value.Length > 0)
{
WriteDelayed();
m_stream.Write(value);
}
return this;
}
public Emitter WriteFormat(string value)
{
if (value.Length > 0)
{
WriteDelayed();
if (value.Length > 2 && value.StartsWith("m_", StringComparison.Ordinal))
{
m_sb.Append(value, 2, value.Length - 2);
if (char.IsUpper(m_sb[0]))
{
m_sb[0] = char.ToLower(m_sb[0]);
}
value = m_sb.ToString();
m_sb.Clear();
}
m_stream.Write(value);
}
return this;
}
public Emitter WriteRaw(string value)
{
m_stream.Write(value);
return this;
}
public Emitter WriteClose(char @char)
{
m_isNeedSeparator = false;
m_isNeedWhitespace = false;
m_isNeedLineBreak = false;
return Write(@char);
}
public Emitter WriteClose(string @string)
{
m_isNeedSeparator = false;
m_isNeedWhitespace = false;
return Write(@string);
}
public Emitter WriteWhitespace()
{
m_isNeedWhitespace = true;
return this;
}
public Emitter WriteSeparator()
{
m_isNeedSeparator = true;
return this;
}
public Emitter WriteLine()
{
m_isNeedLineBreak = true;
return this;
}
public void WriteMeta(MetaType type, string value)
{
Write('%').Write(type.ToString()).WriteWhitespace();
Write(value).WriteLine();
}
public void WriteDelayed()
{
if (m_isNeedLineBreak)
{
m_stream.Write('\n');
m_isNeedSeparator = false;
m_isNeedWhitespace = false;
m_isNeedLineBreak = false;
WriteIndent();
}
if (m_isNeedSeparator)
{
m_stream.Write(',');
m_isNeedSeparator = false;
}
if (m_isNeedWhitespace)
{
m_stream.Write(' ');
m_isNeedWhitespace = false;
}
}
private void WriteIndent()
{
for (int i = 0; i < m_indent * 2; i++)
{
m_stream.Write(' ');
}
}
public bool IsFormatKeys { get; }
public bool IsKey { get; set; }
private readonly TextWriter m_stream;
private readonly StringBuilder m_sb;
private int m_indent = 0;
private bool m_isNeedWhitespace = false;
private bool m_isNeedSeparator = false;
private bool m_isNeedLineBreak = false;
}
}

View File

@@ -0,0 +1,7 @@
namespace AssetStudio
{
public interface IYAMLExportable
{
YAMLNode ExportYAML(int[] version);
}
}

View File

@@ -0,0 +1,18 @@
namespace AssetStudio
{
/// <summary>
/// Specifies the style of a mapping.
/// </summary>
public enum MappingStyle
{
/// <summary>
/// The block mapping style.
/// </summary>
Block,
/// <summary>
/// The flow mapping style.
/// </summary>
Flow
}
}

View File

@@ -0,0 +1,8 @@
namespace AssetStudio
{
internal enum MetaType
{
YAML,
TAG,
}
}

View File

@@ -0,0 +1,28 @@
namespace AssetStudio
{
/// <summary>
/// Specifies the style of a YAML scalar.
/// </summary>
public enum ScalarStyle
{
/// <summary>
/// The plain scalar style.
/// </summary>
Plain,
/// <summary>
///
/// </summary>
Hex,
/// <summary>
/// The single-quoted scalar style.
/// </summary>
SingleQuoted,
/// <summary>
/// The double-quoted scalar style.
/// </summary>
DoubleQuoted,
}
}

View File

@@ -0,0 +1,17 @@
namespace AssetStudio
{
internal enum ScalarType
{
Boolean,
Byte,
UInt16,
Int16,
UInt32,
Int32,
UInt64,
Int64,
Single,
Double,
String,
}
}

View File

@@ -0,0 +1,51 @@
namespace AssetStudio
{
/// <summary>
/// Specifies the style of a sequence.
/// </summary>
public enum SequenceStyle
{
/// <summary>
/// The block sequence style
/// </summary>
Block,
/// <summary>
/// The block sequence style but with curly braces
/// </summary>
BlockCurve,
/// <summary>
/// The flow sequence style
/// </summary>
Flow,
/// <summary>
/// Single line with hex data
/// </summary>
Raw,
}
public static class SequenceStyleExtensions
{
public static bool IsRaw(this SequenceStyle _this)
{
return _this == SequenceStyle.Raw;
}
public static bool IsAnyBlock(this SequenceStyle _this)
{
return _this == SequenceStyle.Block || _this == SequenceStyle.BlockCurve;
}
/// <summary>
/// Get scalar style corresponding to current sequence style
/// </summary>
/// <param name="_this">Sequence style</param>
/// <returns>Corresponding scalar style</returns>
public static ScalarStyle ToScalarStyle(this SequenceStyle _this)
{
return _this == SequenceStyle.Raw ? ScalarStyle.Hex : ScalarStyle.Plain;
}
}
}

View File

@@ -0,0 +1,42 @@
namespace AssetStudio
{
public sealed class YAMLDocument
{
public YAMLDocument()
{
}
public YAMLScalarNode CreateScalarRoot()
{
YAMLScalarNode root = new YAMLScalarNode();
Root = root;
return root;
}
public YAMLSequenceNode CreateSequenceRoot()
{
YAMLSequenceNode root = new YAMLSequenceNode();
Root = root;
return root;
}
public YAMLMappingNode CreateMappingRoot()
{
YAMLMappingNode root = new YAMLMappingNode();
Root = root;
return root;
}
internal void Emit(Emitter emitter, bool isSeparator)
{
if(isSeparator)
{
emitter.Write("---").WriteWhitespace();
}
Root.Emit(emitter);
}
public YAMLNode Root { get; private set; }
}
}

View File

@@ -0,0 +1,330 @@
using System;
using System.Collections.Generic;
namespace AssetStudio
{
public sealed class YAMLMappingNode : YAMLNode
{
public YAMLMappingNode()
{
}
public YAMLMappingNode(MappingStyle style)
{
Style = style;
}
public void Add(int key, long value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(int key, string value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(int key, YAMLNode value)
{
YAMLScalarNode keyNode = new YAMLScalarNode(key);
InsertEnd(keyNode, value);
}
public void Add(uint key, string value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(uint key, YAMLNode value)
{
YAMLScalarNode keyNode = new YAMLScalarNode(key);
InsertEnd(keyNode, value);
}
public void Add(long key, string value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(long key, YAMLNode value)
{
YAMLScalarNode keyNode = new YAMLScalarNode(key);
InsertEnd(keyNode, value);
}
public void Add(string key, bool value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(string key, byte value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(string key, short value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(string key, ushort value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(string key, int value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(string key, uint value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(string key, long value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(string key, ulong value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(string key, float value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(string key, string value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(string key, YAMLNode value)
{
YAMLScalarNode keyNode = new YAMLScalarNode(key, true);
InsertEnd(keyNode, value);
}
public void Add(YAMLNode key, bool value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(YAMLNode key, byte value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(YAMLNode key, short value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(YAMLNode key, ushort value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(YAMLNode key, int value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(YAMLNode key, uint value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(YAMLNode key, long value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(YAMLNode key, ulong value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(YAMLNode key, float value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(YAMLNode key, string value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
Add(key, valueNode);
}
public void Add(YAMLNode key, YAMLNode value)
{
if (key.NodeType != YAMLNodeType.Scalar)
{
throw new Exception($"Only {YAMLNodeType.Scalar} node as a key supported");
}
InsertEnd(key, value);
}
public void Append(YAMLMappingNode map)
{
foreach (KeyValuePair<YAMLNode, YAMLNode> child in map.m_children)
{
Add(child.Key, child.Value);
}
}
public void InsertBegin(string key, int value)
{
YAMLScalarNode valueNode = new YAMLScalarNode(value);
InsertBegin(key, valueNode);
}
public void InsertBegin(string key, YAMLNode value)
{
YAMLScalarNode keyNode = new YAMLScalarNode(key, true);
InsertBegin(keyNode, value);
}
public void InsertBegin(YAMLNode key, YAMLNode value)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
KeyValuePair<YAMLNode, YAMLNode> pair = new KeyValuePair<YAMLNode, YAMLNode>(key, value);
m_children.Insert(0, pair);
}
internal override void Emit(Emitter emitter)
{
base.Emit(emitter);
StartChildren(emitter);
foreach (var kvp in m_children)
{
YAMLNode key = kvp.Key;
YAMLNode value = kvp.Value;
bool iskey = emitter.IsKey;
emitter.IsKey = true;
key.Emit(emitter);
emitter.IsKey = false;
StartTransition(emitter, value);
value.Emit(emitter);
EndTransition(emitter, value);
emitter.IsKey = iskey;
}
EndChildren(emitter);
}
private void StartChildren(Emitter emitter)
{
if (Style == MappingStyle.Block)
{
if (m_children.Count == 0)
{
emitter.Write('{');
}
}
else if (Style == MappingStyle.Flow)
{
emitter.Write('{');
}
}
private void EndChildren(Emitter emitter)
{
if (Style == MappingStyle.Block)
{
if (m_children.Count == 0)
{
emitter.Write('}');
}
emitter.WriteLine();
}
else if (Style == MappingStyle.Flow)
{
emitter.WriteClose('}');
}
}
private void StartTransition(Emitter emitter, YAMLNode next)
{
emitter.Write(':').WriteWhitespace();
if (Style == MappingStyle.Block)
{
if (next.IsMultiline)
{
emitter.WriteLine();
}
}
if (next.IsIndent)
{
emitter.IncreaseIndent();
}
}
private void EndTransition(Emitter emitter, YAMLNode next)
{
if (Style == MappingStyle.Block)
{
emitter.WriteLine();
}
else if (Style == MappingStyle.Flow)
{
emitter.WriteSeparator().WriteWhitespace();
}
if (next.IsIndent)
{
emitter.DecreaseIndent();
}
}
private void InsertEnd(YAMLNode key, YAMLNode value)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
KeyValuePair<YAMLNode, YAMLNode> pair = new KeyValuePair<YAMLNode, YAMLNode>(key, value);
m_children.Add(pair);
}
public static YAMLMappingNode Empty { get; } = new YAMLMappingNode(MappingStyle.Flow);
public override YAMLNodeType NodeType => YAMLNodeType.Mapping;
public override bool IsMultiline => Style == MappingStyle.Block && m_children.Count > 0;
public override bool IsIndent => Style == MappingStyle.Block;
public MappingStyle Style { get; set; }
private readonly List<KeyValuePair<YAMLNode, YAMLNode>> m_children = new List<KeyValuePair<YAMLNode, YAMLNode>>();
}
}

View File

@@ -0,0 +1,40 @@
namespace AssetStudio
{
public abstract class YAMLNode
{
internal virtual void Emit(Emitter emitter)
{
bool isWrote = false;
if (!CustomTag.IsEmpty)
{
emitter.Write(CustomTag.ToString()).WriteWhitespace();
isWrote = true;
}
if (Anchor.Length > 0)
{
emitter.Write("&").Write(Anchor).WriteWhitespace();
isWrote = true;
}
if (isWrote)
{
if (IsMultiline)
{
emitter.WriteLine();
}
}
}
public abstract YAMLNodeType NodeType { get; }
public abstract bool IsMultiline { get; }
public abstract bool IsIndent { get; }
public string Tag
{
get => CustomTag.Content;
set => CustomTag = new YAMLTag(YAMLWriter.DefaultTagHandle, value);
}
public YAMLTag CustomTag { get; set; }
public string Anchor { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,20 @@
namespace AssetStudio
{
public enum YAMLNodeType
{
/// <summary>
/// The node is a <see cref="YamlMappingNode"/>.
/// </summary>
Mapping,
/// <summary>
/// The node is a <see cref="YamlScalarNode"/>.
/// </summary>
Scalar,
/// <summary>
/// The node is a <see cref="YamlSequenceNode"/>.
/// </summary>
Sequence
}
}

View File

@@ -0,0 +1,456 @@
//#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;
}
}

View File

@@ -0,0 +1,213 @@
using System.Collections.Generic;
namespace AssetStudio
{
public sealed class YAMLSequenceNode : YAMLNode
{
public YAMLSequenceNode()
{
}
public YAMLSequenceNode(SequenceStyle style)
{
Style = style;
}
public void Add(bool value)
{
YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw());
Add(node);
}
public void Add(byte value)
{
YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw());
Add(node);
}
public void Add(short value)
{
YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw());
Add(node);
}
public void Add(ushort value)
{
YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw());
Add(node);
}
public void Add(int value)
{
YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw());
Add(node);
}
public void Add(uint value)
{
YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw());
Add(node);
}
public void Add(long value)
{
YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw());
Add(node);
}
public void Add(ulong value)
{
YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw());
Add(node);
}
public void Add(float value)
{
YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw());
Add(node);
}
public void Add(double value)
{
YAMLScalarNode node = new YAMLScalarNode(value, Style.IsRaw());
Add(node);
}
public void Add(string value)
{
YAMLScalarNode node = new YAMLScalarNode(value);
Add(node);
}
public void Add(YAMLNode child)
{
m_children.Add(child);
}
internal override void Emit(Emitter emitter)
{
base.Emit(emitter);
StartChildren(emitter);
foreach (YAMLNode child in m_children)
{
StartChild(emitter, child);
child.Emit(emitter);
EndChild(emitter, child);
}
EndChildren(emitter);
}
private void StartChildren(Emitter emitter)
{
switch (Style)
{
case SequenceStyle.Block:
if (m_children.Count == 0)
{
emitter.Write('[');
}
break;
case SequenceStyle.BlockCurve:
if (m_children.Count == 0)
{
emitter.Write('{');
}
break;
case SequenceStyle.Flow:
emitter.Write('[');
break;
case SequenceStyle.Raw:
if (m_children.Count == 0)
{
emitter.Write('[');
}
break;
}
}
private void EndChildren(Emitter emitter)
{
switch (Style)
{
case SequenceStyle.Block:
if (m_children.Count == 0)
{
emitter.Write(']');
}
emitter.WriteLine();
break;
case SequenceStyle.BlockCurve:
if (m_children.Count == 0)
{
emitter.WriteClose('}');
}
emitter.WriteLine();
break;
case SequenceStyle.Flow:
emitter.WriteClose(']');
break;
case SequenceStyle.Raw:
if (m_children.Count == 0)
{
emitter.Write(']');
}
emitter.WriteLine();
break;
}
}
private void StartChild(Emitter emitter, YAMLNode next)
{
if (Style.IsAnyBlock())
{
emitter.Write('-').Write(' ');
if (next.NodeType == NodeType)
{
emitter.IncreaseIndent();
}
}
if (next.IsIndent)
{
emitter.IncreaseIndent();
}
}
private void EndChild(Emitter emitter, YAMLNode next)
{
if (Style.IsAnyBlock())
{
emitter.WriteLine();
if (next.NodeType == NodeType)
{
emitter.DecreaseIndent();
}
}
else if (Style == SequenceStyle.Flow)
{
emitter.WriteSeparator().WriteWhitespace();
}
if (next.IsIndent)
{
emitter.DecreaseIndent();
}
}
public static YAMLSequenceNode Empty { get; } = new YAMLSequenceNode();
public override YAMLNodeType NodeType => YAMLNodeType.Sequence;
public override bool IsMultiline => Style.IsAnyBlock() && m_children.Count > 0;
public override bool IsIndent => false;
public SequenceStyle Style { get; }
private readonly List<YAMLNode> m_children = new List<YAMLNode>();
}
}

View File

@@ -0,0 +1,26 @@
namespace AssetStudio
{
public readonly struct YAMLTag
{
public YAMLTag(string handle, string content)
{
Handle = handle;
Content = content;
}
public override string ToString()
{
return IsEmpty ? string.Empty : $"{Handle}{Content}";
}
public string ToHeaderString()
{
return IsEmpty ? string.Empty : $"{Handle} {Content}";
}
public bool IsEmpty => string.IsNullOrEmpty(Handle);
public string Handle { get; }
public string Content { get; }
}
}

View File

@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace AssetStudio
{
using Version = System.Version;
public class YAMLWriter
{
public void AddDocument(YAMLDocument document)
{
#if DEBUG
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}
if (m_documents.Contains(document))
{
throw new ArgumentException($"Document {document} is added already", nameof(document));
}
#endif
m_documents.Add(document);
}
public void AddTag(string handle, string content)
{
if(m_tags.Any(t => t.Handle == handle))
{
throw new Exception($"Writer already contains tag {handle}");
}
YAMLTag tag = new YAMLTag(handle, content);
m_tags.Add(tag);
}
public void Write(TextWriter output)
{
WriteHead(output);
foreach (YAMLDocument doc in m_documents)
{
WriteDocument(doc);
}
WriteTail(output);
}
public void WriteHead(TextWriter output)
{
m_emitter = new Emitter(output, IsFormatKeys);
m_isWriteSeparator = false;
if (IsWriteVersion)
{
m_emitter.WriteMeta(MetaType.YAML, Version.ToString());
m_isWriteSeparator = true;
}
if (IsWriteDefaultTag)
{
m_emitter.WriteMeta(MetaType.TAG, DefaultTag.ToHeaderString());
m_isWriteSeparator = true;
}
foreach (YAMLTag tag in m_tags)
{
m_emitter.WriteMeta(MetaType.TAG, tag.ToHeaderString());
m_isWriteSeparator = true;
}
}
public void WriteDocument(YAMLDocument doc)
{
doc.Emit(m_emitter, m_isWriteSeparator);
m_isWriteSeparator = true;
}
public void WriteTail(TextWriter output)
{
output.Write('\n');
}
public static Version Version { get; } = new Version(1, 1);
public const string DefaultTagHandle = "!u!";
public const string DefaultTagContent = "tag:unity3d.com,2011:";
public readonly YAMLTag DefaultTag = new YAMLTag(DefaultTagHandle, DefaultTagContent);
public bool IsWriteVersion { get; set; } = true;
public bool IsWriteDefaultTag { get; set; } = true;
public bool IsFormatKeys { get; set; }
private readonly HashSet<YAMLDocument> m_documents = new HashSet<YAMLDocument>();
private readonly List<YAMLTag> m_tags = new List<YAMLTag>();
private Emitter m_emitter;
private bool m_isWriteSeparator;
}
}

View File

@@ -0,0 +1,25 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
namespace AssetStudio
{
public static class ArrayYAMLExtensions
{
public static YAMLNode ExportYAML(this byte[] _this)
{
StringBuilder sb = new StringBuilder(_this.Length * 2);
for (int i = 0; i < _this.Length; i++)
{
sb.AppendHex(_this[i]);
}
return new YAMLScalarNode(sb.ToString(), true);
}
public static YAMLNode ExportYAML<T>(this T[][] _this, int[] version)
where T : IYAMLExportable
{
return ((IEnumerable<IEnumerable<T>>)_this).ExportYAML(version);
}
}
}

View File

@@ -0,0 +1,107 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace AssetStudio
{
public static class BitConverterExtensions
{
[StructLayout(LayoutKind.Explicit)]
private struct FloatUIntUnion
{
[FieldOffset(0)]
public uint Int;
[FieldOffset(0)]
public float Float;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint ToUInt32(float value)
{
return new FloatUIntUnion { Float = value }.Int;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong ToUInt64(double value)
{
return unchecked((ulong)BitConverter.DoubleToInt64Bits(value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float ToSingle(uint value)
{
return new FloatUIntUnion { Int = value }.Float;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double ToDouble(ulong value)
{
return BitConverter.Int64BitsToDouble(unchecked((long)value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void GetBytes(ushort value, byte[] buffer, int offset)
{
buffer[offset + 0] = unchecked((byte)(value >> 0));
buffer[offset + 1] = unchecked((byte)(value >> 8));
}
public static void GetBytes(uint value, byte[] buffer, int offset)
{
buffer[offset + 0] = unchecked((byte)(value >> 0));
buffer[offset + 1] = unchecked((byte)(value >> 8));
buffer[offset + 2] = unchecked((byte)(value >> 16));
buffer[offset + 3] = unchecked((byte)(value >> 24));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static short Swap(short value)
{
return unchecked((short)(Swap(unchecked((ushort)value))));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort Swap(ushort value)
{
return unchecked((ushort)(value >> 8 | value << 8));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Swap(int value)
{
return unchecked((int)(Swap(unchecked((uint)value))));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Swap(uint value)
{
value = value >> 16 | value << 16;
return ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long Swap(long value)
{
return unchecked((long)(Swap(unchecked((ulong)value))));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Swap(ulong value)
{
value = value >> 32 | value << 32;
value = ((value & 0xFFFF0000FFFF0000) >> 16) | ((value & 0x0000FFFF0000FFFF) << 16);
return ((value & 0xFF00FF00FF00FF00) >> 8) | ((value & 0x00FF00FF00FF00FF) << 8);
}
public static int GetDigitsCount(uint value)
{
int count = 0;
while (value != 0)
{
value /= 10;
count++;
}
return count;
}
}
}

View File

@@ -0,0 +1,82 @@
namespace AssetStudio
{
internal static class EmitterExtensions
{
public static Emitter WriteHex(this Emitter _this, byte value)
{
_this.Write(HexAlphabet[value >> 4]);
_this.Write(HexAlphabet[value & 0xF]);
return _this;
}
public static Emitter WriteHex(this Emitter _this, ushort value)
{
_this.Write(HexAlphabet[(value >> 4) & 0xF]);
_this.Write(HexAlphabet[(value >> 0) & 0xF]);
_this.Write(HexAlphabet[(value >> 12) & 0xF]);
_this.Write(HexAlphabet[(value >> 8) & 0xF]);
return _this;
}
public static Emitter WriteHex(this Emitter _this, short value)
{
return WriteHex(_this, unchecked((ushort)value));
}
public static Emitter WriteHex(this Emitter _this, uint value)
{
_this.Write(HexAlphabet[unchecked((int)(value >> 4) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 0) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 12) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 8) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 20) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 16) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 28) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 24) & 0xF)]);
return _this;
}
public static Emitter WriteHex(this Emitter _this, int value)
{
return WriteHex(_this, unchecked((uint)value));
}
public static Emitter WriteHex(this Emitter _this, ulong value)
{
_this.Write(HexAlphabet[unchecked((int)(value >> 4) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 0) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 12) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 8) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 20) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 16) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 28) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 24) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 36) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 32) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 44) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 40) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 52) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 48) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 60) & 0xF)]);
_this.Write(HexAlphabet[unchecked((int)(value >> 56) & 0xF)]);
return _this;
}
public static Emitter WriteHex(this Emitter _this, long value)
{
return WriteHex(_this, unchecked((ulong)value));
}
public static Emitter WriteHex(this Emitter _this, float value)
{
return WriteHex(_this, BitConverterExtensions.ToUInt32(value));
}
public static Emitter WriteHex(this Emitter _this, double value)
{
return WriteHex(_this, BitConverterExtensions.ToUInt64(value));
}
private static readonly string HexAlphabet = "0123456789ABCDEF";
}
}

View File

@@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
namespace AssetStudio
{
public static class IDictionaryExportYAMLExtensions
{
public static YAMLNode ExportYAML<T>(this IReadOnlyDictionary<int, T> _this, int[] version)
where T : IYAMLExportable
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve);
foreach (var kvp in _this)
{
YAMLMappingNode map = new YAMLMappingNode();
map.Add(kvp.Key, kvp.Value.ExportYAML(version));
node.Add(map);
}
return node;
}
public static YAMLNode ExportYAML<T>(this IReadOnlyDictionary<string, T> _this, int[] version)
where T : IYAMLExportable
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve);
foreach (var kvp in _this)
{
YAMLMappingNode map = new YAMLMappingNode();
map.Add(kvp.Key, kvp.Value.ExportYAML(version));
node.Add(map);
}
return node;
}
public static YAMLNode ExportYAML<T1, T2>(this IReadOnlyDictionary<Tuple<T1, long>, T2> _this, int[] version)
where T1 : IYAMLExportable
where T2 : IYAMLExportable
{
// TODO: test
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve);
foreach (var kvp in _this)
{
YAMLMappingNode kvpMap = new YAMLMappingNode();
YAMLMappingNode keyMap = new YAMLMappingNode();
keyMap.Add("first", kvp.Key.Item1.ExportYAML(version));
keyMap.Add("second", kvp.Key.Item2);
kvpMap.Add("first", keyMap);
kvpMap.Add("second", kvp.Value.ExportYAML(version));
node.Add(kvpMap);
}
return node;
}
public static YAMLNode ExportYAML<T>(this IReadOnlyDictionary<T, int> _this, int[] version)
where T : IYAMLExportable
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve);
foreach (var kvp in _this)
{
YAMLMappingNode map = new YAMLMappingNode();
YAMLNode key = kvp.Key.ExportYAML(version);
if (key.NodeType == YAMLNodeType.Scalar)
{
map.Add(key, kvp.Value);
}
else
{
map.Add("first", key);
map.Add("second", kvp.Value);
}
node.Add(map);
}
return node;
}
public static YAMLNode ExportYAML<T>(this IReadOnlyDictionary<T, float> _this, int[] version)
where T : IYAMLExportable
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve);
foreach (var kvp in _this)
{
YAMLMappingNode map = new YAMLMappingNode();
YAMLNode key = kvp.Key.ExportYAML(version);
if (key.NodeType == YAMLNodeType.Scalar)
{
map.Add(key, kvp.Value);
}
else
{
map.Add("first", key);
map.Add("second", kvp.Value);
}
node.Add(map);
}
return node;
}
public static YAMLNode ExportYAML<T1, T2>(this IReadOnlyDictionary<T1, T2> _this, int[] version)
where T1 : IYAMLExportable
where T2 : IYAMLExportable
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve);
foreach (var kvp in _this)
{
YAMLMappingNode map = new YAMLMappingNode();
YAMLNode key = kvp.Key.ExportYAML(version);
if (key.NodeType == YAMLNodeType.Scalar)
{
map.Add(key, kvp.Value.ExportYAML(version));
}
else
{
map.Add("first", key);
map.Add("second", kvp.Value.ExportYAML(version));
}
node.Add(map);
}
return node;
}
public static YAMLNode ExportYAML<T1, T2>(this IReadOnlyDictionary<T1, T2[]> _this, int[] version)
where T1 : IYAMLExportable
where T2 : IYAMLExportable
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve);
foreach (var kvp in _this)
{
YAMLMappingNode map = new YAMLMappingNode();
YAMLNode key = kvp.Key.ExportYAML(version);
if (key.NodeType == YAMLNodeType.Scalar)
{
map.Add(key, kvp.Value.ExportYAML(version));
}
else
{
map.Add("first", key);
map.Add("second", kvp.Value.ExportYAML(version));
}
node.Add(map);
}
return node;
}
}
}

View File

@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
namespace AssetStudio
{
public static class IDictionaryYAMLExtensions
{
public static YAMLNode ExportYAML(this IReadOnlyDictionary<uint, string> _this)
{
YAMLMappingNode node = new YAMLMappingNode();
foreach (var kvp in _this)
{
node.Add(kvp.Key, kvp.Value);
}
return node;
}
public static YAMLNode ExportYAML(this IReadOnlyDictionary<long, string> _this)
{
YAMLMappingNode node = new YAMLMappingNode();
foreach (var kvp in _this)
{
node.Add(kvp.Key, kvp.Value);
}
return node;
}
public static YAMLNode ExportYAML(this IReadOnlyDictionary<string, string> _this)
{
YAMLMappingNode node = new YAMLMappingNode();
foreach (var kvp in _this)
{
node.Add(kvp.Key, kvp.Value);
}
return node;
}
public static YAMLNode ExportYAML(this IReadOnlyDictionary<string, int> _this)
{
YAMLMappingNode node = new YAMLMappingNode();
foreach (var kvp in _this)
{
node.Add(kvp.Key, kvp.Value);
}
return node;
}
public static YAMLNode ExportYAML(this IReadOnlyDictionary<string, float> _this)
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve);
foreach (var kvp in _this)
{
YAMLMappingNode map = new YAMLMappingNode();
map.Add(kvp.Key, kvp.Value);
node.Add(map);
}
return node;
}
public static YAMLNode ExportYAML(this IReadOnlyDictionary<Tuple<ushort, ushort>, float> _this)
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve);
foreach (var kvp in _this)
{
YAMLMappingNode keyNode = new YAMLMappingNode();
keyNode.Add(kvp.Key.Item1, kvp.Key.Item2);
YAMLMappingNode kvpMap = new YAMLMappingNode();
kvpMap.Add("first", keyNode);
kvpMap.Add("second", kvp.Value);
node.Add(kvpMap);
}
return node;
}
public static YAMLNode ExportYAML(this IReadOnlyDictionary<Tuple<int, long>, string> _this)
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve);
foreach (var kvp in _this)
{
YAMLMappingNode keyNode = new YAMLMappingNode();
keyNode.Add(kvp.Key.Item1, kvp.Key.Item2);
YAMLMappingNode kvpMap = new YAMLMappingNode();
kvpMap.Add("first", keyNode);
kvpMap.Add("second", kvp.Value);
node.Add(kvpMap);
}
return node;
}
public static YAMLNode ExportYAML<T>(this IReadOnlyDictionary<Tuple<T, long>, string> _this, Func<T, int> converter)
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.BlockCurve);
foreach (var kvp in _this)
{
YAMLMappingNode keyNode = new YAMLMappingNode();
keyNode.Add(converter(kvp.Key.Item1), kvp.Key.Item2);
YAMLMappingNode kvpMap = new YAMLMappingNode();
kvpMap.Add("first", keyNode);
kvpMap.Add("second", kvp.Value);
node.Add(kvpMap);
}
return node;
}
}
}

View File

@@ -0,0 +1,273 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace AssetStudio
{
public static class IEnumerableYAMLExtensions
{
public static YAMLNode ExportYAML(this IEnumerable<bool> _this)
{
StringBuilder sb = new StringBuilder();
foreach (bool value in _this)
{
byte bvalue = unchecked((byte)(value ? 1 : 0));
sb.AppendHex(bvalue);
}
return new YAMLScalarNode(sb.ToString(), true);
}
public static YAMLNode ExportYAML(this IEnumerable<char> _this)
{
StringBuilder sb = new StringBuilder();
foreach (char value in _this)
{
sb.AppendHex((ushort)value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
public static YAMLNode ExportYAML(this IEnumerable<byte> _this)
{
StringBuilder sb = new StringBuilder();
foreach (byte value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
public static YAMLNode ExportYAML(this IEnumerable<ushort> _this, bool isRaw)
{
if (isRaw)
{
StringBuilder sb = new StringBuilder();
foreach (ushort value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
else
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (ushort value in _this)
{
node.Add(value);
}
return node;
}
}
public static YAMLNode ExportYAML(this IEnumerable<short> _this, bool isRaw)
{
if (isRaw)
{
StringBuilder sb = new StringBuilder();
foreach (short value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
else
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (short value in _this)
{
node.Add(value);
}
return node;
}
}
public static YAMLNode ExportYAML(this IEnumerable<uint> _this, bool isRaw)
{
if (isRaw)
{
StringBuilder sb = new StringBuilder();
foreach (uint value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
else
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (uint value in _this)
{
node.Add(value);
}
return node;
}
}
public static YAMLNode ExportYAML(this IEnumerable<int> _this, bool isRaw)
{
if (isRaw)
{
StringBuilder sb = new StringBuilder();
foreach (int value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
else
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (int value in _this)
{
node.Add(value);
}
return node;
}
}
public static YAMLNode ExportYAML(this IEnumerable<ulong> _this, bool isRaw)
{
if (isRaw)
{
StringBuilder sb = new StringBuilder();
foreach (ulong value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
else
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (ulong value in _this)
{
node.Add(value);
}
return node;
}
}
public static YAMLNode ExportYAML(this IEnumerable<long> _this, bool isRaw)
{
if (isRaw)
{
StringBuilder sb = new StringBuilder();
foreach (long value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
else
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (long value in _this)
{
node.Add(value);
}
return node;
}
}
public static YAMLNode ExportYAML(this IEnumerable<float> _this)
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (float value in _this)
{
node.Add(value);
}
return node;
}
public static YAMLNode ExportYAML(this IEnumerable<double> _this)
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (double value in _this)
{
node.Add(value);
}
return node;
}
public static YAMLNode ExportYAML(this IEnumerable<string> _this)
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (string value in _this)
{
node.Add(value);
}
return node;
}
public static YAMLNode ExportYAML(this IEnumerable<IEnumerable<string>> _this)
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (IEnumerable<string> export in _this)
{
node.Add(export.ExportYAML());
}
return node;
}
public static YAMLNode ExportYAML<T>(this IEnumerable<T> _this, int[] version)
where T : IYAMLExportable
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (T export in _this)
{
node.Add(export.ExportYAML(version));
}
return node;
}
public static YAMLNode ExportYAML<T>(this IEnumerable<IEnumerable<T>> _this, int[] version)
where T : IYAMLExportable
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (IEnumerable<T> export in _this)
{
node.Add(export.ExportYAML(version));
}
return node;
}
public static YAMLNode ExportYAML<T>(this IEnumerable<Tuple<string, T>> _this, int[] version)
where T : IYAMLExportable
{
YAMLSequenceNode node = new YAMLSequenceNode();
foreach (var kvp in _this)
{
YAMLMappingNode map = new YAMLMappingNode();
map.Add(kvp.Item1, kvp.Item2.ExportYAML(version));
node.Add(map);
}
return node;
}
public static YAMLNode ExportYAML<T1, T2>(this IEnumerable<Tuple<T1, T2>> _this, Func<T1, int> converter, int[] version)
where T2 : IYAMLExportable
{
YAMLSequenceNode node = new YAMLSequenceNode();
foreach (var kvp in _this)
{
YAMLMappingNode map = new YAMLMappingNode();
map.Add(converter(kvp.Item1), kvp.Item2.ExportYAML(version));
node.Add(map);
}
return node;
}
public static YAMLNode ExportYAML<T>(this IEnumerable<KeyValuePair<string, T>> _this, int[] version)
where T : IYAMLExportable
{
YAMLSequenceNode node = new YAMLSequenceNode();
foreach (var kvp in _this)
{
YAMLMappingNode map = new YAMLMappingNode();
map.Add(kvp.Key, kvp.Value.ExportYAML(version));
node.Add(map);
}
return node;
}
}
}

View File

@@ -0,0 +1,171 @@
using System.Collections.Generic;
using System.Text;
namespace AssetStudio
{
public static class IListYAMLExtensions
{
public static YAMLNode ExportYAML(this IReadOnlyList<bool> _this)
{
StringBuilder sb = new StringBuilder(_this.Count * 2);
foreach (bool value in _this)
{
byte bvalue = unchecked((byte)(value ? 1 : 0));
sb.AppendHex(bvalue);
}
return new YAMLScalarNode(sb.ToString(), true);
}
public static YAMLNode ExportYAML(this IReadOnlyList<char> _this)
{
StringBuilder sb = new StringBuilder(_this.Count * 4);
foreach (char value in _this)
{
sb.AppendHex((ushort)value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
public static YAMLNode ExportYAML(this IReadOnlyList<byte> _this)
{
StringBuilder sb = new StringBuilder(_this.Count * 2);
foreach (byte value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
public static YAMLNode ExportYAML(this IReadOnlyList<ushort> _this, bool isRaw)
{
if (isRaw)
{
StringBuilder sb = new StringBuilder(_this.Count * 4);
foreach (ushort value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
else
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (ushort value in _this)
{
node.Add(value);
}
return node;
}
}
public static YAMLNode ExportYAML(this IReadOnlyList<short> _this, bool isRaw)
{
if (isRaw)
{
StringBuilder sb = new StringBuilder(_this.Count * 4);
foreach (short value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
else
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (short value in _this)
{
node.Add(value);
}
return node;
}
}
public static YAMLNode ExportYAML(this IReadOnlyList<uint> _this, bool isRaw)
{
if (isRaw)
{
StringBuilder sb = new StringBuilder(_this.Count * 8);
foreach (uint value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
else
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (uint value in _this)
{
node.Add(value);
}
return node;
}
}
public static YAMLNode ExportYAML(this IReadOnlyList<int> _this, bool isRaw)
{
if (isRaw)
{
StringBuilder sb = new StringBuilder(_this.Count * 8);
foreach (int value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
else
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (int value in _this)
{
node.Add(value);
}
return node;
}
}
public static YAMLNode ExportYAML(this IReadOnlyList<ulong> _this, bool isRaw)
{
if (isRaw)
{
StringBuilder sb = new StringBuilder(_this.Count * 16);
foreach (ulong value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
else
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (ulong value in _this)
{
node.Add(value);
}
return node;
}
}
public static YAMLNode ExportYAML(this IReadOnlyList<long> _this, bool isRaw)
{
if (isRaw)
{
StringBuilder sb = new StringBuilder(_this.Count * 16);
foreach (long value in _this)
{
sb.AppendHex(value);
}
return new YAMLScalarNode(sb.ToString(), true);
}
else
{
YAMLSequenceNode node = new YAMLSequenceNode(SequenceStyle.Block);
foreach (long value in _this)
{
node.Add(value);
}
return node;
}
}
}
}

View File

@@ -0,0 +1,79 @@
namespace AssetStudio
{
public static class PrimitiveExtensions
{
public static int ParseDigit(this char _this)
{
return _this - '0';
}
public static string ToHexString(this byte _this)
{
return _this.ToString("x2");
}
public static string ToHexString(this short _this)
{
ushort value = unchecked((ushort)_this);
return ToHexString(value);
}
public static string ToHexString(this ushort _this)
{
ushort reverse = unchecked((ushort)(((0xFF00 & _this) >> 8) | ((0x00FF & _this) << 8)));
return reverse.ToString("x4");
}
public static string ToHexString(this int _this)
{
uint value = unchecked((uint)_this);
return ToHexString(value);
}
public static string ToHexString(this uint _this)
{
uint reverse = ((0xFF000000 & _this) >> 24) | ((0x00FF0000 & _this) >> 8) | ((0x0000FF00 & _this) << 8) | ((0x000000FF & _this) << 24);
return reverse.ToString("x8");
}
public static string ToHexString(this long _this)
{
ulong value = unchecked((ulong)_this);
return ToHexString(value);
}
public static string ToHexString(this ulong _this)
{
ulong reverse = (_this & 0x00000000000000FFUL) << 56 | (_this & 0x000000000000FF00UL) << 40 |
(_this & 0x0000000000FF0000UL) << 24 | (_this & 0x00000000FF000000UL) << 8 |
(_this & 0x000000FF00000000UL) >> 8 | (_this & 0x0000FF0000000000UL) >> 24 |
(_this & 0x00FF000000000000UL) >> 40 | (_this & 0xFF00000000000000UL) >> 56;
return reverse.ToString("x16");
}
public static string ToHexString(this float _this)
{
uint value = BitConverterExtensions.ToUInt32(_this);
return ToHexString(value);
}
public static string ToHexString(this double _this)
{
ulong value = BitConverterExtensions.ToUInt64(_this);
return ToHexString(value);
}
public static int ToClosestInt(this long _this)
{
if (_this > int.MaxValue)
{
return int.MaxValue;
}
if (_this < int.MinValue)
{
return int.MinValue;
}
return unchecked((int)_this);
}
}
}

View File

@@ -0,0 +1,87 @@
using System.Text;
namespace AssetStudio
{
public static class StringBuilderExtensions
{
static StringBuilderExtensions()
{
for (int i = 0; i <= byte.MaxValue; i++)
{
ByteHexRepresentations[i] = i.ToString("x2");
}
}
public static StringBuilder AppendHex(this StringBuilder _this, byte value)
{
_this.Append(ByteHexRepresentations[value]);
return _this;
}
public static StringBuilder AppendHex(this StringBuilder _this, ushort value)
{
_this.Append(ByteHexRepresentations[(value >> 0) & 0xFF]);
_this.Append(ByteHexRepresentations[(value >> 8) & 0xFF]);
return _this;
}
public static StringBuilder AppendHex(this StringBuilder _this, short value)
{
return AppendHex(_this, unchecked((ushort)value));
}
public static StringBuilder AppendHex(this StringBuilder _this, uint value)
{
_this.Append(ByteHexRepresentations[unchecked((int)(value >> 0) & 0xFF)]);
_this.Append(ByteHexRepresentations[unchecked((int)(value >> 8) & 0xFF)]);
_this.Append(ByteHexRepresentations[unchecked((int)(value >> 16) & 0xFF)]);
_this.Append(ByteHexRepresentations[unchecked((int)(value >> 24) & 0xFF)]);
return _this;
}
public static StringBuilder AppendHex(this StringBuilder _this, int value)
{
return AppendHex(_this, unchecked((uint)value));
}
public static StringBuilder AppendHex(this StringBuilder _this, ulong value)
{
_this.Append(ByteHexRepresentations[unchecked((int)(value >> 0) & 0xFF)]);
_this.Append(ByteHexRepresentations[unchecked((int)(value >> 8) & 0xFF)]);
_this.Append(ByteHexRepresentations[unchecked((int)(value >> 16) & 0xFF)]);
_this.Append(ByteHexRepresentations[unchecked((int)(value >> 24) & 0xFF)]);
_this.Append(ByteHexRepresentations[unchecked((int)(value >> 32) & 0xFF)]);
_this.Append(ByteHexRepresentations[unchecked((int)(value >> 40) & 0xFF)]);
_this.Append(ByteHexRepresentations[unchecked((int)(value >> 48) & 0xFF)]);
_this.Append(ByteHexRepresentations[unchecked((int)(value >> 56) & 0xFF)]);
return _this;
}
public static StringBuilder AppendHex(this StringBuilder _this, long value)
{
return AppendHex(_this, unchecked((ulong)value));
}
public static StringBuilder AppendHex(this StringBuilder _this, float value)
{
return AppendHex(_this, BitConverterExtensions.ToUInt32(value));
}
public static StringBuilder AppendHex(this StringBuilder _this, double value)
{
return AppendHex(_this, BitConverterExtensions.ToUInt64(value));
}
public static StringBuilder AppendIndent(this StringBuilder _this, int count)
{
for (int i = 0; i < count; i++)
{
_this.Append('\t');
}
return _this;
}
public static readonly string HexAlphabet = "0123456789abcdef";
public static readonly string[] ByteHexRepresentations = new string[256];
}
}

View File

@@ -0,0 +1,31 @@
namespace AssetStudio
{
public static class YAMLMappingNodeExtensions
{
public static void AddSerializedVersion(this YAMLMappingNode _this, int version)
{
if(version > 1)
{
_this.Add(SerializedVersionName, version);
}
}
public static void ForceAddSerializedVersion(this YAMLMappingNode _this, int version)
{
if (version > 0)
{
_this.Add(SerializedVersionName, version);
}
}
public static void InsertSerializedVersion(this YAMLMappingNode _this, int version)
{
if(version > 1)
{
_this.InsertBegin(SerializedVersionName, version);
}
}
public const string SerializedVersionName = "serializedVersion";
}
}