Skip to content

Commit

Permalink
Updated VdfSerializer and VToken to support comments
Browse files Browse the repository at this point in the history
- VObject has breaking changes, mainly that Children() returns an IEnumerable<VToken> now. This is not ideal, but seems like the right move.
  • Loading branch information
shravan2x committed May 21, 2020
1 parent 8721e97 commit 0855a05
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 30 deletions.
86 changes: 62 additions & 24 deletions Gameloop.Vdf/Linq/VObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@

namespace Gameloop.Vdf.Linq
{
public class VObject : VToken, IDictionary<string, VToken>
public class VObject : VToken, IList<VToken>, IDictionary<string, VToken>
{
private readonly List<VProperty> _children;
private readonly List<VToken> _children;

public VObject()
{
_children = new List<VProperty>();
_children = new List<VToken>();
}

public override VTokenType Type => VTokenType.Object;

public int Count => _children.Count;

public override VToken this[object key]
Expand All @@ -40,6 +42,12 @@ public override VToken this[object key]
}
}

public VToken this[int index]
{
get => _children[index];
set => _children[index] = value;
}

public VToken this[string key]
{
get
Expand All @@ -52,29 +60,33 @@ public VToken this[string key]

set
{
VProperty prop = _children.FirstOrDefault(x => x.Key == key);
VProperty prop = Properties().FirstOrDefault(x => x.Key == key);
if (prop != null)
prop.Value = value;
else
Add(key, value);
}
}

ICollection<string> IDictionary<string, VToken>.Keys => _children.Select(x => x.Key).ToList();
public bool IsReadOnly => false;

ICollection<string> IDictionary<string, VToken>.Keys => Properties().Select(x => x.Key).ToList();

ICollection<VToken> IDictionary<string, VToken>.Values => throw new NotImplementedException();

public override IEnumerable<VProperty> Children()
public override IEnumerable<VToken> Children()
{
return _children;
}

public void Add(string key, VToken value)
public IEnumerable<VProperty> Properties()
{
if (value == null)
throw new ArgumentNullException(nameof(value));
return _children.Where(x => x is VProperty).OfType<VProperty>();
}

_children.Add(new VProperty(key, value));
public void Add(string key, VToken value)
{
Add(new VProperty(key, value));
}

public void Add(VProperty property)
Expand All @@ -87,42 +99,67 @@ public void Add(VProperty property)
_children.Add(property);
}

public void Add(VToken token)
{
_children.Add(token);
}

public void Clear()
{
_children.Clear();
}

public bool Contains(VToken item)
{
return _children.Contains(item);
}

public bool ContainsKey(string key)
{
return _children.Exists(x => x.Key == key);
return Properties().Any(x => x.Key == key);
}

public void CopyTo(VProperty[] array, int arrayIndex)
public void CopyTo(VToken[] array, int arrayIndex)
{
_children.CopyTo(array, arrayIndex);
}

public int IndexOf(VToken item)
{
return _children.IndexOf(item);
}

public void Insert(int index, VToken item)
{
_children.Insert(index, item);
}

public bool Remove(string key)
{
return _children.RemoveAll(x => x.Key == key) != 0;
return _children.RemoveAll(x => x is VProperty p && p.Key == key) != 0;
}

public bool TryGetValue(string key, out VToken value)
public bool Remove(VToken item)
{
value = _children.FirstOrDefault(x => x.Key == key)?.Value;
return (value != null);
return _children.Remove(item);
}

public void RemoveAt(string key)
public void RemoveAt(int index)
{
_children.RemoveAll(x => x.Key == key);
_children.RemoveAt(index);
}

public bool TryGetValue(string key, out VToken value)
{
value = Properties().FirstOrDefault(x => x.Key == key)?.Value;
return (value != null);
}

