static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
static guint32 mono_field_resolve_flags (MonoClassField *field);
+static MonoClass *
+mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, gboolean case_sensitive, MonoError *error);
+
GENERATE_GET_CLASS_WITH_CACHE (valuetype, "System", "ValueType")
GENERATE_TRY_GET_CLASS_WITH_CACHE (handleref, "System.Runtime.InteropServices", "HandleRef")
typedef struct {
gconstpointer key;
+ GSList *values;
+} FindAllUserData;
+
+static void
+find_all_nocase (gpointer key, gpointer value, gpointer user_data)
+{
+ char *name = (char*)key;
+ FindAllUserData *data = (FindAllUserData*)user_data;
+ if (mono_utf8_strcasecmp (name, (char*)data->key) == 0)
+ data->values = g_slist_prepend (data->values, value);
+}
+
+typedef struct {
+ gconstpointer key;
gpointer value;
} FindUserData;
MonoClass *
mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
{
- MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
- guint32 cols [MONO_TYPEDEF_SIZE];
- const char *n;
- const char *nspace;
- guint32 i, visib;
-
- error_init (error);
-
- if (image_is_dynamic (image)) {
- guint32 token = 0;
- FindUserData user_data;
-
- mono_image_init_name_cache (image);
- mono_image_lock (image);
-
- user_data.key = name_space;
- user_data.value = NULL;
- g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
-
- if (user_data.value) {
- GHashTable *nspace_table = (GHashTable*)user_data.value;
-
- user_data.key = name;
- user_data.value = NULL;
+ MonoClass *klass;
+ GHashTable *visited_images;
- g_hash_table_foreach (nspace_table, find_nocase, &user_data);
-
- if (user_data.value)
- token = GPOINTER_TO_UINT (user_data.value);
- }
+ visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
- mono_image_unlock (image);
-
- if (token)
- return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
- else
- return NULL;
+ klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, FALSE, error);
- }
+ g_hash_table_destroy (visited_images);
- /* add a cache if needed */
- for (i = 1; i <= t->rows; ++i) {
- mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
- visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
- /*
- * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
- * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
- */
- if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
- continue;
- n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
- nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
- if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
- return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
- }
- return NULL;
+ return klass;
}
static MonoClass*
-return_nested_in (MonoClass *klass, char *nested)
+return_nested_in (MonoClass *klass, char *nested, gboolean case_sensitive)
{
MonoClass *found;
char *s = strchr (nested, '/');
}
while ((found = mono_class_get_nested_types (klass, &iter))) {
- if (strcmp (m_class_get_name (found), nested) == 0) {
+ const char *name = m_class_get_name (found);
+ gint strcmp_result;
+ if (case_sensitive)
+ strcmp_result = strcmp (name, nested);
+ else
+ strcmp_result = mono_utf8_strcasecmp (name, nested);
+
+ if (strcmp_result == 0) {
if (s)
- return return_nested_in (found, s);
+ return return_nested_in (found, s, case_sensitive);
return found;
}
}
}
static MonoClass*
-search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
+search_modules (MonoImage *image, const char *name_space, const char *name, gboolean case_sensitive, MonoError *error)
{
MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
MonoImage *file_image;
file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
if (file_image) {
- klass = mono_class_from_name_checked (file_image, name_space, name, error);
+ if (case_sensitive)
+ klass = mono_class_from_name_checked (file_image, name_space, name, error);
+ else
+ klass = mono_class_from_name_case_checked (file_image, name_space, name, error);
+
if (klass || !is_ok (error))
return klass;
}
}
static MonoClass *
-mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
+mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, gboolean case_sensitive, MonoError *error)
{
- GHashTable *nspace_table;
- MonoImage *loaded_image;
+ GHashTable *nspace_table = NULL;
+ MonoImage *loaded_image = NULL;
guint32 token = 0;
int i;
MonoClass *klass;
}
/* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
- if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
+ // The AOT cache in get_class_from_name is case-sensitive, so don't bother with it for case-insensitive lookups
+ if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0 && case_sensitive) {
gboolean res = get_class_from_name (image, name_space, name, &klass);
if (res) {
if (!klass) {
- klass = search_modules (image, name_space, name, error);
+ klass = search_modules (image, name_space, name, case_sensitive, error);
if (!is_ok (error))
return NULL;
}
if (nested)
- return klass ? return_nested_in (klass, nested) : NULL;
+ return klass ? return_nested_in (klass, nested, case_sensitive) : NULL;
else
return klass;
}
mono_image_init_name_cache (image);
mono_image_lock (image);
- nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
+ if (case_sensitive) {
+ nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
+
+ if (nspace_table)
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
+ } else {
+ FindAllUserData all_user_data = { name_space, NULL };
+ FindUserData user_data = { name, NULL };
+ GSList *values;
- if (nspace_table)
- token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
+ // We're forced to check all matching namespaces, not just the first one found,
+ // because our desired type could be in any of the ones that match case-insensitively.
+ g_hash_table_foreach (image->name_cache, find_all_nocase, &all_user_data);
+
+ values = all_user_data.values;
+ while (values && !user_data.value) {
+ nspace_table = (GHashTable*)values->data;
+ g_hash_table_foreach (nspace_table, find_nocase, &user_data);
+ values = values->next;
+ }
+
+ g_slist_free (all_user_data.values);
+
+ if (user_data.value)
+ token = GPOINTER_TO_UINT (user_data.value);
+ }
mono_image_unlock (image);
for (i = 0; i < image->module_count; ++i) {
MonoImage *module = image->modules [i];
- klass = mono_class_from_name_checked (module, name_space, name, error);
+ if (case_sensitive)
+ klass = mono_class_from_name_checked (module, name_space, name, error);
+ else
+ klass = mono_class_from_name_case_checked (module, name_space, name, error);
+
if (klass || !is_ok (error))
return klass;
}
}
if (!token) {
- klass = search_modules (image, name_space, name, error);
+ klass = search_modules (image, name_space, name, case_sensitive, error);
if (klass || !is_ok (error))
return klass;
return NULL;
loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
if (!loaded_image)
return NULL;
- klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
+ klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, case_sensitive, error);
if (nested)
- return klass ? return_nested_in (klass, nested) : NULL;
+ return klass ? return_nested_in (klass, nested, case_sensitive) : NULL;
return klass;
} else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
guint32 assembly_idx;
g_assert (image->references [assembly_idx - 1]);
if (image->references [assembly_idx - 1] == (gpointer)-1)
return NULL;
- klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
+ klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, case_sensitive, error);
if (nested)
- return klass ? return_nested_in (klass, nested) : NULL;
+ return klass ? return_nested_in (klass, nested, case_sensitive) : NULL;
return klass;
} else {
g_assert_not_reached ();
klass = mono_class_get_checked (image, token, error);
if (nested)
- return return_nested_in (klass, nested);
+ return return_nested_in (klass, nested, case_sensitive);
return klass;
}
visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
- klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
+ klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, TRUE, error);
g_hash_table_destroy (visited_images);