Skip to content

Commit

Permalink
Allow 0-length arrays to be returned from Mmap.mmap. Fixes #10516
Browse files Browse the repository at this point in the history
  • Loading branch information
quinnj committed Oct 20, 2015
1 parent e60d546 commit 2a006e1
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 22 deletions.
37 changes: 20 additions & 17 deletions base/mmap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,18 @@ end # @unix_only

@windows_only begin

const PAGE_READONLY = UInt32(0x02)
const PAGE_READWRITE = UInt32(0x04)
const PAGE_WRITECOPY = UInt32(0x08)
const PAGE_EXECUTE_READ = UInt32(0x20)
const PAGE_EXECUTE_READWRITE = UInt32(0x40)
const PAGE_EXECUTE_WRITECOPY = UInt32(0x80)
const FILE_MAP_COPY = UInt32(0x01)
const FILE_MAP_WRITE = UInt32(0x02)
const FILE_MAP_READ = UInt32(0x04)
const FILE_MAP_EXECUTE = UInt32(0x20)
typealias DWORD Culong

const PAGE_READONLY = DWORD(0x02)
const PAGE_READWRITE = DWORD(0x04)
const PAGE_WRITECOPY = DWORD(0x08)
const PAGE_EXECUTE_READ = DWORD(0x20)
const PAGE_EXECUTE_READWRITE = DWORD(0x40)
const PAGE_EXECUTE_WRITECOPY = DWORD(0x80)
const FILE_MAP_COPY = DWORD(0x01)
const FILE_MAP_WRITE = DWORD(0x02)
const FILE_MAP_READ = DWORD(0x04)
const FILE_MAP_EXECUTE = DWORD(0x20)

function gethandle(io::IO)
handle = Libc._get_osfhandle(RawFD(fd(io))).handle
Expand All @@ -86,7 +88,7 @@ function gethandle(io::IO)
end

settings(sh::Anonymous) = utf16(sh.name), sh.readonly, sh.create
settings(io::IO) = convert(Ptr{Cwchar_t},C_NULL), isreadonly(io), true
settings(io::IO) = Ptr{Cwchar_t}(0), isreadonly(io), true
end # @windows_only

# core impelementation of mmap
Expand All @@ -99,7 +101,8 @@ function mmap{T,N}(io::IO,
isbits(T) || throw(ArgumentError("unable to mmap $T; must satisfy isbits(T) == true"))

len = prod(dims) * sizeof(T)
len > 0 || throw(ArgumentError("requested size must be > 0, got $len"))
len >= 0 || throw(ArgumentError("requested size must be ≥ 0, got $len"))
len == 0 && return Array(T,ntuple(x->0,N))
len < typemax(Int) - PAGESIZE || throw(ArgumentError("requested size must be < $(typemax(Int)-PAGESIZE), got $len"))

offset >= 0 || throw(ArgumentError("requested offset must be ≥ 0, got $offset"))
Expand All @@ -121,14 +124,14 @@ function mmap{T,N}(io::IO,

@windows_only begin
name, readonly, create = settings(io)
szfile = convert(Csize_t, len + offset)
szfile = convert(DWORD, len + offset)
readonly && szfile > filesize(io) && throw(ArgumentError("unable to increase file size to $szfile due to read-only permissions"))
handle = create ? ccall(:CreateFileMappingW, stdcall, Ptr{Void}, (Cptrdiff_t, Ptr{Void}, Cint, Cint, Cint, Cwstring),
handle = create ? ccall(:CreateFileMappingW, stdcall, Ptr{Void}, (Cptrdiff_t, Ptr{Void}, DWORD, DWORD, DWORD, Cwstring),
file_desc, C_NULL, readonly ? PAGE_READONLY : PAGE_READWRITE, szfile >> 32, szfile & typemax(UInt32), name) :
ccall(:OpenFileMappingW, stdcall, Ptr{Void}, (Cint, Cint, Cwstring),
readonly ? FILE_MAP_READ : FILE_MAP_WRITE, true, name)
ccall(:OpenFileMappingW, stdcall, Ptr{Void}, (DWORD, Cint, Cwstring),
readonly ? FILE_MAP_READ : FILE_MAP_WRITE, true, name)
handle == C_NULL && error("could not create file mapping: $(Libc.FormatMessage())")
ptr = ccall(:MapViewOfFile, stdcall, Ptr{Void}, (Ptr{Void}, Cint, Cint, Cint, Csize_t),
ptr = ccall(:MapViewOfFile, stdcall, Ptr{Void}, (Ptr{Void}, DWORD, DWORD, DWORD, DWORD),
handle, readonly ? FILE_MAP_READ : FILE_MAP_WRITE, offset_page >> 32, offset_page & typemax(UInt32), (offset - offset_page) + len)
ptr == C_NULL && error("could not create mapping view: $(Libc.FormatMessage())")
end # @windows_only
Expand Down
10 changes: 5 additions & 5 deletions test/mmap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ gc(); gc()
gc(); gc()
@test Mmap.mmap(file, Array{UInt8,3}, (1,1,11)) == reshape(t,(1,1,11))
gc(); gc()
@test_throws ArgumentError Mmap.mmap(file, Array{UInt8,3}, (11,0,1)) # 0-dimension results in len=0
@test Mmap.mmap(file, Array{UInt8,3}, (11,0,1)) == Array(UInt8,(0,0,0))
@test Mmap.mmap(file, Vector{UInt8}, (11,)) == t
gc(); gc()
@test Mmap.mmap(file, Array{UInt8,2}, (1,11)) == t'
gc(); gc()
@test_throws ArgumentError Mmap.mmap(file, Array{UInt8,2}, (0,12))
@test Mmap.mmap(file, Array{UInt8,2}, (0,12)) == Array(UInt8,(0,0))
m = Mmap.mmap(file, Array{UInt8,3}, (1,2,1))
@test m == reshape("He".data,(1,2,1))
finalize(m); m=nothing; gc()
Expand Down Expand Up @@ -48,8 +48,8 @@ close(s)
gc(); gc()

s = open(f->f,file,"w")
@test_throws ArgumentError Mmap.mmap(file) # requested len=0 on empty file
@test_throws ArgumentError Mmap.mmap(file,Vector{UInt8},0)
@test Mmap.mmap(file) == Array(UInt8, 0) # requested len=0 on empty file
@test Mmap.mmap(file,Vector{UInt8},0) == Array(UInt8, 0)
m = Mmap.mmap(file,Vector{UInt8},12)
m[:] = "Hello World\n".data
Mmap.sync!(m)
Expand Down Expand Up @@ -284,4 +284,4 @@ n = similar(m, (2,2))
n = similar(m, 12)
@test length(n) == 12
@test size(n) == (12,)
finalize(m); m = nothing; gc()
finalize(m); m = nothing; gc()

0 comments on commit 2a006e1

Please sign in to comment.