private static void SwitchNumber <T>(this ILGenerator ilGen, Action <ILGenerator> emitLoadValue, Action <ILGenerator, T> emitLoadItem, CaseInfo <T>[] cases, Label defaultLabel, int begin, int index, int end) { if (begin > end) { ilGen.Branch(defaultLabel); return; } if (begin + 1 == end) { emitLoadValue(ilGen); emitLoadItem(ilGen, cases[begin].Value); ilGen.BranchIfEqual(cases[begin].Label); emitLoadValue(ilGen); emitLoadItem(ilGen, cases[end].Value); ilGen.BranchIfEqual(cases[end].Label); ilGen.Branch(defaultLabel); return; } if (begin == end) { emitLoadValue(ilGen); emitLoadItem(ilGen, cases[begin].Value); ilGen.BranchIfEqual(cases[begin].Label); ilGen.Branch(defaultLabel); return; } var greaterLabel = ilGen.DefineLabel(); emitLoadValue(ilGen); emitLoadItem(ilGen, cases[index].Value); ilGen.BranchIfGreater(greaterLabel); SwitchNumber(ilGen, emitLoadValue, emitLoadItem, cases, defaultLabel, begin, (begin + index) / 2, index); ilGen.MarkLabel(greaterLabel); SwitchNumber(ilGen, emitLoadValue, emitLoadItem, cases, defaultLabel, index + 1, (index + 1 + end) / 2, end); }
private static void SwitchObject <T>(this ILGenerator ilGen, Action <ILGenerator> emitLoadValue, Action <ILGenerator> emitLoadHashCode, Action <ILGenerator, T> emitLoadItem, IHashComparer <T> comparer, List <KeyValuePair <int, List <CaseInfo <T> > > > cases, Label defaultLabel, int begin, int index, int end) { if (begin > end) { return; } if (begin == end) { emitLoadHashCode(ilGen); ilGen.LoadConstant(cases[begin].Key); ilGen.BranchIfNotEqualUnsigned(defaultLabel); if (SwitchDoNotVerify && cases[begin].Value.Count == 1) { ilGen.Branch(cases[begin].Value[0].Label); } else { foreach (var item in cases[begin].Value) { emitLoadValue(ilGen); emitLoadItem(ilGen, item.Value); comparer.EmitEquals(ilGen); ilGen.BranchTrue(item.Label); } } ilGen.Branch(defaultLabel); return; } if (begin + 1 == end) { var endLabel = ilGen.DefineLabel(); emitLoadHashCode(ilGen); ilGen.LoadConstant(cases[begin].Key); ilGen.BranchIfNotEqualUnsigned(endLabel); if (SwitchDoNotVerify && cases[begin].Value.Count == 1) { ilGen.Branch(cases[begin].Value[0].Label); } else { foreach (var item in cases[begin].Value) { emitLoadValue(ilGen); emitLoadItem(ilGen, item.Value); comparer.EmitEquals(ilGen); ilGen.BranchTrue(item.Label); } } ilGen.MarkLabel(endLabel); emitLoadHashCode(ilGen); ilGen.LoadConstant(cases[end].Key); ilGen.BranchIfNotEqualUnsigned(defaultLabel); if (SwitchDoNotVerify && cases[end].Value.Count == 1) { ilGen.Branch(cases[end].Value[0].Label); } else { foreach (var item in cases[end].Value) { emitLoadValue(ilGen); emitLoadItem(ilGen, item.Value); comparer.EmitEquals(ilGen); ilGen.BranchTrue(item.Label); } } ilGen.Branch(defaultLabel); return; } var greaterLabel = ilGen.DefineLabel(); emitLoadHashCode(ilGen); ilGen.LoadConstant(cases[index].Key); ilGen.BranchIfGreater(greaterLabel); SwitchObject( ilGen, emitLoadValue, emitLoadHashCode, emitLoadItem, comparer, cases, defaultLabel, begin, (begin + index) / 2, index); ilGen.MarkLabel(greaterLabel); SwitchObject( ilGen, emitLoadValue, emitLoadHashCode, emitLoadItem, comparer, cases, defaultLabel, index + 1, (index + 1 + end) / 2, end); }