Initial revision
[mono.git] / mcs / class / corlib / System.Reflection.Emit / CustomAttributeBuilder.cs
1
2 //
3 // System.Reflection.Emit/CustomAttributeBuilder.cs
4 //
5 // Author:
6 //   Paolo Molaro (lupus@ximian.com)
7 //
8 // (C) 2001 Ximian, Inc.  http://www.ximian.com
9 //
10
11 using System;
12 using System.Reflection;
13 using System.Reflection.Emit;
14 using System.Runtime.CompilerServices;
15 using System.Runtime.InteropServices;
16
17 namespace System.Reflection.Emit {
18         public class CustomAttributeBuilder {
19                 ConstructorInfo ctor;
20                 byte[] data;
21
22                 internal ConstructorInfo Ctor {
23                         get {return ctor;}
24                 }
25
26                 internal byte[] Data {
27                         get {return data;}
28                 }
29                 
30                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
31                 static extern byte[] GetBlob(ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues, FieldInfo[] namedFields, object[] fieldValues);
32                 
33                 internal CustomAttributeBuilder( ConstructorInfo con, byte[] cdata) {
34                         ctor = con;
35                         data = (byte[])cdata.Clone ();
36                         /* should we check that the user supplied data is correct? */
37                 }
38                 
39                 public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs)
40                         : this (con, constructorArgs, null, null, null, null) {
41                 }
42                 public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs, FieldInfo[] namedFields, object[] fieldValues)
43                         : this (con, constructorArgs, null, null, namedFields, fieldValues) {
44                 }
45                 public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues)
46                         : this (con, constructorArgs, namedProperties, propertyValues, null, null) {
47                 }
48                 public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues, FieldInfo[] namedFields, object[] fieldValues) {
49                         ctor = con;
50                         data = GetBlob (con, constructorArgs, namedProperties, propertyValues, namedFields, fieldValues);
51                 }
52
53                 /* helper methods */
54                 internal static int decode_len (byte[] data, int pos, out int rpos) {
55                         int len = 0;
56                         if ((data [pos] & 0x80) == 0) {
57                                 len = (int)(data [pos++] & 0x7f);
58                         } else if ((data [pos] & 0x40) == 0) {
59                                 len = ((data [pos] & 0x3f) << 8) + data [pos + 1];
60                                 pos += 2;
61                         } else {
62                                 len = ((data [pos] & 0x1f) << 24) + (data [pos + 1] << 16) + (data [pos + 2] << 8) + data [pos + 3];
63                                 pos += 4;
64                         }
65                         rpos = pos;
66                         return len;
67                 }
68
69                 internal static string string_from_bytes (byte[] data, int pos, int len) {
70                         char[] chars = new char [len];
71                         // FIXME: use a utf8 decoder here
72                         for (int i = 0; i < len; ++i)
73                                 chars [i] = (char)data [pos + i];
74                         return new String (chars);
75                 }
76
77                 internal static UnmanagedMarshal get_umarshal (CustomAttributeBuilder customBuilder, bool is_field) {
78                         byte[] data = customBuilder.Data;
79                         UnmanagedType subtype = UnmanagedType.I4;
80                         int value;
81                         int utype; /* the (stupid) ctor takes a short or an enum ... */
82                         utype = (int)data [2];
83                         utype |= ((int)data [3]) << 8;
84
85                         string first_type_name = customBuilder.Ctor.GetParameters()[0].ParameterType.FullName;
86                         int pos = 6;
87                         if (first_type_name == "System.Int16")
88                                 pos = 4;
89                         int nnamed = (int)data [pos++];
90                         nnamed |= ((int)data [pos++]) << 8;
91                         
92                         for (int i = 0; i < nnamed; ++i) {
93                                 byte type = data [pos++];
94                                 int len = decode_len (data, pos, out pos);
95                                 string named_name = string_from_bytes (data, pos, len);
96                                 pos += len;
97                                 switch (named_name) {
98                                 case "ArraySubType":
99                                         value = (int)data [pos++];
100                                         value |= ((int)data [pos++]) << 8;
101                                         value |= ((int)data [pos++]) << 16;
102                                         value |= ((int)data [pos++]) << 24;
103                                         subtype = (UnmanagedType)value;
104                                         break;
105                                 default:
106                                         break;
107                                 }
108                         }
109
110                         switch ((UnmanagedType)utype) {
111                         case UnmanagedType.LPArray:
112                                 return UnmanagedMarshal.DefineLPArray (subtype);
113                         case UnmanagedType.SafeArray:
114                                 return UnmanagedMarshal.DefineSafeArray (subtype);
115                         case UnmanagedType.ByValArray:
116                         case UnmanagedType.ByValTStr:
117                         default:
118                                 return UnmanagedMarshal.DefineUnmanagedMarshal ((UnmanagedType)utype);
119                         }
120                 }
121
122         }
123 }