Ejemplo n.º 1
0
        public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
        {
            var enoughBytesForLengthLabel = il.DefineLabel();
            var enoughBytesForDataLabel = il.DefineLabel();
            var lengthIsMinusOneLabel = il.DefineLabel();
            var lengthIsZeroLabel = il.DefineLabel();
            var labelGroup = new[] {lengthIsMinusOneLabel, lengthIsZeroLabel};
            var lengthIsPositiveLabel = il.DefineLabel();
            var endOfMethodLabel = il.DefineLabel();

            if (!doNotCheckBounds)
            {
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= sizeof(int))
                il.Emit_Ldc_I4(sizeof(int));                            //     goto enoughBytesForLengthLabel
                il.Emit(OpCodes.Bge, enoughBytesForLengthLabel);

                // not enough bytes for length
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException(...)
            }

            // enough bytes for length
            il.MarkLabel(enoughBytesForLengthLabel);
            var lengthVar = locals.GetOrAdd("length",                   // var length = *(int*)data
                lil => lil.DeclareLocal(typeof(int)));
            il.Emit(OpCodes.Ldloc, locals.DataPointer);
            il.Emit(OpCodes.Ldind_I4);
            il.Emit(OpCodes.Stloc, lengthVar);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));   // data += sizeof(int)
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeof(int));// remainingBytes -= sizeof(int)
            il.Emit(OpCodes.Ldloc, lengthVar);                          // switch(length + 1)
            il.Emit_Ldc_I4(1);                                          //     case 0:  goto lengthIsMinusOneLabel
            il.Emit(OpCodes.Add);                                       //     case 1:  goto lengthIsZeroLabel
            il.Emit(OpCodes.Switch, labelGroup);                        //     default: goto lengthIsPositiveLabel
            il.Emit(OpCodes.Br, lengthIsPositiveLabel);

            // length is -1
            il.MarkLabel(lengthIsMinusOneLabel);
            il.Emit(OpCodes.Ldnull);                                    // stack_0 = null
            il.Emit(OpCodes.Br, endOfMethodLabel);                      // goto endOfMethodLabel

            // length is 0
            il.MarkLabel(lengthIsZeroLabel);
            il.Emit_Ldc_I4(0);                                          // stack_0 = new T[0]
            il.Emit(OpCodes.Newarr, typeOfStruct);
            il.Emit(OpCodes.Br, endOfMethodLabel);                      // goto endOfMethodLabel

            // length is positive
            il.MarkLabel(lengthIsPositiveLabel);
            var sizeVar = locals.GetOrAdd("sizeInBytes",                // var sizeInBytes = length * sizeOfStruct
                lil => lil.DeclareLocal(typeof(int)));
            il.Emit(OpCodes.Ldloc, lengthVar);
            il.Emit_Ldc_I4(sizeOfStruct);
            il.Emit(OpCodes.Mul);
            il.Emit(OpCodes.Stloc, sizeVar);

            if (!doNotCheckBounds)
            {
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= sizeInBytes)
                il.Emit(OpCodes.Ldloc, sizeVar);                        //     goto enoughBytesForDataLabel
                il.Emit(OpCodes.Bge, enoughBytesForDataLabel);

                // not enough bytes for data
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException(...)
            }

            // enough bytes for data
            il.MarkLabel(enoughBytesForDataLabel);
            var resultVar = locals.GetOrAdd(                            // var result = new T[length]
                "arrayOf" + typeOfStruct.FullName,
                lil => lil.DeclareLocal(typeOfStruct.MakeArrayType()));
            il.Emit(OpCodes.Ldloc, lengthVar);
            il.Emit(OpCodes.Newarr, typeOfStruct);
            il.Emit(OpCodes.Stloc, resultVar);
            var arrayPointerVar = il.Emit_PinArray(                     // var pinned arrayPointer = pin(value)
                typeOfStruct, locals, resultVar);
            il.Emit(OpCodes.Ldloc, arrayPointerVar);                    // cpblk((byte*)arrayPointer, data, sizeInBytes)
            il.Emit(OpCodes.Conv_I);
            il.Emit(OpCodes.Ldloc, locals.DataPointer);
            il.Emit(OpCodes.Ldloc, sizeVar);
            il.Emit(OpCodes.Cpblk);
            il.Emit_UnpinArray(arrayPointerVar);                        // unpin(arrayPointer)
            il.Emit_IncreasePointer(locals.DataPointer, sizeVar);       // data += size
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeVar);    // remainingBytes -= size
            il.Emit(OpCodes.Ldloc, resultVar);                          // stack_0 = result
            il.MarkLabel(endOfMethodLabel);
        }
