private object GenReadUnknownType(NodeTree node, bool requireBoxing) { object proto; // Try Known Type if (TryGenKnownType(node, requireBoxing, out proto)) { } 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 readfunc = ReadValueArray.MakeGenericMethod(typeof(byte)); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, readfunc); proto = new byte[0]; } // Map else if (node.Type == "map") { proto = GenReadDic(node); } // Array else if (node.HasChildren && node.Children[0].Type == "Array") { proto = GenReadArray(node.Children[0]); } else { proto = GenReadObject(node); } if (node.IsAligned) { GenAlign(); } return(proto); }
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); }