xdgmime - support the new case sensitive flag
authorAlexander Larsson <alexl@redhat.com>
Fri, 2 Oct 2009 07:49:51 +0000 (09:49 +0200)
committerAlexander Larsson <alexl@redhat.com>
Fri, 2 Oct 2009 10:55:54 +0000 (12:55 +0200)
gio/xdgmime/xdgmimecache.c
gio/xdgmime/xdgmimeglob.c

index 0f2d83a..60e2e4f 100644 (file)
@@ -361,7 +361,8 @@ typedef struct {
 static int
 cache_glob_lookup_literal (const char *file_name,
                           const char *mime_types[],
-                          int         n_mime_types)
+                          int         n_mime_types,
+                          int         case_sensitive_check)
 {
   const char *ptr;
   int i, min, max, mid, cmp;
@@ -382,17 +383,25 @@ cache_glob_lookup_literal (const char *file_name,
          offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * mid);
          ptr = cache->buffer + offset;
          cmp = strcmp (ptr, file_name);
-         
+
          if (cmp < 0)
            min = mid + 1;
          else if (cmp > 0)
            max = mid - 1;
          else
            {
-             offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * mid + 4);
-             mime_types[0] = (const char *)(cache->buffer + offset);
-             
-             return 1;
+             int weight = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * mid + 8);
+             int case_sensitive = weight & 0x100;
+             weight = weight & 0xff;
+
+             if (case_sensitive_check || !case_sensitive)
+               {
+                 offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * mid + 4);
+                 mime_types[0] = (const char *)(cache->buffer + offset);
+
+                 return 1;
+               }
+             return 0;
            }
        }
     }
@@ -423,6 +432,7 @@ cache_glob_lookup_fnmatch (const char *file_name,
          xdg_uint32_t offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * j);
          xdg_uint32_t mimetype_offset = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * j + 4);
          int weight = GET_UINT32 (cache->buffer, list_offset + 4 + 12 * j + 8);
+         weight = weight & 0xff;
          ptr = cache->buffer + offset;
          mime_type = cache->buffer + mimetype_offset;
 
@@ -448,7 +458,7 @@ cache_glob_node_lookup_suffix (XdgMimeCache  *cache,
                               xdg_uint32_t   offset,
                               const char    *file_name,
                               int            len,
-                              int            ignore_case,
+                              int            case_sensitive_check,
                               MimeWeight     mime_types[],
                               int            n_mime_types)
 {
@@ -458,12 +468,11 @@ cache_glob_node_lookup_suffix (XdgMimeCache  *cache,
   xdg_uint32_t n_children;
   xdg_uint32_t child_offset; 
   int weight;
+  int case_sensitive;
 
   int min, max, mid, n, i;
 
   character = file_name[len - 1];
-  if (ignore_case)
-    character = tolower (character);
 
   assert (character != 0);
 
@@ -489,7 +498,7 @@ cache_glob_node_lookup_suffix (XdgMimeCache  *cache,
               n = cache_glob_node_lookup_suffix (cache, 
                                                  n_children, child_offset,
                                                  file_name, len, 
-                                                 ignore_case,
+                                                 case_sensitive_check,
                                                  mime_types,
                                                  n_mime_types);
             }
@@ -504,10 +513,15 @@ cache_glob_node_lookup_suffix (XdgMimeCache  *cache,
 
                  mimetype_offset = GET_UINT32 (cache->buffer, child_offset + 12 * i + 4);
                  weight = GET_UINT32 (cache->buffer, child_offset + 12 * i + 8);
+                 case_sensitive = weight & 0x100;
+                 weight = weight & 0xff;
 
-                 mime_types[n].mime = cache->buffer + mimetype_offset;
-                 mime_types[n].weight = weight;
-                 n++;
+                 if (case_sensitive_check || !case_sensitive)
+                   {
+                     mime_types[n].mime = cache->buffer + mimetype_offset;
+                     mime_types[n].weight = weight;
+                     n++;
+                   }
                  i++;
                }
            }
@@ -555,6 +569,22 @@ static int compare_mime_weight (const void *a, const void *b)
   return aa->weight - bb->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
 cache_glob_lookup_file_name (const char *file_name, 
                             const char *mime_types[],
@@ -565,20 +595,36 @@ cache_glob_lookup_file_name (const char *file_name,
   int n_mimes = 10;
   int i;
   int len;
-  
+  char *lower_case;
+  int try_lower_case;
+
   assert (file_name != NULL && n_mime_types > 0);
 
   /* First, check the literals */
-  n = cache_glob_lookup_literal (file_name, mime_types, n_mime_types);
+
+  lower_case = ascii_tolower (file_name);
+
+  n = cache_glob_lookup_literal (lower_case, mime_types, n_mime_types, FALSE);
   if (n > 0)
-    return n;
+    {
+      free (lower_case);
+      return n;
+    }
 
-  len = strlen (file_name);
-  n = cache_glob_lookup_suffix (file_name, len, FALSE, mimes, n_mimes);
+  n = cache_glob_lookup_literal (file_name, mime_types, n_mime_types, TRUE);
+  if (n > 0)
+    {
+      free (lower_case);
+      return n;
+    }
 
+  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);
-  
+
+  free (lower_case);
+
   /* Last, try fnmatch */
   if (n == 0)
     n = cache_glob_lookup_fnmatch (file_name, mimes, n_mimes);
index 392eaab..b2ebda8 100644 (file)
@@ -54,6 +54,7 @@ struct XdgGlobHashNode
   xdg_unichar_t character;
   const char *mime_type;
   int weight;
+  int case_sensitive;
   XdgGlobHashNode *next;
   XdgGlobHashNode *child;
 };
@@ -62,6 +63,7 @@ struct XdgGlobList
   const char *data;
   const char *mime_type;
   int weight;
+  int case_sensitive;
   XdgGlobList *next;
 };
 
@@ -111,15 +113,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;
 
@@ -168,7 +182,8 @@ 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 +247,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 +269,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 +280,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 +295,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 +304,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 +318,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 +330,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 +342,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 +359,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;
@@ -365,6 +385,22 @@ static int compare_mime_weight (const void *a, const void *b)
   return aa->weight - bb->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;
+}
+
 int
 _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash,
                                 const char  *file_name,
@@ -376,6 +412,8 @@ _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash,
   MimeWeight mimes[10];
   int n_mimes = 10;
   int len;
+  char *lower_case;
+  int try_lower_case;
 
   /* First, check the literals */
 
@@ -383,17 +421,32 @@ _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,
@@ -411,6 +464,7 @@ _xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash,
            }
         }
     }
+  free (lower_case);
 
   qsort (mimes, n, sizeof (MimeWeight), compare_mime_weight);
 
@@ -506,13 +560,13 @@ _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;
     }
 }