From fa3228ae42d3bc92ad66fe91e108511583129ffd Mon Sep 17 00:00:00 2001 From: Ivel Date: Thu, 5 Feb 2026 20:21:41 +0100 Subject: [PATCH] libc: reimplement swab in Zig (#31130) This PR replaces the bundled musl swab() implementation with zig's one. Contributes towards #30978. It looks like there are not test cases for swab() in test-libc. Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31130 Reviewed-by: Andrew Kelley Co-authored-by: Ivel Co-committed-by: Ivel --- lib/c/unistd.zig | 42 +++++++++++++++++++++++++++++++++ lib/libc/musl/src/string/swab.c | 13 ---------- src/libs/musl.zig | 1 - src/libs/wasi_libc.zig | 1 - 4 files changed, 42 insertions(+), 15 deletions(-) delete mode 100644 lib/libc/musl/src/string/swab.c diff --git a/lib/c/unistd.zig b/lib/c/unistd.zig index f903ef78a8..98290f0e04 100644 --- a/lib/c/unistd.zig +++ b/lib/c/unistd.zig @@ -43,6 +43,9 @@ comptime { @export(&execveLinux, .{ .name = "execve", .linkage = common.linkage, .visibility = common.visibility }); } + if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) { + @export(&swab, .{ .name = "swab", .linkage = common.linkage, .visibility = common.visibility }); + } } fn _exit(exit_code: c_int) callconv(.c) noreturn { @@ -181,3 +184,42 @@ fn unlinkatLinux(fd: c_int, path: [*:0]const c_char, flags: c_int) callconv(.c) fn execveLinux(path: [*:0]const c_char, argv: [*:null]const ?[*:0]c_char, envp: [*:null]const ?[*:0]c_char) callconv(.c) c_int { return common.errno(linux.execve(@ptrCast(path), @ptrCast(argv), @ptrCast(envp))); } + +fn swab(noalias src_ptr: *const anyopaque, noalias dest_ptr: *anyopaque, n: isize) callconv(.c) void { + var src: [*]const u8 = @ptrCast(src_ptr); + var dest: [*]u8 = @ptrCast(dest_ptr); + var i = n; + + while (i > 1) : (i -= 2) { + dest[0] = src[1]; + dest[1] = src[0]; + dest += 2; + src += 2; + } +} + +test swab { + var a: [4]u8 = undefined; + @memset(a[0..], '\x00'); + swab("abcd", &a, 4); + try std.testing.expectEqualSlices(u8, "badc", &a); + + // Partial copy + @memset(a[0..], '\x00'); + swab("abcd", &a, 2); + try std.testing.expectEqualSlices(u8, "ba\x00\x00", &a); + + // n < 1 + @memset(a[0..], '\x00'); + swab("abcd", &a, 0); + try std.testing.expectEqualSlices(u8, "\x00" ** 4, &a); + swab("abcd", &a, -1); + try std.testing.expectEqualSlices(u8, "\x00" ** 4, &a); + + // Odd n + @memset(a[0..], '\x00'); + swab("abcd", &a, 1); + try std.testing.expectEqualSlices(u8, "\x00" ** 4, &a); + swab("abcd", &a, 3); + try std.testing.expectEqualSlices(u8, "ba\x00\x00", &a); +} diff --git a/lib/libc/musl/src/string/swab.c b/lib/libc/musl/src/string/swab.c deleted file mode 100644 index ace0f4666d..0000000000 --- a/lib/libc/musl/src/string/swab.c +++ /dev/null @@ -1,13 +0,0 @@ -#include - -void swab(const void *restrict _src, void *restrict _dest, ssize_t n) -{ - const char *src = _src; - char *dest = _dest; - for (; n>1; n-=2) { - dest[0] = src[1]; - dest[1] = src[0]; - dest += 2; - src += 2; - } -} diff --git a/src/libs/musl.zig b/src/libs/musl.zig index 1974e0e4ea..ebbd285665 100644 --- a/src/libs/musl.zig +++ b/src/libs/musl.zig @@ -1579,7 +1579,6 @@ const src_files = [_][]const u8{ "musl/src/string/strndup.c", "musl/src/string/strsignal.c", "musl/src/string/strverscmp.c", - "musl/src/string/swab.c", "musl/src/string/wcscasecmp.c", "musl/src/string/wcscasecmp_l.c", "musl/src/string/wcsdup.c", diff --git a/src/libs/wasi_libc.zig b/src/libs/wasi_libc.zig index 8e0ade2a0d..24a0ead598 100644 --- a/src/libs/wasi_libc.zig +++ b/src/libs/wasi_libc.zig @@ -957,7 +957,6 @@ const libc_top_half_src_files = [_][]const u8{ "musl/src/string/strerror_r.c", "musl/src/string/strndup.c", "musl/src/string/strverscmp.c", - "musl/src/string/swab.c", "musl/src/string/wcscasecmp.c", "musl/src/string/wcscasecmp_l.c", "musl/src/string/wcsdup.c",