コード例 #1
0
 /// <summary>
 ///     Puts the specified type code at <c>result</c>[<c>index</c>]
 /// </summary>
 /// <param name="typeCode">Type code to put</param>
 public void WriteTypeCode(GroBufTypeCode typeCode)
 {
     Il.Ldc_I4(1);
     AssertLength();
     GoToCurrentLocation();    // stack: [&result[index]]
     Il.Ldc_I4((int)typeCode); // stack: [&result[index], typeCode]
     Il.Stind(typeof(byte));   // result[index] = typeCode
     IncreaseIndexBy1();       // index = index + 1
 }
コード例 #2
0
 private GroBufTypeCode GetTypeCodeForBool(GroBufTypeCode typeCode)
 {
     if (typeCode == GroBufTypeCode.Single)
     {
         return(GroBufTypeCode.Int32);
     }
     if (typeCode == GroBufTypeCode.Double)
     {
         return(GroBufTypeCode.Int64);
     }
     return(typeCode);
 }
コード例 #3
0
        private static void EmitReadPrimitiveValue(GroboIL il, GroBufTypeCode typeCode)
        {
            switch (typeCode)
            {
            case GroBufTypeCode.Int8:
                il.Ldind(typeof(sbyte));
                break;

            case GroBufTypeCode.UInt8:
            case GroBufTypeCode.Boolean:
                il.Ldind(typeof(byte));
                break;

            case GroBufTypeCode.Int16:
                il.Ldind(typeof(short));
                break;

            case GroBufTypeCode.UInt16:
                il.Ldind(typeof(ushort));
                break;

            case GroBufTypeCode.Int32:
                il.Ldind(typeof(int));
                break;

            case GroBufTypeCode.UInt32:
                il.Ldind(typeof(uint));
                break;

            case GroBufTypeCode.Int64:
            case GroBufTypeCode.DateTimeNew:
                il.Ldind(typeof(long));
                break;

            case GroBufTypeCode.UInt64:
                il.Ldind(typeof(ulong));
                break;

            case GroBufTypeCode.Single:
                il.Ldind(typeof(float));
                break;

            case GroBufTypeCode.Double:
                il.Ldind(typeof(double));
                break;

            default:
                throw new NotSupportedException("Type with type code '" + typeCode + "' is not supported");
            }
        }
コード例 #4
0
        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);
        }
コード例 #5
0
ファイル: GroBufTypeCodeMap.cs プロジェクト: skbkontur/GroBuf
 private static GroBufTypeCode[] BuildItemToArrayMap()
 {
     var result = new GroBufTypeCode[256];
     for (int i = 0; i < 256; ++i)
         result[i] = GroBufTypeCode.Array;
     result[(int)GroBufTypeCode.Int8] = GroBufTypeCode.Int8Array;
     result[(int)GroBufTypeCode.UInt8] = GroBufTypeCode.UInt8Array;
     result[(int)GroBufTypeCode.Int16] = GroBufTypeCode.Int16Array;
     result[(int)GroBufTypeCode.UInt16] = GroBufTypeCode.UInt16Array;
     result[(int)GroBufTypeCode.Int32] = GroBufTypeCode.Int32Array;
     result[(int)GroBufTypeCode.UInt32] = GroBufTypeCode.UInt32Array;
     result[(int)GroBufTypeCode.Int64] = GroBufTypeCode.Int64Array;
     result[(int)GroBufTypeCode.UInt64] = GroBufTypeCode.UInt64Array;
     result[(int)GroBufTypeCode.Single] = GroBufTypeCode.SingleArray;
     result[(int)GroBufTypeCode.Double] = GroBufTypeCode.DoubleArray;
     result[(int)GroBufTypeCode.Boolean] = GroBufTypeCode.BooleanArray;
     return result;
 }
