SharpGen/CppModel/CppElementFinder.cs (67 lines of code) (raw):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace SharpGen.CppModel
{
public sealed class CppElementFinder
{
public enum SelectionMode
{
MatchedElement,
Parent
}
public CppElementFinder(CppElement root)
{
Root = root;
}
private CppElement Root { get; }
private List<string> CurrentContexts { get; } = new();
private void AddContext(string contextName)
{
CurrentContexts.Add(contextName);
}
public void AddContexts(IEnumerable<string> contextNames)
{
foreach (var contextName in contextNames)
AddContext(contextName);
}
public void ClearCurrentContexts()
{
CurrentContexts.Clear();
}
public IEnumerable<T> Find<T>(Regex regex, SelectionMode mode = SelectionMode.MatchedElement)
where T : CppElement
{
return Find<T>(Root, regex, mode);
}
private IEnumerable<T> Find<T>(CppElement currentNode, Regex regex, SelectionMode mode) where T : CppElement
{
var path = currentNode.FullName;
var selectedElement = mode switch
{
SelectionMode.MatchedElement => currentNode,
SelectionMode.Parent => currentNode.Parent,
_ => throw new ArgumentException("Invalid selection mode.", nameof(mode))
};
if (path != null && selectedElement is T cppElement && regex.Match(path).Success)
{
yield return cppElement;
}
if (currentNode is not CppContainer container)
yield break;
var elements = container.AllItems;
// Optimized version with context attributes
if (currentNode == Root && CurrentContexts.Count != 0)
{
elements = elements.Where(element => CurrentContexts.Contains(element.Name));
}
foreach (var innerElement in elements)
{
foreach (var item in Find<T>(innerElement, regex, mode))
{
yield return item;
}
}
}
}
}