From 49572a549983c8d84575a379ccf764558e1893c3 Mon Sep 17 00:00:00 2001 From: Sari Sakse Dalum Date: Fri, 19 Aug 2022 11:56:38 +0200 Subject: [PATCH 1/2] Add mutating `stat!` function for non-allocating filesystem `stat` --- base/stat.jl | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/base/stat.jl b/base/stat.jl index 13dbca7780b61..99c24608daca0 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -144,14 +144,13 @@ show(io::IO, ::MIME"text/plain", st::StatStruct) = show_statstruct(io, st, false # stat & lstat functions -macro stat_call(sym, arg1type, arg) +macro stat_call!(stat_buf, sym, arg1type, arg) return quote - stat_buf = zeros(UInt8, Int(ccall(:jl_sizeof_stat, Int32, ()))) - r = ccall($(Expr(:quote, sym)), Int32, ($(esc(arg1type)), Ptr{UInt8}), $(esc(arg)), stat_buf) + r = ccall($(Expr(:quote, sym)), Int32, ($(esc(arg1type)), Ptr{UInt8}), $(esc(arg)), $(esc(stat_buf))) if !(r in (0, Base.UV_ENOENT, Base.UV_ENOTDIR, Base.UV_EINVAL)) uv_error(string("stat(", repr($(esc(arg))), ")"), r) end - st = StatStruct($(esc(arg)), stat_buf) + st = StatStruct($(esc(arg)), $(esc(stat_buf))) if ispath(st) != (r == 0) error("stat returned zero type for a valid path") end @@ -159,13 +158,18 @@ macro stat_call(sym, arg1type, arg) end end -stat(fd::OS_HANDLE) = @stat_call jl_fstat OS_HANDLE fd -stat(path::AbstractString) = @stat_call jl_stat Cstring path -lstat(path::AbstractString) = @stat_call jl_lstat Cstring path +stat!(stat_buf::Vector{UInt8}, fd::OS_HANDLE) = @stat_call! stat_buf jl_fstat OS_HANDLE fd +stat!(stat_buf::Vector{UInt8}, path::AbstractString) = @stat_call! stat_buf jl_stat Cstring path +lstat!(stat_buf::Vector{UInt8}, path::AbstractString) = @stat_call! stat_buf jl_lstat Cstring path if RawFD !== OS_HANDLE - global stat(fd::RawFD) = stat(Libc._get_osfhandle(fd)) + global stat!(stat_buf::Vector{UInt8}, fd::RawFD) = stat!(stat_buf, Libc._get_osfhandle(fd)) end -stat(fd::Integer) = stat(RawFD(fd)) +stat!(stat_buf::Vector{UInt8}, fd::Integer) = stat!(stat_buf, RawFD(fd)) + +stat(x) = stat!(get_stat_buf(), x) +lstat(x) = lstat!(get_stat_buf(), x) + +get_stat_buf() = zeros(UInt8, Int(ccall(:jl_sizeof_stat, Int32, ()))) """ stat(file) From 4ed7aec910cb8ef96c9bdbf510cd5d1cad391e61 Mon Sep 17 00:00:00 2001 From: Sari Sakse Dalum Date: Fri, 19 Aug 2022 11:57:16 +0200 Subject: [PATCH 2/2] Add docstrings --- base/stat.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/base/stat.jl b/base/stat.jl index 99c24608daca0..c12feb888f0bd 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -158,6 +158,13 @@ macro stat_call!(stat_buf, sym, arg1type, arg) end end +""" + stat!(stat_buf::Vector{UInt8}, file) + +Like [`stat`](@ref), but avoids internal allocations by using a pre-allocated buffer, +`stat_buf`. For a small performance gain over `stat`, consecutive calls to `stat!` can use +the same `stat_buf`. See also [`Base.Filesystem.get_stat_buf`](@ref). +""" stat!(stat_buf::Vector{UInt8}, fd::OS_HANDLE) = @stat_call! stat_buf jl_fstat OS_HANDLE fd stat!(stat_buf::Vector{UInt8}, path::AbstractString) = @stat_call! stat_buf jl_stat Cstring path lstat!(stat_buf::Vector{UInt8}, path::AbstractString) = @stat_call! stat_buf jl_lstat Cstring path @@ -169,6 +176,11 @@ stat!(stat_buf::Vector{UInt8}, fd::Integer) = stat!(stat_buf, RawFD(fd stat(x) = stat!(get_stat_buf(), x) lstat(x) = lstat!(get_stat_buf(), x) +""" + get_stat_buf() + +Return a buffer of bytes of the right size for [`stat!`](@ref). +""" get_stat_buf() = zeros(UInt8, Int(ccall(:jl_sizeof_stat, Int32, ()))) """