Ejemplo n.º 1
0
        protected override void EmitRead(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom)
        {
            Type listType;

#if NO_GENERICS
            listType = typeof(BasicList);
#else
            listType = typeof(System.Collections.Generic.List <>).MakeGenericType(itemType);
#endif
            using (Compiler.Local oldArr = ctx.GetLocalWithValue(ExpectedType, valueFrom))
                using (Compiler.Local newArr = new Compiler.Local(ctx, ExpectedType))
                    using (Compiler.Local list = new Compiler.Local(ctx, listType))
                    {
                        ctx.EmitCtor(listType);
                        ctx.StoreValue(list);
                        ListDecorator.EmitReadList(ctx, list, Tail, listType.GetMethod("Add"), packedWireType);

                        // leave this "using" here, as it can share the "FieldNumber" local with EmitReadList
                        using (Compiler.Local oldLen = new ProtoBuf.Compiler.Local(ctx, typeof(int))) {
                            ctx.LoadLength(oldArr, true);
                            ctx.CopyValue();
                            ctx.StoreValue(oldLen);
                            ctx.LoadAddress(list, listType);
                            ctx.LoadValue(listType.GetProperty("Count"));
                            ctx.Add();
                            ctx.CreateArray(itemType, null); // length is on the stack
                            ctx.StoreValue(newArr);

                            ctx.LoadValue(oldLen);
                            Compiler.CodeLabel nothingToCopy = ctx.DefineLabel();
                            ctx.BranchIfFalse(nothingToCopy, true);
                            ctx.LoadValue(oldArr);
                            ctx.LoadValue(newArr);
                            ctx.LoadValue(oldLen);
                            Type[] argTypes = new Type[] { typeof(Array), typeof(int) };
                            ctx.EmitCall(ExpectedType.GetMethod("CopyTo", argTypes));
                            ctx.MarkLabel(nothingToCopy);

                            ctx.LoadValue(list);
                            ctx.LoadValue(newArr);
                            ctx.LoadValue(oldLen);
                            argTypes[0] = ExpectedType; // // prefer: CopyTo(T[], int)
                            MethodInfo copyTo = listType.GetMethod("CopyTo", argTypes);
                            if (copyTo == null)
                            { // fallback: CopyTo(Array, int)
                                argTypes[1] = typeof(Array);
                                copyTo      = listType.GetMethod("CopyTo", argTypes);
                            }
                            ctx.EmitCall(copyTo);
                        }
                        ctx.LoadValue(newArr);
                    }
        }
        protected override void EmitRead(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom)
        {
            Type listType;

            listType = ctx.MapType(typeof(System.Collections.Generic.List <>)).MakeGenericType(itemType);
            Type expected = ExpectedType;

            using (Compiler.Local oldArr = AppendToCollection ? ctx.GetLocalWithValue(expected, valueFrom) : null)
                using (Compiler.Local newArr = new Compiler.Local(ctx, expected))
                    using (Compiler.Local list = new Compiler.Local(ctx, listType))
                    {
                        ctx.EmitCtor(listType);
                        ctx.StoreValue(list);
                        ListDecorator.EmitReadList(ctx, list, Tail, listType.GetMethod("Add"), packedWireType, false);

                        // leave this "using" here, as it can share the "FieldNumber" local with EmitReadList
                        using (Compiler.Local oldLen = AppendToCollection ? new ProtoBuf.Compiler.Local(ctx, ctx.MapType(typeof(int))) : null)
                        {
                            Type[] copyToArrayInt32Args = new Type[] { ctx.MapType(typeof(Array)), ctx.MapType(typeof(int)) };

                            if (AppendToCollection)
                            {
                                ctx.LoadLength(oldArr, true);
                                ctx.CopyValue();
                                ctx.StoreValue(oldLen);

                                ctx.LoadAddress(list, listType);
                                ctx.LoadValue(listType.GetProperty("Count"));
                                ctx.Add();
                                ctx.CreateArray(itemType, null); // length is on the stack
                                ctx.StoreValue(newArr);

                                ctx.LoadValue(oldLen);
                                Compiler.CodeLabel nothingToCopy = ctx.DefineLabel();
                                ctx.BranchIfFalse(nothingToCopy, true);
                                ctx.LoadValue(oldArr);
                                ctx.LoadValue(newArr);
                                ctx.LoadValue(0); // index in target

                                ctx.EmitCall(expected.GetMethod("CopyTo", copyToArrayInt32Args));
                                ctx.MarkLabel(nothingToCopy);

                                ctx.LoadValue(list);
                                ctx.LoadValue(newArr);
                                ctx.LoadValue(oldLen);
                            }
                            else
                            {
                                ctx.LoadAddress(list, listType);
                                ctx.LoadValue(listType.GetProperty("Count"));
                                ctx.CreateArray(itemType, null);
                                ctx.StoreValue(newArr);

                                ctx.LoadAddress(list, listType);
                                ctx.LoadValue(newArr);
                                ctx.LoadValue(0);
                            }

                            copyToArrayInt32Args[0] = expected; // // prefer: CopyTo(T[], int)
                            MethodInfo copyTo = listType.GetMethod("CopyTo", copyToArrayInt32Args);
                            if (copyTo == null)
                            { // fallback: CopyTo(Array, int)
                                copyToArrayInt32Args[1] = ctx.MapType(typeof(Array));
                                copyTo = listType.GetMethod("CopyTo", copyToArrayInt32Args);
                            }
                            ctx.EmitCall(copyTo);
                        }
                        ctx.LoadValue(newArr);
                    }
        }
