[glib] xdgmime - support the new case sensitive flag



commit e1643fd76daf66ccffd9e6818e4f4ec8272e2a51
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Oct 2 09:49:51 2009 +0200

    xdgmime - support the new case sensitive flag

 gio/xdgmime/xdgmimecache.c |   86 +++++++++++++++++++++++++++++++++----------
 gio/xdgmime/xdgmimeglob.c  |   88 +++++++++++++++++++++++++++++++++++--------
 2 files changed, 137 insertions(+), 37 deletions(-)
---
diff --git a/gio/xdgmime/xdgmimecache.c b/gio/xdgmime/xdgmimecache.c
index 0f2d83a..60e2e4f 100644
--- a/gio/xdgmime/xdgmimecache.c
+++ b/gio/xdgmime/xdgmimecache.c
@@ -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);
diff --git a/gio/xdgmime/xdgmimeglob.c b/gio/xdgmime/xdgmimeglob.c
index 392eaab..b2ebda8 100644
--- a/gio/xdgmime/xdgmimeglob.c
+++ b/gio/xdgmime/xdgmimeglob.c
@@ -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;
     }
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]