authorgravatar for gereeter+code@gmail.comJonathan S <gereeter+code@gmail.com> 2020-03-28 00:12:40-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-29 18:27:39-04:00
log0674b51453d5631f400936b4da7c74788f745e90
tree0d2e39e7b23e75565c0a36be48e9af8f75964b7c
parentab3931fa9581776ef3654b9b55ff447ad91e7949

In getCwdAlloc, geometrically allocate larger buffers to find an appropriate size.


1 files changed, 22 insertions(+), 4 deletions(-)

lib/std/process.zig+22-4
...@@ -21,10 +21,28 @@ pub fn getCwd(out_buffer: []u8) ![]u8 {...@@ -21,10 +21,28 @@ pub fn getCwd(out_buffer: []u8) ![]u8 {
2121
22/// Caller must free the returned memory.22/// Caller must free the returned memory.
23pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {23pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
24 // TODO(#4812): Consider looping with larger and larger buffers to handle24 // The use of MAX_PATH_BYTES here is just a heuristic: most paths will fit
25 // overlong paths.25 // in stack_buf, avoiding an extra allocation in the common case.
26 var buf: [fs.MAX_PATH_BYTES]u8 = undefined;26 var stack_buf: [fs.MAX_PATH_BYTES]u8 = undefined;
27 return mem.dupe(allocator, u8, try os.getcwd(&buf));27 var heap_buf: ?[]u8 = null;
28 defer if (heap_buf) |buf| allocator.free(buf);
29
30 var current_buf: []u8 = &stack_buf;
31 while (true) {
32 if (os.getcwd(current_buf)) |slice| {
33 return mem.dupe(allocator, u8, slice);
34 } else |err| switch(err) {
35 error.NameTooLong => {
36 // The path is too long to fit in stack_buf. Allocate geometrically
37 // increasing buffers until we find one that works
38 const new_capacity = current_buf.len * 2;
39 if (heap_buf) |buf| allocator.free(buf);
40 current_buf = try allocator.alloc(u8, new_capacity);
41 heap_buf = current_buf;
42 },
43 else => return err,
44 }
45 }
28}46}
2947
30test "getCwdAlloc" {48test "getCwdAlloc" {