Skip to content

Commit 08d534e

Browse files
authored
Introduce common strcasecmp and strncasecmp implementations (#23840)
1 parent bc37718 commit 08d534e

File tree

5 files changed

+64
-37
lines changed

5 files changed

+64
-37
lines changed

lib/c/string.zig

+64
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ comptime {
66
@export(&strcmp, .{ .name = "strcmp", .linkage = common.linkage, .visibility = common.visibility });
77
@export(&strlen, .{ .name = "strlen", .linkage = common.linkage, .visibility = common.visibility });
88
@export(&strncmp, .{ .name = "strncmp", .linkage = common.linkage, .visibility = common.visibility });
9+
@export(&strcasecmp, .{ .name = "strcasecmp", .linkage = common.linkage, .visibility = common.visibility });
10+
@export(&strncasecmp, .{ .name = "strncasecmp", .linkage = common.linkage, .visibility = common.visibility });
11+
@export(&__strcasecmp_l, .{ .name = "__strcasecmp_l", .linkage = common.linkage, .visibility = common.visibility });
12+
@export(&__strncasecmp_l, .{ .name = "__strncasecmp_l", .linkage = common.linkage, .visibility = common.visibility });
13+
@export(&__strcasecmp_l, .{ .name = "strcasecmp_l", .linkage = .weak, .visibility = common.visibility });
14+
@export(&__strncasecmp_l, .{ .name = "strncasecmp_l", .linkage = .weak, .visibility = common.visibility });
915
}
1016

1117
fn strcmp(s1: [*:0]const c_char, s2: [*:0]const c_char) callconv(.c) c_int {
@@ -33,6 +39,64 @@ fn strncmp(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize) callconv(.c)
3339
return @as(c_int, l[0]) - @as(c_int, r[0]);
3440
}
3541

42+
fn strcasecmp(s1: [*:0]const c_char, s2: [*:0]const c_char) callconv(.c) c_int {
43+
const toLower = std.ascii.toLower;
44+
var l: [*:0]const u8 = @ptrCast(s1);
45+
var r: [*:0]const u8 = @ptrCast(s2);
46+
47+
while (l[0] != 0 and r[0] != 0 and (l[0] == r[0] or toLower(l[0]) == toLower(r[0]))) {
48+
l += 1;
49+
r += 1;
50+
}
51+
52+
return @as(c_int, toLower(l[0])) - @as(c_int, toLower(r[0]));
53+
}
54+
55+
fn __strcasecmp_l(s1: [*:0]const c_char, s2: [*:0]const c_char, locale: *anyopaque) callconv(.c) c_int {
56+
_ = locale;
57+
return strcasecmp(s1, s2);
58+
}
59+
60+
fn strncasecmp(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize) callconv(.c) c_int {
61+
const toLower = std.ascii.toLower;
62+
var l: [*:0]const u8 = @ptrCast(s1);
63+
var r: [*:0]const u8 = @ptrCast(s2);
64+
var i = n - 1;
65+
66+
while (l[0] != 0 and r[0] != 0 and i != 0 and (l[0] == r[0] or toLower(l[0]) == toLower(r[0]))) {
67+
l += 1;
68+
r += 1;
69+
i -= 1;
70+
}
71+
72+
return @as(c_int, toLower(l[0])) - @as(c_int, toLower(r[0]));
73+
}
74+
75+
fn __strncasecmp_l(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize, locale: *anyopaque) callconv(.c) c_int {
76+
_ = locale;
77+
return strncasecmp(s1, s2, n);
78+
}
79+
80+
test strcasecmp {
81+
try std.testing.expect(strcasecmp(@ptrCast("a"), @ptrCast("b")) < 0);
82+
try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("a")) > 0);
83+
try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("b")) < 0);
84+
try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("A")) > 0);
85+
try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("A")) == 0);
86+
try std.testing.expect(strcasecmp(@ptrCast("B"), @ptrCast("b")) == 0);
87+
try std.testing.expect(strcasecmp(@ptrCast("bb"), @ptrCast("AA")) > 0);
88+
}
89+
90+
test strncasecmp {
91+
try std.testing.expect(strncasecmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
92+
try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
93+
try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("b"), 1) < 0);
94+
try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("A"), 1) > 0);
95+
try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("A"), 1) == 0);
96+
try std.testing.expect(strncasecmp(@ptrCast("B"), @ptrCast("b"), 1) == 0);
97+
try std.testing.expect(strncasecmp(@ptrCast("bb"), @ptrCast("AA"), 2) > 0);
98+
}
99+
36100
test strncmp {
37101
try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
38102
try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("c"), 1) < 0);

lib/libc/musl/src/string/strcasecmp.c

-16
This file was deleted.

lib/libc/musl/src/string/strncasecmp.c

-17
This file was deleted.

src/libs/musl.zig

-2
Original file line numberDiff line numberDiff line change
@@ -1853,7 +1853,6 @@ const src_files = [_][]const u8{
18531853
"musl/src/string/rindex.c",
18541854
"musl/src/string/stpcpy.c",
18551855
"musl/src/string/stpncpy.c",
1856-
"musl/src/string/strcasecmp.c",
18571856
"musl/src/string/strcasestr.c",
18581857
"musl/src/string/strcat.c",
18591858
"musl/src/string/strchr.c",
@@ -1864,7 +1863,6 @@ const src_files = [_][]const u8{
18641863
"musl/src/string/strerror_r.c",
18651864
"musl/src/string/strlcat.c",
18661865
"musl/src/string/strlcpy.c",
1867-
"musl/src/string/strncasecmp.c",
18681866
"musl/src/string/strncat.c",
18691867
"musl/src/string/strncpy.c",
18701868
"musl/src/string/strndup.c",

src/libs/wasi_libc.zig

-2
Original file line numberDiff line numberDiff line change
@@ -1055,7 +1055,6 @@ const libc_top_half_src_files = [_][]const u8{
10551055
"musl/src/string/rindex.c",
10561056
"musl/src/string/stpcpy.c",
10571057
"musl/src/string/stpncpy.c",
1058-
"musl/src/string/strcasecmp.c",
10591058
"musl/src/string/strcasestr.c",
10601059
"musl/src/string/strcat.c",
10611060
"musl/src/string/strchr.c",
@@ -1066,7 +1065,6 @@ const libc_top_half_src_files = [_][]const u8{
10661065
"musl/src/string/strerror_r.c",
10671066
"musl/src/string/strlcat.c",
10681067
"musl/src/string/strlcpy.c",
1069-
"musl/src/string/strncasecmp.c",
10701068
"musl/src/string/strncat.c",
10711069
"musl/src/string/strncpy.c",
10721070
"musl/src/string/strndup.c",

0 commit comments

Comments
 (0)