public override void WriteTo(VdfWriter writer)
{
writer.WriteObjectStart();

foreach (VProperty child in _children)
foreach (VToken child in _children)
child.WriteTo(writer);

writer.WriteObjectEnd();
Expand All @@ -132,7 +169,7 @@ public override void WriteTo(VdfWriter writer)

public IEnumerator<KeyValuePair<string, VToken>> GetEnumerator()
{
foreach (VProperty property in _children)
foreach (VProperty property in Properties())
yield return new KeyValuePair<string, VToken>(property.Key, property.Value);
}

Expand All @@ -148,7 +185,7 @@ void ICollection<KeyValuePair<string, VToken>>.Clear()

bool ICollection<KeyValuePair<string, VToken>>.Contains(KeyValuePair<string, VToken> item)
{
VProperty property = _children.FirstOrDefault(x => x.Key == item.Key);
VProperty property = Properties().FirstOrDefault(x => x.Key == item.Key);
if (property == null)
return false;

Expand All @@ -166,8 +203,9 @@ void ICollection<KeyValuePair<string, VToken>>.CopyTo(KeyValuePair<string, VToke
if (Count > array.Length - arrayIndex)
throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array.");

for (int index = 0; index < _children.Count; index++)
array[arrayIndex + index] = new KeyValuePair<string, VToken>(_children[index].Key, _children[index].Value);
int index = 0;
foreach (VProperty property in Properties())
array[arrayIndex + index++] = new KeyValuePair<string, VToken>(property.Key, property.Value);
}

bool ICollection<KeyValuePair<string, VToken>>.IsReadOnly => false;
Expand Down Expand Up @@ -211,7 +249,7 @@ public override bool TrySetMember(VObject instance, SetMemberBinder binder, obje

public override IEnumerable<string> GetDynamicMemberNames(VObject instance)
{
return instance.Children().Select(p => p.Key);
return instance.Properties().Select(p => p.Key);
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions Gameloop.Vdf/Linq/VProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public VProperty(string key, VToken value)
Value = value;
}

public override VTokenType Type => VTokenType.Property;

public override void WriteTo(VdfWriter writer)
{
writer.WriteKey(Key);
Expand Down
6 changes: 4 additions & 2 deletions Gameloop.Vdf/Linq/VToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public abstract class VToken : IVEnumerable<VToken>, IDynamicMetaObjectProvider

public abstract void WriteTo(VdfWriter writer);

public abstract VTokenType Type { get; }

IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<VToken>) this).GetEnumerator();
Expand All @@ -43,9 +45,9 @@ public virtual T Value<T>(object key)
return (token == null ? default(T) : Extensions.Convert<VToken, T>(token));
}

public virtual IEnumerable<VProperty> Children()
public virtual IEnumerable<VToken> Children()
{
return Enumerable.Empty<VProperty>();
return Enumerable.Empty<VToken>();
}

public IEnumerable<T> Children<T>() where T : VToken
Expand Down
11 changes: 11 additions & 0 deletions Gameloop.Vdf/Linq/VTokenType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Gameloop.Vdf.Linq
{
public enum VTokenType
{
None,
Property,
Object,
Value,
Comment
}
}
19 changes: 17 additions & 2 deletions Gameloop.Vdf/Linq/VValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,36 @@ namespace Gameloop.Vdf.Linq
{
public class VValue : VToken
{
private readonly VTokenType _tokenType;
public object Value { get; set; }

public VValue(object value)
private VValue(object value, VTokenType type)
{
Value = value;
_tokenType = type;
}

public VValue(object value)
: this(value, VTokenType.Value) { }

public override VTokenType Type => _tokenType;

public override void WriteTo(VdfWriter writer)
{
writer.WriteValue(this);
if (_tokenType == VTokenType.Comment)
writer.WriteComment(ToString());
else
writer.WriteValue(this);
}

public override string ToString()
{
return Value?.ToString() ?? String.Empty;
}

public static VValue CreateComment(string value)
{
return new VValue(value, VTokenType.Comment);
}
}
}
19 changes: 17 additions & 2 deletions Gameloop.Vdf/VdfSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ public VProperty Deserialize(TextReader textReader)
{
if (!vdfReader.ReadToken())
throw new VdfException("Incomplete VDF data.");

// For now, we discard these comments.
while (vdfReader.CurrentState == VdfReader.State.Comment)
if (!vdfReader.ReadToken())
throw new VdfException("Incomplete VDF data.");

return ReadProperty(vdfReader);
}
}
Expand All @@ -38,6 +44,11 @@ private VProperty ReadProperty(VdfReader reader)
if (!reader.ReadToken())
throw new VdfException("Incomplete VDF data.");

// For now, we discard these comments.
while (reader.CurrentState == VdfReader.State.Comment)
if (!reader.ReadToken())
throw new VdfException("Incomplete VDF data.");

if (reader.CurrentState == VdfReader.State.Property)
result.Value = new VValue(reader.Value);
else
Expand All @@ -53,9 +64,13 @@ private VObject ReadObject(VdfReader reader)
if (!reader.ReadToken())
throw new VdfException("Incomplete VDF data.");

while (reader.CurrentState != VdfReader.State.Object || reader.Value != VdfStructure.ObjectEnd.ToString())
while (!(reader.CurrentState == VdfReader.State.Object && reader.Value == VdfStructure.ObjectEnd.ToString()))
{
result.Add(ReadProperty(reader));
if (reader.CurrentState == VdfReader.State.Comment)
result.Add(VValue.CreateComment(reader.Value));
else
result.Add(ReadProperty(reader));

if (!reader.ReadToken())
throw new VdfException("Incomplete VDF data.");
}
Expand Down

0 comments on commit 0855a05

Please sign in to comment.