[vlc-devel] [PATCH] directory: reconcile numerical and alphabetical sorting
Jean-Baptiste Kempf
jb at videolan.org
Wed Nov 30 22:52:10 CET 2016
I very much like the idea, if it behaves like I expect it.
But, shouldn't we have tests to check the different cases for sorting?
BR,
On Wed, 30 Nov 2016, at 22:43, RĂ©mi Denis-Courmont wrote:
> Also mark the --directory-sort option obsolete.
> ---
> include/vlc_access.h | 4 +-
> modules/access/fs.c | 1 +
> modules/demux/playlist/playlist.c | 12 ------
> src/input/access.c | 83
> ++++++++++++++++++---------------------
> 4 files changed, 41 insertions(+), 59 deletions(-)
>
> diff --git a/include/vlc_access.h b/include/vlc_access.h
> index dc91e47..0531035 100644
> --- a/include/vlc_access.h
> +++ b/include/vlc_access.h
> @@ -102,7 +102,6 @@ struct access_fsdir
> int i_sub_autodetect_fuzzy;
> bool b_show_hiddenfiles;
> char *psz_ignored_exts;
> - char *psz_sort;
> };
>
> /**
> @@ -117,8 +116,7 @@ VLC_API void access_fsdir_init(struct access_fsdir
> *p_fsdir,
> /**
> * Finish adding items to the node
> *
> - * \param b_success if true, items of the node will be sorted according
> - * "directory-sort" option.
> + * \param b_success if true, items of the node will be sorted.
> */
> VLC_API void access_fsdir_finish(struct access_fsdir *p_fsdir, bool
> b_success);
>
> diff --git a/modules/access/fs.c b/modules/access/fs.c
> index edce520..fc516b4 100644
> --- a/modules/access/fs.c
> +++ b/modules/access/fs.c
> @@ -52,4 +52,5 @@ vlc_module_begin ()
>
> add_bool("list-special-files", false, N_("List special files"),
> N_("Include devices and pipes when listing directories"),
> true)
> + add_obsolete_string("directory-sort") /* since 3.0.0 */
> vlc_module_end ()
> diff --git a/modules/demux/playlist/playlist.c
> b/modules/demux/playlist/playlist.c
> index 58f89ba..c8a74e9 100644
> --- a/modules/demux/playlist/playlist.c
> +++ b/modules/demux/playlist/playlist.c
> @@ -62,16 +62,6 @@ static const char *const psz_recursive_list_text[] = {
> "collapse: subdirectories appear but are expanded on first
> play.\n" \
> "expand: all subdirectories are expanded.\n" )
>
> -static const char *const psz_sort_list[] = { "collate", "version",
> "none" };
> -static const char *const psz_sort_list_text[] = {
> - N_("Sort alphabetically according to the current language's
> collation rules."),
> - N_("Sort items in a natural order (for example: 1.ogg 2.ogg 10.ogg).
> This method does not take the current language's collation rules into
> account."),
> - N_("Do not sort the items.") };
> -
> -#define SORT_TEXT N_("Directory sort order")
> -#define SORT_LONGTEXT N_( \
> - "Define the sort algorithm used when adding items from a directory."
> )
> -
> #define IGNORE_TEXT N_("Ignored extensions")
> #define IGNORE_LONGTEXT N_( \
> "Files with these extensions will not be added to playlist when
> " \
> @@ -182,8 +172,6 @@ vlc_module_begin ()
> change_string_list( psz_recursive_list,
> psz_recursive_list_text )
> add_string( "ignore-filetypes",
> "m3u,db,nfo,ini,jpg,jpeg,ljpg,gif,png,pgm,pgmyuv,pbm,pam,tga,bmp,pnm,xpm,xcf,pcx,tif,tiff,lbm,sfv,txt,sub,idx,srt,cue,ssa",
> IGNORE_TEXT, IGNORE_LONGTEXT, false )
> - add_string( "directory-sort", "collate", SORT_TEXT,
> SORT_LONGTEXT, false )
> - change_string_list( psz_sort_list, psz_sort_list_text )
> add_bool( "show-hiddenfiles", false,
> SHOW_HIDDENFILES_TEXT, SHOW_HIDDENFILES_LONGTEXT,
> false )
> vlc_module_end ()
> diff --git a/src/input/access.c b/src/input/access.c
> index 6c48431..ed3e40f 100644
> --- a/src/input/access.c
> +++ b/src/input/access.c
> @@ -29,6 +29,9 @@
> #include <stdlib.h>
> #include <string.h>
> #include <ctype.h>
> +#ifdef HAVE_STRCOLL
> +# define strcoll strcasecmp
> +#endif
>
> #include <vlc_common.h>
> #include <vlc_url.h>
> @@ -332,9 +335,7 @@ static int compar_type(input_item_t *p1, input_item_t
> *p2)
> return 0;
> }
>
> -/* Some code duplication between comparison functions.
> - * GNU qsort_r() would be needed to solve this. */
> -static int compar_collate(const void *a, const void *b)
> +static int compar_filename(const void *a, const void *b)
> {
> input_item_node_t *const *na = a, *const *nb = b;
> input_item_t *ia = (*na)->p_item, *ib = (*nb)->p_item;
> @@ -343,28 +344,40 @@ static int compar_collate(const void *a, const void
> *b)
> if (i_ret != 0)
> return i_ret;
>
> -#ifdef HAVE_STRCOLL
> - /* The program's LOCAL defines if case is ignored */
> - return strcoll(ia->psz_name, ib->psz_name);
> -#else
> - return strcasecmp(ia->psz_name, ib->psz_name);
> -#endif
> + size_t i;
> + char c;
> +
> + /* Attempt to guess if the sorting algorithm should be alphabetic
> + * (i.e. collation) or numeric:
> + * - If the first mismatching characters are not both digits,
> + * then collation is the only option.
> + * - If one of the first mismatching characters is 0 and the other
> is also
> + * a digit, the comparands are probably left-padded numerical
> values.
> + * It does not matter which algorithm is used: the zero will be
> smaller
> + * than non-zero either way.
> + * - Otherwise, the comparands are numerical values, and might not
> be
> + * aligned (i.e. not same order of magnitude). If so, collation
> would
> + * fail. So numerical comparison is performed. */
> + for (i = 0; (c = ia->psz_name[i]) == ib->psz_name[i]; i++)
> + if (c == '\0')
> + return 0; /* strings are exactly identical */
> +
> + if ((unsigned)(c - '0') > 9)
> + return strcoll(ia->psz_name, ib->psz_name);
> +
> + unsigned long long ua = strtoull(ia->psz_name + i, NULL, 10);
> + unsigned long long ub = strtoull(ib->psz_name + i, NULL, 10);
> +
> + /* The number may be identical in two cases:
> + * - leading zero (e.g. "012" and "12")
> + * - overflow on both sides (#ULLONG_MAX) */
> + if (ua == ub)
> + return strcoll(ia->psz_name, ib->psz_name);
> +
> + return (ua > ub) ? +1 : -1;
> }
>
> -static int compar_version(const void *a, const void *b)
> -{
> - input_item_node_t *const *na = a, *const *nb = b;
> - input_item_t *ia = (*na)->p_item, *ib = (*nb)->p_item;
> -
> - int i_ret = compar_type(ia, ib);
> - if (i_ret != 0)
> - return i_ret;
> -
> - return strverscmp(ia->psz_name, ib->psz_name);
> -}
> -
> -static void fsdir_sort_sub(input_item_node_t *p_node,
> - int (*compar)(const void *, const void *))
> +static void fsdir_sort(input_item_node_t *p_node)
> {
> if (p_node->i_children <= 0)
> return;
> @@ -376,7 +389,7 @@ static void fsdir_sort_sub(input_item_node_t *p_node,
>
> /* Sort current node */
> qsort(p_node->pp_children, p_node->i_children,
> - sizeof(input_item_node_t *), compar);
> + sizeof(input_item_node_t *), compar_filename);
>
> /* Unlock all children */
> for (int i = 0; i < p_node->i_children; i++)
> @@ -384,23 +397,7 @@ static void fsdir_sort_sub(input_item_node_t
> *p_node,
>
> /* Sort all children */
> for (int i = 0; i < p_node->i_children; i++)
> - fsdir_sort_sub(p_node->pp_children[i], compar);
> -}
> -
> -static void fsdir_sort(struct access_fsdir *p_fsdir)
> -{
> - int (*pf_compar)(const void *, const void *) = NULL;
> -
> - if (p_fsdir->psz_sort != NULL)
> - {
> - if (!strcasecmp(p_fsdir->psz_sort, "version"))
> - pf_compar = compar_version;
> - else if(strcasecmp(p_fsdir->psz_sort, "none"))
> - pf_compar = compar_collate;
> -
> - if (pf_compar != NULL)
> - fsdir_sort_sub(p_fsdir->p_node, pf_compar);
> - }
> + fsdir_sort(p_node->pp_children[i]);
> }
>
> /**
> @@ -636,7 +633,6 @@ void access_fsdir_init(struct access_fsdir *p_fsdir,
> p_fsdir->p_node = p_node;
> p_fsdir->b_show_hiddenfiles = var_InheritBool(p_access,
> "show-hiddenfiles");
> p_fsdir->psz_ignored_exts = var_InheritString(p_access,
> "ignore-filetypes");
> - p_fsdir->psz_sort = var_InheritString(p_access, "directory-sort");
> bool b_autodetect = var_InheritBool(p_access,
> "sub-autodetect-file");
> p_fsdir->i_sub_autodetect_fuzzy = !b_autodetect ? 0 :
> var_InheritInteger(p_access, "sub-autodetect-fuzzy");
> @@ -648,10 +644,9 @@ void access_fsdir_finish(struct access_fsdir
> *p_fsdir, bool b_success)
> if (b_success)
> {
> fsdir_attach_slaves(p_fsdir);
> - fsdir_sort(p_fsdir);
> + fsdir_sort(p_fsdir->p_node);
> }
> free(p_fsdir->psz_ignored_exts);
> - free(p_fsdir->psz_sort);
>
> /* Remove unmatched slaves */
> for (unsigned int i = 0; i < p_fsdir->i_slaves; i++)
> --
> 2.10.2
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
--
Jean-Baptiste Kempf - President
+33 672 704 734
More information about the vlc-devel
mailing list