diff --git a/SrcMod/Shell/Valve/KeyValueConvert.cs b/SrcMod/Shell/Valve/KeyValueConvert.cs new file mode 100644 index 0000000..a52b2fe --- /dev/null +++ b/SrcMod/Shell/Valve/KeyValueConvert.cs @@ -0,0 +1,30 @@ +namespace SrcMod.Shell.Valve; + +public static class KeyValueConvert +{ + private static readonly Dictionary 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 escapeCode in p_escapeCodes) + content = content.Replace(escapeCode.Key, escapeCode.Value); + + return content; + } +} diff --git a/SrcMod/Shell/Valve/KeyValueNode.cs b/SrcMod/Shell/Valve/KeyValueNode.cs new file mode 100644 index 0000000..5d88f77 --- /dev/null +++ b/SrcMod/Shell/Valve/KeyValueNode.cs @@ -0,0 +1,18 @@ +namespace SrcMod.Shell.Valve; + +public class KeyValueNode +{ + public int SubNodeCount => p_subNodes.Count; + + public object value; + + private Dictionary p_subNodes; + + internal KeyValueNode() + { + value = new(); + p_subNodes = new(); + } + + public KeyValueNode this[string name] => p_subNodes[name]; +} diff --git a/SrcMod/Shell/Valve/KeyValueSerializer.cs b/SrcMod/Shell/Valve/KeyValueSerializer.cs new file mode 100644 index 0000000..399ac4a --- /dev/null +++ b/SrcMod/Shell/Valve/KeyValueSerializer.cs @@ -0,0 +1,41 @@ +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; + } + } +}