Пример #1
0
            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);
            }