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