[tracker-miners/wip/carlosg/term-ellipsizing] libtracker-miners-common: Improve terminal ellipsizing helper




commit ef6ebab3b4697843f4884964358ca19a42120b38
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Feb 4 22:29:24 2021 +0100

    libtracker-miners-common: Improve terminal ellipsizing helper
    
    This was in a sorry state for some reasons:
    - It was pretty oblivious to UTF-8, so it might cut the string
      mid-character.
    - It uses g_memdup(), which should be best avoided. See
      https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1928
    
    For the former, use g_utf8_* API to count characters (which is
    what we want for terminal formatting purposes). For the latter,
    use g_strndup(), which is gchar* oriented and takes gsize, to
    avoid vulnerabilities and incompatibilities.

 src/libtracker-miners-common/tracker-term-utils.c | 25 ++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)
---
diff --git a/src/libtracker-miners-common/tracker-term-utils.c 
b/src/libtracker-miners-common/tracker-term-utils.c
index 96e90da5f..d619d209d 100644
--- a/src/libtracker-miners-common/tracker-term-utils.c
+++ b/src/libtracker-miners-common/tracker-term-utils.c
@@ -39,18 +39,37 @@ tracker_term_ellipsize (const gchar          *str,
                         gint                  max_len,
                         TrackerEllipsizeMode  mode)
 {
-       gint len = strlen (str);
+       gsize size = strlen (str);
+       glong len = g_utf8_strlen (str, size);
+       const gchar *begin, *end, *pos;
        gchar *substr, *retval;
+       gint i;
 
        if (len < max_len)
                return g_strdup (str);
 
+       /* Account for the ellipsizing char */
+       max_len--;
+       if (max_len <= 0)
+               return g_strdup ("…");
+
+       begin = str;
+       end = &str[size];
+
        if (mode == TRACKER_ELLIPSIZE_START) {
-               substr = g_memdup (str + len - max_len + 1, max_len - 1);
+               pos = begin;
+               for (i = 0; i < max_len; i++)
+                       pos = g_utf8_find_next_char (pos, end);
+
+               substr = g_strndup (begin, pos - begin);
                retval = g_strdup_printf ("…%s", substr);
                g_free (substr);
        } else {
-               substr = g_memdup (str, max_len - 1);
+               pos = end;
+               for (i = 0; i < max_len; i++)
+                       pos = g_utf8_find_prev_char (begin, pos);
+
+               substr = g_strndup (pos, end - pos);
                retval = g_strdup_printf ("%s…", substr);
                g_free (substr);
        }


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