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

This commit is contained in:
Jonathan S 2020-03-28 00:12:40 -05:00 committed by Andrew Kelley
parent ab3931fa95
commit 0674b51453

View File

@ -21,10 +21,28 @@ pub fn getCwd(out_buffer: []u8) ![]u8 {
/// Caller must free the returned memory.
pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
// TODO(#4812): Consider looping with larger and larger buffers to handle
// overlong paths.
var buf: [fs.MAX_PATH_BYTES]u8 = undefined;
return mem.dupe(allocator, u8, try os.getcwd(&buf));
// The use of MAX_PATH_BYTES here is just a heuristic: most paths will fit
// in stack_buf, avoiding an extra allocation in the common case.
var stack_buf: [fs.MAX_PATH_BYTES]u8 = undefined;
var heap_buf: ?[]u8 = null;
defer if (heap_buf) |buf| allocator.free(buf);
var current_buf: []u8 = &stack_buf;
while (true) {
if (os.getcwd(current_buf)) |slice| {
return mem.dupe(allocator, u8, slice);
} else |err| switch(err) {
error.NameTooLong => {
// The path is too long to fit in stack_buf. Allocate geometrically
// increasing buffers until we find one that works
const new_capacity = current_buf.len * 2;
if (heap_buf) |buf| allocator.free(buf);
current_buf = try allocator.alloc(u8, new_capacity);
heap_buf = current_buf;
},
else => return err,
}
}
}
test "getCwdAlloc" {