private bool TryGenKnownType(NodeTree node, bool requireBoxing, out object prototype) { // Try Primitive Type Type type; if (PrimitiveTypeDic.TryGetValue(node.Type, out type)) { // reader.Read<T>() il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, PrimitiveReaderDic[type]); if (requireBoxing) { il.Emit(OpCodes.Box, type); } prototype = Activator.CreateInstance(type); return(true); } // Try String else if (node.Type == "string") { GenReadString(); prototype = ""; return(true); } else { prototype = null; return(false); } }
private bool TryGenKnownType(NodeTree node, bool requireUnboxing, Action <ILGenerator> loader) { // Try Primitive Type Type type; if (PrimitiveTypeDic.TryGetValue(node.Type, out type)) { // writer.Write<T>((type)value) il.Emit(OpCodes.Ldarg_0); loader(il); if (requireUnboxing) { il.Emit(OpCodes.Unbox_Any, type); } il.Emit(OpCodes.Call, PrimitiveWriterDic[type]); return(true); } // Try String else if (node.Type == "string") { il.Emit(OpCodes.Ldarg_0); loader(il); if (requireUnboxing) { il.Emit(OpCodes.Castclass, typeof(string)); } il.Emit(OpCodes.Call, WriteAlignedString); return(true); } else { return(false); } }
private void GenWriteDic(NodeTree node, Action <ILGenerator> loader) { Type keytype, valuetype; NodeTree pair = node.Children[0].Children[1]; // Determine Key/Value Type if (PrimitiveTypeDic.TryGetValue(pair.Children[0].Type, out keytype)) { } else if (pair.Children[0].Type == "string") { keytype = typeof(string); } else { keytype = typeof(object); } if (PrimitiveTypeDic.TryGetValue(pair.Children[1].Type, out valuetype)) { } else if (pair.Children[1].Type == "string") { valuetype = typeof(string); } else { valuetype = typeof(object); } // Load Dictionary<keytype, valuetype> Type dictype = typeof(DynamicAssetDictionary <,>).MakeGenericType(keytype, valuetype); MethodInfo getter = dictype.GetMethod("Item", new Type[] { keytype, valuetype }); MethodInfo Count = dictype.GetProperty("Count").GetMethod; int dic = locman.AllocLocal(dictype); loader(il); il.Emit(OpCodes.Castclass, dictype); il.EmitStloc(dic); // Write Count il.Emit(OpCodes.Ldarg_0); il.EmitLdloc(dic); il.Emit(OpCodes.Callvirt, Count); il.Emit(OpCodes.Call, WriteInt); // Write KeyValuePairs // foreach(var kv in dic) Type enumtype = typeof(Dictionary <,> .Enumerator).MakeGenericType(keytype, valuetype); int enumerator = locman.AllocLocal(enumtype); Type kvtype = typeof(KeyValuePair <,>).MakeGenericType(keytype, valuetype); int kv = locman.AllocLocal(kvtype); MethodInfo getenumerator = dictype.GetMethod("GetEnumerator"); MethodInfo movenext = enumtype.GetMethod("MoveNext"); MethodInfo getcurrent = enumtype.GetProperty("Current").GetMethod; MethodInfo getkey = kvtype.GetProperty("Key").GetMethod; MethodInfo getvalue = kvtype.GetProperty("Value").GetMethod; var l_foreachstart = il.DefineLabel(); var l_movenext = il.DefineLabel(); // Get Enumerator loader(il); il.Emit(OpCodes.Castclass, dictype); il.Emit(OpCodes.Callvirt, getenumerator); il.EmitStloc(enumerator); il.BeginExceptionBlock(); il.Emit(OpCodes.Br, l_movenext); // Main il.MarkLabel(l_foreachstart); il.EmitLdloca(enumerator); il.Emit(OpCodes.Call, getcurrent); il.EmitStloc(kv); // Key GenWriteUnknownType(pair.Children[0], requireUnboxing: false, loader: (cil) => { cil.EmitLdloca(kv); cil.Emit(OpCodes.Call, getkey); }); // Value GenWriteUnknownType(pair.Children[1], requireUnboxing: false, loader: (cil) => { cil.EmitLdloca(kv); cil.Emit(OpCodes.Call, getvalue); }); // MoveNext il.MarkLabel(l_movenext); il.EmitLdloca(enumerator); il.Emit(OpCodes.Call, movenext); il.Emit(OpCodes.Brtrue, l_foreachstart); // Finally(Dispose) il.BeginFinallyBlock(); il.EmitLdloca(enumerator); il.Emit(OpCodes.Constrained, enumtype); il.Emit(OpCodes.Callvirt, Dispose); il.EndExceptionBlock(); if (node.Children[0].IsAligned) { GenAlign(); } locman.ReleaseLocal(enumtype); locman.ReleaseLocal(kvtype); locman.ReleaseLocal(dictype); }
private void GenWriteArray(NodeTree node, Action <ILGenerator> loader) { NodeTree elem = node.Children[1]; // Try Primitive Type Type elemtype; if (PrimitiveTypeDic.TryGetValue(elem.Type, out elemtype)) { // reader.ReadValueArray<T>() var writefunc = WriteValueArray.MakeGenericMethod(elemtype); il.Emit(OpCodes.Ldarg_0); loader(il); il.Emit(OpCodes.Castclass, elemtype.MakeArrayType()); il.Emit(OpCodes.Call, writefunc); } // Try String else if (elem.Type == "string") { Type arytype = typeof(string).MakeArrayType(); int ary = locman.AllocLocal(arytype); loader(il); il.Emit(OpCodes.Castclass, arytype); il.EmitStloc(ary); // Write length // writer.WriteInt(ary.Length); il.Emit(OpCodes.Ldarg_0); il.EmitLdloc(ary); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); il.Emit(OpCodes.Call, WriteInt); int i = locman.AllocLocal(typeof(int)); // for(int i = 0; i < ary.Length; i++) il.EmitFor(i, cond: (cil) => { il.EmitLdloc(ary); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); il.EmitLdloc(i); return(OpCodes.Ble_S); }, block: (cil) => { // w.WriteAlignedString(ary[i]); il.Emit(OpCodes.Ldarg_0); il.EmitLdloc(ary); il.EmitLdloc(i); il.Emit(OpCodes.Ldelem_Ref); il.Emit(OpCodes.Call, WriteAlignedString); } ); locman.ReleaseLocal(typeof(int)); locman.ReleaseLocal(arytype); } else if (elem.Type == "map") { throw new NotImplementedException("Array of map is not supported"); } // Object else { // Load DynamicAssetArray.elems Type arytype = typeof(IDynamicAssetBase).MakeArrayType(); int ary = locman.AllocLocal(arytype); loader(il); il.Emit(OpCodes.Castclass, typeof(DynamicAssetArray)); il.Emit(OpCodes.Ldfld, DynamicAssetArrayelems); il.EmitStloc(ary); // Write length // writer.WriteInt(ary.Length); il.Emit(OpCodes.Ldarg_0); il.EmitLdloc(ary); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); il.Emit(OpCodes.Call, WriteInt); // for(int i = 0; i < ary.Length; i++) int i = locman.AllocLocal(typeof(int)); il.EmitFor(i, (cil) => { il.EmitLdloc(ary); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); il.EmitLdloc(i); return(OpCodes.Ble); }, (cil) => { // GenWriteUnknownType(ary[i]); GenWriteUnknownType(elem, requireUnboxing: false, loader: (ccil) => { ccil.EmitLdloc(ary); ccil.EmitLdloc(i); ccil.Emit(OpCodes.Ldelem_Ref); }); } ); locman.ReleaseLocal(typeof(int)); locman.ReleaseLocal(arytype); } if (node.IsAligned) { GenAlign(); } }
private object GenReadDic(NodeTree node) { Type keytype, valuetype; NodeTree pair = node.Children[0].Children[1]; // Determine Key/Value Type if (PrimitiveTypeDic.TryGetValue(pair.Children[0].Type, out keytype)) { } else if (pair.Children[0].Type == "string") { keytype = typeof(string); } else { keytype = typeof(object); } if (PrimitiveTypeDic.TryGetValue(pair.Children[1].Type, out valuetype)) { } else if (pair.Children[1].Type == "string") { valuetype = typeof(string); } else { valuetype = typeof(object); } string keyFQN = (keytype == typeof(object)) ? protoman.GetFQN(pair.Children[0].Type) : keytype.GetCSharpName(); string valueFQN = (valuetype == typeof(object)) ? protoman.GetFQN(pair.Children[1].Type) : valuetype.GetCSharpName(); // int cnt = reader.ReadInt(); int cnt = locman.AllocLocal(typeof(int)); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, ReadInt); il.EmitStloc(cnt); // Create Dictionary<keytype, valuetype> Type dictype = typeof(DynamicAssetDictionary <,>).MakeGenericType(keytype, valuetype); MethodInfo add = dictype.GetMethod("Add", new Type[] { keytype, valuetype }); il.EmitLdloc(cnt); il.Emit(OpCodes.Ldstr, keyFQN); il.Emit(OpCodes.Ldstr, valueFQN); il.Emit(OpCodes.Newobj, dictype.GetConstructor(BindingFlags.InvokeMethod | BindingFlags.Instance | #if DEBUG BindingFlags.Public #else BindingFlags.NonPublic #endif , null, new Type[] { typeof(int), typeof(string), typeof(string) }, null)); // Read KeyValuePairs // for(int i = 0; i < cnt; i++) int i = locman.AllocLocal(typeof(int)); il.EmitFor(i, (cil) => { il.EmitLdloc(i); il.EmitLdloc(cnt); return(OpCodes.Bge); }, (cil) => { // dic.Add( il.Emit(OpCodes.Dup); // Read Key GenReadUnknownType(pair.Children[0], requireBoxing: false); // Read Value GenReadUnknownType(pair.Children[1], requireBoxing: false); // Add KeyValuePair il.Emit(OpCodes.Callvirt, add); } ); locman.ReleaseLocal(typeof(int)); locman.ReleaseLocal(typeof(int)); if (node.Children[0].IsAligned) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4_4); il.Emit(OpCodes.Call, AlignReader); } // Make prototype return(Activator.CreateInstance(dictype, BindingFlags.Instance | #if DEBUG BindingFlags.Public #else BindingFlags.NonPublic #endif , null, new object[] { 0, keyFQN, valueFQN }, null)); }
private object GenReadArray(NodeTree node) { NodeTree elem = node.Children[1]; object proto; // Try Primitive Type Type elemtype; if (PrimitiveTypeDic.TryGetValue(elem.Type, out elemtype)) { // reader.ReadValueArray<T>() var readfunc = ReadValueArray.MakeGenericMethod(elemtype); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, readfunc); proto = Activator.CreateInstance(elemtype.MakeArrayType(), new object[] { 0 }); } // Try String else if (elem.Type == "string") { // var ary = new string[reader.ReadInt()]; il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, ReadInt); il.Emit(OpCodes.Newarr, typeof(string)); int i = locman.AllocLocal(typeof(int)); // for(int i = 0; i < ary.Length; i++) il.EmitFor(i, cond: (cil) => { il.Emit(OpCodes.Dup); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); il.EmitLdloc(i); return(OpCodes.Ble_S); }, block: (cil) => { // ary[i] = r.ReadAlignedString(); il.Emit(OpCodes.Dup); il.EmitLdloc(i); GenReadString(); il.Emit(OpCodes.Stelem, typeof(string)); } ); locman.ReleaseLocal(typeof(int)); proto = new string[0]; } else if (elem.Type == "map") { throw new NotImplementedException("Array of map is not supported"); } // Object else { string FQN = protoman.GetFQN(elem.Type); // vec = new DynamicAssetArray(reader.ReadInt(), protoname) il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, ReadInt); il.Emit(OpCodes.Ldstr, FQN); il.Emit(OpCodes.Newobj, DynamicAssetArrayCtor); // ary = vec.elems; il.Emit(OpCodes.Dup); il.Emit(OpCodes.Ldfld, DynamicAssetArrayelems); // for(int i = 0; i < ary.Length; i++) int i = locman.AllocLocal(typeof(int)); il.EmitFor(i, (cil) => { il.Emit(OpCodes.Dup); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); il.EmitLdloc(i); return(OpCodes.Ble); }, (cil) => { // ary[i] = new DynamicAsset(GenReadUnkownType()); il.Emit(OpCodes.Dup); il.EmitLdloc(i); // Fallback GenReadUnknownType(elem, requireBoxing: false); il.Emit(OpCodes.Stelem_Ref); } ); il.Emit(OpCodes.Pop); proto = new DynamicAssetArray(0, FQN); } if (node.IsAligned) { GenAlign(); } return(proto); }