Example #1
0
        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);
        }
Example #2
0
        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);
        }