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 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); }