libc: implement insque and remque in Zig

Implements insque() and remque() doubly-linked list functions
in lib/c/search.zig and removes musl C implementation.
Contributes to #30978
This commit is contained in:
Neel 2026-02-11 21:49:48 -06:00 committed by Andrew Kelley
parent 4a3adaaa23
commit 5132d78e83
5 changed files with 68 additions and 34 deletions

View file

@ -68,6 +68,7 @@ comptime {
_ = @import("c/malloc.zig");
}
_ = @import("c/math.zig");
_ = @import("c/search.zig");
_ = @import("c/stdlib.zig");
_ = @import("c/string.zig");
_ = @import("c/strings.zig");

67
lib/c/search.zig Normal file
View file

@ -0,0 +1,67 @@
const std = @import("std");
const builtin = @import("builtin");
const symbol = @import("../c.zig").symbol;
comptime {
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
symbol(&insque, "insque");
symbol(&remque, "remque");
}
}
const Node = extern struct {
next: ?*Node,
prev: ?*Node,
};
fn insque(element: *anyopaque, pred: ?*anyopaque) callconv(.c) void {
const e: *Node = @ptrCast(@alignCast(element));
if (pred) |p_ptr| {
const p: *Node = @ptrCast(@alignCast(p_ptr));
e.next = p.next;
e.prev = p;
p.next = e;
if (e.next) |next| {
next.prev = e;
}
} else {
e.next = null;
e.prev = null;
}
}
fn remque(element: *anyopaque) callconv(.c) void {
const e: *Node = @ptrCast(@alignCast(element));
if (e.next) |next| next.prev = e.prev;
if (e.prev) |prev| prev.next = e.next;
}
test "insque and remque" {
var first = Node{ .next = null, .prev = null };
var second = Node{ .next = null, .prev = null };
var third = Node{ .next = null, .prev = null };
insque(&first, null);
try std.testing.expectEqual(@as(?*Node, null), first.next);
try std.testing.expectEqual(@as(?*Node, null), first.prev);
insque(&second, &first);
try std.testing.expectEqual(@as(?*Node, &second), first.next);
try std.testing.expectEqual(@as(?*Node, &first), second.prev);
insque(&third, &first);
try std.testing.expectEqual(@as(?*Node, &third), first.next);
try std.testing.expectEqual(@as(?*Node, &second), third.next);
try std.testing.expectEqual(@as(?*Node, &first), third.prev);
try std.testing.expectEqual(@as(?*Node, &third), second.prev);
remque(&third);
try std.testing.expectEqual(@as(?*Node, &second), first.next);
try std.testing.expectEqual(@as(?*Node, &first), second.prev);
remque(&second);
try std.testing.expectEqual(@as(?*Node, null), first.next);
}

View file

@ -1,32 +0,0 @@
#include <search.h>
struct node {
struct node *next;
struct node *prev;
};
void insque(void *element, void *pred)
{
struct node *e = element;
struct node *p = pred;
if (!p) {
e->next = e->prev = 0;
return;
}
e->next = p->next;
e->prev = p;
p->next = e;
if (e->next)
e->next->prev = e;
}
void remque(void *element)
{
struct node *e = element;
if (e->next)
e->next->prev = e->prev;
if (e->prev)
e->prev->next = e->next;
}

View file

@ -1296,7 +1296,6 @@ const src_files = [_][]const u8{
"musl/src/sched/sched_setscheduler.c",
"musl/src/sched/sched_yield.c",
"musl/src/search/hsearch.c",
"musl/src/search/insque.c",
"musl/src/search/lsearch.c",
"musl/src/search/tdelete.c",
"musl/src/search/tdestroy.c",

View file

@ -848,7 +848,6 @@ const libc_top_half_src_files = [_][]const u8{
"musl/src/regex/fnmatch.c",
"musl/src/regex/regerror.c",
"musl/src/search/hsearch.c",
"musl/src/search/insque.c",
"musl/src/search/lsearch.c",
"musl/src/search/tdelete.c",
"musl/src/search/tdestroy.c",