Ejemplo n.º 2
0
        public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
        {
            var strIsNotNullLabel = il.DefineLabel();
            var endOfSubmethodLabel = il.DefineLabel();

            if (!doNotCheckBounds)
            {
                var canReadSizeLabel = il.DefineLabel();
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= sizeof(int))
                il.Emit_Ldc_I4(sizeof(int));                            //     goto canReadSizeLabel
                il.Emit(OpCodes.Bge, canReadSizeLabel);
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException("...")
                il.MarkLabel(canReadSizeLabel);                         // label canReadSizeLabel
            }
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // stack_0 = *(int*) data
            il.Emit(OpCodes.Ldind_I4);
            var tempInteger = locals.GetOrAdd("tempInteger",            // var tempInteger = stack_0
                g => g.DeclareLocal(typeof(int)));
            il.Emit(OpCodes.Stloc, tempInteger);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));   // data += sizeof(int)
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeof(int));// remainingBytes -= sizeof(int)
            il.Emit(OpCodes.Ldloc, tempInteger);
            il.Emit_Ldc_I4(-1);
            il.Emit(OpCodes.Bne_Un, strIsNotNullLabel);

            // String is null branch
            il.Emit(OpCodes.Ldnull);                                    // stack_0 = null
            il.Emit(OpCodes.Br, endOfSubmethodLabel);                   // goto endOfSubmethodLabel

            // String is not null branch
            il.MarkLabel(strIsNotNullLabel);                            // label strIsNotNullLabel
            if (!doNotCheckBounds)
            {
                var canReadDataLabel = il.DefineLabel();
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= tempInteger)
                il.Emit(OpCodes.Ldloc, tempInteger);                    //     goto canReadDataLabel
                il.Emit(OpCodes.Bge, canReadDataLabel);
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException("...")
                il.MarkLabel(canReadDataLabel);                         // label canReadDataLabel
            }
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // stack_0 = data
            il.Emit_Ldc_I4(0);                                          // stack_1 = 0
            il.Emit(OpCodes.Ldloc, tempInteger);                        // stack_2 = tempInteger >> 1
            il.Emit_Ldc_I4(1);
            il.Emit(OpCodes.Shr);
            il.Emit(OpCodes.Newobj, NewString);                         // stack_0 = new string(stack_0, stack_1, stack_2)
            il.Emit_IncreasePointer(locals.DataPointer, tempInteger);   // data += tempInteger
            il.Emit_DecreaseInteger(locals.RemainingBytes, tempInteger);// remainingBytes -= tempInteger
            il.MarkLabel(endOfSubmethodLabel);                          // label endOfSubmethodLabel
        }
Ejemplo n.º 3
0
        public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
        {
            var valueIsNotNullLabel = il.DefineLabel();
            var loopStartLabel = il.DefineLabel();
            var loopConditionLabel = il.DefineLabel();
            var endOfMethodLabel = il.DefineLabel();

            var resultVar = il.DeclareLocal(type.MakeArrayType());      // T[] result
            var iVar = il.DeclareLocal(typeof(int));                    // int i

            if (!doNotCheckBounds)
            {
                var canReadLengthLabel = il.DefineLabel();
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);          // if (remainingBytes >= sizeof(int))
                il.Emit_Ldc_I4(sizeof(int));                            //     goto canReadLengthLabel
                il.Emit(OpCodes.Bge, canReadLengthLabel);
                il.Emit_ThrowUnexpectedEndException();                  // throw new InvalidDataException("...")
                il.MarkLabel(canReadLengthLabel);                       // label canReadLengthLabel
            }

            var lengthVar = locals.GetOrAdd("refArrayLength",
                lil => lil.DeclareLocal(typeof(int)));
            il.Emit(OpCodes.Ldloc, locals.DataPointer);                 // var length = *(int*) data
            il.Emit(OpCodes.Ldind_I4);
            il.Emit(OpCodes.Stloc, lengthVar);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));   // data += sizeof(int)
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeof(int));// remainingBytes -= sizeof(int)
            il.Emit(OpCodes.Ldloc, lengthVar);                          // if (length == -1)
            il.Emit_Ldc_I4(-1);                                         //     goto valueIsNotNullLabel
            il.Emit(OpCodes.Bne_Un, valueIsNotNullLabel);

            // value is null branch
            il.Emit(OpCodes.Ldnull);                                    // stack_0 = null
            il.Emit(OpCodes.Br, endOfMethodLabel);                      // goto endOfMethodLabel

            // value is not null branch
            il.MarkLabel(valueIsNotNullLabel);                          // label valueIsNotNullLabel
            il.Emit(OpCodes.Ldloc, lengthVar);                          // result = new T[length]
            il.Emit(OpCodes.Newarr, type);
            il.Emit(OpCodes.Stloc, resultVar);
            il.Emit_Ldc_I4(0);                                          // i = 0
            il.Emit(OpCodes.Stloc, iVar);
            il.Emit(OpCodes.Br, loopConditionLabel);                    // goto loopConditionLabel

            // loop start
            il.MarkLabel(loopStartLabel);                               // label loopStartLabel
            il.Emit(OpCodes.Ldloc, resultVar);                          // result[i] = decode(data, remainingBytes)
            il.Emit(OpCodes.Ldloc, iVar);
            EmitDecodeAndStore(il, locals, doNotCheckBounds);
            il.Emit(OpCodes.Ldloc, iVar);                               // i++
            il.Emit_Ldc_I4(1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc, iVar);

            // loop condition
            il.MarkLabel(loopConditionLabel);                           // label loopConditionLabel
            il.Emit(OpCodes.Ldloc, iVar);                               // if (i < (int)result.Length)
            il.Emit(OpCodes.Ldloc, resultVar);                          //     goto loopStartLabel
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Blt, loopStartLabel);

            il.Emit(OpCodes.Ldloc, resultVar);                          // stack_0 = result
            il.MarkLabel(endOfMethodLabel);                             // label endOfMethodLabel
        }
