* HtmlControl.cs: Make disabled an attribute of the control so it
[mono.git] / mcs / mcs / support.cs
1 //
2 // support.cs: Support routines to work around the fact that System.Reflection.Emit
3 // can not introspect types that are being constructed
4 //
5 // Author:
6 //   Miguel de Icaza (miguel@ximian.com)
7 //
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
9 //
10
11 using System;
12 using System.IO;
13 using System.Text;
14 using System.Reflection;
15 using System.Collections;
16 using System.Reflection.Emit;
17 using System.Globalization;
18
19 namespace Mono.CSharp {
20
21         public interface ParameterData {
22                 Type ParameterType (int pos);
23                 int  Count { get; }
24                 string ParameterName (int pos);
25                 string ParameterDesc (int pos);
26                 Parameter.Modifier ParameterModifier (int pos);
27         }
28
29         public class ReflectionParameters : ParameterData {
30                 ParameterInfo [] pi;
31                 bool last_arg_is_params = false;
32                 
33                 public ReflectionParameters (ParameterInfo [] pi)
34                 {
35                         object [] attrs;
36                         
37                         this.pi = pi;
38                         int count = pi.Length-1;
39
40                         if (count >= 0) {
41                                 attrs = pi [count].GetCustomAttributes (TypeManager.param_array_type, true);
42
43                                 if (attrs == null)
44                                         return;
45                                 
46                                 if (attrs.Length == 0)
47                                         return;
48
49                                 last_arg_is_params = true;
50                         }
51                 }
52                        
53                 public Type ParameterType (int pos)
54                 {
55                         if (last_arg_is_params && pos >= pi.Length - 1)
56                                 return pi [pi.Length - 1].ParameterType;
57                         else {
58                                 Type t = pi [pos].ParameterType;
59
60                                 return t;
61                         }
62                 }
63
64                 public string ParameterName (int pos)
65                 {
66                         if (last_arg_is_params && pos >= pi.Length - 1)
67                                 return pi [pi.Length - 1].Name;
68                         else 
69                                 return pi [pos].Name;
70                 }
71
72                 public string ParameterDesc (int pos)
73                 {
74                         StringBuilder sb = new StringBuilder ();
75
76                         if (pi [pos].IsIn)
77                                 sb.Append ("in ");
78
79                         Type partype = ParameterType (pos);
80                         if (partype.IsByRef){
81                                 partype = TypeManager.GetElementType (partype);
82                                 if (pi [pos].IsOut)
83                                         sb.Append ("out ");
84                                 else
85                                         sb.Append ("ref ");
86                         } 
87
88                         if (pos >= pi.Length - 1 && last_arg_is_params)
89                                 sb.Append ("params ");
90                         
91                         sb.Append (TypeManager.CSharpName (partype));
92
93                         return sb.ToString ();
94                         
95                 }
96
97                 public Parameter.Modifier ParameterModifier (int pos)
98                 {
99                         int len = pi.Length;
100
101                         if (pos >= len - 1)
102                                 if (last_arg_is_params)
103                                         return Parameter.Modifier.PARAMS;
104                         
105                         Type t = pi [pos].ParameterType;
106                         if (t.IsByRef){
107                                 if ((pi [pos].Attributes & ParameterAttributes.Out) != 0)
108                                         return Parameter.Modifier.ISBYREF | Parameter.Modifier.OUT;
109                                 else
110                                         return Parameter.Modifier.ISBYREF | Parameter.Modifier.REF;
111                         }
112                         
113                         return Parameter.Modifier.NONE;
114                 }
115
116                 public int Count {
117                         get {
118                                 return pi.Length;
119                         }
120                 }
121                 
122         }
123
124         public class InternalParameters : ParameterData {
125                 Type [] param_types;
126
127                 public readonly Parameters Parameters;
128                 
129                 public InternalParameters (Type [] param_types, Parameters parameters)
130                 {
131                         this.param_types = param_types;
132                         this.Parameters = parameters;
133                 }
134
135                 public InternalParameters (DeclSpace ds, Parameters parameters)
136                         : this (parameters.GetParameterInfo (ds), parameters)
137                 {
138                 }
139
140                 public int Count {
141                         get {
142                                 if (param_types == null)
143                                         return 0;
144
145                                 return param_types.Length;
146                         }
147                 }
148
149                 Parameter GetParameter (int pos)
150                 {
151                         Parameter [] fixed_pars = Parameters.FixedParameters;
152                         if (fixed_pars != null){
153                                 int len = fixed_pars.Length;
154                                 if (pos < len)
155                                         return Parameters.FixedParameters [pos];
156                         }
157
158                         return Parameters.ArrayParameter;
159                 }
160
161                 public Type ParameterType (int pos)
162                 {
163                         if (param_types == null)
164                                 return null;
165
166                         return GetParameter (pos).ExternalType ();
167                 }
168
169
170                 public string ParameterName (int pos)
171                 {
172                         return GetParameter (pos).Name;
173                 }
174
175                 public string ParameterDesc (int pos)
176                 {
177                         string tmp = String.Empty;
178                         Parameter p = GetParameter (pos);
179
180                         //
181                         // We need to and for REF/OUT, because if either is set the
182                         // extra flag ISBYREF will be set as well
183                         //
184                         if ((p.ModFlags & Parameter.Modifier.REF) != 0)
185                                 tmp = "ref ";
186                         else if ((p.ModFlags & Parameter.Modifier.OUT) != 0)
187                                 tmp = "out ";
188                         else if (p.ModFlags == Parameter.Modifier.PARAMS)
189                                 tmp = "params ";
190
191                         Type t = ParameterType (pos);
192
193                         return tmp + TypeManager.CSharpName (t);
194                 }
195
196                 public Parameter.Modifier ParameterModifier (int pos)
197                 {
198                         Parameter.Modifier mod = GetParameter (pos).ModFlags;
199
200                         if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
201                                 mod |= Parameter.Modifier.ISBYREF;
202
203                         return mod;
204                 }
205                 
206         }
207
208         class PtrHashtable : Hashtable {
209                 class PtrComparer : IComparer {
210                         public int Compare (object x, object y)
211                         {
212                                 if (x == y)
213                                         return 0;
214                                 else
215                                         return 1;
216                         }
217                 }
218                 
219                 public PtrHashtable ()
220                 {
221                         comparer = new PtrComparer ();
222                 }
223         }
224
225         //
226         // Compares member infos based on their name and
227         // also allows one argument to be a string
228         //
229         class MemberInfoCompare : IComparer {
230
231                 public int Compare (object a, object b)
232                 {
233                         if (a == null || b == null){
234                                 Console.WriteLine ("Invalid information passed");
235                                 throw new Exception ();
236                         }
237                         
238                         if (a is string)
239                                 return String.Compare ((string) a, ((MemberInfo)b).Name);
240
241                         if (b is string)
242                                 return String.Compare (((MemberInfo)a).Name, (string) b);
243
244                         return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name);
245                 }
246         }
247
248         struct Pair {
249                 public object First;
250                 public object Second;
251                 
252                 public Pair (object f, object s)
253                 {
254                         First = f;
255                         Second = s;
256                 }
257         }
258
259         /// <summary>
260         ///   This is a wrapper around StreamReader which is seekable.
261         /// </summary>
262         public class SeekableStreamReader
263         {
264                 public SeekableStreamReader (StreamReader reader)
265                 {
266                         this.reader = reader;
267                         this.buffer = new char [DefaultCacheSize];
268                 }
269
270                 public SeekableStreamReader (Stream stream, Encoding encoding, bool detect_encoding_from_bytemarks)
271                         : this (new StreamReader (stream, encoding, detect_encoding_from_bytemarks))
272                 { }
273
274                 StreamReader reader;
275
276                 private const int DefaultCacheSize = 1024;
277
278                 char[] buffer;
279                 int buffer_start;
280                 int buffer_size;
281                 int pos;
282
283                 /// <remarks>
284                 ///   The difference to the StreamReader's BaseStream.Position is that this one is reliable; ie. it
285                 //    always reports the correct position and if it's modified, it also takes care of the buffered data.
286                 /// </remarks>
287                 public int Position {
288                         get {
289                                 return buffer_start + pos;
290                         }
291
292                         set {
293                                 // This one is easy: we're modifying the position within our current
294                                 // buffer.
295                                 if ((value >= buffer_start) && (value < buffer_start + buffer_size)) {
296                                         pos = value - buffer_start;
297                                         return;
298                                 }
299
300                                 // Ok, now we need to seek.
301                                 reader.DiscardBufferedData ();
302                                 reader.BaseStream.Position = buffer_start = value;
303                                 buffer_size = pos = 0;
304                         }
305                 }
306
307                 private bool ReadBuffer ()
308                 {
309                         pos = 0;
310                         buffer_start += buffer_size;
311                         buffer_size = reader.Read (buffer, 0, buffer.Length);
312                         return buffer_size > 0;
313                 }
314
315                 public int Peek ()
316                 {
317                         if ((pos >= buffer_size) && !ReadBuffer ())
318                                 return -1;
319
320                         return buffer [pos];
321                 }
322
323                 public int Read ()
324                 {
325                         if ((pos >= buffer_size) && !ReadBuffer ())
326                                 return -1;
327
328                         return buffer [pos++];
329                 }
330         }
331
332         public class DoubleHash {
333                 Hashtable l = new Hashtable ();
334                 
335                 public DoubleHash ()
336                 {
337                 }
338
339                 public bool Lookup (object a, object b, out object res)
340                 {
341                         object r = l [a];
342                         if (r == null){
343                                 res = null;
344                                 return false;
345                         }
346                         Hashtable ht = (Hashtable) r;
347                         if (ht.Contains (b)){
348                                 res = ht [b];
349                                 return true;
350                         }
351                         res = null;
352                         return false;
353                 }
354
355                 public void Insert (object a, object b, object value)
356                 {
357                         Hashtable ht;
358                         object r = l [a];
359                         if (r == null){
360                                 ht = new Hashtable ();
361                                 l [a] = ht;
362                                 ht [b] = value;
363                                 return;
364                         }
365                         ht = (Hashtable) r;
366                         ht [b] = value;
367                 }
368         }
369 }