Some development with the serializer.

This commit is contained in:
That-One-Nerd 2023-04-26 20:38:28 -04:00
parent 4d64b0bae6
commit 4e2a8ec05c
10 changed files with 148 additions and 89 deletions

View File

@ -7,6 +7,7 @@ global using SrcMod.Shell.Extensions;
global using SrcMod.Shell.Interop; global using SrcMod.Shell.Interop;
global using SrcMod.Shell.Modules.ObjectModels; global using SrcMod.Shell.Modules.ObjectModels;
global using SrcMod.Shell.ObjectModels; global using SrcMod.Shell.ObjectModels;
global using SrcMod.Shell.Valve;
global using System; global using System;
global using System.Collections; global using System.Collections;
global using System.Collections.Generic; global using System.Collections.Generic;

View File

@ -1,30 +0,0 @@
namespace SrcMod.Shell.Valve;
public static class KeyValueConvert
{
private static readonly Dictionary<string, string> p_escapeCodes = new()
{
{ "\'", "\\\'" },
{ "\"", "\\\"" },
{ "\\", "\\\\" },
{ "\0", "\\\0" },
{ "\a", "\\\a" },
{ "\b", "\\\b" },
{ "\f", "\\\f" },
{ "\n", "\\\n" },
{ "\r", "\\\r" },
{ "\t", "\\\t" },
{ "\v", "\\\v" }
};
public static string SerializeName(string content, KeyValueSerializer.Options? options = null)
{
options ??= KeyValueSerializer.Options.Default;
if (options.useNameQuotes) content = $"\"{content}\"";
if (options.useEscapeCodes)
foreach (KeyValuePair<string, string> escapeCode in p_escapeCodes)
content = content.Replace(escapeCode.Key, escapeCode.Value);
return content;
}
}

View File

@ -1,18 +0,0 @@
namespace SrcMod.Shell.Valve;
public class KeyValueNode
{
public int SubNodeCount => p_subNodes.Count;
public object value;
private Dictionary<string, KeyValueNode> p_subNodes;
internal KeyValueNode()
{
value = new();
p_subNodes = new();
}
public KeyValueNode this[string name] => p_subNodes[name];
}

View File

@ -1,41 +0,0 @@
namespace SrcMod.Shell.Valve;
public class KeyValueSerializer
{
public int? IndentSize => p_options.indentSize;
public bool UseEscapeCodes => p_options.useEscapeCodes;
public bool UseNameQuotes => p_options.useNameQuotes;
public bool UseValueQuotes => p_options.useValueQuotes;
private readonly Options p_options;
public KeyValueSerializer() : this(Options.Default) { }
public KeyValueSerializer(Options options)
{
p_options = options;
}
public StringBuilder Serialize(StringBuilder builder, KeyValueNode parentNode, string? parentNodeName = null)
{
if (parentNodeName is not null) builder.AppendLine(KeyValueConvert.SerializeName(parentNodeName, p_options));
return builder;
}
public record class Options
{
public static Options Default => new();
public int? indentSize;
public bool useEscapeCodes;
public bool useNameQuotes;
public bool useValueQuotes;
public Options()
{
indentSize = null;
useEscapeCodes = false;
useNameQuotes = true;
useValueQuotes = false;
}
}
}

View File

@ -0,0 +1,58 @@
namespace SrcMod.Shell.Valve;
interface static class VdfConvert
{
private static readonly Dictionary<string, string> p_escapeCodes = new()
{
{ "\'", "\\\'" },
{ "\"", "\\\"" },
{ "\\", "\\\\" },
{ "\0", "\\\0" },
{ "\a", "\\\a" },
{ "\b", "\\\b" },
{ "\f", "\\\f" },
{ "\n", "\\\n" },
{ "\r", "\\\r" },
{ "\t", "\\\t" },
{ "\v", "\\\v" }
};
public static void SerializeNode(StreamWriter writer, VdfNode node, string name,
ref VdfOptions options, int indentLevel)
{
if (node is VdfSingleNode single) SerializeSingleNode(writer, single, name, ref options, indentLevel);
else if (node is VdfTreeNode tree) SerializeTreeNode(writer, tree, name, ref options, indentLevel);
else throw new("Unknown node type.");
}
private static void SerializeSingleNode(StreamWriter writer, VdfSingleNode node, string name,
ref VdfOptions options, int indentLevel)
{
string serializedName = SerializeString(name, ref options),
serializedValue = SerializeObject(node.value, ref options);
writer.WriteLine($"{new string(' ', indentLevel)}{serializedName} {serializedValue}");
}
private static void SerializeTreeNode(StreamWriter writer, VdfTreeNode node, string name,
ref VdfOptions options, int indentLevel)
{
string serializedName = SerializeString(name, ref options),
serializedValue = ""; // TODO: serialize each value with a higher indent
string indent = new(' ', indentLevel);
writer.WriteLine($"{indent}{serializedName}\n{indent}{{\n{serializedValue}\n{indent}}}");
}
private static string SerializeObject(object obj, ref VdfOptions options)
{
// TODO: serialize an object
return "";
}
private static string SerializeString(string content, ref VdfOptions options)
{
if (options.useEscapeCodes)
foreach (KeyValuePair<string, string> escapeCode in p_escapeCodes)
content = content.Replace(escapeCode.Key, escapeCode.Value);
return content;
}
}

View File

@ -0,0 +1,6 @@
namespace SrcMod.Shell.Valve;
public abstract class VdfNode
{
}

View File

@ -0,0 +1,19 @@
namespace SrcMod.Shell.Valve;
public record class VdfOptions
{
public static VdfOptions Default => new();
public bool closeWhenFinished;
public int indentSize;
public bool useEscapeCodes;
public bool useQuotes;
public VdfOptions()
{
closeWhenFinished = true;
indentSize = 4;
useEscapeCodes = false;
useQuotes = false;
}
}

View File

@ -0,0 +1,21 @@
namespace SrcMod.Shell.Valve;
public class VdfSerializer
{
public VdfOptions Options => p_options;
private VdfOptions p_options;
public VdfSerializer() : this(VdfOptions.Default) { }
public VdfSerializer(VdfOptions options)
{
p_options = options;
}
public void Serialize(Stream stream, VdfNode parentNode, string parentNodeName)
{
StreamWriter writer = p_options.closeWhenFinished ? new(stream) : new(stream, leaveOpen: true);
VdfConvert.SerializeNode(writer, parentNode, parentNodeName, ref p_options, 0);
writer.Close();
}
}

View File

@ -0,0 +1,11 @@
namespace SrcMod.Shell.Valve;
public class VdfSingleNode : VdfNode
{
public object value;
public VdfSingleNode(object? value = null) : base()
{
this.value = value ?? new();
}
}

View File

@ -0,0 +1,32 @@
namespace SrcMod.Shell.Valve;
public class VdfTreeNode : VdfNode
{
public int SubNodeCount => p_subNodes.Count;
private Dictionary<string, VdfNode> p_subNodes;
public VdfTreeNode(Dictionary<string, VdfNode>? subNodes = null) : base()
{
p_subNodes = subNodes ?? new();
}
public VdfNode this[string key]
{
get => p_subNodes[key];
set
{
if (p_subNodes.ContainsKey(key)) p_subNodes[key] = value;
else p_subNodes.Add(key, value);
}
}
public VdfNode this[int index]
{
get => p_subNodes.Values.ElementAt(index);
set
{
if (p_subNodes.Count >= index || index < 0) throw new IndexOutOfRangeException();
p_subNodes[p_subNodes.Keys.ElementAt(index)] = value;
}
}
}