2006-10-06 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / metadata.c
index fc8d5cb09ed3e87e84a37acf570e6e5a85ca7740..5b41c7add2d2e18e18dd797419dbab13e2e7f780 100644 (file)
@@ -175,7 +175,11 @@ const static unsigned char TableSchemas [] = {
        MONO_MT_TABLE_IDX,  /* "EventType" }, TypeDef or TypeRef  */
        MONO_MT_END,
 
-#define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
+#define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
+       MONO_MT_TABLE_IDX,  /* "Event" }, */
+       MONO_MT_END,
+
+#define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
        MONO_MT_UINT32,     /* "Flags" }, */
        MONO_MT_TABLE_IDX,  /* "TypeDefId" }, */
        MONO_MT_STRING_IDX, /* "TypeName" }, */
@@ -204,7 +208,11 @@ const static unsigned char TableSchemas [] = {
        MONO_MT_TABLE_IDX,  /* "Field:Field" }, */
        MONO_MT_END,
 
-#define FILE_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
+#define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
+       MONO_MT_TABLE_IDX,  /* "Field" }, */
+       MONO_MT_END,
+
+#define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
        MONO_MT_UINT32,     /* "Flags" }, */
        MONO_MT_STRING_IDX, /* "Name" }, */
        MONO_MT_BLOB_IDX,   /* "Value" },  */
@@ -256,7 +264,11 @@ const static unsigned char TableSchemas [] = {
        MONO_MT_HS_IDX,     /* "Association" }, */
        MONO_MT_END,
 
-#define MODULE_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
+#define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
+       MONO_MT_TABLE_IDX,  /* "Method" }, */
+       MONO_MT_END,
+
+#define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
        MONO_MT_UINT16,     /* "Generation" }, */
        MONO_MT_STRING_IDX, /* "Name" }, */
        MONO_MT_GUID_IDX,   /* "MVID" }, */
@@ -279,13 +291,21 @@ const static unsigned char TableSchemas [] = {
        MONO_MT_STRING_IDX, /* "Name" }, */
        MONO_MT_END,
 
-#define PROPERTY_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
+#define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
+       MONO_MT_TABLE_IDX,  /* "Param" }, */
+       MONO_MT_END,
+
+#define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
        MONO_MT_UINT16,     /* "Flags" }, */
        MONO_MT_STRING_IDX, /* "Name" }, */
        MONO_MT_BLOB_IDX,   /* "Type" }, */
        MONO_MT_END,
 
-#define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
+#define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
+       MONO_MT_TABLE_IDX, /* "Property" }, */
+       MONO_MT_END,
+
+#define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
        MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
        MONO_MT_TABLE_IDX,  /* "PropertyList:Property" }, */
        MONO_MT_END,
@@ -340,11 +360,11 @@ table_description [] = {
        MODULE_SCHEMA_OFFSET,
        TYPEREF_SCHEMA_OFFSET,
        TYPEDEF_SCHEMA_OFFSET,
-       NULL_SCHEMA_OFFSET,
+       FIELD_POINTER_SCHEMA_OFFSET,
        FIELD_SCHEMA_OFFSET,
-       NULL_SCHEMA_OFFSET,
+       METHOD_POINTER_SCHEMA_OFFSET,
        METHOD_SCHEMA_OFFSET,
-       NULL_SCHEMA_OFFSET,
+       PARAM_POINTER_SCHEMA_OFFSET,
        PARAM_SCHEMA_OFFSET,
        IFACEMAP_SCHEMA_OFFSET,
        MEMBERREF_SCHEMA_OFFSET, /* 0xa */
@@ -356,10 +376,10 @@ table_description [] = {
        FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */
        STDALON_SIG_SCHEMA_OFFSET,
        EVENTMAP_SCHEMA_OFFSET,
-       NULL_SCHEMA_OFFSET,
+       EVENT_POINTER_SCHEMA_OFFSET,
        EVENT_SCHEMA_OFFSET,
        PROPERTY_MAP_SCHEMA_OFFSET,
-       NULL_SCHEMA_OFFSET,
+       PROPERTY_POINTER_SCHEMA_OFFSET,
        PROPERTY_SCHEMA_OFFSET,
        METHOD_SEMA_SCHEMA_OFFSET,
        METHOD_IMPL_SCHEMA_OFFSET,
@@ -512,6 +532,9 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                                field_size = MAX (idx_size (MONO_TABLE_TYPEDEF), idx_size(MONO_TABLE_TYPEREF));
                                field_size = MAX (field_size, idx_size(MONO_TABLE_TYPESPEC));
                                break;
+                       case MONO_TABLE_EVENT_POINTER:
+                               g_assert (i == 0);
+                               field_size = idx_size (MONO_TABLE_EVENT); break;
                        case MONO_TABLE_EXPORTEDTYPE:
                                g_assert (i == 1);
                                /* the index is in another metadata file, so it must be 4 */
@@ -522,6 +545,9 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                        case MONO_TABLE_FIELDRVA:
                                g_assert (i == 1);
                                field_size = idx_size (MONO_TABLE_FIELD); break;
+                       case MONO_TABLE_FIELD_POINTER:
+                               g_assert (i == 0);
+                               field_size = idx_size (MONO_TABLE_FIELD); break;
                        case MONO_TABLE_IMPLMAP:
                                g_assert (i == 3);
                                field_size = idx_size (MONO_TABLE_MODULEREF); break;
@@ -537,14 +563,23 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                        case MONO_TABLE_METHODSEMANTICS:
                                g_assert (i == 1);
                                field_size = idx_size (MONO_TABLE_METHOD); break;
+                       case MONO_TABLE_METHOD_POINTER:
+                               g_assert (i == 0);
+                               field_size = idx_size (MONO_TABLE_METHOD); break;
                        case MONO_TABLE_NESTEDCLASS:
                                g_assert (i == 0 || i == 1);
                                field_size = idx_size (MONO_TABLE_TYPEDEF); break;
+                       case MONO_TABLE_PARAM_POINTER:
+                               g_assert (i == 0);
+                               field_size = idx_size (MONO_TABLE_PARAM); break;
                        case MONO_TABLE_PROPERTYMAP:
                                g_assert (i == 0 || i == 1);
                                field_size = i ? idx_size (MONO_TABLE_PROPERTY):
                                        idx_size(MONO_TABLE_TYPEDEF); 
                                break;
+                       case MONO_TABLE_PROPERTY_POINTER:
+                               g_assert (i == 0);
+                               field_size = idx_size (MONO_TABLE_PROPERTY); break;
                        case MONO_TABLE_TYPEDEF:
                                g_assert (i == 4 || i == 5);
                                field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
@@ -967,6 +1002,7 @@ mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col)
        }
        return 0;
 }
+
 /**
  * mono_metadata_decode_blob_size:
  * @ptr: pointer to a blob object
@@ -1068,6 +1104,81 @@ mono_metadata_decode_signed_value (const char *ptr, const char **rptr)
        return ival - 0x20000000;
 }
 
+/* 
+ * Translates the given 1-based index into the Method, Field, Event, or Param tables
+ * using the *Ptr tables in uncompressed metadata, if they are available.
+ *
+ * FIXME: The caller is not forced to call this function, which is error-prone, since 
+ * forgetting to call it would only show up as a bug on uncompressed metadata.
+ */
+guint32
+mono_metadata_translate_token_index (MonoImage *image, int table, guint32 idx)
+{
+       if (!image->uncompressed_metadata)
+               return idx;
+
+       switch (table) {
+       case MONO_TABLE_METHOD:
+               if (image->tables [MONO_TABLE_METHOD_POINTER].rows)
+                       return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD_POINTER], idx - 1, MONO_METHOD_POINTER_METHOD);
+               else
+                       return idx;
+       case MONO_TABLE_FIELD:
+               if (image->tables [MONO_TABLE_FIELD_POINTER].rows)
+                       return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_FIELD_POINTER], idx - 1, MONO_FIELD_POINTER_FIELD);
+               else
+                       return idx;
+       case MONO_TABLE_EVENT:
+               if (image->tables [MONO_TABLE_EVENT_POINTER].rows)
+                       return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_EVENT_POINTER], idx - 1, MONO_EVENT_POINTER_EVENT);
+               else
+                       return idx;
+       case MONO_TABLE_PROPERTY:
+               if (image->tables [MONO_TABLE_PROPERTY_POINTER].rows)
+                       return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PROPERTY_POINTER], idx - 1, MONO_PROPERTY_POINTER_PROPERTY);
+               else
+                       return idx;
+       case MONO_TABLE_PARAM:
+               if (image->tables [MONO_TABLE_PARAM_POINTER].rows)
+                       return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PARAM_POINTER], idx - 1, MONO_PARAM_POINTER_PARAM);
+               else
+                       return idx;
+       default:
+               return idx;
+       }
+}
+
+/**
+ * mono_metadata_decode_table_row:
+ *
+ *   Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
+ * uncompressed metadata into account, so it should be used to access the
+ * Method, Field, Param and Event tables.
+ */
+void
+mono_metadata_decode_table_row (MonoImage *image, int table, int idx, guint32 *res, int res_size)
+{
+       if (image->uncompressed_metadata)
+               idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
+
+       mono_metadata_decode_row (&image->tables [table], idx, res, res_size);
+}
+
+/**
+ * mono_metadata_decode_table_row_col:
+ *
+ *   Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
+ * uncompressed metadata into account, so it should be used to access the
+ * Method, Field, Param and Event tables.
+ */
+guint32 mono_metadata_decode_table_row_col (MonoImage *image, int table, int idx, guint col)
+{
+       if (image->uncompressed_metadata)
+               idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
+
+       return mono_metadata_decode_row_col (&image->tables [table], idx, col);
+}
+
 /*
  * mono_metadata_parse_typedef_or_ref:
  * @m: a metadata context.
@@ -1518,16 +1629,16 @@ mono_metadata_get_param_attrs (MonoImage *m, int def)
        MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
        MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
        guint32 cols [MONO_PARAM_SIZE];
-       guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
+       guint lastp, i, param_index = mono_metadata_decode_table_row_col (m, MONO_TABLE_METHOD, def - 1, MONO_METHOD_PARAMLIST);
        int *pattrs = NULL;
 
        if (def < methodt->rows)
-               lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
+               lastp = mono_metadata_decode_table_row_col (m, MONO_TABLE_METHOD, def, MONO_METHOD_PARAMLIST);
        else
                lastp = paramt->rows + 1;
 
        for (i = param_index; i < lastp; ++i) {
-               mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
+               mono_metadata_decode_table_row (m, MONO_TABLE_PARAM, i - 1, cols, MONO_PARAM_SIZE);
                if (cols [MONO_PARAM_FLAGS]) {
                        if (!pattrs)
                                pattrs = g_new0 (int, 1 + (lastp - param_index));
@@ -4455,6 +4566,13 @@ mono_type_get_array_type (MonoType *type)
        return type->data.array;
 }
 
+/* For MONO_TYPE_PTR */
+MonoType*
+mono_type_get_ptr_type (MonoType *type)
+{
+       return type->data.type;
+}
+
 MonoClass*
 mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
 {