sort: locale-based collation is not supported
Component
sort
Description
GNU sort uses locale-based string comparison (collation) when the LC_COLLATE environment variable is set to a non-C locale. This affects the default alphabetical ordering of strings.
In GNU sort, the program checks if the locale is hard.
hard_LC_COLLATE = hard_locale (LC_COLLATE);
When hard_LC_COLLATE is true, GNU sort uses the xmemcoll0 function for string comparison at line 2958.
else if (hard_LC_COLLATE)
{
/* xmemcoll0 is a performance enhancement as
it will not unconditionally write '\0' after the
passed in buffers, which was seen to give around
a 3% increase in performance for short lines. */
diff = xmemcoll0 (a->text, alen + 1, b->text, blen + 1);
}
else
{
diff = memcmp (a->text, b->text, MIN (alen, blen));
if (!diff)
diff = _GL_CMP (alen, blen);
}
The xmemcoll0 function internally uses strcoll() which respects the locale's collation rules. In en_US.UTF-8 locale, lowercase and uppercase letters are interleaved (a, A, b, B, ...).
However, in uutils sort, the default comparison always uses byte-wise comparison.
pub fn custom_str_cmp(
a: &[u8],
b: &[u8],
ignore_non_printing: bool,
ignore_non_dictionary: bool,
ignore_case: bool,
) -> Ordering {
if !(ignore_case || ignore_non_dictionary || ignore_non_printing) {
// There are no custom settings. Fall back to the default strcmp, which is faster.
return a.cmp(b); // Byte comparison, ignores locale
}
...
}
The a.cmp(b) performs a simple byte comparison (equivalent to memcmp), which always follows ASCII order regardless of the locale setting.
Test / Reproduction Steps
# GNU sort (en_US.UTF-8 locale)
$ printf 'a\nA\nb\nB\n' | LC_ALL=en_US.UTF-8 sort
a
A
b
B
# uutils sort (en_US.UTF-8 locale)
$ printf 'a\nA\nb\nB\n' | LC_ALL=en_US.UTF-8 coreutils sort
A
B
a
b
# Both should be identical in C locale
$ printf 'a\nA\nb\nB\n' | LC_ALL=C sort
A
B
a
b
$ printf 'a\nA\nb\nB\n' | LC_ALL=C coreutils sort
A
B
a
b
Impact
Sorting output differs from GNU sort when using non-C locales (e.g., en_US.UTF-8).
Recommendations
Implement locale-based collation using strcoll() via FFI or a Unicode collation library.
sort: locale-based collation is not supported
Component
sort
Description
GNU sort uses locale-based string comparison (collation) when the
LC_COLLATEenvironment variable is set to a non-C locale. This affects the default alphabetical ordering of strings.In GNU sort, the program checks if the locale is hard.
When
hard_LC_COLLATEis true, GNU sort uses thexmemcoll0function for string comparison at line 2958.The
xmemcoll0function internally usesstrcoll()which respects the locale's collation rules. Inen_US.UTF-8locale, lowercase and uppercase letters are interleaved (a, A, b, B, ...).However, in uutils sort, the default comparison always uses byte-wise comparison.
The
a.cmp(b)performs a simple byte comparison (equivalent tomemcmp), which always follows ASCII order regardless of the locale setting.Test / Reproduction Steps
Impact
Sorting output differs from GNU sort when using non-C locales (e.g.,
en_US.UTF-8).Recommendations
Implement locale-based collation using
strcoll()via FFI or a Unicode collation library.