vlc | branch: master | Rémi Denis-Courmont <r...@remlab.net> | Wed Nov 30 23:43:08 2016 +0200| [40b946f2154af61d880f2de1187ec03f7d606d51] | committer: Rémi Denis-Courmont
directory: reconcile numerical and alphabetical sorting > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=40b946f2154af61d880f2de1187ec03f7d606d51 --- 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 f755e14..48c531f 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++) _______________________________________________ vlc-commits mailing list vlc-commits@videolan.org https://mailman.videolan.org/listinfo/vlc-commits