+
+/*
+ * mono_metadata_events_from_typedef:
+ * @meta: metadata context
+ * @index: 0-based index (in the TypeDef table) describing a type
+ *
+ * Returns: the 0-based index in the Event table for the events in the
+ * type. The last event that belongs to the type (plus 1) is stored
+ * in the @end_idx pointer.
+ */
+guint32
+mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
+{
+ locator_t loc;
+ guint32 start, end;
+ MonoTableInfo *tdef = &meta->tables [MONO_TABLE_EVENTMAP];
+
+ *end_idx = 0;
+
+ if (!tdef->base)
+ return 0;
+
+ loc.t = tdef;
+ loc.col_idx = MONO_EVENT_MAP_PARENT;
+ loc.idx = index + 1;
+
+ if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+ return 0;
+
+ start = mono_metadata_decode_row_col (tdef, loc.result, MONO_EVENT_MAP_EVENTLIST);
+ if (loc.result + 1 < tdef->rows) {
+ end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_EVENT_MAP_EVENTLIST) - 1;
+ } else {
+ end = meta->tables [MONO_TABLE_EVENT].rows;
+ }
+
+ *end_idx = end;
+ return start - 1;
+}
+
+/*
+ * mono_metadata_methods_from_event:
+ * @meta: metadata context
+ * @index: 0-based index (in the Event table) describing a event
+ *
+ * Returns: the 0-based index in the MethodDef table for the methods in the
+ * event. The last method that belongs to the event (plus 1) is stored
+ * in the @end_idx pointer.
+ */
+guint32
+mono_metadata_methods_from_event (MonoImage *meta, guint32 index, guint *end_idx)
+{
+ locator_t loc;
+ guint start, end;
+ guint32 cols [MONO_METHOD_SEMA_SIZE];
+ MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
+
+ *end_idx = 0;
+ if (!msemt->base)
+ return 0;
+
+ loc.t = msemt;
+ loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
+ loc.idx = ((index + 1) << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT; /* Method association coded index */
+
+ if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
+ return 0;
+
+ start = loc.result;
+ /*
+ * We may end up in the middle of the rows...
+ */
+ while (start > 0) {
+ if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
+ start--;
+ else
+ break;
+ }
+ end = start + 1;
+ while (end < msemt->rows) {
+ mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
+ if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
+ break;
+ ++end;
+ }
+ *end_idx = end;
+ return start;
+}
+
+/*
+ * mono_metadata_properties_from_typedef:
+ * @meta: metadata context
+ * @index: 0-based index (in the TypeDef table) describing a type
+ *
+ * Returns: the 0-based index in the Property table for the properties in the
+ * type. The last property that belongs to the type (plus 1) is stored
+ * in the @end_idx pointer.
+ */
+guint32
+mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
+{
+ locator_t loc;
+ guint32 start, end;
+ MonoTableInfo *tdef = &meta->tables [MONO_TABLE_PROPERTYMAP];
+
+ *end_idx = 0;
+
+ if (!tdef->base)
+ return 0;
+
+ loc.t = tdef;
+ loc.col_idx = MONO_PROPERTY_MAP_PARENT;
+ loc.idx = index + 1;
+
+ if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+ return 0;
+
+ start = mono_metadata_decode_row_col (tdef, loc.result, MONO_PROPERTY_MAP_PROPERTY_LIST);
+ if (loc.result + 1 < tdef->rows) {
+ end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_PROPERTY_MAP_PROPERTY_LIST) - 1;
+ } else {
+ end = meta->tables [MONO_TABLE_PROPERTY].rows;
+ }
+
+ *end_idx = end;
+ return start - 1;
+}
+
+/*
+ * mono_metadata_methods_from_property:
+ * @meta: metadata context
+ * @index: 0-based index (in the PropertyDef table) describing a property
+ *
+ * Returns: the 0-based index in the MethodDef table for the methods in the
+ * property. The last method that belongs to the property (plus 1) is stored
+ * in the @end_idx pointer.
+ */
+guint32
+mono_metadata_methods_from_property (MonoImage *meta, guint32 index, guint *end_idx)
+{
+ locator_t loc;
+ guint start, end;
+ guint32 cols [MONO_METHOD_SEMA_SIZE];
+ MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
+
+ *end_idx = 0;
+ if (!msemt->base)
+ return 0;
+
+ loc.t = msemt;
+ loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
+ loc.idx = ((index + 1) << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY; /* Method association coded index */
+
+ if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
+ return 0;
+
+ start = loc.result;
+ /*
+ * We may end up in the middle of the rows...
+ */
+ while (start > 0) {
+ if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
+ start--;
+ else
+ break;
+ }
+ end = start + 1;
+ while (end < msemt->rows) {
+ mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
+ if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
+ break;
+ ++end;
+ }
+ *end_idx = end;
+ return start;
+}
+
+/**
+ * @image: context where the image is created
+ * @type_spec: typespec token
+ *
+ * Creates a MonoType representing the TypeSpec indexed by the @type_spec
+ * token.
+ */
+MonoType *
+mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
+{
+ guint32 idx = mono_metadata_token_index (type_spec);
+ MonoTableInfo *t;
+ guint32 cols [MONO_TYPESPEC_SIZE];
+ const char *ptr;
+ guint32 len;
+ MonoType *type;
+
+ t = &image->tables [MONO_TABLE_TYPESPEC];
+
+ mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
+ ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
+ len = mono_metadata_decode_value (ptr, &ptr);
+ type = mono_metadata_parse_type (image, MONO_PARSE_TYPE, 0, ptr, &ptr);
+
+ return type;
+}
+