protected override void EmitRead(CompilerContext ctx, Local valueFrom) { using (Compiler.Local list = AppendToCollection ? ctx.GetLocalWithValue(ExpectedType, valueFrom) : new Compiler.Local(ctx, typeof(TDictionary))) using (Compiler.Local token = new Compiler.Local(ctx, typeof(SubItemToken))) using (Compiler.Local key = new Compiler.Local(ctx, typeof(TKey))) using (Compiler.Local @value = new Compiler.Local(ctx, typeof(TValue))) using (Compiler.Local fieldNumber = new Compiler.Local(ctx, typeof(int))) { if (!AppendToCollection) { // always new ctx.LoadNullRef(); ctx.StoreValue(list); } if (concreteType != null) { ctx.LoadValue(list); Compiler.CodeLabel notNull = ctx.DefineLabel(); ctx.BranchIfTrue(notNull, true); ctx.EmitCtor(concreteType); ctx.StoreValue(list); ctx.MarkLabel(notNull); } var redoFromStart = ctx.DefineLabel(); ctx.MarkLabel(redoFromStart); // key = default(TKey); value = default(TValue); if (typeof(TKey) == typeof(string)) { ctx.LoadValue(""); ctx.StoreValue(key); } else { ctx.InitLocal(typeof(TKey), key); } if (typeof(TValue) == typeof(string)) { ctx.LoadValue(""); ctx.StoreValue(value); } else { ctx.InitLocal(typeof(TValue), @value); } // token = ProtoReader.StartSubItem(reader); ctx.LoadReader(true); ctx.EmitCall(typeof(ProtoReader).GetMethod("StartSubItem", ProtoReader.State.ReaderStateTypeArray)); ctx.StoreValue(token); Compiler.CodeLabel @continue = ctx.DefineLabel(), processField = ctx.DefineLabel(); // while ... ctx.Branch(@continue, false); // switch(fieldNumber) ctx.MarkLabel(processField); ctx.LoadValue(fieldNumber); CodeLabel @default = ctx.DefineLabel(), one = ctx.DefineLabel(), two = ctx.DefineLabel(); ctx.Switch(new[] { @default, one, two }); // zero based, hence explicit 0 // case 0: default: reader.SkipField(); ctx.MarkLabel(@default); ctx.LoadReader(true); ctx.EmitCall(typeof(ProtoReader).GetMethod("SkipField", ProtoReader.State.StateTypeArray)); ctx.Branch(@continue, false); // case 1: key = ... ctx.MarkLabel(one); keyTail.EmitRead(ctx, null); ctx.StoreValue(key); ctx.Branch(@continue, false); // case 2: value = ... ctx.MarkLabel(two); Tail.EmitRead(ctx, Tail.RequiresOldValue ? @value : null); ctx.StoreValue(value); // (fieldNumber = reader.ReadFieldHeader()) > 0 ctx.MarkLabel(@continue); ctx.EmitBasicRead("ReadFieldHeader", typeof(int)); ctx.CopyValue(); ctx.StoreValue(fieldNumber); ctx.LoadValue(0); ctx.BranchIfGreater(processField, false); // ProtoReader.EndSubItem(token, reader); ctx.LoadValue(token); ctx.LoadReader(true); ctx.EmitCall(typeof(ProtoReader).GetMethod("EndSubItem", new[] { typeof(SubItemToken), typeof(ProtoReader), ProtoReader.State.ByRefStateType })); // list[key] = value; ctx.LoadAddress(list, ExpectedType); ctx.LoadValue(key); ctx.LoadValue(@value); ctx.EmitCall(indexerSet); // while reader.TryReadFieldReader(fieldNumber) ctx.LoadReader(true); ctx.LoadValue(this.fieldNumber); ctx.EmitCall(typeof(ProtoReader).GetMethod("TryReadFieldHeader", new[] { ProtoReader.State.ByRefStateType, typeof(int) })); ctx.BranchIfTrue(redoFromStart, false); if (ReturnsValue) { ctx.LoadValue(list); } } }
void IProtoSerializer.EmitRead(CompilerContext ctx, Local valueFrom) { Type expectedType = this.ExpectedType; using (Local local = ctx.GetLocalWithValue(expectedType, valueFrom)) { using (Local local2 = new Local(ctx, ctx.MapType(typeof(int)))) { if (this.HasCallbacks(TypeModel.CallbackType.BeforeDeserialize)) { if (this.ExpectedType.IsValueType) { this.EmitCallbackIfNeeded(ctx, local, TypeModel.CallbackType.BeforeDeserialize); } else { CodeLabel label = ctx.DefineLabel(); ctx.LoadValue(local); ctx.BranchIfFalse(label, false); this.EmitCallbackIfNeeded(ctx, local, TypeModel.CallbackType.BeforeDeserialize); ctx.MarkLabel(label); } } CodeLabel label2 = ctx.DefineLabel(); CodeLabel label3 = ctx.DefineLabel(); ctx.Branch(label2, false); ctx.MarkLabel(label3); BasicList.NodeEnumerator enumerator = BasicList.GetContiguousGroups(this.fieldNumbers, this.serializers).GetEnumerator(); while (enumerator.MoveNext()) { BasicList.Group current = (BasicList.Group)enumerator.Current; CodeLabel label4 = ctx.DefineLabel(); int count = current.Items.Count; if (count == 1) { ctx.LoadValue(local2); ctx.LoadValue(current.First); CodeLabel label5 = ctx.DefineLabel(); ctx.BranchIfEqual(label5, true); ctx.Branch(label4, false); this.WriteFieldHandler(ctx, expectedType, local, label5, label2, (IProtoSerializer)current.Items[0]); } else { ctx.LoadValue(local2); ctx.LoadValue(current.First); ctx.Subtract(); CodeLabel[] jumpTable = new CodeLabel[count]; for (int i = 0; i < count; i++) { jumpTable[i] = ctx.DefineLabel(); } ctx.Switch(jumpTable); ctx.Branch(label4, false); for (int j = 0; j < count; j++) { this.WriteFieldHandler(ctx, expectedType, local, jumpTable[j], label2, (IProtoSerializer)current.Items[j]); } } ctx.MarkLabel(label4); } this.EmitCreateIfNull(ctx, local); ctx.LoadReaderWriter(); if (this.isExtensible) { ctx.LoadValue(local); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("AppendExtensionData")); } else { ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("SkipField")); } ctx.MarkLabel(label2); ctx.EmitBasicRead("ReadFieldHeader", ctx.MapType(typeof(int))); ctx.CopyValue(); ctx.StoreValue(local2); ctx.LoadValue(0); ctx.BranchIfGreater(label3, false); this.EmitCreateIfNull(ctx, local); this.EmitCallbackIfNeeded(ctx, local, TypeModel.CallbackType.AfterDeserialize); if ((valueFrom != null) && !local.IsSame(valueFrom)) { ctx.LoadValue(local); ctx.Cast(valueFrom.Type); ctx.StoreValue(valueFrom); } } } }
public void EmitRead(CompilerContext ctx, Local incoming) { using (Local local = ctx.GetLocalWithValue(this.ExpectedType, incoming)) { Local[] localArray = new Local[this.members.Length]; try { for (int i = 0; i < localArray.Length; i++) { Type memberType = this.GetMemberType(i); bool flag = true; localArray[i] = new Local(ctx, memberType); if (this.ExpectedType.IsValueType) { continue; } if (memberType.IsValueType) { switch (Helpers.GetTypeCode(memberType)) { case ProtoTypeCode.Boolean: case ProtoTypeCode.SByte: case ProtoTypeCode.Byte: case ProtoTypeCode.Int16: case ProtoTypeCode.UInt16: case ProtoTypeCode.Int32: case ProtoTypeCode.UInt32: ctx.LoadValue(0); goto Label_0108; case ProtoTypeCode.Int64: case ProtoTypeCode.UInt64: ctx.LoadValue((long)0L); goto Label_0108; case ProtoTypeCode.Single: ctx.LoadValue((float)0f); goto Label_0108; case ProtoTypeCode.Double: ctx.LoadValue((double)0.0); goto Label_0108; case ProtoTypeCode.Decimal: ctx.LoadValue((decimal)0M); goto Label_0108; case ProtoTypeCode.Guid: ctx.LoadValue(Guid.Empty); goto Label_0108; } ctx.LoadAddress(localArray[i], memberType); ctx.EmitCtor(memberType); flag = false; } else { ctx.LoadNullRef(); } Label_0108: if (flag) { ctx.StoreValue(localArray[i]); } } CodeLabel label = this.ExpectedType.IsValueType ? new CodeLabel() : ctx.DefineLabel(); if (!this.ExpectedType.IsValueType) { ctx.LoadAddress(local, this.ExpectedType); ctx.BranchIfFalse(label, false); } for (int j = 0; j < this.members.Length; j++) { ctx.LoadAddress(local, this.ExpectedType); switch (this.members[j].MemberType) { case MemberTypes.Field: ctx.LoadValue((FieldInfo)this.members[j]); break; case MemberTypes.Property: ctx.LoadValue((PropertyInfo)this.members[j]); break; } ctx.StoreValue(localArray[j]); } if (!this.ExpectedType.IsValueType) { ctx.MarkLabel(label); } using (Local local2 = new Local(ctx, ctx.MapType(typeof(int)))) { CodeLabel label2 = ctx.DefineLabel(); CodeLabel label3 = ctx.DefineLabel(); CodeLabel label4 = ctx.DefineLabel(); ctx.Branch(label2, false); CodeLabel[] jumpTable = new CodeLabel[this.members.Length]; for (int m = 0; m < this.members.Length; m++) { jumpTable[m] = ctx.DefineLabel(); } ctx.MarkLabel(label3); ctx.LoadValue(local2); ctx.LoadValue(1); ctx.Subtract(); ctx.Switch(jumpTable); ctx.Branch(label4, false); for (int n = 0; n < jumpTable.Length; n++) { ctx.MarkLabel(jumpTable[n]); IProtoSerializer tail = this.tails[n]; Local valueFrom = tail.RequiresOldValue ? localArray[n] : null; ctx.ReadNullCheckedTail(localArray[n].Type, tail, valueFrom); if (tail.ReturnsValue) { if (localArray[n].Type.IsValueType) { ctx.StoreValue(localArray[n]); } else { CodeLabel label5 = ctx.DefineLabel(); CodeLabel label6 = ctx.DefineLabel(); ctx.CopyValue(); ctx.BranchIfTrue(label5, true); ctx.DiscardValue(); ctx.Branch(label6, true); ctx.MarkLabel(label5); ctx.StoreValue(localArray[n]); ctx.MarkLabel(label6); } } ctx.Branch(label2, false); } ctx.MarkLabel(label4); ctx.LoadReaderWriter(); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("SkipField")); ctx.MarkLabel(label2); ctx.EmitBasicRead("ReadFieldHeader", ctx.MapType(typeof(int))); ctx.CopyValue(); ctx.StoreValue(local2); ctx.LoadValue(0); ctx.BranchIfGreater(label3, false); } for (int k = 0; k < localArray.Length; k++) { ctx.LoadValue(localArray[k]); } ctx.EmitCtor(this.ctor); ctx.StoreValue(local); } finally { for (int num6 = 0; num6 < localArray.Length; num6++) { if (localArray[num6] != null) { localArray[num6].Dispose(); } } } } }
public void EmitRead(CompilerContext ctx, Local incoming) { Local local; using (Local localWithValue = ctx.GetLocalWithValue(this.ExpectedType, incoming)) { Local[] localArray = new Local[(int)this.members.Length]; try { for (int i = 0; i < (int)localArray.Length; i++) { Type memberType = this.GetMemberType(i); bool flag = true; localArray[i] = new Local(ctx, memberType); if (!this.ExpectedType.IsValueType) { if (!memberType.IsValueType) { ctx.LoadNullRef(); } else { ProtoTypeCode typeCode = Helpers.GetTypeCode(memberType); switch (typeCode) { case ProtoTypeCode.Boolean: case ProtoTypeCode.SByte: case ProtoTypeCode.Byte: case ProtoTypeCode.Int16: case ProtoTypeCode.UInt16: case ProtoTypeCode.Int32: case ProtoTypeCode.UInt32: { ctx.LoadValue(0); break; } case ProtoTypeCode.Char: { ctx.LoadAddress(localArray[i], memberType); ctx.EmitCtor(memberType); flag = false; break; } case ProtoTypeCode.Int64: case ProtoTypeCode.UInt64: { ctx.LoadValue((long)0); break; } case ProtoTypeCode.Single: { ctx.LoadValue(0f); break; } case ProtoTypeCode.Double: { ctx.LoadValue(0); break; } case ProtoTypeCode.Decimal: { ctx.LoadValue(new decimal(0)); break; } default: { if (typeCode == ProtoTypeCode.Guid) { ctx.LoadValue(Guid.Empty); break; } else { goto case ProtoTypeCode.Char; } } } } if (flag) { ctx.StoreValue(localArray[i]); } } } CodeLabel codeLabel = (this.ExpectedType.IsValueType ? new CodeLabel() : ctx.DefineLabel()); if (!this.ExpectedType.IsValueType) { ctx.LoadAddress(localWithValue, this.ExpectedType); ctx.BranchIfFalse(codeLabel, false); } for (int j = 0; j < (int)this.members.Length; j++) { ctx.LoadAddress(localWithValue, this.ExpectedType); MemberTypes memberType1 = this.members[j].MemberType; if (memberType1 == MemberTypes.Field) { ctx.LoadValue((FieldInfo)this.members[j]); } else if (memberType1 == MemberTypes.Property) { ctx.LoadValue((PropertyInfo)this.members[j]); } ctx.StoreValue(localArray[j]); } if (!this.ExpectedType.IsValueType) { ctx.MarkLabel(codeLabel); } using (Local local1 = new Local(ctx, ctx.MapType(typeof(int)))) { CodeLabel codeLabel1 = ctx.DefineLabel(); CodeLabel codeLabel2 = ctx.DefineLabel(); CodeLabel codeLabel3 = ctx.DefineLabel(); ctx.Branch(codeLabel1, false); CodeLabel[] codeLabelArray = new CodeLabel[(int)this.members.Length]; for (int k = 0; k < (int)this.members.Length; k++) { codeLabelArray[k] = ctx.DefineLabel(); } ctx.MarkLabel(codeLabel2); ctx.LoadValue(local1); ctx.LoadValue(1); ctx.Subtract(); ctx.Switch(codeLabelArray); ctx.Branch(codeLabel3, false); for (int l = 0; l < (int)codeLabelArray.Length; l++) { ctx.MarkLabel(codeLabelArray[l]); IProtoSerializer protoSerializer = this.tails[l]; if (protoSerializer.RequiresOldValue) { local = localArray[l]; } else { local = null; } ctx.ReadNullCheckedTail(localArray[l].Type, protoSerializer, local); if (protoSerializer.ReturnsValue) { if (!localArray[l].Type.IsValueType) { CodeLabel codeLabel4 = ctx.DefineLabel(); CodeLabel codeLabel5 = ctx.DefineLabel(); ctx.CopyValue(); ctx.BranchIfTrue(codeLabel4, true); ctx.DiscardValue(); ctx.Branch(codeLabel5, true); ctx.MarkLabel(codeLabel4); ctx.StoreValue(localArray[l]); ctx.MarkLabel(codeLabel5); } else { ctx.StoreValue(localArray[l]); } } ctx.Branch(codeLabel1, false); } ctx.MarkLabel(codeLabel3); ctx.LoadReaderWriter(); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("SkipField")); ctx.MarkLabel(codeLabel1); ctx.EmitBasicRead("ReadFieldHeader", ctx.MapType(typeof(int))); ctx.CopyValue(); ctx.StoreValue(local1); ctx.LoadValue(0); ctx.BranchIfGreater(codeLabel2, false); } for (int m = 0; m < (int)localArray.Length; m++) { ctx.LoadValue(localArray[m]); } ctx.EmitCtor(this.ctor); ctx.StoreValue(localWithValue); } finally { for (int n = 0; n < (int)localArray.Length; n++) { if (localArray[n] != null) { localArray[n].Dispose(); } } } } }