Ejemplo n.º 3
0
        protected override void EmitRead(CompilerContext ctx, Local valueFrom)
        {
            Local localWithValue;
            Local local;
            Type  type = ctx.MapType(typeof(List <>));

            Type[] typeArray    = new Type[] { this.itemType };
            Type   type1        = type.MakeGenericType(typeArray);
            Type   expectedType = this.ExpectedType;

            if (this.AppendToCollection)
            {
                localWithValue = ctx.GetLocalWithValue(expectedType, valueFrom);
            }
            else
            {
                localWithValue = null;
            }
            using (Local local1 = localWithValue)
            {
                using (Local local2 = new Local(ctx, expectedType))
                {
                    using (Local local3 = new Local(ctx, type1))
                    {
                        ctx.EmitCtor(type1);
                        ctx.StoreValue(local3);
                        ListDecorator.EmitReadList(ctx, local3, this.Tail, type1.GetMethod("Add"), this.packedWireType, false);
                        if (this.AppendToCollection)
                        {
                            local = new Local(ctx, ctx.MapType(typeof(int)));
                        }
                        else
                        {
                            local = null;
                        }
                        using (Local local4 = local)
                        {
                            Type[] typeArray1 = new Type[] { ctx.MapType(typeof(Array)), ctx.MapType(typeof(int)) };
                            Type[] typeArray2 = typeArray1;
                            if (!this.AppendToCollection)
                            {
                                ctx.LoadAddress(local3, type1);
                                ctx.LoadValue(type1.GetProperty("Count"));
                                ctx.CreateArray(this.itemType, null);
                                ctx.StoreValue(local2);
                                ctx.LoadAddress(local3, type1);
                                ctx.LoadValue(local2);
                                ctx.LoadValue(0);
                            }
                            else
                            {
                                ctx.LoadLength(local1, true);
                                ctx.CopyValue();
                                ctx.StoreValue(local4);
                                ctx.LoadAddress(local3, type1);
                                ctx.LoadValue(type1.GetProperty("Count"));
                                ctx.Add();
                                ctx.CreateArray(this.itemType, null);
                                ctx.StoreValue(local2);
                                ctx.LoadValue(local4);
                                CodeLabel codeLabel = ctx.DefineLabel();
                                ctx.BranchIfFalse(codeLabel, true);
                                ctx.LoadValue(local1);
                                ctx.LoadValue(local2);
                                ctx.LoadValue(0);
                                ctx.EmitCall(expectedType.GetMethod("CopyTo", typeArray2));
                                ctx.MarkLabel(codeLabel);
                                ctx.LoadValue(local3);
                                ctx.LoadValue(local2);
                                ctx.LoadValue(local4);
                            }
                            typeArray2[0] = expectedType;
                            MethodInfo method = type1.GetMethod("CopyTo", typeArray2);
                            if (method == null)
                            {
                                typeArray2[1] = ctx.MapType(typeof(Array));
                                method        = type1.GetMethod("CopyTo", typeArray2);
                            }
                            ctx.EmitCall(method);
                        }
                        ctx.LoadValue(local2);
                    }
                }
            }
        }