Ejemplo n.º 4
0
        public void EmitDecode(ILGenerator il, ILocalVariableCollection locals, bool doNotCheckBounds)
        {
            var resultIsNotNullLabel = il.DefineLabel();
            var endOfSubmethodLabel = il.DefineLabel();

            if (!doNotCheckBounds)
            {
                var canReadFlagLabel = il.DefineLabel();
                il.Emit(OpCodes.Ldloc, locals.RemainingBytes);                  // if (remainingBytes >= sizeof(int))
                il.Emit_Ldc_I4(sizeof(int));                                    //     goto canReadFlagLabel
                il.Emit(OpCodes.Bge, canReadFlagLabel);
                il.Emit_ThrowUnexpectedEndException();                          // throw new InvalidDataException("...")
                il.MarkLabel(canReadFlagLabel);                                 // label canReadFlagLabel
            }

            var flagVar = locals.GetOrAdd("existanceFlag",
                lil => lil.DeclareLocal(typeof(int)));

            il.Emit(OpCodes.Ldloc, locals.DataPointer);                         // flag = *(int*) data
            il.Emit(OpCodes.Ldind_I4);
            il.Emit(OpCodes.Stloc, flagVar);
            il.Emit_IncreasePointer(locals.DataPointer, sizeof(int));           // data += sizeof(int)
            il.Emit_DecreaseInteger(locals.RemainingBytes, sizeof(int));        // remainingBytes -= sizeof(int)
            il.Emit(OpCodes.Ldloc, flagVar);                                    // if (flag)
            il.Emit(OpCodes.Brtrue, resultIsNotNullLabel);                      //     goto resultIsNotNullLabel

            // Result is null branch
            il.Emit(OpCodes.Ldnull);                                            // stack_0 = null
            il.Emit(OpCodes.Br, endOfSubmethodLabel);                           // goto endOfSubmethodLabel

            // Result is not null branch
            il.MarkLabel(resultIsNotNullLabel);                                 // label resultIsNotNullLabel
            il.Emit(OpCodes.Ldtoken, type);                                     // stack_0 = (T)FormatterServices.GetUninitializedObject(typeof(T))
            il.Emit(OpCodes.Call, GetTypeFromHandleMethod);
            il.Emit(OpCodes.Call, GetUninitializedObject);
            il.Emit(OpCodes.Castclass, type);

            foreach (var memberInfo in memberInfos)                             // foreach (Prop)
            {                                                                   // {
                il.Emit(OpCodes.Dup);                                           //     stack_0.Prop = decode()
                memberInfo.Codec.EmitDecode(il, locals, doNotCheckBounds);
                il.Emit(OpCodes.Call, memberInfo.Property.GetSetMethod(true));
            }                                                                   // }

            il.MarkLabel(endOfSubmethodLabel);                                  // label endOfSubmethodLabel
        }