Skip to content

Commit

Permalink
Implement merge keys.
Browse files Browse the repository at this point in the history
  • Loading branch information
aaubry committed Jun 17, 2014
1 parent 47178c1 commit 3010915
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 5 deletions.
73 changes: 73 additions & 0 deletions YamlDotNet/Core/MergingParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System.Collections.Generic;
using System.Linq;
using YamlDotNet.Core.Events;

namespace YamlDotNet.Core
{
/// <summary>
/// Simple implementation of <see cref="IParser"/> that implements merging: http://yaml.org/type/merge.html
/// </summary>
public sealed class MergingParser : IParser
{
private readonly List<ParsingEvent> _allEvents = new List<ParsingEvent>();
private readonly IParser _innerParser;
private int _currentIndex = -1;

public MergingParser(IParser innerParser)
{
_innerParser = innerParser;
}

public ParsingEvent Current { get; private set; }

public bool MoveNext()
{
if (_currentIndex < 0)
{
while (_innerParser.MoveNext())
{
_allEvents.Add(_innerParser.Current);
}

for (int i = _allEvents.Count - 2; i >= 0; --i)
{
var merge = _allEvents[i] as Scalar;
if (merge != null && merge.Value == "<<")
{
var anchorAlias = _allEvents[i + 1] as AnchorAlias;
if (anchorAlias != null)
{
var mergedEvents = GetMappingEvents(anchorAlias.Value);
_allEvents.RemoveRange(i, 2);
_allEvents.InsertRange(i, mergedEvents);
}

}
}
}

var nextIndex = _currentIndex + 1;
if (nextIndex < _allEvents.Count)
{
Current = _allEvents[nextIndex];
_currentIndex = nextIndex;
return true;
}
return false;
}

private IEnumerable<ParsingEvent> GetMappingEvents(string mappingAlias)
{
var nesting = 0;
return _allEvents
.SkipWhile(e =>
{
var mappingStart = e as MappingStart;
return mappingStart == null || mappingStart.Anchor != mappingAlias;
})
.Skip(1)
.TakeWhile(e => (nesting += e.NestingIncrease) >= 0)
.ToList();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,20 +76,20 @@ bool INodeDeserializer.Deserialize(EventReader reader, Type expectedType, Func<E
if (valuePromise == null)
{
// Happy path: both key and value are known
result.Add((TKey)key, (TValue)value);
result[(TKey)key] = (TValue)value;
}
else
{
// Key is known, value is pending
valuePromise.ValueAvailable += v => result.Add((TKey)key, (TValue)v);
valuePromise.ValueAvailable += v => result[(TKey)key] = (TValue)v;
}
}
else
{
if (valuePromise == null)
{
// Key is pending, value is known
keyPromise.ValueAvailable += v => result.Add((TKey)v, (TValue)value);
keyPromise.ValueAvailable += v => result[(TKey)v] = (TValue)value;
}
else
{
Expand All @@ -100,7 +100,7 @@ bool INodeDeserializer.Deserialize(EventReader reader, Type expectedType, Func<E
{
if (hasFirstPart)
{
result.Add((TKey)v, (TValue)value);
result[(TKey)v] = (TValue)value;
}
else
{
Expand All @@ -113,7 +113,7 @@ bool INodeDeserializer.Deserialize(EventReader reader, Type expectedType, Func<E
{
if (hasFirstPart)
{
result.Add((TKey)key, (TValue)v);
result[(TKey)key] = (TValue)v;
}
else
{
Expand Down
1 change: 1 addition & 0 deletions YamlDotNet/YamlDotNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
<Compile Include="Core\IScanner.cs" />
<Compile Include="Core\LookAheadBuffer.cs" />
<Compile Include="Core\Mark.cs" />
<Compile Include="Core\MergingParser.cs" />
<Compile Include="Core\Parser.cs" />
<Compile Include="Core\ParserState.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down

0 comments on commit 3010915

Please sign in to comment.