private void generateUnpackMethod(ClassDescriptor desc, MethodBuilder builder) { ILGenerator il = builder.GetILGenerator(); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Castclass, desc.cls); LocalBuilder obj = il.DeclareLocal(desc.cls); il.Emit(OpCodes.Stloc_0, obj); il.Emit(OpCodes.Ldc_I4, ObjectHeader.Sizeof); LocalBuilder offs = il.DeclareLocal(typeof(int)); il.Emit(OpCodes.Stloc_1, offs); LocalBuilder val = il.DeclareLocal(typeof(object)); ClassDescriptor.FieldDescriptor[] flds = desc.allFields; for (int i = 0, n = flds.Length; i < n; i++) { ClassDescriptor.FieldDescriptor fd = flds[i]; FieldInfo f = fd.field; if (f == null) { switch (fd.type) { case ClassDescriptor.FieldType.tpByte: case ClassDescriptor.FieldType.tpSByte: case ClassDescriptor.FieldType.tpBoolean: il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpShort: case ClassDescriptor.FieldType.tpUShort: case ClassDescriptor.FieldType.tpChar: il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_2); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpEnum: case ClassDescriptor.FieldType.tpInt: case ClassDescriptor.FieldType.tpUInt: case ClassDescriptor.FieldType.tpFloat: il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_4); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpLong: case ClassDescriptor.FieldType.tpULong: case ClassDescriptor.FieldType.tpDate: case ClassDescriptor.FieldType.tpDouble: il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_8); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpDecimal: case ClassDescriptor.FieldType.tpGuid: il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4, 16); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; default: il.Emit(OpCodes.Ldarg_1); // storage il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldnull); // fd il.Emit(OpCodes.Ldc_I4, (int)fd.type); il.Emit(OpCodes.Call, skipField); il.Emit(OpCodes.Stloc_1, offs); // offs continue; } } else { switch (fd.type) { case ClassDescriptor.FieldType.tpByte: il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldelem_U1); il.Emit(OpCodes.Stfld, f); il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpSByte: il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldelem_U1); il.Emit(OpCodes.Conv_I1); il.Emit(OpCodes.Stfld, f); il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpBoolean: il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldelem_U1); il.Emit(OpCodes.Stfld, f); il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpShort: il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Call, unpackI2); il.Emit(OpCodes.Stfld, f); il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_2); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpUShort: case ClassDescriptor.FieldType.tpChar: il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Call, unpackI2); il.Emit(OpCodes.Conv_U2); il.Emit(OpCodes.Stfld, f); il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_2); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpEnum: case ClassDescriptor.FieldType.tpInt: case ClassDescriptor.FieldType.tpUInt: il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Call, unpackI4); il.Emit(OpCodes.Stfld, f); il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_4); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpLong: case ClassDescriptor.FieldType.tpULong: il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Call, unpackI8); il.Emit(OpCodes.Stfld, f); il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_8); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpFloat: il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Call, unpackF4); il.Emit(OpCodes.Stfld, f); il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_4); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpDouble: il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Call, unpackF8); il.Emit(OpCodes.Stfld, f); il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_8); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpDecimal: il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Call, unpackDecimal); il.Emit(OpCodes.Stfld, f); il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4, 16); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpGuid: il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Call, unpackGuid); il.Emit(OpCodes.Stfld, f); il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4, 16); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpDate: il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Call, unpackDate); il.Emit(OpCodes.Stfld, f); il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldc_I4_8); il.Emit(OpCodes.Add); il.Emit(OpCodes.Stloc_1, offs); continue; case ClassDescriptor.FieldType.tpString: il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldflda, f); il.Emit(OpCodes.Ldarg_S, 5); // encoding il.Emit(OpCodes.Call, unpackString); il.Emit(OpCodes.Stloc_1, offs); continue; default: il.Emit(OpCodes.Ldarg_1); // storage il.Emit(OpCodes.Ldarg_3); // body il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldarg_S, 4); // recursiveLoading il.Emit(OpCodes.Ldloca, val); il.Emit(OpCodes.Ldnull); // fd il.Emit(OpCodes.Ldc_I4, (int)fd.type); il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Call, unpackField); il.Emit(OpCodes.Stloc_1, offs); // offs il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldloc, val); il.Emit(OpCodes.Castclass, f.FieldType); il.Emit(OpCodes.Stfld, f); continue; } } } il.Emit(OpCodes.Ret); }
private void generatePackMethod(ClassDescriptor desc, MethodBuilder builder) { ILGenerator il = builder.GetILGenerator(); il.Emit(OpCodes.Ldarg_2); // obj il.Emit(OpCodes.Castclass, desc.cls); obj = il.DeclareLocal(desc.cls); il.Emit(OpCodes.Stloc_0, obj); il.Emit(OpCodes.Ldc_I4, ObjectHeader.Sizeof); offs = il.DeclareLocal(typeof(int)); il.Emit(OpCodes.Stloc_1, offs); ClassDescriptor.FieldDescriptor[] flds = desc.allFields; for (int i = 0, n = flds.Length; i < n; i++) { ClassDescriptor.FieldDescriptor fd = flds[i]; FieldInfo f = fd.field; switch (fd.type) { case ClassDescriptor.FieldType.tpByte: case ClassDescriptor.FieldType.tpSByte: generatePackField(il, f, packI1); continue; case ClassDescriptor.FieldType.tpBoolean: generatePackField(il, f, packBool); continue; case ClassDescriptor.FieldType.tpShort: case ClassDescriptor.FieldType.tpUShort: case ClassDescriptor.FieldType.tpChar: generatePackField(il, f, packI2); continue; case ClassDescriptor.FieldType.tpEnum: case ClassDescriptor.FieldType.tpInt: case ClassDescriptor.FieldType.tpUInt: generatePackField(il, f, packI4); continue; case ClassDescriptor.FieldType.tpLong: case ClassDescriptor.FieldType.tpULong: generatePackField(il, f, packI8); continue; case ClassDescriptor.FieldType.tpFloat: generatePackField(il, f, packF4); continue; case ClassDescriptor.FieldType.tpDouble: generatePackField(il, f, packF8); continue; case ClassDescriptor.FieldType.tpDecimal: generatePackField(il, f, packDecimal); continue; case ClassDescriptor.FieldType.tpGuid: generatePackField(il, f, packGuid); continue; case ClassDescriptor.FieldType.tpDate: generatePackField(il, f, packDate); continue; case ClassDescriptor.FieldType.tpString: generatePackField(il, f, packString); continue; default: il.Emit(OpCodes.Ldarg_1); // storage il.Emit(OpCodes.Ldarg_3); // buf il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ldloc_0, obj); il.Emit(OpCodes.Ldfld, f); il.Emit(OpCodes.Ldnull); // fd il.Emit(OpCodes.Ldc_I4, (int)fd.type); il.Emit(OpCodes.Call, packField); il.Emit(OpCodes.Stloc_1, offs); continue; } } il.Emit(OpCodes.Ldloc_1, offs); il.Emit(OpCodes.Ret); }
internal int exportObject(ClassDescriptor desc, byte[] body, int offs, int indent) { ClassDescriptor.FieldDescriptor[] all = desc.allFields; for (int i = 0, n = all.Length; i < n; i++) { ClassDescriptor.FieldDescriptor fd = all[i]; FieldInfo f = fd.field; indentation(indent); String fieldName = exportIdentifier(fd.fieldName); writer.Write("<" + fieldName + ">"); switch (fd.type) { case ClassDescriptor.FieldType.tpBoolean: writer.Write(body[offs++] != 0?"1":"0"); break; case ClassDescriptor.FieldType.tpByte: writer.Write(System.Convert.ToString((byte)body[offs++])); break; case ClassDescriptor.FieldType.tpSByte: writer.Write(System.Convert.ToString((sbyte)body[offs++])); break; case ClassDescriptor.FieldType.tpChar: writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs))); offs += 2; break; case ClassDescriptor.FieldType.tpShort: writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs))); offs += 2; break; case ClassDescriptor.FieldType.tpUShort: writer.Write(System.Convert.ToString((ushort)Bytes.unpack2(body, offs))); offs += 2; break; case ClassDescriptor.FieldType.tpInt: writer.Write(System.Convert.ToString(Bytes.unpack4(body, offs))); offs += 4; break; case ClassDescriptor.FieldType.tpEnum: writer.Write(Enum.ToObject(f.FieldType, Bytes.unpack4(body, offs))); offs += 4; break; case ClassDescriptor.FieldType.tpUInt: writer.Write(System.Convert.ToString((uint)Bytes.unpack4(body, offs))); offs += 4; break; case ClassDescriptor.FieldType.tpLong: writer.Write(System.Convert.ToString(Bytes.unpack8(body, offs))); offs += 8; break; case ClassDescriptor.FieldType.tpULong: writer.Write(System.Convert.ToString((ulong)Bytes.unpack8(body, offs))); offs += 8; break; case ClassDescriptor.FieldType.tpFloat: writer.Write(System.Convert.ToString(Bytes.unpackF4(body, offs))); offs += 4; break; case ClassDescriptor.FieldType.tpDouble: writer.Write(System.Convert.ToString(Bytes.unpackF8(body, offs))); offs += 8; break; case ClassDescriptor.FieldType.tpGuid: writer.Write("\"" + Bytes.unpackGuid(body, offs) + "\""); offs += 16; break; case ClassDescriptor.FieldType.tpDecimal: writer.Write("\"" + Bytes.unpackDecimal(body, offs) + "\""); offs += 16; break; case ClassDescriptor.FieldType.tpString: offs = exportString(body, offs); break; case ClassDescriptor.FieldType.tpDate: { long msec = Bytes.unpack8(body, offs); offs += 8; if (msec >= 0) { writer.Write("\"" + new System.DateTime(msec) + "\""); } else { writer.Write("null"); } break; } case ClassDescriptor.FieldType.tpObject: exportRef(Bytes.unpack4(body, offs)); offs += 4; break; case ClassDescriptor.FieldType.tpValue: writer.Write('\n'); offs = exportObject(fd.valueDesc, body, offs, indent + 1); indentation(indent); break; #if SUPPORT_RAW_TYPE case ClassDescriptor.FieldType.tpRaw: #endif case ClassDescriptor.FieldType.tpArrayOfByte: case ClassDescriptor.FieldType.tpArrayOfSByte: offs = exportBinary(body, offs); break; case ClassDescriptor.FieldType.tpArrayOfBoolean: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (body[offs++] != 0?"1":"0") + "</element>\n"); } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfChar: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (Bytes.unpack2(body, offs) & 0xFFFF) + "</element>\n"); offs += 2; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfShort: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpack2(body, offs) + "</element>\n"); offs += 2; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfUShort: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (ushort)Bytes.unpack2(body, offs) + "</element>\n"); offs += 2; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfInt: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpack4(body, offs) + "</element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfEnum: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { Type elemType = f.FieldType.GetElementType(); writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Enum.ToObject(elemType, Bytes.unpack4(body, offs)) + "</element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfUInt: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (uint)Bytes.unpack4(body, offs) + "</element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfLong: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpack8(body, offs) + "</element>\n"); offs += 8; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfULong: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + (ulong)Bytes.unpack8(body, offs) + "</element>\n"); offs += 8; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfFloat: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpackF4(body, offs) + "</element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfDouble: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>" + Bytes.unpackF8(body, offs) + "</element>\n"); offs += 8; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfDate: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>\"" + Bytes.unpackDate(body, offs) + "\"</element>\n"); offs += 8; } } break; } case ClassDescriptor.FieldType.tpArrayOfGuid: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { writer.Write("<element>\"" + Bytes.unpackGuid(body, offs) + "\"</element>\n"); offs += 16; } } break; } case ClassDescriptor.FieldType.tpArrayOfDecimal: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { writer.Write("<element>\"" + Bytes.unpackDecimal(body, offs) + "\"</element>\n"); offs += 16; } } break; } case ClassDescriptor.FieldType.tpArrayOfString: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>"); offs = exportString(body, offs); writer.Write("</element>\n"); } indentation(indent); } break; } case ClassDescriptor.FieldType.tpLink: case ClassDescriptor.FieldType.tpArrayOfObject: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); int oid = Bytes.unpack4(body, offs); if (oid != 0 && (exportedBitmap[oid >> 5] & (1 << (oid & 31))) == 0) { markedBitmap[oid >> 5] |= 1 << (oid & 31); } writer.Write("<element><ref id=\"" + oid + "\"/></element>\n"); offs += 4; } indentation(indent); } break; } case ClassDescriptor.FieldType.tpArrayOfValue: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>\n"); offs = exportObject(fd.valueDesc, body, offs, indent + 2); indentation(indent + 1); writer.Write("</element>\n"); } indentation(indent); } break; } #if SUPPORT_RAW_TYPE case ClassDescriptor.FieldType.tpArrayOfRaw: { int len = Bytes.unpack4(body, offs); offs += 4; if (len < 0) { writer.Write("null"); } else { writer.Write('\n'); while (--len >= 0) { indentation(indent + 1); writer.Write("<element>"); offs = exportBinary(body, offs); writer.Write("</element>\n"); } indentation(indent); } break; } #endif } writer.Write("</" + fieldName + ">\n"); } return(offs); }