Ticket #4374: fix file sort by version.

filevercmp: don't treat entire filename as suffix.

Sync with gnulib 1ba2b66ea45f9bc43cdc0f6f93efa59157d2b2ba.

(file_prefixlen): When stripping (\.[A-Za-z~][A-Za-z0-9~]*)*$ suffixes,
do not strip the entire file name.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
Andrew Borodin 2022-06-04 08:51:04 +03:00
parent 34d3726b79
commit dc67246c27
3 changed files with 17 additions and 9 deletions

View File

@ -577,6 +577,8 @@ int str_verscmp (const char *s1, const char *s2);
(\.[A-Za-z~][A-Za-z0-9~]*)*$ are removed and the strings compared without them, using version sort
without special priority; if they do not compare equal, this comparison result is used and
the suffixes are effectively ignored. Otherwise, the entire strings are compared using version sort.
When removing a suffix from a nonempty string, remove the maximal-length suffix such that
the remaining string is nonempty.
*/
int filevercmp (const char *a, const char *b);

View File

@ -39,6 +39,9 @@
/* Return the length of a prefix of @s that corresponds to the suffix defined by this extended
* regular expression in the C locale: (\.[A-Za-z~][A-Za-z0-9~]*)*$
*
* Use the longest suffix matching this regular expression, except do not use all of s as a suffix
* if s is nonempty.
*
* If *len is -1, s is a string; set *lem to s's length.
* Otherwise, *len should be nonnegative, s is a char array, and *len does not change.
*/
@ -46,17 +49,13 @@ static ssize_t
file_prefixlen (const char *s, ssize_t * len)
{
size_t n = (size_t) (*len); /* SIZE_MAX if N == -1 */
size_t i;
size_t i = 0;
size_t prefixlen = 0;
for (i = 0;; i++)
while (TRUE)
{
size_t prefixlen = i;
gboolean done;
while (i + 1 < n && s[i] == '.' && (g_ascii_isalpha (s[i + 1]) || s[i + 1] == '~'))
for (i += 2; i < n && (g_ascii_isalnum (s[i]) || s[i] == '~'); i++)
;
if (*len < 0)
done = s[i] == '\0';
else
@ -67,6 +66,13 @@ file_prefixlen (const char *s, ssize_t * len)
*len = (ssize_t) i;
return (ssize_t) prefixlen;
}
i++;
prefixlen = i;
while (i + 1 < n && s[i] == '.' && (g_ascii_isalpha (s[i + 1]) || s[i + 1] == '~'))
for (i += 2; i < n && (g_ascii_isalnum (s[i]) || s[i] == '~'); i++)
;
}
}

View File

@ -139,6 +139,8 @@ static const char *filevercmp_test_ds2[] = {
"",
".",
"..",
".0",
".9",
".A",
".Z",
".a~",
@ -149,8 +151,6 @@ static const char *filevercmp_test_ds2[] = {
".zz~",
".zz",
".zz.~1~",
".0",
".9",
".zz.0",
".\1",
".\1.txt",