std.posix.getenv: early-return comparison (#23265)

Fixes std.posix.getenv() being slower than musl getenv() even when linking libc
This commit is contained in:
g-logunov 2025-04-11 20:44:18 +01:00 committed by GitHub
parent fa59153896
commit 326f254972
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 18 additions and 7 deletions

View file

@ -2007,14 +2007,18 @@ pub fn getenv(key: []const u8) ?[:0]const u8 {
if (native_os == .windows) { if (native_os == .windows) {
@compileError("std.posix.getenv is unavailable for Windows because environment strings are in WTF-16 format. See std.process.getEnvVarOwned for a cross-platform API or std.process.getenvW for a Windows-specific API."); @compileError("std.posix.getenv is unavailable for Windows because environment strings are in WTF-16 format. See std.process.getEnvVarOwned for a cross-platform API or std.process.getenvW for a Windows-specific API.");
} }
if (mem.indexOfScalar(u8, key, '=') != null) {
return null;
}
if (builtin.link_libc) { if (builtin.link_libc) {
var ptr = std.c.environ; var ptr = std.c.environ;
while (ptr[0]) |line| : (ptr += 1) { while (ptr[0]) |line| : (ptr += 1) {
var line_i: usize = 0; var line_i: usize = 0;
while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {} while (line[line_i] != 0) : (line_i += 1) {
const this_key = line[0..line_i]; if (line_i == key.len) break;
if (line[line_i] != key[line_i]) break;
if (!mem.eql(u8, this_key, key)) continue; }
if ((line_i != key.len) or (line[line_i] != '=')) continue;
return mem.sliceTo(line + line_i + 1, 0); return mem.sliceTo(line + line_i + 1, 0);
} }
@ -2028,9 +2032,11 @@ pub fn getenv(key: []const u8) ?[:0]const u8 {
// TODO see https://github.com/ziglang/zig/issues/4524 // TODO see https://github.com/ziglang/zig/issues/4524
for (std.os.environ) |ptr| { for (std.os.environ) |ptr| {
var line_i: usize = 0; var line_i: usize = 0;
while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} while (ptr[line_i] != 0) : (line_i += 1) {
const this_key = ptr[0..line_i]; if (line_i == key.len) break;
if (!mem.eql(u8, key, this_key)) continue; if (ptr[line_i] != key[line_i]) break;
}
if ((line_i != key.len) or (ptr[line_i] != '=')) continue;
return mem.sliceTo(ptr + line_i + 1, 0); return mem.sliceTo(ptr + line_i + 1, 0);
} }

View file

@ -733,6 +733,11 @@ test "getenv" {
if (native_os == .windows) { if (native_os == .windows) {
try expect(std.process.getenvW(&[_:0]u16{ 'B', 'O', 'G', 'U', 'S', 0x11, 0x22, 0x33, 0x44, 0x55 }) == null); try expect(std.process.getenvW(&[_:0]u16{ 'B', 'O', 'G', 'U', 'S', 0x11, 0x22, 0x33, 0x44, 0x55 }) == null);
} else { } else {
try expect(posix.getenv("") == null);
try expect(posix.getenv("BOGUSDOESNOTEXISTENVVAR") == null);
if (builtin.link_libc) {
try testing.expectEqualStrings(posix.getenv("USER") orelse "", mem.span(std.c.getenv("USER") orelse ""));
}
try expect(posix.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null); try expect(posix.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null);
} }
} }