[easytag/wip/core-refactoring: 1/6] Add a case-insensitive UTF-8 string comparison



commit b4ee3527b86dc16ec6109b86b484e2699b197343
Author: David King <amigadave amigadave com>
Date:   Mon Feb 1 22:01:21 2016 +0000

    Add a case-insensitive UTF-8 string comparison
    
    Add et_normalized_strcasecmp0(), a function much like strcasecmp(), but
    that handles UTF-8 text by normalizing it, casefolding it and then
    comparing with g_utf8_collate(). Use the new function when sorting the
    album/artist list.

 src/file_list.c |   40 +++++++++++++++++++++++-----------------
 src/misc.c      |   42 ++++++++++++++++++++++++++++++++++++++++++
 src/misc.h      |    1 +
 3 files changed, 66 insertions(+), 17 deletions(-)
---
diff --git a/src/file_list.c b/src/file_list.c
index 27a7dc3..550cc71 100644
--- a/src/file_list.c
+++ b/src/file_list.c
@@ -1,5 +1,5 @@
 /* EasyTAG - tag editor for audio files
- * Copyright (C) 2014  David King <amigadave amigadave com>
+ * Copyright (C) 2014-2016  David King <amigadave amigadave com>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -537,22 +537,25 @@ ET_Comp_Func_Sort_Artist_Item_By_Ascending_Artist (const GList *AlbumList1,
     const gchar *etfile1_artist;
     const gchar *etfile2_artist;
 
-    if (!AlbumList1
-    || !(etfilelist1    = (GList *)AlbumList1->data)
-    || !(etfile1        = (ET_File *)etfilelist1->data)
-    || !(etfile1_artist = ((File_Tag *)etfile1->FileTag->data)->artist) )
+    if (!AlbumList1 || !(etfilelist1 = (GList *)AlbumList1->data)
+        || !(etfile1 = (ET_File *)etfilelist1->data))
+    {
         return -1;
+    }
 
-    if (!AlbumList2
-    || !(etfilelist2    = (GList *)AlbumList2->data)
-    || !(etfile2        = (ET_File *)etfilelist2->data)
-    || !(etfile2_artist = ((File_Tag *)etfile2->FileTag->data)->artist) )
+    if (!AlbumList2 || !(etfilelist2 = (GList *)AlbumList2->data)
+        || !(etfile2 = (ET_File *)etfilelist2->data))
+    {
         return 1;
+    }
+
+    etfile1_artist = ((File_Tag *)etfile1->FileTag->data)->artist;
+    etfile2_artist = ((File_Tag *)etfile2->FileTag->data)->artist;
 
     /*if (g_settings_get_boolean (MainSettings, "sort-case-sensitive"))
      *    return strcmp(etfile1_artist,etfile2_artist); */
     //else
-        return strcasecmp(etfile1_artist,etfile2_artist);
+        return et_normalized_strcasecmp0 (etfile1_artist, etfile2_artist);
 }
 
 /*
@@ -567,20 +570,23 @@ ET_Comp_Func_Sort_Album_Item_By_Ascending_Album (const GList *etfilelist1,
     const gchar *etfile1_album;
     const gchar *etfile2_album;
 
-    if (!etfilelist1
-    || !(etfile1        = (ET_File *)etfilelist1->data)
-    || !(etfile1_album  = ((File_Tag *)etfile1->FileTag->data)->album) )
+    if (!etfilelist1 || !(etfile1 = (ET_File *)etfilelist1->data))
+    {
         return -1;
+    }
 
-    if (!etfilelist2
-    || !(etfile2        = (ET_File *)etfilelist2->data)
-    || !(etfile2_album  = ((File_Tag *)etfile2->FileTag->data)->album) )
+    if (!etfilelist2 || !(etfile2 = (ET_File *)etfilelist2->data))
+    {
         return 1;
+    }
+
+    etfile1_album  = ((File_Tag *)etfile1->FileTag->data)->album;
+    etfile2_album  = ((File_Tag *)etfile2->FileTag->data)->album;
 
     /*if (g_settings_get_boolean (MainSettings, "sort-case-sensitive"))
      *    return strcmp(etfile1_album,etfile2_album); */
     //else
-        return strcasecmp(etfile1_album,etfile2_album);
+        return et_normalized_strcasecmp0 (etfile1_album, etfile2_album);
 }
 
 /*
diff --git a/src/misc.c b/src/misc.c
index 326ffe6..89cbafa 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -622,6 +622,48 @@ et_normalized_strcmp0 (const gchar *str1,
 }
 
 /*
+ * et_normalized_strcasecmp0:
+ * @str1: UTF-8 string, or %NULL
+ * @str2: UTF-8 string to compare against, or %NULL
+ *
+ * Compare two UTF-8 strings, normalizing them before doing so, in a
+ * case-insensitive manner.
+ *
+ * Returns: an integer less than, equal to, or greater than zero, if str1 is
+ * less than, equal to or greater than str2
+ */
+gint
+et_normalized_strcasecmp0 (const gchar *str1,
+                           const gchar *str2)
+{
+    gint result;
+    gchar *casefolded1;
+    gchar *casefolded2;
+
+    /* Check for NULL, as it cannot be passed to g_utf8_casefold(). */
+    if (!str1)
+    {
+        return -(str1 != str2);
+    }
+
+    if (!str2)
+    {
+        return str1 != str2;
+    }
+
+    /* The strings are automatically normalized during casefolding. */
+    casefolded1 = g_utf8_casefold (str1, -1);
+    casefolded2 = g_utf8_casefold (str2, -1);
+
+    result = g_utf8_collate (casefolded1, casefolded2);
+
+    g_free (casefolded1);
+    g_free (casefolded2);
+
+    return result;
+}
+
+/*
  * et_str_empty:
  * @str: string to test for emptiness
  *
diff --git a/src/misc.h b/src/misc.h
index abf1add..18a77f2 100644
--- a/src/misc.h
+++ b/src/misc.h
@@ -42,6 +42,7 @@ gboolean et_rename_file (const gchar *old_filename, const gchar *new_filename, G
 
 guint et_undo_key_new (void);
 gint et_normalized_strcmp0 (const gchar *str1, const gchar *str2);
+gint et_normalized_strcasecmp0 (const gchar *str1, const gchar *str2);
 gboolean et_str_empty (const gchar *str);
 
 G_END_DECLS


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