コード例 #6
0
        private KeyValuePair <Delegate, IntPtr> BuildPrimitiveValueReader(ModuleBuilder module, GroBufTypeCode typeCode)
        {
            var method = new DynamicMethod("Read_" + Type.Name + "_from_" + typeCode + "_" + Guid.NewGuid(), typeof(void), new[] { typeof(IntPtr), Type.MakeByRefType() }, module, true);

            using (var il = new GroboIL(method))
            {
                var expectedTypeCode = GroBufTypeCodeMap.GetTypeCode(Type);

                il.Ldarg(1); // stack: [ref result]
                if (typeCode == GroBufTypeCode.Decimal)
                {
                    if (expectedTypeCode == GroBufTypeCode.Boolean)
                    {
                        il.Ldarg(0);            // stack: [ref result, &temp, address]
                        il.Ldind(typeof(long)); // stack: [ref result, &temp, (long)*address]
                        il.Ldarg(0);            // stack: [ref result, &temp + 8, address]
                        il.Ldc_I4(8);           // stack: [ref result, &temp + 8, address, 8]
                        il.Add();               // stack: [ref result, &temp + 8, address + 8]
                        il.Ldind(typeof(long)); // stack: [ref result, &temp + 8, (long)*(address + 8)]
                        il.Or();
                        il.Ldc_I4(0);           // stack: [ref result, value, 0]
                        il.Conv <long>();
                        il.Ceq();               // stack: [ref result, value == 0]
                        il.Ldc_I4(1);           // stack: [ref result, value == 0, 1]
                        il.Xor();               // stack: [ref result, value != 0]
                    }
                    else
                    {
                        var temp = il.DeclareLocal(typeof(decimal));
                        il.Ldloca(temp);        // stack: [ref result, &temp]
                        il.Ldarg(0);            // stack: [ref result, &temp, address]
                        il.Ldind(typeof(long)); // stack: [ref result, &temp, (long)*address]
                        il.Stind(typeof(long)); // *temp = *address;
                        il.Ldloca(temp);        // stack: [ref result, &temp]
                        il.Ldc_I4(8);           // stack: [ref result, &temp, 8]
                        il.Add();               // stack: [ref result, &temp + 8]
                        il.Ldarg(0);            // stack: [ref result, &temp + 8, address]
                        il.Ldc_I4(8);           // stack: [ref result, &temp + 8, address, 8]
                        il.Add();               // stack: [ref result, &temp + 8, address + 8]
                        il.Ldind(typeof(long)); // stack: [ref result, &temp + 8, (long)*(address + 8)]
                        il.Stind(typeof(long)); // *(temp + 8) = *(address + 8);

                        il.Ldloc(temp);         // stack: [ref result, ref temp]
                        switch (expectedTypeCode)
                        {
                        case GroBufTypeCode.Int8:
                            il.Call(decimalToInt8Method); // stack: [ref result, (sbyte)temp]
                            break;

                        case GroBufTypeCode.UInt8:
                            il.Call(decimalToUInt8Method); // stack: [ref result, (byte)temp]
                            break;

                        case GroBufTypeCode.Int16:
                            il.Call(decimalToInt16Method); // stack: [ref result, (short)temp]
                            break;

                        case GroBufTypeCode.UInt16:
                            il.Call(decimalToUInt16Method); // stack: [ref result, (ushort)temp]
                            break;

                        case GroBufTypeCode.Int32:
                            il.Call(decimalToInt32Method); // stack: [ref result, (int)temp]
                            break;

                        case GroBufTypeCode.UInt32:
                            il.Call(decimalToUInt32Method); // stack: [ref result, (uint)temp]
                            break;

                        case GroBufTypeCode.Int64:
                            il.Call(decimalToInt64Method); // stack: [ref result, (long)temp]
                            break;

                        case GroBufTypeCode.UInt64:
                            il.Call(decimalToUInt64Method); // stack: [ref result, (ulong)temp]
                            break;

                        case GroBufTypeCode.Single:
                            il.Call(decimalToSingleMethod); // stack: [ref result, (float)temp]
                            break;

                        case GroBufTypeCode.Double:
                            il.Call(decimalToDoubleMethod); // stack: [ref result, (double)temp]
                            break;

                        case GroBufTypeCode.Decimal:
                            break;

                        default:
                            throw new NotSupportedException("Type with type code '" + expectedTypeCode + "' is not supported");
                        }
                    }
                }
                else
                {
                    il.Ldarg(0);                                                                                // stack: [ref result, address]
                    EmitReadPrimitiveValue(il, Type == typeof(bool) ? GetTypeCodeForBool(typeCode) : typeCode); // stack: [ref result, value]
                    if (Type == typeof(bool))
                    {
                        il.Conv <long>();
                        il.Ldc_I4(0); // stack: [ref result, value, 0]
                        il.Conv <long>();
                        il.Ceq();     // stack: [ref result, value == 0]
                        il.Ldc_I4(1); // stack: [ref result, value == 0, 1]
                        il.Xor();     // stack: [ref result, value != 0]
                    }
                    else
                    {
                        EmitConvertValue(il, typeCode, expectedTypeCode);
                    }
                }
                switch (expectedTypeCode)
                {
                case GroBufTypeCode.Int8:
                case GroBufTypeCode.UInt8:
                case GroBufTypeCode.Boolean:
                    il.Stind(typeof(byte)); // result = value
                    break;

                case GroBufTypeCode.Int16:
                case GroBufTypeCode.UInt16:
                    il.Stind(typeof(short)); // result = value
                    break;

                case GroBufTypeCode.Int32:
                case GroBufTypeCode.UInt32:
                    il.Stind(typeof(int)); // result = value
                    break;

                case GroBufTypeCode.Int64:
                case GroBufTypeCode.UInt64:
                    il.Stind(typeof(long)); // result = value
                    break;

                case GroBufTypeCode.Single:
                    il.Stind(typeof(float)); // result = value
                    break;

                case GroBufTypeCode.Double:
                    il.Stind(typeof(double)); // result = value
                    break;

                case GroBufTypeCode.Decimal:
                    il.Stobj(typeof(decimal)); // result = value
                    break;

                default:
                    throw new NotSupportedException("Type with type code '" + expectedTypeCode + "' is not supported");
                }
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(PrimitiveValueReaderDelegate <>).MakeGenericType(Type));

            return(new KeyValuePair <Delegate, IntPtr>(@delegate, GroBufHelpers.ExtractDynamicMethodPointer(method)));
        }
