authorgravatar for 85320007+g-logunov@users.noreply.github.comg-logunov <85320007+g-logunov@users.noreply.github.com> 2025-04-11 20:44:18+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-04-11 12:44:18-07:00
log326f254972d6f65d387f6dd29dc229e214ea61a4
tree8c8ff83add6c44a01a5f9027ecb13faea5e4d5c1
parentfa5915389640c2b00a093914fd803d7d87dc2e91
signaturebadge-check Signed by PGP key B5690EEEBB952194

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

Fixes std.posix.getenv() being slower than musl getenv() even when linking libc

2 files changed, 18 insertions(+), 7 deletions(-)

lib/std/posix.zig+13-7
......@@ -2007,14 +2007,18 @@ pub fn getenv(key: []const u8) ?[:0]const u8 {
20072007 if (native_os == .windows) {
20082008 @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.");
20092009 }
2010 if (mem.indexOfScalar(u8, key, '=') != null) {
2011 return null;
2012 }
20102013 if (builtin.link_libc) {
20112014 var ptr = std.c.environ;
20122015 while (ptr[0]) |line| : (ptr += 1) {
20132016 var line_i: usize = 0;
2014 while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {}
2015 const this_key = line[0..line_i];
2016
2017 if (!mem.eql(u8, this_key, key)) continue;
2017 while (line[line_i] != 0) : (line_i += 1) {
2018 if (line_i == key.len) break;
2019 if (line[line_i] != key[line_i]) break;
2020 }
2021 if ((line_i != key.len) or (line[line_i] != '=')) continue;
20182022
20192023 return mem.sliceTo(line + line_i + 1, 0);
20202024 }
......@@ -2028,9 +2032,11 @@ pub fn getenv(key: []const u8) ?[:0]const u8 {
20282032 // TODO see https://github.com/ziglang/zig/issues/4524
20292033 for (std.os.environ) |ptr| {
20302034 var line_i: usize = 0;
2031 while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
2032 const this_key = ptr[0..line_i];
2033 if (!mem.eql(u8, key, this_key)) continue;
2035 while (ptr[line_i] != 0) : (line_i += 1) {
2036 if (line_i == key.len) break;
2037 if (ptr[line_i] != key[line_i]) break;
2038 }
2039 if ((line_i != key.len) or (ptr[line_i] != '=')) continue;
20342040
20352041 return mem.sliceTo(ptr + line_i + 1, 0);
20362042 }
lib/std/posix/test.zig+5
......@@ -733,6 +733,11 @@ test "getenv" {
733733 if (native_os == .windows) {
734734 try expect(std.process.getenvW(&[_:0]u16{ 'B', 'O', 'G', 'U', 'S', 0x11, 0x22, 0x33, 0x44, 0x55 }) == null);
735735 } else {
736 try expect(posix.getenv("") == null);
737 try expect(posix.getenv("BOGUSDOESNOTEXISTENVVAR") == null);
738 if (builtin.link_libc) {
739 try testing.expectEqualStrings(posix.getenv("USER") orelse "", mem.span(std.c.getenv("USER") orelse ""));
740 }
736741 try expect(posix.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null);
737742 }
738743}