3 // author: Dan Lewis (dihlewis@yahoo.co.uk)
8 using System
.Reflection
;
9 using System
.Collections
;
12 public Peer (Type clr_type
, string name
, bool is_opaque
) {
13 this.clr_type
= clr_type
;
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
);
31 get { return clr_type; }
34 public bool IsOpaque
{
35 get { return is_opaque; }
38 public bool IsValueType
{
39 get { return is_value_type; }
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
) {
67 return String
.Format ("{0} ", name
);
69 return String
.Format ("{0} {1}", name
, new string ('*', refs
));
74 internal static bool CLRIsValueType (Type clr_type
) {
75 return clr_type
.IsValueType
;
77 if (clr_type.BaseType == null)
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)
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,
104 new object[] { type }
111 private Type clr_type
;
112 private bool is_opaque
;
113 private bool is_value_type
;
114 private bool is_enum
;
117 private Peer nearest_base
;
118 private Peer underlying
;
119 private IDictionary enum_constants
;
120 private PeerFieldCollection fields
;
124 public PeerField (Peer peer
, string name
) {
141 class PeerFieldCollection
: CollectionBase
{
142 public void Add (PeerField f
) {
146 public PeerField
this[int i
] {
147 get { return (PeerField)List[i]; }
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
] {
170 if (peers
.Contains (clr_type
))
171 return (Peer
)peers
[clr_type
];
177 public Peer
GetPeer (Type clr_type
) {
180 if (Peer
.CLRIsValueType (clr_type
)) {
181 peer
= this[clr_type
];
185 if (Peer
.CLRIsEnum (clr_type
)) {
186 peer
= this[Peer
.CLRUnderlyingType (clr_type
)];
190 throw new ArgumentException ("Could not find peer or underlying peer for enum " + clr_type
);
193 throw new ArgumentException ("Could not find peer for value type " + clr_type
);
196 Type type
= clr_type
;
197 while (type
!= null) {
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
|
218 foreach (Peer peer
in Peers
) {
219 if (peer
.IsOpaque
|| peer
.IsValueType
|| peer
.CLRType
.BaseType
== null)
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);
231 foreach (Peer peer
in Peers
) {
232 if (peer
.IsOpaque
|| peer
.IsEnum
)
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
),
257 peer
.Fields
.Add (field
);
264 foreach (Peer peer
in Peers
) {
265 if (peer
.IsOpaque
|| !peer
.IsEnum
)
268 Type clr_type
= peer
.CLRType
;
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
;
283 private Hashtable peers
;