Back to index

lightning-sunbird  0.9+nobinonly
typeinfo.cs
Go to the documentation of this file.
00001 using System;
00002 using System.Runtime.InteropServices;
00003 using Mozilla.XPCOM;
00004 
00005 namespace Mozilla.XPCOM {
00006 
00007 /* This doesn't need to be public, but making it 'internal' causes stress with
00008  * TypeDescriptor.op_Implicit(XPTType). */
00009 [StructLayout(LayoutKind.Sequential)]
00010 public struct XPTType
00011 {
00012     public const byte FlagMask = 0xE0;
00013     public const byte TagMask = 0x1F;
00014     public byte   prefix;
00015     public byte   arg1;
00016     public byte   arg2;
00017     public byte   padding;
00018     public UInt16 arg3;
00019 
00020     static public implicit operator XPTType(TypeInfo.TypeDescriptor td)
00021     {
00022         XPTType t = new XPTType();
00023         t.prefix = (byte) ((byte)td.flags | (byte)td.tag);
00024         t.arg1 = td.arg1;
00025         t.arg2 = td.arg2;
00026         t.arg3 = td.arg3;
00027         return t;
00028     }
00029 }
00030 
00031 [StructLayout(LayoutKind.Sequential)]
00032 struct XPTParamDescriptor
00033 {
00034     public byte    param_flags;
00035     public byte    padding1;
00036     public XPTType type;
00037 }
00038 
00039 [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
00040 struct XPTMethodDescriptor
00041 {
00042     public String name;
00043     public IntPtr args; /* XPTParamDescriptor */
00044     public IntPtr result; /* XPTParamDescriptor */
00045     public byte   flags;
00046     public byte   numArgs;
00047 }
00048 
00049 public class TypeInfo
00050 {
00051     [Flags]
00052     public enum TypeFlags : byte
00053     {
00054         Pointer = 0x80, UniquePointer = 0x40, Reference = 0x20
00055     }
00056     
00057     public enum TypeTag : byte
00058     {
00059         Int8 = 0, Int16 = 1, Int32 = 2, Int64 = 3,
00060         UInt8 = 4, UInt16 = 5, UInt32 = 6, UInt64 = 7,
00061         Float = 8, Double = 9, Bool = 10, Char = 11,
00062         WChar = 12, Void = 13, NSIdPtr = 14, AString = 15,
00063         String = 16, WString = 17, Interface = 18, InterfaceIs = 19,
00064         Array = 20, StringSizeIs = 21, WStringSizeIs = 22, UTF8String = 23,
00065         CString = 24, AString_dup = 25
00066     }
00067 
00068     public struct TypeDescriptor
00069     {
00070         public TypeFlags flags;
00071         public TypeTag   tag;
00072         public byte      arg1;
00073         public byte      arg2;
00074         public UInt16    arg3;
00075         
00076         public override string ToString()
00077         {
00078             string res = String.Empty;
00079             if ((Int32)flags != 0)
00080                 res = "[" + flags.ToString() + "]";
00081             res += tag.ToString();
00082             return res;
00083         }
00084 
00085         public bool IsScalar()
00086         {
00087             if (tag <= TypeTag.WChar ||
00088                 tag == TypeTag.String || tag == TypeTag.WString) {
00089                 return true;
00090             }
00091             return false;
00092         }
00093 
00094         static public implicit operator TypeDescriptor(XPTType t)
00095         {
00096             TypeDescriptor td = new TypeInfo.TypeDescriptor();
00097             td.flags = (TypeFlags)(t.prefix & XPTType.FlagMask);
00098             td.tag = (TypeTag)(t.prefix & XPTType.TagMask);
00099             td.arg1 = t.arg1;
00100             td.arg2 = t.arg2;
00101             td.arg3 = t.arg3;
00102             return td;
00103         }
00104 
00105         public Type AsCLRType()
00106         {
00107             switch (tag) {
00108             case TypeTag.Int8:
00109                 return typeof(sbyte);
00110             case TypeTag.Int16:
00111                 return typeof(Int16);
00112             case TypeTag.Int32:
00113                 return typeof(Int32);
00114             case TypeTag.Int64:
00115                 return typeof(Int64);
00116 
00117             case TypeTag.UInt8:
00118                 return typeof(byte);
00119             case TypeTag.UInt16:
00120                 return typeof(UInt16);
00121             case TypeTag.UInt32:
00122                 return typeof(UInt32);
00123             case TypeTag.UInt64:
00124                 return typeof(UInt64);
00125 
00126             case TypeTag.Float:
00127                 return typeof(Single);
00128             case TypeTag.Double:
00129                 return typeof(Double);
00130             
00131             case TypeTag.Bool:
00132                 return typeof(bool);
00133 
00134             case TypeTag.String:
00135                 return typeof(string);
00136             case TypeTag.WString:
00137                 return typeof(string);
00138 
00139             case TypeTag.Interface:
00140                 return typeof(object);
00141             case TypeTag.InterfaceIs:
00142                 return typeof(object);
00143 
00144             case TypeTag.Char:
00145                 return typeof(byte);
00146             case TypeTag.WChar:
00147                 return typeof(char);
00148 
00149             case TypeTag.NSIdPtr:
00150                 return Type.GetType("System.Guid&");
00151                 // return typeof(Guid).MakeByRefType(); NET_2_0
00152 
00153             default:
00154                 string msg = String.Format("type {0} not yet supported ",
00155                                            tag.ToString());
00156                 
00157                 throw new Exception(msg);
00158             }
00159         }
00160     }
00161 
00162     [Flags]
00163     public enum ParamFlags : byte
00164     {
00165         In = 0x80, Out = 0x40, RetVal = 0x20, Shared = 0x10, Dipper = 0x08
00166     }
00167     
00168     public struct ParamDescriptor
00169     {
00170         public MethodDescriptor method;
00171         public int               index;
00172         public ParamFlags        flags;
00173         public TypeDescriptor     type;
00174 
00175         public Type GetCLRType()
00176         {
00177             Type t = type.AsCLRType();
00178             if (IsOut() && !IsRetVal()) {
00179                 Type reft = System.Type.GetType(t.FullName + "&");
00180                 Console.WriteLine("{0} -> {1}", t.FullName, reft.FullName);
00181                 t = reft;
00182             }
00183             return t;
00184         }
00185 
00186         public override string ToString()
00187         {
00188             return "[" + flags.ToString() + "] " + type.ToString();
00189         }
00190 
00191         public string Name()
00192         {
00193             return method.Name() + ":" + index;
00194         }
00195 
00196         public bool IsOut()
00197         {
00198             return (flags & ParamFlags.Out) != 0;
00199         }
00200 
00201         public bool IsIn()
00202         {
00203             return (flags & ParamFlags.In) != 0;
00204         }
00205 
00206         public bool IsRetVal()
00207         {
00208             return (flags & ParamFlags.RetVal) != 0;
00209         }
00210 
00211         public Guid GetIID()
00212         {
00213             if (type.tag != TypeTag.Interface) {
00214                 throw new Exception(String.Format("{0} not an interface type",
00215                                                   this));
00216             }
00217 
00218             Guid iid;
00219             int res;
00220             res = typeinfo_GetIIDForParam(method.ifaceName, method.index,
00221                                           index, out iid);
00222             if (res != 0) {
00223                 throw new 
00224                     Exception(String.Format("GetIIDForParam failed: {0:X8}",
00225                                             res));
00226             }
00227             return iid;
00228         }
00229 
00230         public string GetInterfaceName()
00231         {
00232             return TypeInfo.NameForIID(GetIID());
00233         }
00234     }
00235     
00236     [Flags]
00237     public enum MethodFlags : byte
00238     {
00239         Getter = 0x80, Setter = 0x40, NotXPCOM = 0x20, Constructor = 0x10,
00240         Hidden = 0x08
00241     }
00242 
00243     public class MethodDescriptor
00244     {
00245         public int               index;
00246         public String            name;
00247         public ParamDescriptor[] args;
00248         public ParamDescriptor   result;
00249         public Type[]            argTypes;
00250         public Type              resultType;
00251         public MethodFlags       flags;
00252         public String            ifaceName;
00253 
00254         public bool IsVisible()
00255         {
00256             return (flags & (MethodFlags.Hidden | MethodFlags.NotXPCOM)) == 0;
00257         }
00258 
00259         public bool IsSetter()
00260         {
00261             return (flags & MethodFlags.Setter) != 0;
00262         }
00263 
00264         public bool IsGetter()
00265         {
00266             return (flags & MethodFlags.Getter) != 0;
00267         }
00268 
00269         public string Name()
00270         {
00271             return ifaceName + ":" + name + "(" + index + ")";
00272         }
00273 
00274         public Type FindResultType()
00275         {
00276             for (int i = 0; i < args.Length; i++) {
00277                 if (args[i].IsRetVal())
00278                     return args[i].GetCLRType();
00279             }
00280             return typeof(void);
00281         }
00282 
00283         public void BuildArgTypes()
00284         {
00285             if (!IsVisible()) {
00286                 argTypes = new Type[] { };
00287                 return;
00288             }
00289 
00290             if (resultType != typeof(void))
00291                 argTypes = new Type[args.Length - 1];
00292             else
00293                 argTypes = new Type[args.Length];
00294             int j = 0;
00295             for (int i = 0; i < args.Length; i++) {
00296                 if (args[i].IsRetVal())
00297                     continue;
00298                 argTypes[j++] = args[i].GetCLRType();
00299             }
00300         }
00301         
00302         public override string ToString()
00303         {
00304             string res = String.Empty;
00305             if (flags != 0)
00306                 res = "[" + flags.ToString() + "] ";
00307             res += result.ToString() + " " + name + "(";
00308             for (int i = 0; i < args.Length; i++) {
00309                 if (i != 0)
00310                     res += ", ";
00311                 res += args[i].ToString();
00312             }
00313             res += ")";
00314             return res;
00315         }
00316     }
00317 
00318     [DllImport("xpcom-dotnet.so")]
00319     static extern int typeinfo_GetAllMethodData(String iface,
00320                                                 out IntPtr infos,
00321                                                 out UInt16 count);
00322 
00323     [DllImport("xpcom-dotnet.so")]
00324     static extern int typeinfo_GetMethodData(String iface, int method,
00325                                              out IntPtr info);
00326 
00327 
00328     [DllImport("xpcom-dotnet.so")]
00329     static extern int typeinfo_GetMethodData_byname(String iface,
00330                                                     String method,
00331                                                     out UInt16 index,
00332                                                     out IntPtr info);
00333 
00334     [DllImport("xpcom-dotnet.so")]
00335     static extern int typeinfo_GetMethodData_iid_index(ref Guid iid, int index,
00336                                                        out IntPtr xptinfo);
00337 
00338     [DllImport("xpcom-dotnet.so")]
00339     static extern int typeinfo_GetIIDForParam(String iface, int method,
00340                                               int param, out Guid iid);
00341 
00342     [DllImport("xpcom-dotnet.so")]
00343     static extern int typeinfo_GetNameForIID(ref Guid iid, out String name);
00344 
00345     [DllImport("xpcom-dotnet.so")]
00346     public static extern IntPtr typeinfo_EnumerateInterfacesStart();
00347 
00348     [DllImport("xpcom-dotnet.so")]
00349     public static extern String typeinfo_EnumerateInterfacesNext(IntPtr e);
00350 
00351     [DllImport("xpcom-dotnet.so")]
00352     public static extern void typeinfo_EnumerateInterfacesStop(IntPtr e);
00353 
00354     [DllImport("xpcom-dotnet.so")]
00355     public static extern int typeinfo_GetParentInfo(String name,
00356                                                     out String parentName,
00357                                                     out UInt16 methodCount);
00358 
00359     public static String GetParentInfo(String name, out UInt16 methodCount)
00360     {
00361         String parentName;
00362         int res = typeinfo_GetParentInfo(name, out parentName,
00363                                          out methodCount);
00364         if (res != 0) {
00365             throw new Exception(String.Format("GetParentInfo({0}) " +
00366                                               "failed: {1:X8}", name, res));
00367         }
00368         return parentName;
00369     }
00370     
00371     static ParamDescriptor BuildParamDescriptor(IntPtr paramptr, int index,
00372                                                 MethodDescriptor method)
00373     {
00374         XPTParamDescriptor xptpd = (XPTParamDescriptor)
00375             Marshal.PtrToStructure(paramptr, typeof(XPTParamDescriptor));
00376         ParamDescriptor pd = new ParamDescriptor();
00377         pd.method = method;
00378         pd.index = index;
00379         pd.flags = (ParamFlags) xptpd.param_flags;
00380         pd.type = xptpd.type;
00381         return pd;
00382     }
00383 
00384     static ParamDescriptor BuildRetValDescriptor(IntPtr paramptr,
00385                                                  MethodDescriptor method)
00386     {
00387         return BuildParamDescriptor(paramptr, -1, method);
00388     }
00389 
00390     static ParamDescriptor[] BuildParamDescriptorArray(IntPtr paramptr,
00391                                                        int count,
00392                                                        MethodDescriptor method)
00393     {
00394         ParamDescriptor[] parr = new ParamDescriptor[count];
00395         
00396         for (int i = 0; i < count; i++) {
00397             parr[i] = BuildParamDescriptor(paramptr, i, method);
00398             paramptr = (IntPtr)(paramptr.ToInt32() + 8);
00399         }
00400         return parr;
00401     }
00402     
00403     static MethodDescriptor ConvertMethodDescriptor(IntPtr xptinfo,
00404                                                     string ifaceName,
00405                                                     int index)
00406     {
00407         XPTMethodDescriptor info;
00408         info = (XPTMethodDescriptor)
00409             Marshal.PtrToStructure(xptinfo, typeof(XPTMethodDescriptor));
00410         MethodDescriptor meth = new MethodDescriptor();
00411         meth.ifaceName = ifaceName;
00412         meth.index = index;
00413         meth.name = System.Char.ToUpper(info.name[0]) + info.name.Substring(1);
00414         meth.flags = (MethodFlags)info.flags;
00415         meth.args = BuildParamDescriptorArray(info.args, info.numArgs, meth);
00416         meth.result = BuildRetValDescriptor(info.result, meth);
00417         if (meth.IsVisible()) {
00418             meth.resultType = meth.FindResultType();
00419             meth.BuildArgTypes();
00420         }
00421         return meth;
00422     }
00423 
00424     static public MethodDescriptor[] GetMethodData(string ifaceName)
00425     {
00426         IntPtr buffer;
00427         UInt16 count;
00428 
00429         int res = typeinfo_GetAllMethodData(ifaceName, out buffer, out count);
00430         if (res != 0) {
00431             throw new Exception(String.Format("GetAllMethodData({0}) " +
00432                                               "failed: {1:X8}",
00433                                               ifaceName, res));
00434         }            
00435 
00436         MethodDescriptor[] methods = new MethodDescriptor[count];
00437 
00438         for (int i = 0; i < (UInt16)count; i++) {
00439             IntPtr infoptr = Marshal.ReadIntPtr(buffer, i * 
00440                                                 Marshal.SizeOf(typeof(IntPtr)));
00441             try {
00442                 methods[i] = ConvertMethodDescriptor(infoptr, ifaceName, i);
00443             } catch (Exception e) {
00444                 Console.WriteLine("skipping {0}[{1}]: {2}",
00445                                   ifaceName, i, e.Message);
00446             }
00447         }
00448 
00449         if (count > 0)
00450             Marshal.FreeCoTaskMem(buffer);
00451 
00452         return methods;
00453     }
00454 
00455     static public MethodDescriptor GetMethodData(Guid iid, int index)
00456     {
00457         IntPtr xptinfo;
00458         int res = typeinfo_GetMethodData_iid_index(ref iid, index,
00459                                                    out xptinfo);
00460         if (res != 0) {
00461             throw new Exception(String.Format("GetMethodData({0}.{1}) " +
00462                                               "failed: {2:X8}",
00463                                               iid, index, res));
00464         }
00465 
00466         String name;
00467         res = typeinfo_GetNameForIID(ref iid, out name);
00468         if (res != 0) {
00469             throw new Exception(String.Format("GetNameForIID failed: {0:X8}",
00470                                               res));
00471         }
00472         return ConvertMethodDescriptor(xptinfo, name, index);
00473     }
00474 
00475     static public String NameForIID(Guid iid)
00476     {
00477         String name;
00478         int res = typeinfo_GetNameForIID(ref iid, out name);
00479         if (res != 0) {
00480             throw new 
00481                 Exception(String.Format("GetNameForIID failed: {0:X8}",
00482                                         res));
00483         }
00484         return name;
00485     }
00486 
00487     static public Type TypeForIID(Guid iid)
00488     {
00489         String ifaceName = "Mozilla.XPCOM.Interfaces." + NameForIID(iid) +
00490             ",Mozilla.XPCOM.Interfaces";
00491         return System.Type.GetType(ifaceName);
00492     }
00493 
00494     static public MethodDescriptor GetMethodData(string ifaceName,
00495                                                  string methodName)
00496     {
00497         IntPtr xptinfo;
00498         UInt16 index;
00499         int res = typeinfo_GetMethodData_byname(ifaceName, methodName,
00500                                                 out index, out xptinfo);
00501 
00502         if (res != 0) {
00503             throw new Exception(String.Format("GetMethodData({0}.{1}) " +
00504                                               "failed: {2:X8}",
00505                                               ifaceName, methodName, res));
00506         }
00507 
00508         // Console.WriteLine("{0} is index {1}", methodName, index);
00509 
00510         return ConvertMethodDescriptor(xptinfo, ifaceName, (int)index);
00511     }
00512 
00513     static public MethodDescriptor GetMethodData(String ifaceName,
00514                                                  int methodIndex)
00515     {
00516         IntPtr xptinfo;
00517         
00518         int res = typeinfo_GetMethodData(ifaceName, methodIndex, out xptinfo);
00519 
00520         if (xptinfo == IntPtr.Zero) {
00521             throw new Exception(String.Format("GetMethodData({0}:{1}) failed:" +
00522                                               " {2:X8}",
00523                                               ifaceName, methodIndex, res));
00524         }
00525 
00526         return ConvertMethodDescriptor(xptinfo, ifaceName, methodIndex);
00527     }
00528 }
00529 
00530 } // namespace Mozilla.XPCOM