private void GenWriteUnknownType(NodeTree node, bool requireUnboxing, Action <ILGenerator> loader) { // Try Known Type if (TryGenKnownType(node, requireUnboxing, loader)) { } else if (node.Type == "TypelessData") { // Assert node.Children[0].Type == "int" && node.Children[0].Name == "size" // Assert node.Children[1].Type == "UInt8" && node.Children[1].Name == "data" var writefunc = WriteValueArray.MakeGenericMethod(typeof(byte)); il.Emit(OpCodes.Ldarg_0); loader(il); il.Emit(OpCodes.Castclass, typeof(byte).MakeArrayType()); il.Emit(OpCodes.Call, writefunc); } // Map else if (node.Type == "map") { GenWriteDic(node, loader); } // Array else if (node.HasChildren && node.Children[0].Type == "Array") { GenWriteArray(node.Children[0], loader); } else { loader(il); GenWriteObject(node); } if (node.IsAligned) { GenAlign(); } }
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(); } }