3 // author: Dan Lewis (dihlewis@yahoo.co.uk)
\r
8 using System.Reflection;
\r
9 using System.Collections;
\r
12 public Peer (Type clr_type, string name, bool is_opaque) {
\r
13 this.clr_type = clr_type;
\r
15 this.is_opaque = is_opaque;
\r
17 this.nearest_base = null; // resolve later
\r
18 this.underlying = null;
\r
19 this.enum_constants = null;
\r
20 this.fields = new PeerFieldCollection ();
\r
22 this.is_enum = CLRIsEnum (clr_type);
\r
23 this.is_value_type = CLRIsValueType (clr_type);
\r
26 public string Name {
\r
27 get { return name; }
\r
30 public Type CLRType {
\r
31 get { return clr_type; }
\r
34 public bool IsOpaque {
\r
35 get { return is_opaque; }
\r
38 public bool IsValueType {
\r
39 get { return is_value_type; }
\r
42 public bool IsEnum {
\r
43 get { return is_enum; }
\r
46 public Peer NearestBase {
\r
47 get { return nearest_base; }
\r
48 set { nearest_base = value; }
\r
51 public Peer UnderlyingPeer {
\r
52 get { return underlying; }
\r
53 set { underlying = value; }
\r
56 public IDictionary EnumConstants {
\r
57 get { return enum_constants; }
\r
58 set { enum_constants = value; }
\r
61 public PeerFieldCollection Fields {
\r
62 get { return fields; }
\r
65 public string GetTypedef (int refs) {
\r
67 return String.Format ("{0} ", name);
\r
69 return String.Format ("{0} {1}", name, new string ('*', refs));
\r
74 internal static bool CLRIsValueType (Type clr_type) {
\r
75 return clr_type.IsValueType;
\r
77 if (clr_type.BaseType == null)
\r
81 clr_type.BaseType.FullName == "System.ValueType" ||
\r
82 clr_type.BaseType.FullName == "System.Enum";
\r
86 internal static bool CLRIsEnum (Type clr_type) {
\r
87 return clr_type.IsEnum;
\r
89 if (clr_type.BaseType == null)
\r
92 return clr_type.BaseType.FullName == "System.Enum";
\r
96 internal static Type CLRUnderlyingType (Type clr_type) {
\r
97 return Enum.GetUnderlyingType (clr_type);
\r
99 Type ebase = type.BaseType;
\r
101 return (Type)ebase.InvokeMember ("GetUnderlyingType",
\r
102 BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static,
\r
104 new object[] { type }
\r
111 private Type clr_type;
\r
112 private bool is_opaque;
\r
113 private bool is_value_type;
\r
114 private bool is_enum;
\r
116 private string name;
\r
117 private Peer nearest_base;
\r
118 private Peer underlying;
\r
119 private IDictionary enum_constants;
\r
120 private PeerFieldCollection fields;
\r
124 public PeerField (Peer peer, string name) {
\r
130 get { return peer; }
\r
133 public string Name {
\r
134 get { return name; }
\r
138 private string name;
\r
141 class PeerFieldCollection : CollectionBase {
\r
142 public void Add (PeerField f) {
\r
146 public PeerField this[int i] {
\r
147 get { return (PeerField)List[i]; }
\r
152 public PeerMap () {
\r
153 peers = new Hashtable ();
\r
156 public void Add (Peer peer) {
\r
157 Add (peer.CLRType, peer);
\r
160 public void Add (Type clr_type, Peer peer) {
\r
161 peers.Add (clr_type, peer);
\r
164 public ICollection Peers {
\r
165 get { return peers.Values; }
\r
168 public Peer this[Type clr_type] {
\r
170 if (peers.Contains (clr_type))
\r
171 return (Peer)peers[clr_type];
\r
177 public Peer GetPeer (Type clr_type) {
\r
180 if (Peer.CLRIsValueType (clr_type)) {
\r
181 peer = this[clr_type];
\r
185 if (Peer.CLRIsEnum (clr_type)) {
\r
186 peer = this[Peer.CLRUnderlyingType (clr_type)];
\r
190 throw new ArgumentException ("Could not find peer or underlying peer for enum " + clr_type);
\r
193 throw new ArgumentException ("Could not find peer for value type " + clr_type);
\r
196 Type type = clr_type;
\r
197 while (type != null) {
\r
202 type = type.BaseType;
\r
205 throw new ArgumentException ("Could not find peer for class " + clr_type);
\r
209 public void ResolvePeers () {
\r
210 BindingFlags binding =
\r
211 BindingFlags.DeclaredOnly |
\r
212 BindingFlags.Instance |
\r
213 BindingFlags.NonPublic |
\r
214 BindingFlags.Public;
\r
218 foreach (Peer peer in Peers) {
\r
219 if (peer.IsOpaque || peer.IsValueType || peer.CLRType.BaseType == null)
\r
222 peer.NearestBase = GetPeer (peer.CLRType.BaseType);
\r
223 if (peer.NearestBase == null) {
\r
224 Console.Error.WriteLine ("Error: cannot find an internal base type for {0}.", peer.Name);
\r
225 Environment.Exit (-1);
\r
231 foreach (Peer peer in Peers) {
\r
232 if (peer.IsOpaque || peer.IsEnum)
\r
235 Type clr_base = null;
\r
236 if (peer.NearestBase != null)
\r
237 clr_base = peer.NearestBase.CLRType;
\r
239 Stack declared = new Stack ();
\r
240 Type type = peer.CLRType;
\r
242 while (type != clr_base) {
\r
243 declared.Push (type);
\r
244 type = type.BaseType;
\r
247 // build declared field list
\r
249 while (declared.Count > 0) {
\r
250 type = (Type)declared.Pop ();
\r
251 foreach (FieldInfo info in type.GetFields (binding)) {
\r
252 PeerField field = new PeerField (
\r
253 GetPeer (info.FieldType),
\r
257 peer.Fields.Add (field);
\r
264 foreach (Peer peer in Peers) {
\r
265 if (peer.IsOpaque || !peer.IsEnum)
\r
268 Type clr_type = peer.CLRType;
\r
272 Hashtable constants = new Hashtable ();
\r
273 foreach (string name in Enum.GetNames (clr_type))
\r
274 constants.Add (name, (int)Enum.Parse (clr_type, name));
\r
276 peer.UnderlyingPeer = GetPeer (Enum.GetUnderlyingType (clr_type));
\r
277 peer.EnumConstants = constants;
\r
283 private Hashtable peers;
\r