[libc-commits] [libc] [libc] Implement alphasort in dirent (PR #226487)
Aman Maurya via libc-commits
libc-commits at lists.llvm.org
Fri Sep 25 06:27:24 PDT 2026
https://github.com/amanmaurya92 created https://github.com/llvm/llvm-project/pull/226487
Implement the standard POSIX.1-2008 / POSIX.1-2024 function `alphasort` in `<dirent.h>`.
Fixes #226457
>From 34abd348c27e1e722a026c3f297c1d973c9da129 Mon Sep 17 00:00:00 2001
From: amanmaurya92 <amanmaurya9209 at gmail.com>
Date: Fri, 25 Sep 2026 18:07:01 +0530
Subject: [PATCH] [libc] Implement alphasort in dirent
Implement the standard POSIX.1-2008 / POSIX.1-2024 function lphasort in <dirent.h>, bringing declared <dirent.h> POSIX functions to 100% completion.
Fixes #226457
Assisted by Gemini.
---
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/arm/entrypoints.txt | 1 +
libc/config/linux/riscv/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/src/dirent/CMakeLists.txt | 14 +++
libc/src/dirent/alphasort.cpp | 27 ++++++
libc/src/dirent/alphasort.h | 26 ++++++
libc/test/src/dirent/CMakeLists.txt | 13 +++
libc/test/src/dirent/alphasort_test.cpp | 105 ++++++++++++++++++++++
9 files changed, 189 insertions(+)
create mode 100644 libc/src/dirent/alphasort.cpp
create mode 100644 libc/src/dirent/alphasort.h
create mode 100644 libc/test/src/dirent/alphasort_test.cpp
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 15a5367f5fc95d..614e17bf21a97f 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1117,6 +1117,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.compiler.__stack_chk_fail
# dirent.h entrypoints
+ libc.src.dirent.alphasort
libc.src.dirent.closedir
libc.src.dirent.dirfd
libc.src.dirent.opendir
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 1441146393c5fd..07b75376a60573 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -324,6 +324,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.setjmp.sigsetjmp
# dirent.h entrypoints
+ libc.src.dirent.alphasort
libc.src.dirent.closedir
libc.src.dirent.dirfd
libc.src.dirent.opendir
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 8f4dded27de68c..436f5198f6c4d7 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1321,6 +1321,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.compiler.__stack_chk_fail
# dirent.h entrypoints
+ libc.src.dirent.alphasort
libc.src.dirent.closedir
libc.src.dirent.dirfd
libc.src.dirent.opendir
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 8ca73cc82cc2db..2ab0d8c06e291d 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1343,6 +1343,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.compiler.__stack_chk_fail
# dirent.h entrypoints
+ libc.src.dirent.alphasort
libc.src.dirent.closedir
libc.src.dirent.dirfd
libc.src.dirent.opendir
diff --git a/libc/src/dirent/CMakeLists.txt b/libc/src/dirent/CMakeLists.txt
index d0ec22e1cc75b8..3254141e2c96d7 100644
--- a/libc/src/dirent/CMakeLists.txt
+++ b/libc/src/dirent/CMakeLists.txt
@@ -62,3 +62,17 @@ add_entrypoint_object(
libc.src.__support.File.dir
libc.src.errno.errno
)
+
+add_entrypoint_object(
+ alphasort
+ SRCS
+ alphasort.cpp
+ HDRS
+ alphasort.h
+ DEPENDS
+ libc.hdr.types.struct_dirent
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.src.string.strcoll
+)
+
diff --git a/libc/src/dirent/alphasort.cpp b/libc/src/dirent/alphasort.cpp
new file mode 100644
index 00000000000000..91d45c899e4150
--- /dev/null
+++ b/libc/src/dirent/alphasort.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation of the POSIX alphasort function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/dirent/alphasort.h"
+
+#include "hdr/types/struct_dirent.h"
+#include "src/__support/common.h"
+#include "src/string/strcoll.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, alphasort,
+ (const struct dirent **a, const struct dirent **b)) {
+ return LIBC_NAMESPACE::strcoll((*a)->d_name, (*b)->d_name);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/dirent/alphasort.h b/libc/src/dirent/alphasort.h
new file mode 100644
index 00000000000000..2a870a4cf414f2
--- /dev/null
+++ b/libc/src/dirent/alphasort.h
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Declaration of the POSIX alphasort function.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_DIRENT_ALPHASORT_H
+#define LLVM_LIBC_SRC_DIRENT_ALPHASORT_H
+
+#include "hdr/types/struct_dirent.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int alphasort(const struct dirent **a, const struct dirent **b);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_DIRENT_ALPHASORT_H
diff --git a/libc/test/src/dirent/CMakeLists.txt b/libc/test/src/dirent/CMakeLists.txt
index 1d7a3caf790ddd..dcd5985031abf2 100644
--- a/libc/test/src/dirent/CMakeLists.txt
+++ b/libc/test/src/dirent/CMakeLists.txt
@@ -37,3 +37,16 @@ add_libc_test(
libc.hdr.types.DIR
libc.hdr.types.struct_dirent
)
+
+add_libc_test(
+ alphasort_test
+ SUITE
+ libc_dirent_unittests
+ SRCS
+ alphasort_test.cpp
+ DEPENDS
+ libc.hdr.types.struct_dirent
+ libc.src.dirent.alphasort
+ libc.src.stdlib.qsort
+)
+
diff --git a/libc/test/src/dirent/alphasort_test.cpp b/libc/test/src/dirent/alphasort_test.cpp
new file mode 100644
index 00000000000000..045ec0e4187941
--- /dev/null
+++ b/libc/test/src/dirent/alphasort_test.cpp
@@ -0,0 +1,105 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Unit tests for the POSIX alphasort function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/dirent/alphasort.h"
+
+#include "hdr/types/struct_dirent.h"
+#include "src/stdlib/qsort.h"
+#include "test/UnitTest/Test.h"
+
+namespace {
+
+template <size_t N = 64> struct MockDirent {
+ alignas(struct dirent) char buf[sizeof(struct dirent) + N]{};
+
+ const struct dirent *create(const char *name) {
+ auto *d = reinterpret_cast<struct dirent *>(buf);
+ char *dst = d->d_name;
+ while (*name)
+ *dst++ = *name++;
+ *dst = '\0';
+ return d;
+ }
+};
+
+} // namespace
+
+TEST(LlvmLibcAlphasortTest, BasicComparison) {
+ MockDirent<> ent_a{};
+ MockDirent<> ent_b{};
+ const struct dirent *a = ent_a.create("apple");
+ const struct dirent *b = ent_b.create("banana");
+
+ EXPECT_LT(LIBC_NAMESPACE::alphasort(&a, &b), 0);
+ EXPECT_GT(LIBC_NAMESPACE::alphasort(&b, &a), 0);
+}
+
+TEST(LlvmLibcAlphasortTest, EqualNames) {
+ MockDirent<> ent_1{};
+ MockDirent<> ent_2{};
+ const struct dirent *d1 = ent_1.create("file.txt");
+ const struct dirent *d2 = ent_2.create("file.txt");
+
+ EXPECT_EQ(LIBC_NAMESPACE::alphasort(&d1, &d2), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::alphasort(&d1, &d1), 0);
+}
+
+TEST(LlvmLibcAlphasortTest, PrefixComparison) {
+ MockDirent<> ent_short{};
+ MockDirent<> ent_long{};
+ const struct dirent *d_short = ent_short.create("file");
+ const struct dirent *d_long = ent_long.create("file.txt");
+
+ EXPECT_LT(LIBC_NAMESPACE::alphasort(&d_short, &d_long), 0);
+ EXPECT_GT(LIBC_NAMESPACE::alphasort(&d_long, &d_short), 0);
+}
+
+TEST(LlvmLibcAlphasortTest, EmptyName) {
+ MockDirent<> ent_empty{};
+ MockDirent<> ent_nonempty{};
+ const struct dirent *d_empty = ent_empty.create("");
+ const struct dirent *d_nonempty = ent_nonempty.create("a");
+
+ EXPECT_LT(LIBC_NAMESPACE::alphasort(&d_empty, &d_nonempty), 0);
+ EXPECT_GT(LIBC_NAMESPACE::alphasort(&d_nonempty, &d_empty), 0);
+ EXPECT_EQ(LIBC_NAMESPACE::alphasort(&d_empty, &d_empty), 0);
+}
+
+TEST(LlvmLibcAlphasortTest, QsortSorting) {
+ MockDirent<> ent_delta{};
+ MockDirent<> ent_alpha{};
+ MockDirent<> ent_charlie{};
+ MockDirent<> ent_bravo{};
+
+ constexpr size_t NUM_ENTRIES = 4;
+ const struct dirent *entries[NUM_ENTRIES] = {
+ ent_delta.create("delta"),
+ ent_alpha.create("alpha"),
+ ent_charlie.create("charlie"),
+ ent_bravo.create("bravo"),
+ };
+
+ using QsortComparator = int (*)(const void *, const void *);
+ LIBC_NAMESPACE::qsort(
+ entries, NUM_ENTRIES, sizeof(const struct dirent *),
+ reinterpret_cast<QsortComparator>(LIBC_NAMESPACE::alphasort));
+
+ const struct dirent *e0 = entries[0];
+ const struct dirent *e1 = entries[1];
+ const struct dirent *e2 = entries[2];
+ const struct dirent *e3 = entries[3];
+
+ EXPECT_LT(LIBC_NAMESPACE::alphasort(&e0, &e1), 0); // alpha < bravo
+ EXPECT_LT(LIBC_NAMESPACE::alphasort(&e1, &e2), 0); // bravo < charlie
+ EXPECT_LT(LIBC_NAMESPACE::alphasort(&e2, &e3), 0); // charlie < delta
+}
More information about the libc-commits
mailing list