/// <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 }
private GroBufTypeCode GetTypeCodeForBool(GroBufTypeCode typeCode) { if (typeCode == GroBufTypeCode.Single) { return(GroBufTypeCode.Int32); } if (typeCode == GroBufTypeCode.Double) { return(GroBufTypeCode.Int64); } return(typeCode); }
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"); } }
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); }
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; }
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))); }
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"); } }