Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 34 additions & 29 deletions src/matfile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,42 @@ type MatFile
filename::String

function MatFile(filename::String, mode::String)
p = ccall(mat_open[], Ptr{Void}, (Ptr{Cchar}, Ptr{Cchar}),
filename, mode)
new(p, filename)
p = ccall(mat_open[], Ptr{Void}, (Ptr{Cchar}, Ptr{Cchar}), filename, mode)
self = new(p, filename)
finalizer(self, release)
return self
end
end
MatFile(filename::String) = MatFile(filename, "r")

function close(f::MatFile)
if f.ptr != C_NULL
ret = ccall(mat_close[], Cint, (Ptr{Void},), f.ptr)
ret == 0 || error("Failed to close file.")
function unsafe_convert(::Type{Ptr{Void}}, f::MatFile)
ptr = f.ptr
ptr == C_NULL && throw(UndefRefError())
return ptr
end

function release(f::MatFile)
ptr = f.ptr
if ptr != C_NULL
ccall(mat_close[], Cint, (Ptr{Void},), ptr)
end
f.ptr = C_NULL
return nothing
end

function close(f::MatFile)
ret = ccall(mat_close[], Cint, (Ptr{Void},), f)
ret != 0 && throw(MEngineError("failed to close file (err = $ret)"))
f.ptr = C_NULL
return nothing
end


# get & put variables

function get_mvariable(f::MatFile, name::String)
f.ptr != C_NULL || error("Cannot get variable from a null file.")
pm = ccall(mat_get_variable[], Ptr{Void}, (Ptr{Void}, Ptr{Cchar}),
f.ptr, name)
pm != C_NULL || error("Attempt to get variable $(name) failed.")
pm = ccall(mat_get_variable[], Ptr{Void}, (Ptr{Void}, Ptr{Cchar}), f, name)
pm == C_NULL && error("Attempt to get variable $(name) failed.")
MxArray(pm)
end

Expand All @@ -35,11 +50,9 @@ get_variable(f::MatFile, name::String) = jvalue(get_mvariable(f, name))
get_variable(f::MatFile, name::Symbol) = jvalue(get_mvariable(f, name))

function put_variable(f::MatFile, name::String, v::MxArray)
f.ptr != C_NULL || error("Cannot put variable to a null file.")
v.ptr != C_NULL || error("Cannot put an null variable.")
ret = ccall(mat_put_variable[], Cint, (Ptr{Void}, Ptr{Cchar}, Ptr{Void}),
f.ptr, name, v.ptr)
ret == 0 || error("Attempt to put variable $(name) failed.")
ret = ccall(mat_put_variable[], Cint, (Ptr{Void}, Ptr{Cchar}, Ptr{Void}), f, name, v)
ret != 0 && error("Attempt to put variable $(name) failed.")
return nothing
end

put_variable(f::MatFile, name::Symbol, v::MxArray) = put_variable(f, string(name), v)
Expand All @@ -57,18 +70,14 @@ end

function write_matfile(filename::String; kwargs...)
mf = MatFile(filename, "w")
try
put_variables(mf; kwargs...)
finally
close(mf)
end
put_variables(mf; kwargs...)
close(mf)
end

function variable_names(f::MatFile)
# get a list of all variable names
_n = Cint[0]
_a = ccall(mat_get_dir[], Ptr{Ptr{Cchar}}, (Ptr{Void}, Ptr{Cint}),
f.ptr, _n)
_a = ccall(mat_get_dir[], Ptr{Ptr{Cchar}}, (Ptr{Void}, Ptr{Cint}), f, _n)

n = Int(_n[1])
a = unsafe_wrap(Array, _a, (n,))
Expand All @@ -91,11 +100,7 @@ end

function read_matfile(filename::String)
f = MatFile(filename, "r")
local r
try
r = read_matfile(f)
finally
close(f)
end
r = read_matfile(f)
close(f)
return r
end
4 changes: 4 additions & 0 deletions test/matfile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@ gc() # make sure that ra, rb, rc, rd remain valid
@test !jscalar(get_field(rss, 2, "y"))
@test jvector(get_field(rss, 2, "z")) == ss[2].z

# segfault on deleted references
s = MatFile("test.mat", "r")
close(s)
@test_throws UndefRefError close(s)