/// <summary>
        ///     Puts TypeCode.Empty in <c>result</c> if <c>writeEmpty</c> = true and returns
        /// </summary>
        public void WriteNull()
        {
            var retLabel = Il.DefineLabel("return");

            LoadWriteEmpty();     // stack: [writeEmpty]
            Il.Brfalse(retLabel); // if(!writeEmpty) goto ret;
            WriteTypeCode(GroBufTypeCode.Empty);
            Il.MarkLabel(retLabel);
            Il.Ret();
        }
        public void AssertTypeCode(GroBufTypeCode expectedTypeCode)
        {
            Il.Ldloc(TypeCode);               // stack: [typeCode]
            Il.Ldc_I4((int)expectedTypeCode); // stack: [typeCode, expectedTypeCode]

            var okLabel = Il.DefineLabel("ok");

            Il.Beq(okLabel);

            SkipValue();
            Il.Ret();

            Il.MarkLabel(okLabel);
        }
        public void SkipValue()
        {
            LoadIndexByRef(); // stack: [ref index]
            LoadIndex();      // stack: [ref index, index]

            // todo: сделать switch
            Il.Ldloc(TypeCode);                         // stack: [ref index, index, TypeCode]
            Il.Ldc_I4((int)GroBufTypeCode.DateTimeOld); // stack: [ref index, index, TypeCode, GroBufTypeCode.DateTimeOld]
            var notDateTimeLabel = Il.DefineLabel("notDateTime");

            Il.Bne_Un(notDateTimeLabel); // if(TypeCode != GroBufTypeCode.DateTimeOld) goto notDateTime; stack: [ref index, index]
            Il.Ldc_I4(8);                // stack: [ref index, index, 8]
            AssertLength();
            GoToCurrentLocation();       // stack: [ref index, index, &data[index]]
            Il.Ldc_I4(4);
            Il.Add();
            Il.Ldind(typeof(int)); // stack: [ref index, index, (int)(&data[index])]
            Il.Ldc_I4(31);         // stack: [ref index, index, (int)&data[index], 31]
            Il.Shr(true);          // stack: [ref index, index, (int)&data[index] >> 31]
            Il.Ldc_I4(8);          // stack: [ref index, index, (int)&data[index] >> 31, 8]
            Il.Add();              // stack: [ref index, index, (int)&data[index] >> 31 + 8]
            var increaseLabel = Il.DefineLabel("increase");

            Il.Br(increaseLabel);

            Il.MarkLabel(notDateTimeLabel);
            LoadField(Context.Lengths);

            Il.Ldloc(TypeCode);       // stack: [ref index, index, lengths, typeCode]
            Il.Ldelem(typeof(int));   // stack: [ref index, index, lengths[typeCode]]
            Il.Dup();                 // stack: [ref index, index, lengths[typeCode], lengths[typeCode]]
            Il.Ldc_I4(-1);            // stack: [ref index, index, lengths[typeCode], lengths[typeCode], -1]
            Il.Bne_Un(increaseLabel); // if(lengths[typeCode] != -1) goto increase;

            Il.Ldc_I4(4);
            AssertLength();
            Il.Pop();               // stack: [ref index, index]
            Il.Dup();               // stack: [ref index, index, index]
            LoadData();             // stack: [ref index, index, index, pinnedData]
            Il.Add();               // stack: [ref index, index, index + pinnedData]
            Il.Ldind(typeof(uint)); // stack: [ref index, index, *(uint*)(pinnedData + index)]
            Il.Ldc_I4(4);           // stack: [ref index, index, *(uint*)(pinnedData + index), 4]
            Il.Add();               // stack: [ref index, *(uint*)(pinnedData + index) + 4]

            Il.MarkLabel(increaseLabel);
            Il.Dup();              // stack: [ref index, length, length]
            AssertLength();        // stack: [ref index, length]
            Il.Add();              // stack: [ref index, index + length]
            Il.Stind(typeof(int)); // index = index + length
        }
        /// <summary>
        ///     Asserts that the specified number of bytes can be read from <c>data</c> starting at <c>index</c>
        ///     <para></para>
        ///     The number of bytes must be pushed onto the evaluation stack
        /// </summary>
        public void AssertLength()
        {
            LoadIndex();      // stack: [length, index]
            Il.Add();         // stack: [length + index]
            LoadDataLength(); // stack: [length + index, dataLength]
            var bigEnoughLabel = Il.DefineLabel("bigEnough");

            Il.Ble(bigEnoughLabel, true);
            Il.Ldstr("Unexpected end of data");
            var constructor = typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) });

            if (constructor == null)
            {
                throw new MissingConstructorException(typeof(DataCorruptedException), typeof(string));
            }
            Il.Newobj(constructor);
            Il.Throw();
            Il.MarkLabel(bigEnoughLabel);
        }
        /// <summary>
        ///     Asserts that the specified number of bytes can be written to <c>result</c> starting at <c>index</c>
        ///     <para></para>
        ///     The number of bytes must be pushed onto the evaluation stack
        /// </summary>
        public void AssertLength()
        {
            LoadIndex();        // stack: [length, index]
            Il.Add();           // stack: [length + index]
            LoadResultLength(); // stack: [length + index, resultLength]
            var bigEnoughLabel = Il.DefineLabel("bigEnough");

            Il.Ble(bigEnoughLabel, true);
            Il.Ldstr("Seems like the object being serialized has been changed during serialization");
            var constructor = typeof(InvalidOperationException).GetConstructor(new[] { typeof(string) });

            if (constructor == null)
            {
                throw new MissingConstructorException(typeof(InvalidOperationException), typeof(string));
            }
            Il.Newobj(constructor);
            Il.Throw();
            Il.MarkLabel(bigEnoughLabel);
        }
        /// <summary>
        ///     Checks TypeCode and throws Exception if it is invalid
        /// </summary>
        public void CheckTypeCode()
        {
            LoadField(Context.Lengths);
            Il.Ldloc(TypeCode);     // stack: [lengths, typeCode]
            Il.Ldelem(typeof(int)); // stack: [lengths[typeCode]]
            var okLabel = Il.DefineLabel("ok");

            Il.Brtrue(okLabel); // if(lengths[typeCode] != 0) goto ok;
            Il.Ldstr("Unknown type code: ");
            Il.Ldloca(TypeCode);
            Il.Call(HackHelpers.GetMethodDefinition <int>(x => x.ToString()), typeof(int));
            Il.Call(HackHelpers.GetMethodDefinition <string>(s => s + "zzz"));
            var constructor = typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) });

            if (constructor == null)
            {
                throw new MissingConstructorException(typeof(DataCorruptedException), typeof(string));
            }
            Il.Newobj(constructor);
            Il.Throw();
            Il.MarkLabel(okLabel);
        }
        public void StoreObject(Type type)
        {
            if (Index == null)
            {
                return;
            }
            if (type.IsValueType)
            {
                throw new InvalidOperationException("A reference type expected");
            }
            // Store in array of all references
            LoadContext();                        // stack: [context]
            Il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects]
            var doneLabel = Il.DefineLabel("done");

            Il.Brfalse(doneLabel);                                                                           // if(context.objects == null) goto done; stack: []

            LoadContext();                                                                                   // stack: [context]
            Il.Ldfld(ReaderContext.ObjectsField);                                                            // stack: [context.objects]
            Il.Ldloc(Index);                                                                                 // stack: [context.objects, index]
            LoadResult(type);                                                                                // stack: [context.objects, index, result]
            Il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.Add(0, null))); // context.objects.Add(index, result)
            Il.MarkLabel(doneLabel);
        }
示例#8
0
 public void MarkLabelAndSurroundWithSP(GroboIL.Label label)
 {
     MarkHiddenSP();
     Il.MarkLabel(label);
     MarkHiddenSP();
 }