コード例 #7
0
        private static void EmitConvertValue(GroboIL il, GroBufTypeCode typeCode, GroBufTypeCode expectedTypeCode)
        {
            if (expectedTypeCode == typeCode)
            {
                return;
            }
            switch (expectedTypeCode)
            {
            case GroBufTypeCode.Int8:
                il.Conv <sbyte>();
                break;

            case GroBufTypeCode.UInt8:
            case GroBufTypeCode.Boolean:
                il.Conv <byte>();
                break;

            case GroBufTypeCode.Int16:
                il.Conv <short>();
                break;

            case GroBufTypeCode.UInt16:
                il.Conv <ushort>();
                break;

            case GroBufTypeCode.Int32:
                if (typeCode == GroBufTypeCode.Int64 || typeCode == GroBufTypeCode.UInt64 || typeCode == GroBufTypeCode.Double || typeCode == GroBufTypeCode.Single || typeCode == GroBufTypeCode.DateTimeNew)
                {
                    il.Conv <int>();
                }
                break;

            case GroBufTypeCode.UInt32:
                if (typeCode == GroBufTypeCode.Int64 || typeCode == GroBufTypeCode.UInt64 || typeCode == GroBufTypeCode.Double || typeCode == GroBufTypeCode.Single || typeCode == GroBufTypeCode.DateTimeNew)
                {
                    il.Conv <uint>();
                }
                break;

            case GroBufTypeCode.Int64:
                if (typeCode != GroBufTypeCode.UInt64)
                {
                    if (typeCode == GroBufTypeCode.UInt8 || typeCode == GroBufTypeCode.UInt16 || typeCode == GroBufTypeCode.UInt32)
                    {
                        il.Conv <ulong>();
                    }
                    else
                    {
                        il.Conv <long>();
                    }
                }
                break;

            case GroBufTypeCode.UInt64:
                if (typeCode != GroBufTypeCode.Int64 && typeCode != GroBufTypeCode.DateTimeNew)
                {
                    if (typeCode == GroBufTypeCode.Int8 || typeCode == GroBufTypeCode.Int16 || typeCode == GroBufTypeCode.Int32)
                    {
                        il.Conv <long>();
                    }
                    else
                    {
                        il.Conv <ulong>();
                    }
                }
                break;

            case GroBufTypeCode.Single:
                if (typeCode == GroBufTypeCode.UInt64 || typeCode == GroBufTypeCode.UInt32)
                {
                    il.Conv_R_Un();
                }
                il.Conv <float>();
                break;

            case GroBufTypeCode.Double:
                if (typeCode == GroBufTypeCode.UInt64 || typeCode == GroBufTypeCode.UInt32)
                {
                    il.Conv_R_Un();
                }
                il.Conv <double>();
                break;

            case GroBufTypeCode.Decimal:
                switch (typeCode)
                {
                case GroBufTypeCode.Boolean:
                case GroBufTypeCode.Int8:
                case GroBufTypeCode.Int16:
                case GroBufTypeCode.Int32:
                case GroBufTypeCode.UInt8:
                case GroBufTypeCode.UInt16:
                    il.Newobj(decimalByIntConstructor);
                    break;

                case GroBufTypeCode.UInt32:
                    il.Newobj(decimalByUIntConstructor);
                    break;

                case GroBufTypeCode.Int64:
                case GroBufTypeCode.DateTimeNew:
                    il.Newobj(decimalByLongConstructor);
                    break;

                case GroBufTypeCode.UInt64:
                    il.Newobj(decimalByULongConstructor);
                    break;

                case GroBufTypeCode.Single:
                    il.Call(decimalByFloatMethod);
                    break;

                case GroBufTypeCode.Double:
                    il.Call(decimalByDoubleMethod);
                    break;

                default:
                    throw new NotSupportedException("Type with type code '" + typeCode + "' is not supported");
                }
                break;

            default:
                throw new NotSupportedException("Type with type code '" + expectedTypeCode + "' is not supported");
            }
        }