private LoopContext.LoopEvalResult InnerLoop(IList<SubRecord> subs,
Dictionary<int, Conditional> conditions,
LoopContext context)
{
while (true)
{
if (context.idx >= subs.Count || context.ssidx >= context.sss.Length)
{
return LoopContext.LoopEvalResult.Success;
}
var ssb = context.sss[context.ssidx];
var sb = subs[context.idx];
if (ssb is SubrecordGroup)
{
var sg = ssb as SubrecordGroup;
var newcontext = new LoopContext(context.idx, sg.elements);
LoopContext.LoopEvalResult result = this.InnerLoop(subs, conditions, newcontext);
if (context.idx == newcontext.idx)
{
if (ssb.optional > 0 || (ssb.repeat > 0 && context.matches > 0))
{
++context.ssidx;
context.matches = 0;
continue;
}
}
else if (result == LoopContext.LoopEvalResult.Success)
{
if (ssb.repeat == 0)
{
++context.ssidx;
}
else
{
++context.matches;
}
context.idx = newcontext.idx;
continue;
}
break;
}
else if (ssb is SubrecordStructure)
{
var ss = (SubrecordStructure)ssb;
if (ss.Condition != CondType.None && !MatchRecordCheckCondition(conditions, ss))
{
++context.ssidx;
continue;
}
if (sb.Name == ss.name && (ss.size == 0 || ss.size == sb.Size))
{
sb.AttachStructure(ss);
if (ss.ContainsConditionals)
{
foreach (var elem in this.EnumerateElements(sb))
{
if (elem != null && elem.Structure != null)
{
var es = elem.Structure;
if (es.CondID != 0)
{
conditions[es.CondID] = new Conditional(elem.Type, elem.Value);
}
}
}
}
++context.idx;
if (ss.repeat == 0)
{
++context.ssidx;
context.matches = 0;
}
else
{
// keep ss context and try again
++context.matches;
}
continue;
}
else
{
if (ss.optional > 0 || (ss.repeat > 0 && context.matches > 0))
{
++context.ssidx;
context.matches = 0;
continue;
}
else
{
// true failure
break;
}
}
}
}
return LoopContext.LoopEvalResult.Failed;
}