[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