libc: strdup, strndup, wcsdup (#31935)

Contributes to: #30978

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31935
Reviewed-by: Andrew Kelley <andrew@ziglang.org>
This commit is contained in:
Chris Boesch
2026-04-22 01:57:58 +02:00
committed by Andrew Kelley
parent 22945fbbdc
commit 3ea77badf9
11 changed files with 108 additions and 38 deletions
+20
View File
@@ -1,6 +1,7 @@
const builtin = @import("builtin");
const std = @import("std");
const symbol = @import("../c.zig").symbol;
const c = std.c;
comptime {
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
@@ -24,6 +25,8 @@ comptime {
symbol(&strpbrk, "strpbrk");
symbol(&strstr, "strstr");
symbol(&strtok, "strtok");
symbol(&strdup, "strdup");
symbol(&strndup, "strndup");
// strlen is in compiler_rt
symbol(&strtok_r, "strtok_r");
@@ -164,6 +167,23 @@ fn strtok(noalias maybe_str: ?[*:0]c_char, noalias values: [*:0]const c_char) ca
return strtok_r(maybe_str, values, &state.str);
}
fn strdup(str: [*:0]const c_char) callconv(.c) ?[*:0]c_char {
const len = std.mem.len(str);
const d_opaque = c.malloc(len + 1) orelse return null;
const d: [*]c_char = @ptrCast(d_opaque);
@memcpy(d[0 .. len + 1], str[0 .. len + 1]);
return @ptrCast(d);
}
fn strndup(str: [*:0]const c_char, n: usize) callconv(.c) ?[*:0]c_char {
const len = strnlen(str, n);
const d_opaque = c.malloc(len + 1) orelse return null;
const d: [*]c_char = @ptrCast(d_opaque);
@memcpy(d[0..len], str[0..len]);
d[len] = 0;
return @ptrCast(d);
}
// strlen is in compiler_rt
fn strtok_r(noalias maybe_str: ?[*:0]c_char, noalias values: [*:0]const c_char, noalias state: *?[*:0]c_char) callconv(.c) ?[*:0]c_char {
+10
View File
@@ -5,6 +5,7 @@ const wint_t = std.c.wint_t;
const wchar_t = std.c.wchar_t;
const symbol = @import("../c.zig").symbol;
const c = std.c;
comptime {
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
@@ -30,6 +31,7 @@ comptime {
symbol(&wcspbrk, "wcspbrk");
symbol(&wcstok, "wcstok");
symbol(&wcsstr, "wcsstr");
symbol(&wcsdup, "wcsdup");
symbol(&wcswcs, "wcswcs");
}
@@ -189,3 +191,11 @@ fn wcsstr(noalias haystack: [*:0]const wchar_t, noalias needle: [*:0]const wchar
fn wcswcs(noalias haystack: [*:0]const wchar_t, noalias needle: [*:0]const wchar_t) callconv(.c) ?[*:0]wchar_t {
return wcsstr(haystack, needle);
}
fn wcsdup(str: [*:0]const wchar_t) callconv(.c) ?[*:0]wchar_t {
const len = wcslen(str);
const size = (len + 1) * @sizeOf(wchar_t);
const d_opaque = c.malloc(size) orelse return null;
const d: [*]wchar_t = @ptrCast(@alignCast(d_opaque));
return @ptrCast(wmemcpy(d, str, len + 1));
}
-10
View File
@@ -1,10 +0,0 @@
#include <stdlib.h>
#include <string.h>
char *strdup(const char *s)
{
size_t l = strlen(s);
char *d = malloc(l+1);
if (!d) return NULL;
return memcpy(d, s, l+1);
}
-12
View File
@@ -1,12 +0,0 @@
#include <stdlib.h>
#include <string.h>
char *strndup(const char *s, size_t n)
{
size_t l = strnlen(s, n);
char *d = malloc(l+1);
if (!d) return NULL;
memcpy(d, s, l);
d[l] = 0;
return d;
}
-10
View File
@@ -1,10 +0,0 @@
#include <stdlib.h>
#include <wchar.h>
wchar_t *wcsdup(const wchar_t *s)
{
size_t l = wcslen(s);
wchar_t *d = malloc((l+1)*sizeof(wchar_t));
if (!d) return NULL;
return wmemcpy(d, s, l+1);
}
+3
View File
@@ -11136,6 +11136,9 @@ pub extern "c" fn swab(noalias from: *const anyopaque, noalias to: *anyopaque, n
pub extern "c" fn strncmp(a: [*:0]const c_char, b: [*:0]const c_char, max: usize) c_int;
pub extern "c" fn strcasecmp(a: [*:0]const c_char, b: [*:0]const c_char) c_int;
pub extern "c" fn strncasecmp(a: [*:0]const c_char, b: [*:0]const c_char, max: usize) c_int;
pub extern "c" fn strdup(s: [*:0]const c_char) ?[*:0]c_char;
pub extern "c" fn strndup(s: [*:0]const c_char, n: usize) ?[*:0]c_char;
pub extern "c" fn wcsdup(s: [*:0]const wchar_t) ?[*:0]wchar_t;
pub extern "c" fn ffs(i: c_int) c_int;
pub extern "c" fn ffsl(i: c_long) c_long;