Skip to content

Commit

Permalink
Sort playlists ignoring extension.
Browse files Browse the repository at this point in the history
"Sony - PlayStation 2" sorts before "Sony - PlayStation" because when
the menu sorts, it includes the `.lpl` extension, and space comes
before period.
  • Loading branch information
warmenhoven committed Oct 28, 2023
1 parent 6d1b769 commit c53bb64
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 1 deletion.
9 changes: 9 additions & 0 deletions libretro-common/include/lists/dir_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,15 @@ bool dir_list_initialize(struct string_list *list,
**/
void dir_list_sort(struct string_list *list, bool dir_first);

/**
* dir_list_sort_ignore_ext:
* @list : pointer to the directory listing.
* @dir_first : move the directories in the listing to the top?
*
* Sorts a directory listing. File extensions are ignored.
**/
void dir_list_sort_ignore_ext(struct string_list *list, bool dir_first);

/**
* dir_list_free:
* @list : pointer to the directory listing
Expand Down
43 changes: 43 additions & 0 deletions libretro-common/lists/dir_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,22 @@ static int qstrcmp_plain(const void *a_, const void *b_)
return strcasecmp(a->data, b->data);
}

static int qstrcmp_plain_noext(const void *a_, const void *b_)
{
const struct string_list_elem *a = (const struct string_list_elem*)a_;
const struct string_list_elem *b = (const struct string_list_elem*)b_;

const char *ext_a = path_get_extension(a->data);
size_t l_a = string_is_empty(ext_a) ? strlen(a->data) : (ext_a - a->data - 1);
const char *ext_b = path_get_extension(b->data);
size_t l_b = string_is_empty(ext_b) ? strlen(b->data) : (ext_b - b->data - 1);

int rv = strncasecmp(a->data, b->data, MIN(l_a, l_b));
if (rv == 0 && l_a != l_b)
return (int)(l_a - l_b);
return rv;
}

static int qstrcmp_dir(const void *a_, const void *b_)
{
const struct string_list_elem *a = (const struct string_list_elem*)a_;
Expand All @@ -59,6 +75,19 @@ static int qstrcmp_dir(const void *a_, const void *b_)
return strcasecmp(a->data, b->data);
}

static int qstrcmp_dir_noext(const void *a_, const void *b_)
{
const struct string_list_elem *a = (const struct string_list_elem*)a_;
const struct string_list_elem *b = (const struct string_list_elem*)b_;
int a_type = a->attr.i;
int b_type = b->attr.i;

/* Sort directories before files. */
if (a_type != b_type)
return b_type - a_type;
return qstrcmp_plain_noext(a, b);
}

/**
* dir_list_sort:
* @list : pointer to the directory listing.
Expand All @@ -73,6 +102,20 @@ void dir_list_sort(struct string_list *list, bool dir_first)
dir_first ? qstrcmp_dir : qstrcmp_plain);
}

/**
* dir_list_sort_ignore_ext:
* @list : pointer to the directory listing.
* @dir_first : move the directories in the listing to the top?
*
* Sorts a directory listing. File extensions are ignored.
**/
void dir_list_sort_ignore_ext(struct string_list *list, bool dir_first)
{
if (list)
qsort(list->elems, list->size, sizeof(struct string_list_elem),
dir_first ? qstrcmp_dir_noext : qstrcmp_plain_noext);
}

/**
* dir_list_free:
* @list : pointer to the directory listing
Expand Down
2 changes: 1 addition & 1 deletion menu/menu_displaylist.c
Original file line number Diff line number Diff line change
Expand Up @@ -4152,7 +4152,7 @@ static unsigned menu_displaylist_parse_playlists(

content_count = count;

dir_list_sort(&str_list, true);
dir_list_sort_ignore_ext(&str_list, true);

list_size = str_list.size;

Expand Down

0 comments on commit c53bb64

Please sign in to comment.