Skip to content
Open
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
10 changes: 6 additions & 4 deletions src/MAT.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ module MAT

using HDF5, SparseArrays

include("MAT_subsys.jl")
include("MAT_HDF5.jl")
include("MAT_v5.jl")
include("MAT_v4.jl")

using .MAT_HDF5, .MAT_v5, .MAT_v4
using .MAT_HDF5, .MAT_v5, .MAT_v4, .MAT_subsys

export matopen, matread, matwrite, @read, @write

Expand All @@ -40,7 +41,7 @@ function matopen(filename::AbstractString, rd::Bool, wr::Bool, cr::Bool, tr::Boo
# When creating new files, create as HDF5 by default
fs = filesize(filename)
if cr && (tr || fs == 0)
return MAT_HDF5.matopen(filename, rd, wr, cr, tr, ff, compress)
return MAT_HDF5.matopen(filename, rd, wr, cr, tr, ff, compress, Base.ENDIAN_BOM == 0x04030201)
elseif fs == 0
error("File \"$filename\" does not exist and create was not specified")
end
Expand Down Expand Up @@ -76,7 +77,7 @@ function matopen(filename::AbstractString, rd::Bool, wr::Bool, cr::Bool, tr::Boo
seek(rawfid, offset)
if read!(rawfid, Vector{UInt8}(undef, 8)) == HDF5_HEADER
close(rawfid)
return MAT_HDF5.matopen(filename, rd, wr, cr, tr, ff, compress)
return MAT_HDF5.matopen(filename, rd, wr, cr, tr, ff, compress, endian_indicator == 0x494D)
end
end

Expand Down Expand Up @@ -133,6 +134,7 @@ function matread(filename::AbstractString)
try
vars = read(file)
finally
MAT_subsys.clear_subsys!()
close(file)
end
vars
Expand Down Expand Up @@ -165,7 +167,7 @@ function matwrite(filename::AbstractString, dict::AbstractDict{S, T}; compress::
end

else

file = matopen(filename, "w"; compress = compress)
try
for (k, v) in dict
Expand Down
86 changes: 64 additions & 22 deletions src/MAT_HDF5.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
module MAT_HDF5

using HDF5, SparseArrays
using ..MAT_subsys

import Base: names, read, write, close
import HDF5: Reference
Expand Down Expand Up @@ -69,8 +70,13 @@ function close(f::MatlabHDF5File)
unsafe_copyto!(magicptr, idptr, length(identifier))
end
magic[126] = 0x02
magic[127] = 0x49
magic[128] = 0x4d
if Base.ENDIAN_BOM == 0x04030201
magic[127] = 0x49
magic[128] = 0x4d
else
magic[127] = 0x4d
magic[128] = 0x49
end
rawfid = open(f.plain.filename, "r+")
write(rawfid, magic)
close(rawfid)
Expand All @@ -80,7 +86,7 @@ function close(f::MatlabHDF5File)
nothing
end

function matopen(filename::AbstractString, rd::Bool, wr::Bool, cr::Bool, tr::Bool, ff::Bool, compress::Bool)
function matopen(filename::AbstractString, rd::Bool, wr::Bool, cr::Bool, tr::Bool, ff::Bool, compress::Bool, endian_indicator::Bool)
local f
if ff && !wr
error("Cannot append to a read-only file")
Expand Down Expand Up @@ -109,6 +115,11 @@ function matopen(filename::AbstractString, rd::Bool, wr::Bool, cr::Bool, tr::Boo
fid.refcounter = length(g)-1
close(g)
end
subsys_refs = "#subsystem#"
if haskey(fid.plain, subsys_refs)
subsys_data = m_read(fid.plain[subsys_refs])
MAT_subsys.load_subsys!(subsys_data, endian_indicator)
end
fid
end

Expand All @@ -118,6 +129,7 @@ const name_type_attr_matlab = "MATLAB_class"
const empty_attr_matlab = "MATLAB_empty"
const sparse_attr_matlab = "MATLAB_sparse"
const int_decode_attr_matlab = "MATLAB_int_decode"
const object_type_attr_matlab = "MATLAB_object_decode"

### Reading
function read_complex(dtype::HDF5.Datatype, dset::HDF5.Dataset, ::Type{T}) where T
Expand All @@ -128,6 +140,21 @@ function read_complex(dtype::HDF5.Datatype, dset::HDF5.Dataset, ::Type{T}) where
return read(dset, Complex{T})
end

function read_cell(dset::HDF5.Dataset)
refs = read(dset, Reference)
out = Array{Any}(undef, size(refs))
f = HDF5.file(dset)
for i = 1:length(refs)
dset = f[refs[i]]
try
out[i] = m_read(dset)
finally
close(dset)
end
end
return out
end

function m_read(dset::HDF5.Dataset)
if haskey(dset, empty_attr_matlab)
# Empty arrays encode the dimensions as the dataset
Expand All @@ -150,36 +177,46 @@ function m_read(dset::HDF5.Dataset)
end

mattype = haskey(dset, name_type_attr_matlab) ? read_attribute(dset, name_type_attr_matlab) : "cell"
objecttype = haskey(dset, object_type_attr_matlab) ? read_attribute(dset, object_type_attr_matlab) : nothing

if mattype == "cell"
if mattype == "cell" && objecttype === nothing
# Cell arrays, represented as an array of refs
refs = read(dset, Reference)
out = Array{Any}(undef, size(refs))
f = HDF5.file(dset)
for i = 1:length(refs)
dset = f[refs[i]]
try
out[i] = m_read(dset)
finally
close(dset)
end
return read_cell(dset)
elseif objecttype !== nothing
if objecttype != 3
@warn "MATLAB Object Type $mattype is currently not supported."
return missing
end
if mattype == "FileWrapper__"
return read_cell(dset)
end
if haskey(dset, "MATLAB_fields")
@warn "Enumeration Instances are not supported currently."
return missing
end
return out
elseif !haskey(str2type_matlab,mattype)
@warn "MATLAB $mattype values are currently not supported"
@warn "MATLAB $mattype values are currently not supported."
return missing
end

# Regular arrays of values
# Convert to Julia type
T = str2type_matlab[mattype]
if objecttype === nothing
T = str2type_matlab[mattype]
else
T = UInt32 # FIXME: Default for MATLAB objects?
end

# Check for a COMPOUND data set, and if so handle complex numbers specially
dtype = datatype(dset)
try
class_id = HDF5.API.h5t_get_class(dtype.id)
d = class_id == HDF5.API.H5T_COMPOUND ? read_complex(dtype, dset, T) : read(dset, T)
length(d) == 1 ? d[1] : d
if objecttype !== nothing
return MAT_subsys.load_mcos_object(d, "MCOS")
else
return length(d) == 1 ? d[1] : d
end
finally
close(dtype)
end
Expand All @@ -194,7 +231,11 @@ end

# reading a struct, struct array, or sparse matrix
function m_read(g::HDF5.Group)
mattype = read_attribute(g, name_type_attr_matlab)
if HDF5.name(g) == "/#subsystem#"
mattype = "#subsystem#"
else
mattype = read_attribute(g, name_type_attr_matlab)
end
if mattype != "struct"
# Check if this is a sparse matrix.
fn = keys(g)
Expand Down Expand Up @@ -226,10 +267,11 @@ function m_read(g::HDF5.Group)
end
return SparseMatrixCSC(convert(Int, read_attribute(g, sparse_attr_matlab)), length(jc)-1, jc, ir, data)
elseif mattype == "function_handle"
@warn "MATLAB $mattype values are currently not supported"
return missing
# Fall through
else
@warn "Unknown non-struct group of type $mattype detected; attempting to read as struct"
if mattype != "#subsystem#"
@warn "Unknown non-struct group of type $mattype detected; attempting to read as struct"
end
end
end
if haskey(g, "MATLAB_fields")
Expand Down
Loading
Loading