Add g_output_stream_write_all_async()
[platform/upstream/glib.git] / gio / xdgmime / xdgmimeglob.c
index 392eaab..73ef7a5 100644 (file)
@@ -20,9 +20,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifdef HAVE_CONFIG_H
 #include <assert.h>
 #include <string.h>
 #include <fnmatch.h>
-#include <ctype.h>
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
 
 #ifndef        FALSE
 #define        FALSE   (0)
@@ -54,6 +55,7 @@ struct XdgGlobHashNode
   xdg_unichar_t character;
   const char *mime_type;
   int weight;
+  int case_sensitive;
   XdgGlobHashNode *next;
   XdgGlobHashNode *child;
 };
@@ -62,6 +64,7 @@ struct XdgGlobList
   const char *data;
   const char *mime_type;
   int weight;
+  int case_sensitive;
   XdgGlobList *next;
 };
 
@@ -111,15 +114,27 @@ static XdgGlobList *
 _xdg_glob_list_append (XdgGlobList *glob_list,
                       void        *data,
                       const char  *mime_type,
-                      int          weight)
+                      int          weight,
+                      int          case_sensitive)
 {
   XdgGlobList *new_element;
   XdgGlobList *tmp_element;
 
+  tmp_element = glob_list;
+  while (tmp_element != NULL)
+    {
+      if (strcmp (tmp_element->data, data) == 0 &&
+         strcmp (tmp_element->mime_type, mime_type) == 0)
+       return glob_list;
+
+      tmp_element = tmp_element->next;
+    }
+
   new_element = _xdg_glob_list_new ();
   new_element->data = data;
   new_element->mime_type = mime_type;
   new_element->weight = weight;
+  new_element->case_sensitive = case_sensitive;
   if (glob_list == NULL)
     return new_element;
 
@@ -145,6 +160,8 @@ _xdg_glob_hash_node_new (void)
   return glob_hash_node;
 }
 
+#ifdef NOT_USED_IN_GIO
+
 static void
 _xdg_glob_hash_node_dump (XdgGlobHashNode *glob_hash_node,
                          int depth)
@@ -164,11 +181,14 @@ _xdg_glob_hash_node_dump (XdgGlobHashNode *glob_hash_node,
     _xdg_glob_hash_node_dump (glob_hash_node->next, depth);
 }
 
