From e63262d49d40a36060613fb1d0ed468ca5dddc19 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 25 Oct 2009 02:55:46 -0400 Subject: [PATCH] Don't give up too early when collecting mime types Since returning exactly one match has special significance, don't give up matching before we've found at least 2 types. Also, make sure that we don't return the same mime type more than once. Bug 541236. --- gio/xdgmime/xdgmimecache.c | 67 +++++++++++++++++++++++++++++++++------------- gio/xdgmime/xdgmimeglob.c | 43 +++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 23 deletions(-) diff --git a/gio/xdgmime/xdgmimecache.c b/gio/xdgmime/xdgmimecache.c index 97fe975..43cda89 100644 --- a/gio/xdgmime/xdgmimecache.c +++ b/gio/xdgmime/xdgmimecache.c @@ -444,11 +444,11 @@ cache_glob_lookup_fnmatch (const char *file_name, } } - if (n > 0) - return n; + if (n == n_mime_types) + break; } - - return 0; + + return n; } static int @@ -539,6 +539,7 @@ cache_glob_lookup_suffix (const char *file_name, { int i, n; + n = 0; for (i = 0; _caches[i]; i++) { XdgMimeCache *cache = _caches[i]; @@ -547,17 +548,17 @@ cache_glob_lookup_suffix (const char *file_name, xdg_uint32_t n_entries = GET_UINT32 (cache->buffer, list_offset); xdg_uint32_t offset = GET_UINT32 (cache->buffer, list_offset + 4); - n = cache_glob_node_lookup_suffix (cache, - n_entries, offset, - file_name, len, - ignore_case, - mime_types, - n_mime_types); - if (n > 0) - return n; + n += cache_glob_node_lookup_suffix (cache, + n_entries, offset, + file_name, len, + ignore_case, + mime_types + n, + n_mime_types - n); + if (n == n_mime_types) + break; } - return 0; + return n; } static int compare_mime_weight (const void *a, const void *b) @@ -585,7 +586,35 @@ ascii_tolower (const char *str) } static int -cache_glob_lookup_file_name (const char *file_name, +filter_out_dupes (MimeWeight mimes[], int n_mimes) +{ + int last; + int i, j; + + last = n_mimes; + + for (i = 0; i < last; i++) + { + j = i + 1; + while (j < last) + { + if (strcmp (mimes[i].mime, mimes[j].mime) == 0) + { + mimes[i].weight = MAX (mimes[i].weight, mimes[j].weight); + last--; + mimes[j].mime = mimes[last].mime; + mimes[j].weight = mimes[last].weight; + } + else + j++; + } + } + + return last; +} + +static int +cache_glob_lookup_file_name (const char *file_name, const char *mime_types[], int n_mime_types) { @@ -619,14 +648,16 @@ cache_glob_lookup_file_name (const char *file_name, len = strlen (file_name); n = cache_glob_lookup_suffix (lower_case, len, FALSE, mimes, n_mimes); - if (n == 0) - n = cache_glob_lookup_suffix (file_name, len, TRUE, mimes, n_mimes); + if (n < 2) + n += cache_glob_lookup_suffix (file_name, len, TRUE, mimes + n, n_mimes - n); free (lower_case); /* Last, try fnmatch */ - if (n == 0) - n = cache_glob_lookup_fnmatch (file_name, mimes, n_mimes); + if (n < 2) + n += cache_glob_lookup_fnmatch (file_name, mimes + n, n_mimes - n); + + n = filter_out_dupes (mimes, n); qsort (mimes, n, sizeof (MimeWeight), compare_mime_weight); diff --git a/gio/xdgmime/xdgmimeglob.c b/gio/xdgmime/xdgmimeglob.c index c82bf22..daea606 100644 --- a/gio/xdgmime/xdgmimeglob.c +++ b/gio/xdgmime/xdgmimeglob.c @@ -37,6 +37,10 @@ #include #include +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + #ifndef FALSE #define FALSE (0) #endif @@ -400,6 +404,34 @@ ascii_tolower (const char *str) return lower; } +static int +filter_out_dupes (MimeWeight mimes[], int n_mimes) +{ + int last; + int i, j; + + last = n_mimes; + + for (i = 0; i < last; i++) + { + j = i + 1; + while (j < last) + { + if (strcmp (mimes[i].mime, mimes[j].mime) == 0) + { + mimes[i].weight = MAX (mimes[i].weight, mimes[j].weight); + last--; + mimes[j].mime = mimes[last].mime; + mimes[j].weight = mimes[last].weight; + } + else + j++; + } + } + + return last; +} + int _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash, const char *file_name, @@ -412,7 +444,6 @@ _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash, int n_mimes = 10; int len; char *lower_case; - int try_lower_case; /* First, check the literals */ @@ -447,11 +478,11 @@ _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash, len = strlen (file_name); n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, lower_case, len, FALSE, mimes, n_mimes); - if (n == 0) - n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, file_name, len, TRUE, - mimes, n_mimes); + if (n < 2) + n += _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, file_name, len, TRUE, + mimes + n, n_mimes - n); - if (n == 0) + if (n < 2) { for (list = glob_hash->full_list; list && n < n_mime_types; list = list->next) { @@ -465,6 +496,8 @@ _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash, } free (lower_case); + n = filter_out_dupes (mimes, n); + qsort (mimes, n, sizeof (MimeWeight), compare_mime_weight); if (n_mime_types < n) -- 2.7.4