Merge pull request #3678 from mono/seq-read
[mono.git] / mono / metadata / class-accessors.c
1 /*
2  * Copyright 2016 Microsoft
3  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
4  */
5 #include <mono/metadata/class-internals.h>
6 #include <mono/metadata/tabledefs.h>
7
8
9 enum InfrequentDataKind {
10         PROP_MARSHAL_INFO = 1, /* MonoMarshalType */
11         PROP_EXT = 2, /* MonoClassExt */
12         PROP_REF_INFO_HANDLE = 3, /* gchandle */
13 };
14
15 /* Accessors based on class kind*/
16
17 /*
18 * mono_class_get_generic_class:
19 *
20 *   Return the MonoGenericClass of @klass, which MUST be a generic instance.
21 */
22 MonoGenericClass*
23 mono_class_get_generic_class (MonoClass *klass)
24 {
25         g_assert (mono_class_is_ginst (klass));
26         return ((MonoClassGenericInst*)klass)->generic_class;
27 }
28
29 /*
30 * mono_class_try_get_generic_class:
31 *
32 *   Return the MonoGenericClass if @klass is a ginst, NULL otherwise
33 */
34 MonoGenericClass*
35 mono_class_try_get_generic_class (MonoClass *klass)
36 {
37         if (mono_class_is_ginst (klass))
38                 return ((MonoClassGenericInst*)klass)->generic_class;
39         return NULL;
40 }
41
42 /**
43  * mono_class_get_flags:
44  * @klass: the MonoClass to act on
45  *
46  * Return the TypeAttributes flags of @klass.
47  * See the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the different values.
48  *
49  * Returns: The type flags
50  */
51 guint32
52 mono_class_get_flags (MonoClass *klass)
53 {
54         switch (klass->class_kind) {
55         case MONO_CLASS_DEF:
56         case MONO_CLASS_GTD:
57                 return ((MonoClassDef*)klass)->flags;
58         case MONO_CLASS_GINST:
59                 return mono_class_get_flags (((MonoClassGenericInst*)klass)->generic_class->container_class);
60         case MONO_CLASS_GPARAM:
61                 return TYPE_ATTRIBUTE_PUBLIC;
62         case MONO_CLASS_ARRAY:
63                 /* all arrays are marked serializable and sealed, bug #42779 */
64                 return TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
65         case MONO_CLASS_POINTER:
66                 return TYPE_ATTRIBUTE_CLASS | (mono_class_get_flags (klass->element_class) & TYPE_ATTRIBUTE_VISIBILITY_MASK);
67         }
68         g_assert_not_reached ();
69 }
70
71 void
72 mono_class_set_flags (MonoClass *klass, guint32 flags)
73 {
74         g_assert (klass->class_kind == MONO_CLASS_DEF || klass->class_kind == MONO_CLASS_GTD);
75         ((MonoClassDef*)klass)->flags = flags;
76 }
77
78 /*
79  * mono_class_get_generic_container:
80  *
81  *   Return the generic container of KLASS which should be a generic type definition.
82  */
83 MonoGenericContainer*
84 mono_class_get_generic_container (MonoClass *klass)
85 {
86         g_assert (mono_class_is_gtd (klass));
87
88         return ((MonoClassGtd*)klass)->generic_container;
89 }
90
91 MonoGenericContainer*
92 mono_class_try_get_generic_container (MonoClass *klass)
93 {
94         if (mono_class_is_gtd (klass))
95                 return ((MonoClassGtd*)klass)->generic_container;
96         return NULL;
97 }
98
99
100 void
101 mono_class_set_generic_container (MonoClass *klass, MonoGenericContainer *container)
102 {
103         g_assert (mono_class_is_gtd (klass));
104
105         ((MonoClassGtd*)klass)->generic_container = container;
106 }
107
108 /*
109  * mono_class_get_first_method_idx:
110  *
111  *   Return the table index of the first method for metadata classes.
112  */
113 guint32
114 mono_class_get_first_method_idx (MonoClass *klass)
115 {
116         g_assert (mono_class_has_static_metadata (klass));
117
118         return ((MonoClassDef*)klass)->first_method_idx;
119 }
120
121 void
122 mono_class_set_first_method_idx (MonoClass *klass, guint32 idx)
123 {
124         g_assert (mono_class_has_static_metadata (klass));
125
126         ((MonoClassDef*)klass)->first_method_idx = idx;
127 }
128
129 guint32
130 mono_class_get_first_field_idx (MonoClass *klass)
131 {
132         if (mono_class_is_ginst (klass))
133                 return mono_class_get_first_field_idx (mono_class_get_generic_class (klass)->container_class);
134
135         g_assert (mono_class_has_static_metadata (klass));
136
137         return ((MonoClassDef*)klass)->first_field_idx;
138 }
139
140 void
141 mono_class_set_first_field_idx (MonoClass *klass, guint32 idx)
142 {
143         g_assert (mono_class_has_static_metadata (klass));
144
145         ((MonoClassDef*)klass)->first_field_idx = idx;
146 }
147
148 guint32
149 mono_class_get_method_count (MonoClass *klass)
150 {
151         switch (klass->class_kind) {
152         case MONO_CLASS_DEF:
153         case MONO_CLASS_GTD:
154                 return ((MonoClassDef*)klass)->method_count;
155         case MONO_CLASS_GINST:
156                 return mono_class_get_method_count (((MonoClassGenericInst*)klass)->generic_class->container_class);
157         case MONO_CLASS_GPARAM:
158                 return 0;
159         case MONO_CLASS_ARRAY:
160                 return ((MonoClassArray*)klass)->method_count;
161         case MONO_CLASS_POINTER:
162                 return 0;
163         default:
164                 g_assert_not_reached ();
165                 return 0;
166         }
167 }
168
169 void
170 mono_class_set_method_count (MonoClass *klass, guint32 count)
171 {
172         switch (klass->class_kind) {
173         case MONO_CLASS_DEF:
174         case MONO_CLASS_GTD:
175                 ((MonoClassDef*)klass)->method_count = count;
176                 break;
177         case MONO_CLASS_GINST:
178                 break;
179         case MONO_CLASS_GPARAM:
180         case MONO_CLASS_POINTER:
181                 g_assert (count == 0);
182                 break;
183         case MONO_CLASS_ARRAY:
184                 ((MonoClassArray*)klass)->method_count = count;
185                 break;
186         default:
187                 g_assert_not_reached ();
188                 break;
189         }
190 }
191
192 guint32
193 mono_class_get_field_count (MonoClass *klass)
194 {
195         switch (klass->class_kind) {
196         case MONO_CLASS_DEF:
197         case MONO_CLASS_GTD:
198                 return ((MonoClassDef*)klass)->field_count;
199         case MONO_CLASS_GINST:
200                 return mono_class_get_field_count (((MonoClassGenericInst*)klass)->generic_class->container_class);
201         case MONO_CLASS_GPARAM:
202         case MONO_CLASS_ARRAY:
203         case MONO_CLASS_POINTER:
204                 return 0;
205         default:
206                 g_assert_not_reached ();
207                 return 0;
208         }
209 }
210
211 void
212 mono_class_set_field_count (MonoClass *klass, guint32 count)
213 {
214         switch (klass->class_kind) {
215         case MONO_CLASS_DEF:
216         case MONO_CLASS_GTD:
217                 ((MonoClassDef*)klass)->field_count = count;
218                 break;
219         case MONO_CLASS_GINST:
220                 break;
221         case MONO_CLASS_GPARAM:
222         case MONO_CLASS_ARRAY:
223         case MONO_CLASS_POINTER:
224                 g_assert (count == 0);
225                 break;
226         default:
227                 g_assert_not_reached ();
228                 break;
229         }
230 }
231
232 MonoMarshalType*
233 mono_class_get_marshal_info (MonoClass *class)
234 {
235         return mono_property_bag_get (&class->infrequent_data, PROP_MARSHAL_INFO);
236 }
237
238 void
239 mono_class_set_marshal_info (MonoClass *class, MonoMarshalType *marshal_info)
240 {
241         marshal_info->head.tag = PROP_MARSHAL_INFO;
242         mono_property_bag_add (&class->infrequent_data, marshal_info);
243 }
244
245 MonoClassExt*
246 mono_class_get_ext (MonoClass *class)
247 {
248         return mono_property_bag_get (&class->infrequent_data, PROP_EXT);
249 }
250
251 void
252 mono_class_set_ext (MonoClass *class, MonoClassExt *ext)
253 {
254         ext->head.tag = PROP_EXT;
255         mono_property_bag_add (&class->infrequent_data, ext);
256 }
257
258 typedef struct {
259         MonoPropertyBagItem head;
260         guint32 value;
261 } Uint32Property;
262
263 guint32
264 mono_class_get_ref_info_handle (MonoClass *class)
265 {
266         Uint32Property *prop = mono_property_bag_get (&class->infrequent_data, PROP_REF_INFO_HANDLE);
267         return prop ? prop->value : 0;
268 }
269
270 guint32
271 mono_class_set_ref_info_handle (MonoClass *class, guint32 value)
272 {
273         if (!value) {
274                 Uint32Property *prop = mono_property_bag_get (&class->infrequent_data, PROP_REF_INFO_HANDLE);
275                 if (prop)
276                         prop->value = 0;
277                 return 0;
278         }
279
280         Uint32Property *prop = mono_class_alloc (class, sizeof (Uint32Property));
281         prop->head.tag = PROP_REF_INFO_HANDLE;
282         prop->value = value;
283         prop = mono_property_bag_add (&class->infrequent_data, prop);
284         return prop->value;
285 }