+#endif
+
 static XdgGlobHashNode *
 _xdg_glob_hash_insert_ucs4 (XdgGlobHashNode *glob_hash_node,
                            xdg_unichar_t   *text,
                            const char      *mime_type,
-                           int              weight)
+                           int              weight,
+                           int              case_sensitive)
 {
   XdgGlobHashNode *node;
   xdg_unichar_t character;
@@ -232,11 +252,11 @@ _xdg_glob_hash_insert_ucs4 (XdgGlobHashNode *glob_hash_node,
     {
       if (node->mime_type)
        {
-         if (strcmp (node->mime_type, mime_type))
+         if (strcmp (node->mime_type, mime_type) != 0)
            {
              XdgGlobHashNode *child;
              int found_node = FALSE;
-             
+
              child = node->child;
              while (child && child->character == 0)
                {
@@ -254,6 +274,7 @@ _xdg_glob_hash_insert_ucs4 (XdgGlobHashNode *glob_hash_node,
                  child->character = 0;
                  child->mime_type = strdup (mime_type);
                  child->weight = weight;
+                 child->case_sensitive = case_sensitive;
                  child->child = NULL;
                  child->next = node->child;
                  node->child = child;
@@ -264,11 +285,12 @@ _xdg_glob_hash_insert_ucs4 (XdgGlobHashNode *glob_hash_node,
        {
          node->mime_type = strdup (mime_type);
          node->weight = weight;
+         node->case_sensitive = case_sensitive;
        }
     }
   else
     {
-      node->child = _xdg_glob_hash_insert_ucs4 (node->child, text, mime_type, weight);
+      node->child = _xdg_glob_hash_insert_ucs4 (node->child, text, mime_type, weight, case_sensitive);
     }
   return glob_hash_node;
 }
@@ -278,7 +300,8 @@ static XdgGlobHashNode *
 _xdg_glob_hash_insert_text (XdgGlobHashNode *glob_hash_node,
                            const char      *text,
                            const char      *mime_type,
-                           int              weight)
+                           int              weight,
+                           int              case_sensitive)
 {
   XdgGlobHashNode *node;
   xdg_unichar_t *unitext;
@@ -286,7 +309,7 @@ _xdg_glob_hash_insert_text (XdgGlobHashNode *glob_hash_node,
 
   unitext = _xdg_convert_to_ucs4 (text, &len);
   _xdg_reverse_ucs4 (unitext, len);
-  node = _xdg_glob_hash_insert_ucs4 (glob_hash_node, unitext, mime_type, weight);
+  node = _xdg_glob_hash_insert_ucs4 (glob_hash_node, unitext, mime_type, weight, case_sensitive);
   free (unitext);
   return node;
 }
@@ -300,7 +323,7 @@ static int
 _xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node,
                                      const char      *file_name,
                                      int              len,
-                                     int              ignore_case,
+                                     int              case_sensitive_check,
                                      MimeWeight       mime_types[],
                                      int              n_mime_types)
 {
@@ -312,8 +335,6 @@ _xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node,
     return 0;
 
   character = file_name[len - 1];
-  if (ignore_case)
-    character = tolower(character);
 
   for (node = glob_hash_node; node && character >= node->character; node = node->next)
     {
@@ -326,13 +347,15 @@ _xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node,
              n = _xdg_glob_hash_node_lookup_file_name (node->child,
                                                        file_name,
                                                        len,
-                                                       ignore_case,
+                                                       case_sensitive_check,
                                                        mime_types,
                                                        n_mime_types);
            }
          if (n == 0)
            {
-              if (node->mime_type)
+              if (node->mime_type &&
+                 (case_sensitive_check ||
+                  !node->case_sensitive))
                 {
                  mime_types[n].mime = node->mime_type;
                  mime_types[n].weight = node->weight;
@@ -341,7 +364,9 @@ _xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node,
              node = node->child;
              while (n < n_mime_types && node && node->character == 0)
                {
-                  if (node->mime_type)
+                  if (node->mime_type &&
+                     (case_sensitive_check ||
+                      !node->case_sensitive))
                    {
                      mime_types[n].mime = node->mime_type;
                      mime_types[n].weight = node->weight;
@@ -362,7 +387,51 @@ static int compare_mime_weight (const void *a, const void *b)
   const MimeWeight *aa = (const MimeWeight *)a;
   const MimeWeight *bb = (const MimeWeight *)b;
 
-  return aa->weight - bb->weight;
+  return bb->weight - aa->weight;
+}
+
+#define ISUPPER(c)             ((c) >= 'A' && (c) <= 'Z')
+static char *
+ascii_tolower (const char *str)
+{
+  char *p, *lower;
+
+  lower = strdup (str);
+  p = lower;
+  while (*p != 0)
+    {
+      char c = *p;
+      *p++ = ISUPPER (c) ? c - 'A' + 'a' : c;
+    }
+  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
@@ -376,6 +445,7 @@ _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash,
   MimeWeight mimes[10];
   int n_mimes = 10;
   int len;
+  char *lower_case;
 
   /* First, check the literals */
 
@@ -383,23 +453,38 @@ _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash,
 
   n = 0;
 
+  lower_case = ascii_tolower (file_name);
+
   for (list = glob_hash->literal_list; list; list = list->next)
     {
       if (strcmp ((const char *)list->data, file_name) == 0)
        {
          mime_types[0] = list->mime_type;
+         free (lower_case);
+         return 1;
+       }
+    }
+
+  for (list = glob_hash->literal_list; list; list = list->next)
+    {
+      if (!list->case_sensitive &&
+         strcmp ((const char *)list->data, lower_case) == 0)
+       {
+         mime_types[0] = list->mime_type;
+         free (lower_case);
          return 1;
        }
     }
 
+
   len = strlen (file_name);
-  n = _xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, file_name, len, FALSE,
+  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)
         {
@@ -411,6 +496,9 @@ _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);
 
@@ -506,17 +594,19 @@ _xdg_glob_hash_append_glob (XdgGlobHash *glob_hash,
   switch (type)
     {
     case XDG_GLOB_LITERAL:
-      glob_hash->literal_list = _xdg_glob_list_append (glob_hash->literal_list, strdup (glob), strdup (mime_type), weight);
+      glob_hash->literal_list = _xdg_glob_list_append (glob_hash->literal_list, strdup (glob), strdup (mime_type), weight, case_sensitive);
       break;
     case XDG_GLOB_SIMPLE:
-      glob_hash->simple_node = _xdg_glob_hash_insert_text (glob_hash->simple_node, glob + 1, mime_type, weight);
+      glob_hash->simple_node = _xdg_glob_hash_insert_text (glob_hash->simple_node, glob + 1, mime_type, weight, case_sensitive);
       break;
     case XDG_GLOB_FULL:
-      glob_hash->full_list = _xdg_glob_list_append (glob_hash->full_list, strdup (glob), strdup (mime_type), weight);
+      glob_hash->full_list = _xdg_glob_list_append (glob_hash->full_list, strdup (glob), strdup (mime_type), weight, case_sensitive);
       break;
     }
 }
 
+#ifdef NOT_USED_IN_GIO
+
 void
 _xdg_glob_hash_dump (XdgGlobHash *glob_hash)
 {
@@ -553,6 +643,7 @@ _xdg_glob_hash_dump (XdgGlobHash *glob_hash)
     }
 }
 
+#endif
 
 void
 _xdg_mime_glob_read_from_file (XdgGlobHash *glob_hash,