Ejemplo n.º 4
0
        protected override void EmitRead(CompilerContext ctx, Local valueFrom)
        {
            Local local;
            bool  returnList = this.ReturnList;

            using (Local local1 = (this.AppendToCollection ? ctx.GetLocalWithValue(this.ExpectedType, valueFrom) : new Local(ctx, this.declaredType)))
            {
                if (!returnList || !this.AppendToCollection)
                {
                    local = null;
                }
                else
                {
                    local = new Local(ctx, this.ExpectedType);
                }
                using (Local local2 = local)
                {
                    if (!this.AppendToCollection)
                    {
                        ctx.LoadNullRef();
                        ctx.StoreValue(local1);
                    }
                    else if (returnList)
                    {
                        ctx.LoadValue(local1);
                        ctx.StoreValue(local2);
                    }
                    if (this.concreteType != null)
                    {
                        ctx.LoadValue(local1);
                        CodeLabel codeLabel = ctx.DefineLabel();
                        ctx.BranchIfTrue(codeLabel, true);
                        ctx.EmitCtor(this.concreteType);
                        ctx.StoreValue(local1);
                        ctx.MarkLabel(codeLabel);
                    }
                    bool flag = [email protected](this.declaredType);
                    ListDecorator.EmitReadList(ctx, local1, this.Tail, this.@add, this.packedWireType, flag);
                    if (returnList)
                    {
                        if (!this.AppendToCollection)
                        {
                            ctx.LoadValue(local1);
                        }
                        else
                        {
                            ctx.LoadValue(local2);
                            ctx.LoadValue(local1);
                            CodeLabel codeLabel1 = ctx.DefineLabel();
                            CodeLabel codeLabel2 = ctx.DefineLabel();
                            ctx.BranchIfEqual(codeLabel1, true);
                            ctx.LoadValue(local1);
                            ctx.Branch(codeLabel2, true);
                            ctx.MarkLabel(codeLabel1);
                            ctx.LoadNullRef();
                            ctx.MarkLabel(codeLabel2);
                        }
                    }
                }
            }
        }
        protected override void EmitRead(CompilerContext ctx, Local valueFrom)
        {
            MethodInfo methodInfo;
            MethodInfo methodInfo1;
            Local      localWithValue;

            if (base.AppendToCollection)
            {
                localWithValue = ctx.GetLocalWithValue(this.ExpectedType, valueFrom);
            }
            else
            {
                localWithValue = null;
            }
            using (Local local = localWithValue)
            {
                using (Local local1 = new Local(ctx, this.builderFactory.ReturnType))
                {
                    ctx.EmitCall(this.builderFactory);
                    ctx.StoreValue(local1);
                    if (base.AppendToCollection)
                    {
                        CodeLabel codeLabel = ctx.DefineLabel();
                        if (!this.ExpectedType.IsValueType)
                        {
                            ctx.LoadValue(local);
                            ctx.BranchIfFalse(codeLabel, false);
                        }
                        PropertyInfo property = Helpers.GetProperty(this.ExpectedType, "Length", false) ?? Helpers.GetProperty(this.ExpectedType, "Count", false) ?? Helpers.GetProperty(ImmutableCollectionDecorator.ResolveIReadOnlyCollection(this.ExpectedType, this.Tail.ExpectedType), "Count", false);
                        ctx.LoadAddress(local, local.Type);
                        ctx.EmitCall(Helpers.GetGetMethod(property, false, false));
                        ctx.BranchIfFalse(codeLabel, false);
                        Type type = ctx.MapType(typeof(void));
                        if (this.addRange == null)
                        {
                            MethodInfo enumeratorInfo = base.GetEnumeratorInfo(ctx.Model, out methodInfo, out methodInfo1);
                            Type       returnType     = enumeratorInfo.ReturnType;
                            using (Local local2 = new Local(ctx, returnType))
                            {
                                ctx.LoadAddress(local, this.ExpectedType);
                                ctx.EmitCall(enumeratorInfo);
                                ctx.StoreValue(local2);
                                using (IDisposable disposable = ctx.Using(local2))
                                {
                                    CodeLabel codeLabel1 = ctx.DefineLabel();
                                    CodeLabel codeLabel2 = ctx.DefineLabel();
                                    ctx.Branch(codeLabel2, false);
                                    ctx.MarkLabel(codeLabel1);
                                    ctx.LoadAddress(local1, local1.Type);
                                    ctx.LoadAddress(local2, returnType);
                                    ctx.EmitCall(methodInfo1);
                                    ctx.EmitCall(this.@add);
                                    if ([email protected] != null && [email protected] != type)
                                    {
                                        ctx.DiscardValue();
                                    }
                                    ctx.MarkLabel(codeLabel2);
                                    ctx.LoadAddress(local2, returnType);
                                    ctx.EmitCall(methodInfo);
                                    ctx.BranchIfTrue(codeLabel1, false);
                                }
                            }
                        }
                        else
                        {
                            ctx.LoadValue(local1);
                            ctx.LoadValue(local);
                            ctx.EmitCall(this.addRange);
                            if (this.addRange.ReturnType != null && [email protected] != type)
                            {
                                ctx.DiscardValue();
                            }
                        }
                        ctx.MarkLabel(codeLabel);
                    }
                    ListDecorator.EmitReadList(ctx, local1, this.Tail, this.@add, this.packedWireType, false);
                    ctx.LoadAddress(local1, local1.Type);
                    ctx.EmitCall(this.finish);
                    if (this.ExpectedType != this.finish.ReturnType)
                    {
                        ctx.Cast(this.ExpectedType);
                    }
                }
            }
        }