Skip to content

Commit

Permalink
Fixed strings not being escaped during serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
shravan2x committed Aug 27, 2017
1 parent 3f73be0 commit 8cc43c0
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 35 deletions.
7 changes: 6 additions & 1 deletion Gameloop.Vdf/VdfConvert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ namespace Gameloop.Vdf
public static class VdfConvert
{
public static string Serialize(VToken value)
{
return Serialize(value, VdfSerializerSettings.Common);
}

public static string Serialize(VToken value, VdfSerializerSettings settings)
{
if (value == null)
throw new ArgumentNullException(nameof(value));

StringBuilder stringBuilder = new StringBuilder(256);
StringWriter stringWriter = new StringWriter(stringBuilder, CultureInfo.InvariantCulture);
(new VdfSerializer()).Serialize(stringWriter, value);
(new VdfSerializer(settings)).Serialize(stringWriter, value);

return stringWriter.ToString();
}
Expand Down
2 changes: 1 addition & 1 deletion Gameloop.Vdf/VdfSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public VdfSerializer(VdfSerializerSettings settings)

public void Serialize(TextWriter textWriter, VToken value)
{
using (VdfWriter vdfWriter = new VdfTextWriter(textWriter))
using (VdfWriter vdfWriter = new VdfTextWriter(textWriter, _settings))
value.WriteTo(vdfWriter);
}

Expand Down
42 changes: 42 additions & 0 deletions Gameloop.Vdf/VdfStructure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,47 @@ public static class VdfStructure
// Conditionals
public const string ConditionalXbox360 = "$X360", ConditionalWin32 = "$WIN32";
public const string ConditionalWindows = "$WINDOWS", ConditionalOSX = "$OSX", ConditionalLinux = "$LINUX", ConditionalPosix = "$POSIX";

// Escapes
private const uint EscapeMapLength = 128;
private static readonly bool[] EscapeExistsMap;
private static readonly char[] EscapeMap, UnescapeMap;
private static readonly char[,] EscapeConversions =
{
{ '\n', 'n' },
{ '\t', 't' },
{ '\v', 'v' },
{ '\b', 'b' },
{ '\r', 'r' },
{ '\f', 'f' },
{ '\a', 'a' },
{ '\\', '\\' },
{ '?' , '?' },
{ '\'', '\'' },
{ '\"', '\"' }
};

static VdfStructure()
{
EscapeExistsMap = new bool[EscapeMapLength];
EscapeMap = new char[EscapeMapLength];
UnescapeMap = new char[EscapeMapLength];

for (int index = 0; index < EscapeMapLength; index++)
EscapeMap[index] = UnescapeMap[index] = (char) index;

for (int index = 0; index < EscapeConversions.GetLength(0); index++)
{
char unescaped = EscapeConversions[index, 0], escaped = EscapeConversions[index, 1];

EscapeExistsMap[unescaped] = true;
EscapeMap[unescaped] = escaped;
UnescapeMap[escaped] = unescaped;
}
}

public static bool IsEscapable(char ch) => (ch < EscapeMapLength && EscapeExistsMap[ch]);
public static char GetEscape(char ch) => (ch < EscapeMapLength) ? EscapeMap[ch] : ch;
public static char GetUnescape(char ch) => (ch < EscapeMapLength) ? UnescapeMap[ch] : ch;
}
}
30 changes: 1 addition & 29 deletions Gameloop.Vdf/VdfTextReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,6 @@ namespace Gameloop.Vdf
public class VdfTextReader : VdfReader
{
private const int DefaultBufferSize = 1024;
private static readonly char[][] EscapeConversions =
{
new[] { 'n' , '\n' },
new[] { 't' , '\t' },
new[] { 'v' , '\v' },
new[] { 'b' , '\b' },
new[] { 'r' , '\r' },
new[] { 'f' , '\f' },
new[] { 'a' , '\a' },
new[] { '\\', '\\' },
new[] { '?' , '?' },
new[] { '\'', '\'' },
new[] { '\"', '\"' },
};

private readonly TextReader _reader;
private readonly char[] _charBuffer, _tokenBuffer;
Expand Down Expand Up @@ -60,7 +46,7 @@ public override bool ReadToken()

if (curChar == VdfStructure.Escape)
{
_tokenBuffer[_tokenSize++] = !Settings.UsesEscapeSequences ? curChar : FindConversion(_charBuffer[++_charPos]);
_tokenBuffer[_tokenSize++] = !Settings.UsesEscapeSequences ? curChar : VdfStructure.GetUnescape(_charBuffer[++_charPos]);
_charPos++;
continue;
}
Expand Down Expand Up @@ -181,20 +167,6 @@ private bool EnsureBuffer()
return _charsLen != 0;
}

/// <summary>
/// Converts the given escape code to an escape character.
/// </summary>
/// <param name="ch">The escape code.</param>
/// <returns>the escape character.</returns>
private static char FindConversion(char ch)
{
foreach (char[] conv in EscapeConversions)
if (conv[0] == ch)
return conv[1];

return ch;
}

public override void Close()
{
base.Close();
Expand Down
29 changes: 26 additions & 3 deletions Gameloop.Vdf/VdfTextWriter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Linq;

namespace Gameloop.Vdf
{
Expand All @@ -8,7 +9,9 @@ public class VdfTextWriter : VdfWriter
private readonly TextWriter _writer;
private int _indentationLevel;

public VdfTextWriter(TextWriter writer)
public VdfTextWriter(TextWriter writer) : this(writer, VdfSerializerSettings.Default) { }

public VdfTextWriter(TextWriter writer, VdfSerializerSettings settings) : base(settings)
{
if (writer == null)
throw new ArgumentNullException(nameof(writer));
Expand All @@ -21,15 +24,15 @@ public override void WriteKey(string key)
{
AutoComplete(State.Key);
_writer.Write(VdfStructure.Quote);
_writer.Write(key);
WriteEscapedString(key);
_writer.Write(VdfStructure.Quote);
}

public override void WriteValue(VValue value)
{
AutoComplete(State.Value);
_writer.Write(VdfStructure.Quote);
_writer.Write(value);
WriteEscapedString(value.ToString());
_writer.Write(VdfStructure.Quote);
}

Expand Down Expand Up @@ -81,6 +84,26 @@ private void AutoComplete(State next)
CurrentState = next;
}

private void WriteEscapedString(string str)
{
if (!Settings.UsesEscapeSequences)
{
_writer.Write(str);
return;
}

foreach (char ch in str)
{
if (!VdfStructure.IsEscapable(ch))
_writer.Write(ch);
else
{
_writer.Write(VdfStructure.Escape);
_writer.Write(VdfStructure.GetEscape(ch));
}
}
}

public override void Close()
{
base.Close();
Expand Down
7 changes: 6 additions & 1 deletion Gameloop.Vdf/VdfWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ namespace Gameloop.Vdf
{
public abstract class VdfWriter : IDisposable
{
public VdfSerializerSettings Settings { get; }
public bool CloseOutput { get; set; }
protected internal State CurrentState { get; protected set; }

protected VdfWriter()
protected VdfWriter() : this(VdfSerializerSettings.Default) { }

protected VdfWriter(VdfSerializerSettings settings)
{
Settings = settings;

CurrentState = State.Start;
CloseOutput = true;
}
Expand Down

0 comments on commit 8cc43c0

Please sign in to comment.