Пример #1
0
        internal static void EmitReadList(ProtoBuf.Compiler.CompilerContext ctx, Compiler.Local list, IProtoSerializer tail, MethodInfo add, WireType packedWireType, bool castListForAdd)
        {
            using (Compiler.Local fieldNumber = new Compiler.Local(ctx, typeof(int)))
            {
                Compiler.CodeLabel readPacked = packedWireType == WireType.None ? new Compiler.CodeLabel() : ctx.DefineLabel();
                if (packedWireType != WireType.None)
                {
                    ctx.LoadReader(false);
                    ctx.LoadValue(typeof(ProtoReader).GetProperty("WireType"));
                    ctx.LoadValue((int)WireType.String);
                    ctx.BranchIfEqual(readPacked, false);
                }
                ctx.LoadReader(false);
                ctx.LoadValue(typeof(ProtoReader).GetProperty("FieldNumber"));
                ctx.StoreValue(fieldNumber);

                Compiler.CodeLabel @continue = ctx.DefineLabel();
                ctx.MarkLabel(@continue);

                EmitReadAndAddItem(ctx, list, tail, add, castListForAdd);

                ctx.LoadReader(true);
                ctx.LoadValue(fieldNumber);
                ctx.EmitCall(typeof(ProtoReader).GetMethod("TryReadFieldHeader",
                                                           new[] { ProtoReader.State.ByRefStateType, typeof(int) }));
                ctx.BranchIfTrue(@continue, false);

                if (packedWireType != WireType.None)
                {
                    Compiler.CodeLabel allDone = ctx.DefineLabel();
                    ctx.Branch(allDone, false);
                    ctx.MarkLabel(readPacked);

                    ctx.LoadReader(true);
                    ctx.EmitCall(typeof(ProtoReader).GetMethod("StartSubItem",
                                                               ProtoReader.State.ReaderStateTypeArray));

                    Compiler.CodeLabel testForData = ctx.DefineLabel(), noMoreData = ctx.DefineLabel();
                    ctx.MarkLabel(testForData);
                    ctx.LoadValue((int)packedWireType);
                    ctx.LoadReader(false);
                    ctx.EmitCall(typeof(ProtoReader).GetMethod("HasSubValue"));
                    ctx.BranchIfFalse(noMoreData, false);

                    EmitReadAndAddItem(ctx, list, tail, add, castListForAdd);
                    ctx.Branch(testForData, false);

                    ctx.MarkLabel(noMoreData);
                    ctx.LoadReader(true);
                    ctx.EmitCall(typeof(ProtoReader).GetMethod("EndSubItem",
                                                               new[] { typeof(SubItemToken), typeof(ProtoReader), ProtoReader.State.ByRefStateType }));
                    ctx.MarkLabel(allDone);
                }
            }
        }
Пример #2
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);
                    }
        }
Пример #3
0
        protected override void EmitWrite(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom)
        {
            // int i and T[] arr
            using (Compiler.Local arr = ctx.GetLocalWithValue(arrayType, valueFrom))
                using (Compiler.Local i = new ProtoBuf.Compiler.Local(ctx, typeof(int)))
                {
                    if (packedFieldNumber > 0)
                    {
                        Compiler.CodeLabel allDone = ctx.DefineLabel();
                        ctx.LoadLength(arr, false);
                        ctx.BranchIfFalse(allDone, false);

                        ctx.LoadValue(packedFieldNumber);
                        ctx.LoadValue((int)WireType.String);
                        ctx.LoadReaderWriter();
                        ctx.EmitCall(typeof(ProtoWriter).GetMethod("WriteFieldHeader"));

                        ctx.LoadValue(arr);
                        ctx.LoadReaderWriter();
                        ctx.EmitCall(typeof(ProtoWriter).GetMethod("StartSubItem"));
                        using (Compiler.Local token = new Compiler.Local(ctx, typeof(SubItemToken))) {
                            ctx.StoreValue(token);

                            ctx.LoadValue(packedFieldNumber);
                            ctx.LoadReaderWriter();
                            ctx.EmitCall(typeof(ProtoWriter).GetMethod("SetPackedField"));

                            EmitWriteArrayLoop(ctx, i, arr);

                            ctx.LoadValue(token);
                            ctx.LoadReaderWriter();
                            ctx.EmitCall(typeof(ProtoWriter).GetMethod("EndSubItem"));
                        }
                        ctx.MarkLabel(allDone);
                    }
                    else
                    {
                        EmitWriteArrayLoop(ctx, i, arr);
                    }
                }
        }
        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);
                    }
        }
Пример #5
0
        protected override void EmitWrite(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom)
        {
            using (Compiler.Local list = ctx.GetLocalWithValue(ExpectedType, valueFrom))
            {
                MethodInfo moveNext, current, getEnumerator = GetEnumeratorInfo(out moveNext, out current);
                Helpers.DebugAssert(moveNext != null);
                Helpers.DebugAssert(current != null);
                Helpers.DebugAssert(getEnumerator != null);
                Type enumeratorType = getEnumerator.ReturnType;
                using (Compiler.Local iter = new Compiler.Local(ctx, enumeratorType))
                    using (Compiler.Local token = packedFieldNumber > 0 ? new Compiler.Local(ctx, typeof(SubItemToken)) : null)
                    {
                        ctx.LoadAddress(list, ExpectedType);
                        ctx.EmitCall(getEnumerator);
                        ctx.StoreValue(iter);
                        using (ctx.Using(iter))
                        {
                            Compiler.CodeLabel body           = ctx.DefineLabel(),
                                               @next          = ctx.DefineLabel(),
                                               nothingToWrite = packedFieldNumber > 0 ? ctx.DefineLabel() : new Compiler.CodeLabel();
                            if (packedFieldNumber > 0)
                            {
                                ctx.LoadAddress(iter, enumeratorType);
                                ctx.EmitCall(moveNext);
                                ctx.BranchIfFalse(nothingToWrite, false);

                                ctx.LoadValue(packedFieldNumber);
                                ctx.LoadValue((int)WireType.String);
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(typeof(ProtoWriter).GetMethod("WriteFieldHeader"));

                                ctx.LoadValue(list);
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(typeof(ProtoWriter).GetMethod("StartSubItem"));
                                ctx.StoreValue(token);

                                ctx.LoadValue(packedFieldNumber);
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(typeof(ProtoWriter).GetMethod("SetPackedField"));
                            }
                            else
                            {
                                ctx.Branch(@next, false);
                            }
                            ctx.MarkLabel(body);

                            ctx.LoadAddress(iter, enumeratorType);
                            ctx.EmitCall(current);
                            Type itemType = Tail.ExpectedType;
                            if (itemType != typeof(object) && current.ReturnType == typeof(object))
                            {
                                ctx.CastFromObject(itemType);
                            }
                            Tail.EmitWrite(ctx, null);

                            ctx.MarkLabel(@next);
                            ctx.LoadAddress(iter, enumeratorType);
                            ctx.EmitCall(moveNext);
                            ctx.BranchIfTrue(body, false);
                            if (packedFieldNumber > 0)
                            {
                                ctx.LoadValue(token);
                                ctx.LoadReaderWriter();
                                ctx.EmitCall(typeof(ProtoWriter).GetMethod("EndSubItem"));
                                ctx.MarkLabel(nothingToWrite);
                            }
                        }
                    }
            }
        }