Skip to content

Commit

Permalink
Fix last copy and expunge cruft
Browse files Browse the repository at this point in the history
  • Loading branch information
jruohio-invn authored and timholy committed Feb 18, 2019
1 parent dd036fb commit 9b4c22e
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 71 deletions.
12 changes: 7 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ os:
- linux
- osx
julia:
- 0.6
- 0.7
- 1.0
- 1.1
- nightly
addons:
# apt:
# packages:
# - hdf5-tools
before_script:
# - if [ $TRAVIS_OS_NAME = osx ]; then brew install gcc; brew link --overwrite gcc; brew install hdf5; fi
notifications:
email: false
script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- julia -e 'Pkg.clone(pwd()); Pkg.build("MAT"); Pkg.test("MAT"; coverage=true)'
after_success:
- julia -e 'cd(Pkg.dir("MAT")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
5 changes: 2 additions & 3 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
julia 0.6
HDF5
julia 0.7
HDF5 0.11.0
BufferedStreams 0.2.0
Libz
Compat 1.0
7 changes: 2 additions & 5 deletions src/MAT.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,9 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

VERSION >= v"0.4.0-dev+6521" && __precompile__()

module MAT

using HDF5, Compat
using Compat.SparseArrays
using HDF5, SparseArrays

include("MAT_HDF5.jl")
include("MAT_v5.jl")
Expand Down Expand Up @@ -144,7 +141,7 @@ end
Write a dictionary containing variable names as keys and values as values
to a Matlab file, opening and closing it automatically.
"""
function matwrite(filename::AbstractString, dict::AbstractDict{S, T}) where {S,T}
function matwrite(filename::AbstractString, dict::AbstractDict{S, T}) where {S, T}
file = matopen(filename, "w")
try
for (k, v) in dict
Expand Down
44 changes: 20 additions & 24 deletions src/MAT_HDF5.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,7 @@

module MAT_HDF5

using HDF5
using Compat
using Compat.SparseArrays

@static if VERSION < v"0.7-"
_finalizer(f, x) = finalizer(x, f)
else
_finalizer = finalizer
end
using HDF5, SparseArrays

import Base: read, write, close
import HDF5: names, exists, HDF5ReferenceObj, HDF5BitsKind
Expand All @@ -53,7 +45,7 @@ mutable struct MatlabHDF5File <: HDF5.DataFile
function MatlabHDF5File(plain, toclose::Bool=true, writeheader::Bool=false, refcounter::Int=0)
f = new(plain, toclose, writeheader, refcounter)
if toclose
_finalizer(close, f)
finalizer(close, f)
end
f
end
Expand All @@ -70,7 +62,11 @@ function close(f::MatlabHDF5File)
if f.writeheader
magic = zeros(UInt8, 512)
identifier = "MATLAB 7.3 MAT-file" # minimal but sufficient
magic[1:length(identifier)] = Vector{UInt8}(identifier)
GC.@preserve magic identifier begin
magicptr = pointer(magic)
idptr = pointer(identifier)
unsafe_copyto!(magicptr, idptr, length(identifier))
end
magic[126] = 0x02
magic[127] = 0x49
magic[128] = 0x4d
Expand Down Expand Up @@ -123,7 +119,7 @@ const sparse_attr_matlab = "MATLAB_sparse"
const int_decode_attr_matlab = "MATLAB_int_decode"

### Reading
function read_complex(dtype::HDF5Datatype, dset::HDF5Dataset, ::Type{Array{T}}) where {T}
function read_complex(dtype::HDF5Datatype, dset::HDF5Dataset, ::Type{Array{T}}) where T
if !check_datatype_complex(dtype)
close(dtype)
error("Unrecognized compound data type when reading ", name(dset))
Expand Down Expand Up @@ -301,7 +297,7 @@ toarray(x::Bool) = UInt8[x]
toarray(x) = [x]

# Write the MATLAB type string for dset
m_writetypeattr(dset, ::Type{Complex{T}}) where {T} = m_writetypeattr(dset, T)
m_writetypeattr(dset, ::Type{Complex{T}}) where T = m_writetypeattr(dset, T)
function m_writetypeattr(dset, T)
if !haskey(type2str_matlab, T)
error("Type ", T, " is not (yet) supported")
Expand All @@ -316,7 +312,7 @@ function m_writetypeattr(dset, T)
end

# Writes an empty scalar or array
function m_writeempty(parent::HDF5Parent, name::String, data::Array)
function m_writeempty(parent::HDF5Parent, name::String, data::AbstractArray)
adata = [size(data)...]
dset, dtype = d_create(parent, name, adata)
try
Expand All @@ -330,7 +326,7 @@ function m_writeempty(parent::HDF5Parent, name::String, data::Array)
end

# Write an array to a dataset in a MATLAB file, returning the dataset
function m_writearray(parent::HDF5Parent, name::String, adata::Array{T}) where {T<:HDF5BitsOrBool}
function m_writearray(parent::HDF5Parent, name::String, adata::AbstractArray{T}) where {T<:HDF5BitsOrBool}
dset, dtype = d_create(parent, name, adata)
try
HDF5.writearray(dset, dtype.id, adata)
Expand All @@ -342,14 +338,14 @@ function m_writearray(parent::HDF5Parent, name::String, adata::Array{T}) where {
close(dtype)
end
end
function m_writearray(parent::HDF5Parent, name::String, adata::Array{Complex{T}}) where {T<:HDF5BitsOrBool}
function m_writearray(parent::HDF5Parent, name::String, adata::AbstractArray{Complex{T}}) where {T<:HDF5BitsOrBool}
dtype = build_datatype_complex(T)
try
stype = dataspace(adata)
obj_id = HDF5.h5d_create(parent.id, name, dtype.id, stype.id)
dset = HDF5Dataset(obj_id, file(parent))
try
arr = reinterpret(T, adata, tuple(2, size(adata)...))
arr = reshape(reinterpret(T, adata), tuple(2, size(adata)...))
HDF5.writearray(dset, dtype.id, arr)
catch e
close(dset)
Expand Down Expand Up @@ -378,16 +374,16 @@ function m_write(mfile::MatlabHDF5File, parent::HDF5Parent, name::String, data::
end

# Write sparse arrays
function m_write(mfile::MatlabHDF5File, parent::HDF5Parent, name::String, data::SparseMatrixCSC{T}) where {T}
function m_write(mfile::MatlabHDF5File, parent::HDF5Parent, name::String, data::SparseMatrixCSC{T}) where T
g = g_create(parent, name)
try
m_writetypeattr(g, T)
a_write(g, sparse_attr_matlab, UInt64(size(data, 1)))
if !isempty(data.nzval)
close(m_writearray(g, "data", toarray(data.nzval)))
close(m_writearray(g, "ir", add!(isa(data.rowval, Vector{UInt64}) ? copy(data.rowval) : convert(Vector{UInt64}, data.rowval), reinterpret(UInt64, convert(Int64, -1)))))
close(m_writearray(g, "ir", add!(isa(data.rowval, Vector{UInt64}) ? copy(data.rowval) : convert(Vector{UInt64}, data.rowval), typemax(UInt64))))
end
close(m_writearray(g, "jc", add!(isa(data.colptr, Vector{UInt64}) ? copy(data.colptr) : convert(Vector{UInt64}, data.colptr), reinterpret(UInt64, convert(Int64, -1)))))
close(m_writearray(g, "jc", add!(isa(data.colptr, Vector{UInt64}) ? copy(data.colptr) : convert(Vector{UInt64}, data.colptr), typemax(UInt64))))
finally
close(g)
end
Expand Down Expand Up @@ -431,7 +427,7 @@ function m_write(mfile::MatlabHDF5File, parent::HDF5Parent, name::String, str::A
end

# Write cell arrays
function m_write(mfile::MatlabHDF5File, parent::HDF5Parent, name::String, data::Array{T}) where {T}
function m_write(mfile::MatlabHDF5File, parent::HDF5Parent, name::String, data::Array{T}) where T
pathrefs = "/#refs#"
fid = file(parent)
local g
Expand Down Expand Up @@ -538,7 +534,7 @@ end

## Type conversion operations ##

struct MatlabString; end
struct MatlabString end

const str2type_matlab = Dict(
"canonical empty" => nothing,
Expand Down Expand Up @@ -607,14 +603,14 @@ function read(obj::HDF5Object, ::Type{Bool})
tf = read(obj, UInt8)
tf > 0
end
function read(obj::HDF5Object, ::Type{Array{Bool}})
function read(obj::HDF5Dataset, ::Type{Array{Bool}})
if HDF5.isnull(obj)
return Bool[]
end
# Use the low-level HDF5 API to put the data directly into a Bool array
tf = Array{Bool}(undef, size(obj))
HDF5.h5d_read(obj.id, HDF5.hdf5_type_id(UInt8), tf, obj.xfer)
tf
return tf
end

## Utilities for handling complex numbers
Expand Down
35 changes: 17 additions & 18 deletions src/MAT_v5.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,12 @@
# http://www.mathworks.com/help/pdf_doc/matlab/matfile_format.pdf

module MAT_v5
using Libz, BufferedStreams, HDF5, Compat
using Compat.SparseArrays
using Libz, BufferedStreams, HDF5, SparseArrays
import Base: read, write, close
import HDF5: names, exists

if VERSION < v"0.6.0-dev.1632"
round_uint8(data) = round(UInt8, data)
complex_array(a, b) = complex(a, b)
else
round_uint8(data) = round.(UInt8, data)
complex_array(a, b) = complex.(a, b)
end
round_uint8(data) = round.(UInt8, data)
complex_array(a, b) = complex.(a, b)

mutable struct Matlabv5File <: HDF5.DataFile
ios::IOStream
Expand Down Expand Up @@ -85,9 +79,9 @@ const CONVERT_TYPES = Type[
Union{}, Float64, Float32, Int8, UInt8,
Int16, UInt16, Int32, UInt32, Int64, UInt64]

read_bswap(f::IO, swap_bytes::Bool, ::Type{T}) where {T} =
read_bswap(f::IO, swap_bytes::Bool, ::Type{T}) where T =
swap_bytes ? bswap(read(f, T)) : read(f, T)
function read_bswap(f::IO, swap_bytes::Bool, ::Type{T}, dim::Union{Int, Tuple{Vararg{Int}}}) where {T}
function read_bswap(f::IO, swap_bytes::Bool, ::Type{T}, dim::Union{Int, Tuple{Vararg{Int}}}) where T
d = read!(f, Array{T}(undef, dim))
if swap_bytes
for i = 1:length(d)
Expand All @@ -96,6 +90,15 @@ function read_bswap(f::IO, swap_bytes::Bool, ::Type{T}, dim::Union{Int, Tuple{Va
end
d
end
function read_bswap(f::IO, swap_bytes::Bool, d::AbstractArray{T}) where T
readbytes!(f, reinterpret(UInt8, d))
if swap_bytes
for i = 1:length(d)
@inbounds d[i] = bswap(d[i])
end
end
d
end

skip_padding(f::IO, nbytes::Int, hbytes::Int) = if nbytes % hbytes != 0
skip(f, hbytes-(nbytes % hbytes))
Expand All @@ -115,7 +118,7 @@ function read_header(f::IO, swap_bytes::Bool)
end

# Read data element as a vector of a given type
function read_element(f::IO, swap_bytes::Bool, ::Type{T}) where {T}
function read_element(f::IO, swap_bytes::Bool, ::Type{T}) where T
(dtype, nbytes, hbytes) = read_header(f, swap_bytes)
data = read_bswap(f, swap_bytes, T, Int(div(nbytes, sizeof(T))))
skip_padding(f, nbytes, hbytes)
Expand All @@ -134,7 +137,7 @@ end
# Read data element as encoded type with given dimensions, converting
# to another type if necessary and collapsing one-element matrices to
# scalars
function read_data(f::IO, swap_bytes::Bool, ::Type{T}, dimensions::Vector{Int32}) where {T}
function read_data(f::IO, swap_bytes::Bool, ::Type{T}, dimensions::Vector{Int32}) where T
(dtype, nbytes, hbytes) = read_header(f, swap_bytes)
read_type = READ_TYPES[dtype]
if (read_type === UInt8) && (T === Bool)
Expand Down Expand Up @@ -244,11 +247,7 @@ function read_sparse(f::IO, swap_bytes::Bool, dimensions::Vector{Int32}, flags::
SparseMatrixCSC(m, n, jc, ir, pr)
end

if VERSION >= v"0.4.0-dev+1039"
truncate_to_uint8(x) = x % UInt8
else
truncate_to_uint8(x) = convert(UInt8, x)
end
truncate_to_uint8(x) = x % UInt8

function read_string(f::IO, swap_bytes::Bool, dimensions::Vector{Int32})
(dtype, nbytes, hbytes) = read_header(f, swap_bytes)
Expand Down
12 changes: 3 additions & 9 deletions test/read.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
using MAT

@static if VERSION < v"0.7-"
using Base.Test
else
using Test
end
using MAT, Test

function check(filename, result)
matfile = matopen(filename)
Expand Down Expand Up @@ -95,7 +89,7 @@ for _format in ["v6", "v7", "v7.3"]
"a1x2" => [1.0 2.0],
"a2x1" => zeros(2, 1)+[1.0, 2.0],
"a2x2" => [1.0 3.0; 4.0 2.0],
"a2x2x2" => Compat.cat([1.0 3.0; 4.0 2.0], [1.0 2.0; 3.0 4.0], dims=3),
"a2x2x2" => cat([1.0 3.0; 4.0 2.0], [1.0 2.0; 3.0 4.0]; dims=3),
"empty" => zeros(0, 0),
"string" => "string"
)
Expand Down Expand Up @@ -123,7 +117,7 @@ for _format in ["v6", "v7", "v7.3"]
true false false
false true false
true false false
]
]
)
check("logical.mat", result)

Expand Down
4 changes: 1 addition & 3 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Compat
using Compat.SparseArrays
using Compat.LinearAlgebra
using SparseArrays, LinearAlgebra

include("read.jl")
include("write.jl")
10 changes: 6 additions & 4 deletions test/write.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using MAT

tmpfile = string(tempname, ".mat")
tmpfile = string(tempname(), ".mat")

function test_write(data)
matwrite(tmpfile, data)
Expand Down Expand Up @@ -33,6 +33,8 @@ test_write(Dict(
))

test_write(Dict(
"ComplexInt" => Complex{Int}[1 -1 1+1im 1-1im -1+1im -1-1im 1im],
"ComplexF32" => ComplexF32[1.0 -1.0 1.0+1.0im 1.0-1.0im -1.0+1.0im -1.0-1.0im 1.0im],
"ComplexF64" => [1.0 -1.0 1.0+1.0im 1.0-1.0im -1.0+1.0im -1.0-1.0im 1.0im],
"ComplexPair" => [1 2-3im 4+5im]
))
Expand All @@ -50,7 +52,7 @@ test_write(Dict(
"a1x2" => [1.0 2.0],
"a2x1" => zeros(2, 1)+[1.0, 2.0],
"a2x2" => [1.0 3.0; 4.0 2.0],
"a2x2x2" => Compat.cat([1.0 3.0; 4.0 2.0], [1.0 2.0; 3.0 4.0], dims=3),
"a2x2x2" => cat([1.0 3.0; 4.0 2.0], [1.0 2.0; 3.0 4.0], dims=3),
"empty" => zeros(0, 0),
"string" => "string"
))
Expand Down Expand Up @@ -81,7 +83,7 @@ test_write(Dict(
@test_throws ErrorException test_write(Dict("another invalid key" => "invalid characters"))
@test_throws ErrorException test_write(Dict("yetanotherinvalidkeyyetanotherinvalidkeyyetanotherinvalidkeyyetanotherinvalidkey" => "too long"))

type TestCompositeKind
struct TestCompositeKind
field1::AbstractString
end
fid = matopen(tmpfile, "w")
Expand All @@ -103,6 +105,6 @@ sd = SortedDict(Dict(
"ComplexF64" => [1.0 -1.0 1.0+1.0im 1.0-1.0im -1.0+1.0im -1.0-1.0im 1.0im],
"simple_string" => "the quick brown fox",
"a1x2" => [1.0 2.0],
"sparse_empty" => sparse(Matrix{Float64}(0, 0))
"sparse_empty" => sparse(Matrix{Float64}(undef, 0, 0))
))
test_write(sd)

0 comments on commit 9b4c22e

Please sign in to comment.