[vlc-devel] [PATCH 1/2] strings: add vlc_strfilecmp()

RĂ©mi Denis-Courmont remi at remlab.net
Tue Aug 30 11:53:11 CEST 2016


This should sort file names better than either strverscmp() or
strcoll().
---
 include/vlc_strings.h | 20 ++++++++++++++
 src/libvlccore.sym    |  1 +
 src/text/strings.c    | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 95 insertions(+)

diff --git a/include/vlc_strings.h b/include/vlc_strings.h
index 1bbb82f..d3a25e9 100644
--- a/include/vlc_strings.h
+++ b/include/vlc_strings.h
@@ -134,6 +134,26 @@ VLC_API char * vlc_b64_decode( const char *psz_src );
 VLC_API char *vlc_strftime( const char * );
 
 /**
+ * Sorts file names.
+ *
+ * Compares two file names for sorting purpose.
+ *
+ * @note This functions expects file names, though it will also work with
+ * complete absolute local file paths (if slashes are not duplicated).
+ * The function should also work with a <b>single decoded</b> URI component.
+ *
+ * @warning Sorting will <b>not</b> work with a complete URI,
+ * or rather the result of the comparison will be meaningless.
+ *
+ * @param s1 first file name
+ * @param s2 second file name
+ * @retval >0 if the first file name is larger than the second one
+ * @retval <0 if the first file name is smaller than the second one
+ * @return 0 if the strings are identical
+ */
+VLC_API int vlc_strfilecmp(const char *s1, const char *s2);
+
+/**
  * Formats input meta-data.
  *
  * Formats input and input item meta-informations into a heap-allocated string.
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index ae86025..54d1906 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -424,6 +424,7 @@ vlc_stream_fifo_Write
 vlc_stream_fifo_Close
 vlc_strfinput
 vlc_strftime
+vlc_strfilecmp
 subpicture_Delete
 subpicture_New
 subpicture_NewFromPicture
diff --git a/src/text/strings.c b/src/text/strings.c
index 5ebf46c..83f5abb6 100644
--- a/src/text/strings.c
+++ b/src/text/strings.c
@@ -827,6 +827,80 @@ char *vlc_strfinput(input_thread_t *input, const char *s)
 #endif
 }
 
+static size_t skip_equal_non_numeric(const char *s1, const char *s2)
+{
+    for (size_t i = 0; s1[i] == s2[i]; i++)
+    {
+        if (s1[i] == '\0')
+            return i;
+
+        /* This assumes that numbering characters are always ASCII... */
+        if (atoll(&s1[i]) != 0 && atoll(&s2[i]) != 0)
+        {
+            fprintf(stderr, "s1 += %zu\n", i);
+            return i;
+        }
+    }
+
+    return 0;
+}
+
+int vlc_strfilecmp(const char *s1, const char *s2)
+{
+    while (s1[0] != '\0' && s2[0] != '\0')
+    {
+        char *e1, *e2;
+        long long n1 = strtoll(s1, &e1, 10);
+        long long n2 = strtoll(s2, &e2, 10);
+
+        fprintf(stderr, "%s <> %s\nends: %s, %s\n", s1, s2, e1, e2);
+
+        if (e1 > s1 && e2 > s2)
+        {
+            if (n1 > n2)
+                return +1;
+            if (n1 < n2)
+                return -1;
+            if (n1 != LLONG_MAX && n1 != LLONG_MIN)
+            {
+                s1 = e1;
+                s2 = e2;
+                continue;
+            }
+        }
+
+        /* Check if there is another numeric value after identical text. */
+        size_t skip = skip_equal_non_numeric(e1, e2);
+        if (skip > 0)
+        {
+            s1 = e1 + skip;
+            s2 = e2 + skip;
+            continue;
+        }
+
+        /* Do not use 'i' here; it could point in the middle of a multi-byte
+         * character. strcoll() and strcasecmp() would not work then. */
+        int d;
+#ifdef HAVE_STRCOLL
+        d = strcoll(s1, s2);
+        fprintf(stderr, "coll = %d\n", d);
+        if (d)
+            return d;
+#endif
+        fprintf(stderr, "case? %s <> %s\n", s1, s2);
+
+        d = strcasecmp(s1, s2);
+        if (d)
+            return d;
+
+        return strcmp(s1, s2);
+    }
+
+    /* If one string is a prefix of the other one,
+     * treat the longer string as the biggest. */
+    return s1[0] - s2[0];
+}
+
 /**
  * Sanitize a file name.
  *
-- 
2.9.3



More information about the vlc-devel mailing list