From 0d48cbb822551c07ac987c9c2e20d3251ee3a09c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Apr 2026 20:57:58 -0700 Subject: [PATCH] std.process.Environ.Map: add putAll and clearRetainingCapacity --- lib/std/process/Environ.zig | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/std/process/Environ.zig b/lib/std/process/Environ.zig index 3f467a8db936c6ee0720e1921f46cebc08f0111f..bf0408c31ddc4eebf48a08dea54b6391a524e012 100644 --- a/lib/std/process/Environ.zig +++ b/lib/std/process/Environ.zig @@ -96,6 +96,7 @@ pub const WindowsBlock = struct { } }; +/// Each key and each value are allocated independently and owned by this data structure. pub const Map = struct { array_hash_map: ArrayHashMap, allocator: Allocator, @@ -340,9 +341,6 @@ pub const Map = struct { /// Returns a full copy of `em` allocated with `gpa`, which is not necessarily /// the same allocator used to allocate `em`. pub fn clone(m: *const Map, gpa: Allocator) Allocator.Error!Map { - // Since we need to dupe the keys and values, the only way for error handling to not be a - // nightmare is to add keys to an empty map one-by-one. This could be avoided if this - // abstraction were a bit less... OOP-esque. var new: Map = .init(gpa); errdefer new.deinit(); try new.array_hash_map.ensureUnusedCapacity(gpa, m.array_hash_map.count()); @@ -352,6 +350,32 @@ pub const Map = struct { return new; } + /// Adds all the key-value pairs from `other` into this `m`. + pub fn putAll(m: *Map, other: *const Map) Allocator.Error!void { + const gpa = m.allocator; + try m.array_hash_map.ensureUnusedCapacity(gpa, other.array_hash_map.count()); + const start = m.count(); + errdefer while (m.array_hash_map.count() > start) { + const kv = m.array_hash_map.pop().?; + gpa.free(kv.key); + gpa.free(kv.value); + }; + for (other.array_hash_map.keys(), other.array_hash_map.values()) |key, value| { + try m.put(key, value); + } + } + + /// Set the length to zero, freeing all key and value memory, not freeing + /// the allocation for the entries. + pub fn clearRetainingCapacity(m: *Map) void { + const gpa = m.allocator; + for (m.array_hash_map.keys(), m.array_hash_map.values()) |k, v| { + gpa.free(k); + gpa.free(v); + } + m.array_hash_map.clearRetainingCapacity(); + } + /// Creates a null-delimited environment variable block in the format /// expected by POSIX, from a hash map plus options. pub fn createPosixBlock( -- 2.54.0