diff --git a/.travis.yml b/.travis.yml index 8c1cad1e..78d2dc51 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,12 @@ os: - osx julia: - 0.6 + - 0.7 - nightly +matrix: + fast_finish: true + allow_failures: + - julia: nightly notifications: email: false script: diff --git a/appveyor.yml b/appveyor.yml index db170d5a..c9d986ff 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,9 +2,16 @@ environment: matrix: - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe" - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe" + - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.7/julia-0.7-latest-win32.exe" + - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.7/julia-0.7-latest-win64.exe" - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe" - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe" +matrix: + allow_failures: + - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe" + - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe" + branches: only: - master diff --git a/src/JLD2.jl b/src/JLD2.jl index 90bb23fb..3e40af3b 100644 --- a/src/JLD2.jl +++ b/src/JLD2.jl @@ -4,8 +4,11 @@ module JLD2 using DataStructures, CodecZlib, FileIO import Base.sizeof using Compat -if VERSION >= v"0.7.0-DEV.2009" - using Mmap +using Compat.Printf +using Compat.Mmap + +if !isdefined(Base, :isbitstype) + const isbitstype = isbits # TODO: Add to Compat end export jldopen, @load, @save @@ -54,7 +57,7 @@ const NULL_REFERENCE = RelOffset(0) JLDWriteSession{T} A JLDWriteSession keeps track of references to serialized objects. If `T` is a Dict, -`h5offset` maps an object ID (returned by calling `object_id`) to th `RelOffset` of the +`h5offset` maps an object ID (returned by calling `objectid`) to th `RelOffset` of the written dataset. If it is `Union{}`, then references are not tracked, and objects referenced multiple times are written multiple times. """ @@ -197,7 +200,12 @@ openfile(::Type{IOStream}, fname, wr, create, truncate) = openfile(::Type{MmapIO}, fname, wr, create, truncate) = MmapIO(fname, wr, create, truncate) -read_bytestring(io::IOStream) = chop(String(readuntil(io, 0x00))) +if VERSION >= v"0.7.0-DEV.3510" + # The delimiter is excluded by default + read_bytestring(io::IOStream) = String(readuntil(io, 0x00)) +else + read_bytestring(io::IOStream) = chop(String(readuntil(io, 0x00))) +end const OPEN_FILES = Dict{String,WeakRef}() function jldopen(fname::AbstractString, wr::Bool, create::Bool, truncate::Bool, iotype::T=MmapIO; @@ -240,7 +248,7 @@ function jldopen(fname::AbstractString, wr::Bool, create::Bool, truncate::Bool, f.root_group = Group{typeof(f)}(f) f.types_group = Group{typeof(f)}(f) else - if String(read!(io, Vector{UInt8}(length(REQUIRED_FILE_HEADER)))) != REQUIRED_FILE_HEADER + if String(read!(io, Vector{UInt8}(undef, length(REQUIRED_FILE_HEADER)))) != REQUIRED_FILE_HEADER throw(ArgumentError(string('"', fname, "\" is not a JLD file"))) end diff --git a/src/bufferedio.jl b/src/bufferedio.jl index 4313a2a4..16c2b919 100644 --- a/src/bufferedio.jl +++ b/src/bufferedio.jl @@ -19,7 +19,7 @@ end function BufferedWriter(io::IOStream, buffer_size::Int) pos = position(io) skip(io, buffer_size) - BufferedWriter(io, Vector{UInt8}(buffer_size), pos, Ref{Int}(0)) + BufferedWriter(io, Vector{UInt8}(undef, buffer_size), pos, Ref{Int}(0)) end Base.show(io::IO, ::BufferedWriter) = print(io, "BufferedWriter") @@ -53,7 +53,7 @@ function Base.unsafe_write(io::BufferedWriter, x::Ptr{UInt8}, n::UInt64) buffer = io.buffer position = io.position[] n + position <= length(buffer) || throw(EOFError()) - unsafe_copy!(pointer(buffer, position+1), x, n) + unsafe_copyto!(pointer(buffer, position+1), x, n) io.position[] = position + n # Base.show_backtrace(STDOUT, backtrace()) # gc() @@ -70,7 +70,7 @@ struct BufferedReader <: IO end BufferedReader(io::IOStream) = - BufferedReader(io, Vector{UInt8}(0), position(io), Ref{Int}(0)) + BufferedReader(io, Vector{UInt8}(), position(io), Ref{Int}(0)) Base.show(io::IO, ::BufferedReader) = print(io, "BufferedReader") function readmore!(io::BufferedReader, n::Int) @@ -103,8 +103,8 @@ function Base.read(io::BufferedReader, ::Type{T}, n::Int) where T readmore!(io, sizeof(T)) end io.position[] = position + n - arr = Vector{T}(n) - unsafe_copy!(pointer(arr), Ptr{T}(pointer(buffer, position+1)), n) + arr = Vector{T}(undef, n) + unsafe_copyto!(pointer(arr), Ptr{T}(pointer(buffer, position+1)), n) arr end Base.read(io::BufferedReader, ::Type{T}, n::Integer) where {T} = diff --git a/src/data.jl b/src/data.jl index f1812e25..0d451f92 100644 --- a/src/data.jl +++ b/src/data.jl @@ -1,9 +1,9 @@ const Initialized = Union{Type{Val{true}}, Type{Val{false}}} -const Pointers = Union{Ptr{Void}, IndirectPointer} +const Pointers = Union{Ptr{Cvoid}, IndirectPointer} struct OnDiskRepresentation{Offsets,JLTypes,H5Types} end -odr_sizeof(::Void) = 0 +odr_sizeof(::Nothing) = 0 @Base.pure odr_sizeof(x::DataType) = Int(x.size) struct UnknownType{T} @@ -50,7 +50,7 @@ odr_sizeof(::ReadRepresentation{T,S}) where {T,S} = odr_sizeof(S) # Determines whether a specific field type should be saved in the file @noinline function hasfielddata(@nospecialize T) T === Union{} && return false - !isconcrete(T) && return true + !isconcretetype(T) && return true T = T::DataType (T.mutable || T <: Type) && return true hasdata(T) @@ -85,19 +85,19 @@ function samelayout(T::DataType) end samelayout(::Type) = false -fieldnames(x::Type{T}) where {T<:Tuple} = [Symbol(x) for x = 1:length(x.types)] -fieldnames(@nospecialize x) = Base.fieldnames(x) +fieldnames(x::Type{T}) where {T<:Tuple} = [Symbol(i) for i = 1:length(x.types)] +fieldnames(@nospecialize x) = collect(Base.fieldnames(x)) # fieldodr gives the on-disk representation of a field of a given type, # which is either always initialized (initialized=true) or potentially # uninitialized (initialized=false) @generated function fieldodr(::Type{T}, initialized::Bool) where T - if isconcrete(T) + if isconcretetype(T) if !hasfielddata(T) # A ghost type, so no need to store at all return nothing elseif isa(T, DataType) - if isbits(T) + if isbitstype(T) return :(odr(T)) elseif !T.mutable return :(initialized ? odr(T) : RelOffset) @@ -111,10 +111,10 @@ end # datatype reflecting the on-disk representation. @generated function h5fieldtype(f::JLDFile, writeas::Type{T}, readas::Type, initialized::Initialized) where T - if isconcrete(T) + if isconcretetype(T) if !hasfielddata(T) return nothing - elseif isbits(T) || (isa(initialized, Type{Type{Val{true}}}) && !T.mutable) + elseif isbitstype(T) || (isa(initialized, Type{Type{Val{true}}}) && !T.mutable) return quote @lookup_committed f T $(if isempty(T.types) @@ -283,7 +283,7 @@ function jltype(f::JLDFile, cdt::CommittedDatatype) end end - if isa(julia_type_attr, Void) + if isa(julia_type_attr, Nothing) throw(InvalidDataException()) end julia_type_attr = julia_type_attr::ReadAttribute @@ -371,7 +371,7 @@ function constructrr(f::JLDFile, T::DataType, dt::CompoundDatatype, field_datatypes = read_field_datatypes(f, attrs) # If read type is not a leaf type, reconstruct - if !isconcrete(T) + if !isconcretetype(T) warn("read type $T is not a leaf type in workspace; reconstructing") return reconstruct_compound(f, string(T), dt, field_datatypes) end @@ -383,11 +383,11 @@ function constructrr(f::JLDFile, T::DataType, dt::CompoundDatatype, end mapped = falses(length(dt.names)) - offsets = Vector{Int}(length(T.types)) - types = Vector{Any}(length(T.types)) - odrs = Vector{Any}(length(T.types)) + offsets = Vector{Int}(undef, length(T.types)) + types = Vector{Any}(undef, length(T.types)) + odrs = Vector{Any}(undef, length(T.types)) fn = fieldnames(T) - samelayout = isbits(T) && T.size == dt.size + samelayout = isbitstype(T) && T.size == dt.size dtindex = 0 for i = 1:length(T.types) wstype = T.types[i] @@ -446,7 +446,7 @@ function constructrr(f::JLDFile, T::DataType, dt::CompoundDatatype, # This should theoretically be moved inside the if statement, but then it returns # the wrong result due to a bug in type inference on 0.6 typeof_wodr = typeof(wodr) - offsets = (offsets...) + offsets = (offsets...,) if wodr isa OnDiskRepresentation odr_offsets = typeof_wodr.parameters[1] odr_types = typeof_wodr.parameters[2].parameters @@ -497,11 +497,11 @@ h5convert!(out::Pointers, ::Type{T}, ::JLDFile, x, ::JLDWriteSession) where {T} args = ex.args for i = 1:length(Offsets) member = members[i] - isa(member, Void) && continue + isa(member, Nothing) && continue offset = Offsets[i] conv = :(h5convert!(out+$offset, $(member), file, convert($(types[i]), $getindex_fn(x, $i)), wsession)) - if i > T.ninitialized && (!isconcrete(x.types[i]) || !isbits(x.types[i])) + if i > T.ninitialized && (!isconcretetype(x.types[i]) || !isbitstype(x.types[i])) push!(args, quote if !isdefined(x, $i) h5convert_uninitialized!(out+$offset, $(member)) @@ -758,7 +758,7 @@ end function h5convert!(out::Pointers, fls::FixedLengthString, f::JLDFile, x, ::JLDWriteSession) fls.length == sizeof(x) || throw(InvalidDataException()) - (unsafe_copy!(convert(Ptr{UInt8}, out), pointer(x), fls.length); nothing) + (unsafe_copyto!(convert(Ptr{UInt8}, out), pointer(x), fls.length); nothing) end h5convert!(out::Pointers, ::Type{Vlen{String}}, f::JLDFile, x, wsession::JLDWriteSession) = store_vlen!(out, UInt8, f, Vector{UInt8}(x), wsession) @@ -766,8 +766,8 @@ h5convert!(out::Pointers, ::Type{Vlen{String}}, f::JLDFile, x, wsession::JLDWrit jlconvert(::ReadRepresentation{String,Vlen{String}}, f::JLDFile, ptr::Ptr, ::RelOffset) = String(jlconvert(ReadRepresentation{UInt8,Vlen{UInt8}}(), f, ptr, NULL_REFERENCE)) function jlconvert(rr::FixedLengthString{String}, ::JLDFile, ptr::Ptr, ::RelOffset) - data = Vector{UInt8}(rr.length) - unsafe_copy!(pointer(data), convert(Ptr{UInt8}, ptr), rr.length) + data = Vector{UInt8}(undef, rr.length) + unsafe_copyto!(pointer(data), convert(Ptr{UInt8}, ptr), rr.length) String(data) end @@ -848,9 +848,9 @@ odr(::Type{T}) where {T<:DataType} = DataTypeODR() function typename(T::DataType) tn = Symbol[] m = T.name.module - while m != module_parent(m) + while m != parentmodule(m) push!(tn, module_name(m)) - m = module_parent(m) + m = parentmodule(m) end reverse!(tn) push!(tn, T.name.name) @@ -1025,15 +1025,15 @@ end ## SimpleVectors writeas(::Type{Core.SimpleVector}) = Vector{Any} -wconvert(::Type{Vector{Any}}, x::Core.SimpleVector) = Any[x for x in x] +wconvert(::Type{Vector{Any}}, x::Core.SimpleVector) = collect(Any, x) rconvert(::Type{Core.SimpleVector}, x::Vector{Any}) = Core.svec(x...) ## Dicts writeas(::Type{Dict{K,V}}) where {K,V} = Vector{Pair{K,V}} writeas(::Type{ObjectIdDict}) = Vector{Pair{Any,Any}} -wconvert(::Type{Vector{Pair{K,V}}}, x::Associative{K,V}) where {K,V} = collect(x) -function rconvert(::Type{T}, x::Vector{Pair{K,V}}) where {T<:Associative,K,V} +wconvert(::Type{Vector{Pair{K,V}}}, x::AbstractDict{K,V}) where {K,V} = collect(x) +function rconvert(::Type{T}, x::Vector{Pair{K,V}}) where {T<:AbstractDict,K,V} d = T() isa(d, Dict) && sizehint!(d::Dict, length(x)) for (k,v) in x @@ -1156,8 +1156,8 @@ end function reconstruct_odr(f::JLDFile, dt::CompoundDatatype, field_datatypes::Vector{RelOffset}) # Get the type and ODR information for each field - types = Vector{Any}(length(dt.names)) - h5types = Vector{Any}(length(dt.names)) + types = Vector{Any}(undef, length(dt.names)) + h5types = Vector{Any}(undef, length(dt.names)) for i = 1:length(dt.names) if !isempty(field_datatypes) && (ref = field_datatypes[i]) != NULL_REFERENCE dtrr = jltype(f, f.datatype_locations[ref]) @@ -1166,14 +1166,14 @@ function reconstruct_odr(f::JLDFile, dt::CompoundDatatype, end types[i], h5types[i] = typeof(dtrr).parameters end - return OnDiskRepresentation{(dt.offsets...), Tuple{types...}, Tuple{h5types...}}() + return OnDiskRepresentation{(dt.offsets...,), Tuple{types...}, Tuple{h5types...}}() end # Reconstruct type that is a "lost cause": either we were not able to resolve # the name, or the workspace type has additional fields, or cannot convert # fields to workspace types function reconstruct_compound(f::JLDFile, T::String, dt::H5Datatype, - field_datatypes::Union{Vector{RelOffset},Void}) + field_datatypes::Union{Vector{RelOffset},Nothing}) rodr = reconstruct_odr(f, dt, field_datatypes) types = typeof(rodr).parameters[2].parameters @@ -1236,7 +1236,7 @@ jlconvert(::ReadRepresentation{Core.TypeofBottom,nothing}, f::JLDFile, ptr::Ptr, blk = Expr(:block) args = blk.args - if isbits(T) + if isbitstype(T) # For bits types, we should always inline, because otherwise we'll just # pass a lot of crap around in registers push!(args, Expr(:meta, :inline)) @@ -1308,13 +1308,13 @@ end # A pointer singleton or ghost. We need to write something, but we'll # just write a single byte. return nothing - elseif isbits(T) && samelayout(T) + elseif isbitstype(T) && samelayout(T) # Has a specialized convert method or is an unpadded type return T end offsets = zeros(Int, length(T.types)) - odrs = Vector{Any}(length(T.types)) + odrs = Vector{Any}(undef, length(T.types)) offset = 0 for i = 1:length(T.types) ty = T.types[i] @@ -1329,7 +1329,7 @@ end offset += odr_sizeof(fodr) end - OnDiskRepresentation{(offsets...), Tuple{T.types...}, Tuple{odrs...}}() + OnDiskRepresentation{(offsets...,), Tuple{T.types...}, Tuple{odrs...}}() end abstract type DataMode end @@ -1340,7 +1340,7 @@ struct HasReferences <: DataMode end @Base.pure datamode(::Union{Type{<:Vlen},Type{RelOffset}}) = HasReferences() @Base.pure datamode(::DataType) = ReferenceFree() @Base.pure datamode(::FixedLengthString) = ReferenceFree() -@Base.pure datamode(::Void) = ReferenceFree() +@Base.pure datamode(::Nothing) = ReferenceFree() @generated function datamode(odr::OnDiskRepresentation{Offsets,JLTypes,H5Types} where {Offsets,JLTypes}) where H5Types for ty in H5Types.parameters datamode(ty) == HasReferences() && return HasReferences() diff --git a/src/dataio.jl b/src/dataio.jl index 3ced54bf..a7575d5e 100644 --- a/src/dataio.jl +++ b/src/dataio.jl @@ -54,7 +54,7 @@ end seek(regulario, inptr - io.startptr) unsafe_read(regulario, pointer(v), nb) else - unsafe_copy!(pointer(v), convert(Ptr{T}, inptr), n) + unsafe_copyto!(pointer(v), convert(Ptr{T}, inptr), n) end io.curptr = inptr + odr_sizeof(T) * n v @@ -82,7 +82,7 @@ end inptr = io.curptr data = transcode(ZlibDecompressor, unsafe_wrap(Array, Ptr{UInt8}(inptr), data_length)) @simd for i = 1:length(v) - dataptr = Ptr{Void}(pointer(data, odr_sizeof(RR)*(i-1)+1)) + dataptr = Ptr{Cvoid}(pointer(data, odr_sizeof(RR)*(i-1)+1)) if !jlconvert_canbeuninitialized(rr) || jlconvert_isinitialized(rr, dataptr) @inbounds v[i] = jlconvert(rr, f, dataptr, NULL_REFERENCE) end @@ -174,7 +174,7 @@ function write_data(io::MmapIO, f::JLDFile, data::Array{T}, odr::S, ::HasReferen cp = IndirectPointer(io, p) for i = 1:length(data) - if (isconcrete(T) && isbits(T)) || unsafe_isdefined(data, i) + if (isconcretetype(T) && isbitstype(T)) || unsafe_isdefined(data, i) @inbounds h5convert!(cp, odr, f, data[i], wsession) else @inbounds h5convert_uninitialized!(cp, odr) @@ -191,7 +191,7 @@ end # @inline function read_scalar(f::JLDFile{IOStream}, rr, header_offset::RelOffset) - r = Vector{UInt8}(odr_sizeof(rr)) + r = Vector{UInt8}(undef, odr_sizeof(rr)) unsafe_read(f.io, pointer(r), odr_sizeof(rr)) jlconvert(rr, f, pointer(r), header_offset) end @@ -202,9 +202,9 @@ end io = f.io data_offset = position(io) n = length(v) - data = read!(ZlibDecompressorStream(io), Vector{UInt8}(odr_sizeof(RR)*n)) + data = read!(ZlibDecompressorStream(io), Vector{UInt8}(undef, odr_sizeof(RR)*n)) @simd for i = 1:n - dataptr = Ptr{Void}(pointer(data, odr_sizeof(RR)*(i-1)+1)) + dataptr = Ptr{Cvoid}(pointer(data, odr_sizeof(RR)*(i-1)+1)) if !jlconvert_canbeuninitialized(rr) || jlconvert_isinitialized(rr, dataptr) @inbounds v[i] = jlconvert(rr, f, dataptr, NULL_REFERENCE) end @@ -224,9 +224,9 @@ end n = length(v) nb = odr_sizeof(RR)*n io = f.io - data = read!(io, Vector{UInt8}(nb)) + data = read!(io, Vector{UInt8}(undef, nb)) @simd for i = 1:n - dataptr = Ptr{Void}(pointer(data, odr_sizeof(RR)*(i-1)+1)) + dataptr = Ptr{Cvoid}(pointer(data, odr_sizeof(RR)*(i-1)+1)) if !jlconvert_canbeuninitialized(rr) || jlconvert_isinitialized(rr, dataptr) @inbounds v[i] = jlconvert(rr, f, dataptr, NULL_REFERENCE) end @@ -237,7 +237,7 @@ end function write_data(io::BufferedWriter, f::JLDFile, data, odr::S, ::DataMode, wsession::JLDWriteSession) where S position = io.position[] - h5convert!(Ptr{Void}(pointer(io.buffer, position+1)), odr, f, data, wsession) + h5convert!(Ptr{Cvoid}(pointer(io.buffer, position+1)), odr, f, data, wsession) io.position[] = position + odr_sizeof(odr) nothing end @@ -257,9 +257,9 @@ end function write_data(io::BufferedWriter, f::JLDFile, data::Array{T}, odr::S, ::DataMode, wsession::JLDWriteSession) where {T,S} position = io.position[] - cp = Ptr{Void}(pointer(io.buffer, position+1)) + cp = Ptr{Cvoid}(pointer(io.buffer, position+1)) @simd for i = 1:length(data) - if (isconcrete(T) && isbits(T)) || unsafe_isdefined(data, i) + if (isconcretetype(T) && isbitstype(T)) || unsafe_isdefined(data, i) @inbounds h5convert!(cp, odr, f, data[i], wsession) else @inbounds h5convert_uninitialized!(cp, odr) @@ -273,11 +273,11 @@ end function write_data(io::IOStream, f::JLDFile, data::Array{T}, odr::S, wm::DataMode, wsession::JLDWriteSession) where {T,S} nb = odr_sizeof(odr) * length(data) - buf = Vector{UInt8}(nb) + buf = Vector{UInt8}(undef, nb) pos = position(io) - cp = Ptr{Void}(pointer(buf)) + cp = Ptr{Cvoid}(pointer(buf)) @simd for i = 1:length(data) - if (isconcrete(T) && isbits(T)) || unsafe_isdefined(data, i) + if (isconcretetype(T) && isbitstype(T)) || unsafe_isdefined(data, i) @inbounds h5convert!(cp, odr, f, data[i], wsession) else @inbounds h5convert_uninitialized!(cp, odr) diff --git a/src/datasets.jl b/src/datasets.jl index 3f2185ad..6ea8ae36 100644 --- a/src/datasets.jl +++ b/src/datasets.jl @@ -139,7 +139,7 @@ function read_data(f::JLDFile, dataspace::ReadDataspace, datatype_class::UInt8, datatype_offset::Int64, data_offset::Int64, data_length::Int=-1, filter_id::UInt16=UInt16(0), header_offset::RelOffset=NULL_REFERENCE, - attributes::Union{Vector{ReadAttribute},Void}=nothing) + attributes::Union{Vector{ReadAttribute},Nothing}=nothing) # See if there is a julia type attribute io = f.io if datatype_class == typemax(UInt8) # Committed datatype @@ -164,7 +164,7 @@ end const BOXED_READ_DATASPACE = Ref{Tuple{ReadDataspace,RelOffset,Int,UInt16}}() # Most types can only be scalars or arrays -function read_data(f::JLDFile, rr, attributes::Union{Vector{ReadAttribute},Void}=nothing) +function read_data(f::JLDFile, rr, attributes::Union{Vector{ReadAttribute},Nothing}=nothing) dataspace, header_offset, data_length, filter_id = BOXED_READ_DATASPACE[] if dataspace.dataspace_type == DS_SCALAR filter_id != 0 && throw(UnsupportedFeatureException()) @@ -218,7 +218,7 @@ function read_data(f::JLDFile, dimensions_attr_index = find_dimensions_attr(attributes) if dimensions_attr_index == 0 - jlconvert(rr, f, Ptr{Void}(0), header_offset) + jlconvert(rr, f, Ptr{Cvoid}(0), header_offset) else # dimensions attribute => array of empty type read_empty(rr, f, attributes[dimensions_attr_index], header_offset) @@ -250,16 +250,16 @@ function read_empty(rr::ReadRepresentation{T}, f::JLDFile, seek(io, dimensions_attr.data_offset) v = construct_array(io, T, ndims) - if isconcrete(T) + if isconcretetype(T) for i = 1:length(v) - @inbounds v[i] = jlconvert(rr, f, Ptr{Void}(0), header_offset) + @inbounds v[i] = jlconvert(rr, f, Ptr{Cvoid}(0), header_offset) end end header_offset !== NULL_REFERENCE && (f.jloffset[header_offset] = WeakRef(v)) v end -get_ndims_offset(f::JLDFile, dataspace::ReadDataspace, attributes::Void) = +get_ndims_offset(f::JLDFile, dataspace::ReadDataspace, attributes::Nothing) = (dataspace.dimensionality, dataspace.dimensions_offset) function get_ndims_offset(f::JLDFile, dataspace::ReadDataspace, attributes::Vector{ReadAttribute}) @@ -288,19 +288,19 @@ seeked to the correct position. function construct_array{T}(io::IO, ::Type{T}, ndims::Int)::Array{T} if ndims == 1 n = read(io, Int64) - Vector{T}(n) + Vector{T}(undef, n) elseif ndims == 2 d2 = read(io, Int64) d1 = read(io, Int64) - Matrix{T}(d1, d2) + Matrix{T}(undef, d1, d2) elseif ndims == 3 d3 = read(io, Int64) d2 = read(io, Int64) d1 = read(io, Int64) - Array{T,3}(d1, d2, d3) + Array{T,3}(undef, d1, d2, d3) else - ds = reverse!(read!(io, Vector{Int64}(ndims))) - Array{T}(tuple(ds...)) + ds = reverse!(read!(io, Vector{Int64}(undef, ndims))) + Array{T}(undef, tuple(ds...)) end end @@ -308,7 +308,7 @@ end function read_array(f::JLDFile, dataspace::ReadDataspace, rr::ReadRepresentation{T,RR}, data_length::Int, filter_id::UInt16, header_offset::RelOffset, - attributes::Union{Vector{ReadAttribute},Void}) where {T,RR} + attributes::Union{Vector{ReadAttribute},Nothing}) where {T,RR} io = f.io data_offset = position(io) ndims, offset = get_ndims_offset(f, dataspace, attributes) @@ -335,11 +335,11 @@ end # Like isdefined, but assumes arr is a pointer array, and can be inlined unsafe_isdefined(arr::Array, i::Int) = - unsafe_load(Ptr{Ptr{Void}}(pointer(arr)+(i-1)*sizeof(Ptr{Void}))) != Ptr{Void}(0) + unsafe_load(Ptr{Ptr{Cvoid}}(pointer(arr)+(i-1)*sizeof(Ptr{Cvoid}))) != Ptr{Cvoid}(0) function deflate_data(f::JLDFile, data::Array{T}, odr::S, wsession::JLDWriteSession) where {T,S} - buf = Vector{UInt8}(odr_sizeof(odr) * length(data)) - cp = Ptr{Void}(pointer(buf)) + buf = Vector{UInt8}(undef, odr_sizeof(odr) * length(data)) + cp = Ptr{Cvoid}(pointer(buf)) @simd for i = 1:length(data) @inbounds h5convert!(cp, odr, f, data[i], wsession) cp += odr_sizeof(odr) @@ -356,7 +356,7 @@ function write_dataset(f::JLDFile, dataspace::WriteDataspace, datatype::H5Dataty if datasz < 8192 layout_class = LC_COMPACT_STORAGE psz += sizeof(CompactStorageMessage) + datasz - elseif f.compress && isconcrete(T) && isbits(T) + elseif f.compress && isconcretetype(T) && isbitstype(T) layout_class = LC_CHUNKED_STORAGE psz += chunked_storage_message_size(ndims(data)) + length(DEFLATE_PIPELINE_MESSAGE) else @@ -370,7 +370,7 @@ function write_dataset(f::JLDFile, dataspace::WriteDataspace, datatype::H5Dataty f.end_of_data = header_offset + fullsz if !isa(wsession, JLDWriteSession{Union{}}) - wsession.h5offset[object_id(data)] = h5offset(f, header_offset) + wsession.h5offset[objectid(data)] = h5offset(f, header_offset) push!(wsession.objects, data) end @@ -415,7 +415,7 @@ function write_dataset(f::JLDFile, dataspace::WriteDataspace, datatype::H5Dataty f.end_of_data = header_offset + fullsz if ismutabletype(typeof(data)) && !isa(wsession, JLDWriteSession{Union{}}) - wsession.h5offset[object_id(data)] = h5offset(f, header_offset) + wsession.h5offset[objectid(data)] = h5offset(f, header_offset) push!(wsession.objects, data) end @@ -522,7 +522,7 @@ end end @inline function write_ref_mutable(f::JLDFile, x, wsession::JLDWriteSession) - offset = get(wsession.h5offset, object_id(x), RelOffset(0)) + offset = get(wsession.h5offset, objectid(x), RelOffset(0)) offset != RelOffset(0) ? offset : write_dataset(f, x, wsession)::RelOffset end diff --git a/src/dataspaces.jl b/src/dataspaces.jl index 56f88559..fddc319d 100644 --- a/src/dataspaces.jl +++ b/src/dataspaces.jl @@ -40,25 +40,25 @@ WriteDataspace(f::JLDFile, x::Array{T,0}, ::Type{CustomSerialization{S,ODR}}) wh WriteDataspace(f, x, ODR) WriteDataspace() = WriteDataspace(DS_NULL, (), ()) -WriteDataspace(::JLDFile, ::Any, odr::Void) = WriteDataspace() +WriteDataspace(::JLDFile, ::Any, odr::Nothing) = WriteDataspace() WriteDataspace(::JLDFile, ::Any, ::Any) = WriteDataspace(DS_SCALAR, (), ()) # Ghost type array -WriteDataspace(f::JLDFile, x::Array{T}, ::Void) where {T} = +WriteDataspace(f::JLDFile, x::Array{T}, ::Nothing) where {T} = WriteDataspace(DS_NULL, (), - (WrittenAttribute(f, :dimensions, Int64[x for x in reverse(size(x))]),)) + (WrittenAttribute(f, :dimensions, collect(Int64, reverse(size(x)))),)) # Reference array WriteDataspace(f::JLDFile, x::Array{T,N}, ::Type{RelOffset}) where {T,N} = WriteDataspace(DS_SIMPLE, convert(Tuple{Vararg{Length}}, reverse(size(x))), (WrittenAttribute(f, :julia_type, write_ref(f, T, f.datatype_wsession)),)) -# isbits array +# isbitstype array WriteDataspace(f::JLDFile, x::Array, ::Any) = WriteDataspace(DS_SIMPLE, convert(Tuple{Vararg{Length}}, reverse(size(x))), ()) # Zero-dimensional arrays need an empty dimensions attribute -WriteDataspace(f::JLDFile, x::Array{T,0}, ::Void) where {T} = +WriteDataspace(f::JLDFile, x::Array{T,0}, ::Nothing) where {T} = WriteDataspace(DS_NULL, (Length(1),), (WrittenAttribute(f, :dimensions, EMPTY_DIMENSIONS))) WriteDataspace(f::JLDFile, x::Array{T,0}, ::Type{RelOffset}) where {T} = diff --git a/src/datatypes.jl b/src/datatypes.jl index 256e272c..9cd5c534 100644 --- a/src/datatypes.jl +++ b/src/datatypes.jl @@ -171,9 +171,9 @@ function Base.read(io::IO, ::Type{CompoundDatatype}) nfields = UInt16(dt.bitfield1) | UInt16(dt.bitfield2 << 8) dt.bitfield3 == 0 || throw(UnsupportedFeatureException()) - names = Vector{Symbol}(nfields) - offsets = Vector{Int}(nfields) - members = Vector{H5Datatype}(nfields) + names = Vector{Symbol}(undef, nfields) + offsets = Vector{Int}(undef, nfields) + members = Vector{H5Datatype}(undef, nfields) for i = 1:nfields # Name names[i] = Symbol(read_bytestring(io)) diff --git a/src/global_heaps.jl b/src/global_heaps.jl index bc2d27fd..5b982b9e 100644 --- a/src/global_heaps.jl +++ b/src/global_heaps.jl @@ -132,5 +132,5 @@ function read_heap_object(f::JLDFile, hid::GlobalHeapID, rr::ReadRepresentation{ n = div(len, odr_sizeof(RR)) len == n * odr_sizeof(RR) || throw(InvalidDataException()) - read_array!(Vector{T}(n), f, rr) + read_array!(Vector{T}(undef, n), f, rr) end diff --git a/src/loadsave.jl b/src/loadsave.jl index 1d8740b5..8b21e9ee 100644 --- a/src/loadsave.jl +++ b/src/loadsave.jl @@ -39,7 +39,7 @@ macro save(filename, vars...) end end else - writeexprs = Vector{Expr}(length(vars)) + writeexprs = Vector{Expr}(undef, length(vars)) for i = 1:length(vars) writeexprs[i] = :(write(f, $(string(vars[i])), $(esc(vars[i])), wsession)) end @@ -81,7 +81,7 @@ macro load(filename, vars...) end # Save all the key-value pairs in the dict as top-level variables of the JLD -function save(f::File{format"JLD2"}, dict::Associative; kwargs...) +function save(f::File{format"JLD2"}, dict::AbstractDict; kwargs...) jldopen(FileIO.filename(f), "w"; kwargs...) do file wsession = JLDWriteSession() for (k,v) in dict diff --git a/src/misc.jl b/src/misc.jl index af58296c..898b0bc4 100644 --- a/src/misc.jl +++ b/src/misc.jl @@ -4,10 +4,10 @@ # Redefine unsafe_load, unsafe_store!, read, and write so that they pack the type function define_packed(ty::DataType) - @assert isbits(ty) + @assert isbitstype(ty) packed_offsets = cumsum([sizeof(x) for x in ty.types]) sz = pop!(packed_offsets) - unshift!(packed_offsets, 0) + pushfirst!(packed_offsets, 0) if sz != sizeof(ty) @eval begin diff --git a/src/mmapio.jl b/src/mmapio.jl index 97bce6f5..182be3c0 100644 --- a/src/mmapio.jl +++ b/src/mmapio.jl @@ -20,18 +20,18 @@ mutable struct MmapIO <: IO f::IOStream write::Bool n::Int - startptr::Ptr{Void} - curptr::Ptr{Void} - endptr::Ptr{Void} + startptr::Ptr{Cvoid} + curptr::Ptr{Cvoid} + endptr::Ptr{Cvoid} @static if Compat.Sys.iswindows() - mapping::Ptr{Void} + mapping::Ptr{Cvoid} end end if Compat.Sys.isunix() function mmap!(io::MmapIO, n::Int) oldptr = io.startptr - newptr = ccall(:jl_mmap, Ptr{Void}, (Ptr{Void}, Csize_t, Cint, Cint, Cint, Int64), + newptr = ccall(:jl_mmap, Ptr{Cvoid}, (Ptr{Cvoid}, Csize_t, Cint, Cint, Cint, Int64), C_NULL, n, Mmap.PROT_READ | (io.write*Mmap.PROT_WRITE), Mmap.MAP_SHARED, fd(io.f), 0) io.n = n @@ -41,7 +41,7 @@ if Compat.Sys.isunix() munmap(io::MmapIO) = systemerror("munmap", - ccall(:munmap, Cint, (Ptr{Void}, Int), io.startptr, io.n) != 0) + ccall(:munmap, Cint, (Ptr{Cvoid}, Int), io.startptr, io.n) != 0) function msync(io::MmapIO, offset::Integer=0, len::Integer=UInt(io.endptr - io.startptr), invalidate::Bool=false) @@ -50,7 +50,7 @@ if Compat.Sys.isunix() # add (offset - offset_page) to `len` to get total length of memory-mapped region mmaplen::Int64 = (offset - offset_page) + len systemerror("msync", - ccall(:msync, Cint, (Ptr{Void}, Csize_t, Cint), + ccall(:msync, Cint, (Ptr{Cvoid}, Csize_t, Cint), io.startptr + offset_page, mmaplen, invalidate ? Mmap.MS_INVALIDATE : Mmap.MS_SYNC) != 0) end @@ -58,14 +58,14 @@ elseif Compat.Sys.iswindows() const DWORD = Culong function mmap!(io::MmapIO, n::Int) oldptr = io.startptr - mapping = ccall(:CreateFileMappingW, stdcall, Ptr{Void}, - (Cptrdiff_t, Ptr{Void}, DWORD, DWORD, DWORD, Ptr{Void}), + mapping = ccall(:CreateFileMappingW, stdcall, Ptr{Cvoid}, + (Cptrdiff_t, Ptr{Cvoid}, DWORD, DWORD, DWORD, Ptr{Cvoid}), Mmap.gethandle(io.f), C_NULL, io.write ? Mmap.PAGE_READWRITE : Mmap.PAGE_READONLY, n >> 32, n % UInt32, C_NULL) systemerror("CreateFileMappingW", mapping == C_NULL) - newptr = ccall(:MapViewOfFile, stdcall, Ptr{Void}, - (Ptr{Void}, DWORD, DWORD, DWORD, Csize_t), + newptr = ccall(:MapViewOfFile, stdcall, Ptr{Cvoid}, + (Ptr{Cvoid}, DWORD, DWORD, DWORD, Csize_t), mapping, io.write ? Mmap.FILE_MAP_WRITE : Mmap.FILE_MAP_READ, 0, 0, n) systemerror("MapViewOfFile", newptr == C_NULL) @@ -77,9 +77,9 @@ elseif Compat.Sys.iswindows() function munmap(io::MmapIO) systemerror("UnmapViewOfFile", - ccall(:UnmapViewOfFile, stdcall, Cint, (Ptr{Void},), io.startptr) == 0) + ccall(:UnmapViewOfFile, stdcall, Cint, (Ptr{Cvoid},), io.startptr) == 0) systemerror("CloseHandle", - ccall(:CloseHandle, stdcall, Cint, (Ptr{Void},), io.mapping) == 0) + ccall(:CloseHandle, stdcall, Cint, (Ptr{Cvoid},), io.mapping) == 0) end function msync(io::MmapIO, offset::Integer=0, len::Integer=UInt(io.endptr - io.startptr), @@ -90,7 +90,7 @@ elseif Compat.Sys.iswindows() mmaplen::Int64 = (offset - offset_page) + len systemerror("FlushViewOfFile", ccall(:FlushViewOfFile, stdcall, Cint, - (Ptr{Void}, Csize_t), io.startptr + offset_page, mmaplen) == 0) + (Ptr{Cvoid}, Csize_t), io.startptr + offset_page, mmaplen) == 0) end end @@ -129,7 +129,7 @@ else grow(io::IOStream, sz::Integer) = truncate(io, sz) end -function Base.resize!(io::MmapIO, newend::Ptr{Void}) +function Base.resize!(io::MmapIO, newend::Ptr{Cvoid}) io.write || throw(EOFError()) # Resize file @@ -195,7 +195,7 @@ function Base.unsafe_write(io::MmapIO, x::Ptr{UInt8}, n::UInt) cp = io.curptr ep = cp + n end - unsafe_copy!(Ptr{UInt8}(cp), x, n) + unsafe_copyto!(Ptr{UInt8}(cp), x, n) io.curptr = ep return n end @@ -216,8 +216,8 @@ function Base.read(io::MmapIO, ::Type{T}, n::Int) where T cp = io.curptr ep = cp + sizeof(T)*n ep > io.endptr && throw(EOFError()) - arr = Vector{T}(n) - unsafe_copy!(pointer(arr), Ptr{T}(cp), n) + arr = Vector{T}(undef, n) + unsafe_copyto!(pointer(arr), Ptr{T}(cp), n) io.curptr = ep arr end @@ -261,7 +261,7 @@ computing a memory address until converted to a Ptr{T}, so the memory mapping ca enlarged and addresses will remain valid. """ struct IndirectPointer - ptr::Ptr{Ptr{Void}} + ptr::Ptr{Ptr{Cvoid}} offset::Int end diff --git a/test/customserialization.jl b/test/customserialization.jl index d92843da..f6c3a11f 100644 --- a/test/customserialization.jl +++ b/test/customserialization.jl @@ -19,9 +19,9 @@ Base.:(==)(a::UntypedWrapper, b::UntypedWrapper) = a.x == b.x # This is a type with a custom serialization, where the original type has data # but the custom serialization is empty struct CSA - x::Ptr{Void} + x::Ptr{Cvoid} end -a = CSA(Ptr{Void}(0)) +a = CSA(Ptr{Cvoid}(0)) struct CSASerialization end JLD2.writeas(::Type{CSA}) = CSASerialization @@ -31,7 +31,7 @@ function JLD2.wconvert(::Type{CSASerialization}, x::CSA) end function JLD2.rconvert(::Type{CSA}, x::CSASerialization) global converted = true - CSA(Ptr{Void}(0)) + CSA(Ptr{Cvoid}(0)) end # This is a type with a custom serialization, where the original type has no diff --git a/test/internal.jl b/test/internal.jl index c78ebf85..6f711c44 100644 --- a/test/internal.jl +++ b/test/internal.jl @@ -16,7 +16,7 @@ JLD2.truncate_and_close(f, position(f)) @test filesize(name) == sz f = open(name) -rd = read!(f, Array{UInt8}(sz)) +rd = read!(f, Array{UInt8}(undef, sz)) @test all(rd .== UInt8(6)) close(f) @@ -26,7 +26,7 @@ JLD2.truncate_and_close(f, position(f)) @test filesize(name) == sz f = open(name) -rd = read!(f, Array{UInt8}(sz)) +rd = read!(f, Array{UInt8}(undef, sz)) @test all(rd .== UInt8(6)) close(f) diff --git a/test/lookup3.jl b/test/lookup3.jl index acb94814..66a9087d 100644 --- a/test/lookup3.jl +++ b/test/lookup3.jl @@ -9,7 +9,7 @@ using JLD2, Compat, Compat.Test @test JLD2.Lookup3.hash(UInt8[0, 0, 0]) == 0x6bd0060f @test JLD2.Lookup3.hash(UInt8[23, 187, 98, 217]) == 0x2c88bb51 @test JLD2.Lookup3.hash(UInt8[0, 0, 0, 0]) == 0x049396b8 -large_buf = Vector{UInt8}(3093) +large_buf = Vector{UInt8}(undef, 3093) for i = 1:length(large_buf) large_buf[i] = ((i-1) * 3) % UInt8 end diff --git a/test/runtests.jl b/test/runtests.jl index 2100f8aa..3cf80e5f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,5 +8,10 @@ include("append.jl") include("groups.jl") include("consistency.jl") include("loadsave.jl") -include("recon.jl") + +# Only run the reconstruction tests on versions where `workspace` is a thing +if VERSION < v"0.7.0-DEV.2917" + include("recon.jl") +end + #include("customserialization.jl") currently broken due to #265 diff --git a/test/rw.jl b/test/rw.jl index 1850424e..f3cea3b4 100644 --- a/test/rw.jl +++ b/test/rw.jl @@ -1,4 +1,4 @@ -using JLD2, Compat, Compat.Test +using JLD2, Compat, Compat.Test, Compat.LinearAlgebra macro read(fid, sym) if !isa(sym, Symbol) @@ -35,9 +35,9 @@ B = [-1.5 sqrt(2) NaN 6; 0.0 Inf eps() -Inf] AB = Any[A, B] t = (3, "cat") -c = Complex64(3,7) +c = Complex{Float32}(3,7) cint = 1+im # issue 108 -C = reinterpret(Complex128, B, (4,)) +C = reinterpret(Complex{Float64}, B, (4,)) emptyA = zeros(0,2) emptyB = zeros(2,0) try @@ -72,8 +72,8 @@ typevar = Array{Int}[[1]] typevar_lb = (Vector{U} where U<:Integer)[[1]] typevar_ub = (Vector{U} where U>:Int)[[1]] typevar_lb_ub = (Vector{U} where Int<:U<:Real)[[1]] -undef = Vector{Any}(1) -undefs = Matrix{Any}(2, 2) +arr_undef = Vector{Any}(undef, 1) +arr_undefs = Matrix{Any}(undef, 2, 2) ms_undef = MyStruct(0) # Unexported type: cpus = Base.Sys.cpu_info() @@ -81,7 +81,7 @@ cpus = Base.Sys.cpu_info() rng = 1:5 # Type with a pointer field (#84) struct ObjWithPointer - a::Ptr{Void} + a::Ptr{Cvoid} end objwithpointer = ObjWithPointer(0) # Custom BitsType (#99) @@ -103,7 +103,7 @@ mutable struct EmptyType end emptytype = EmptyType() arr_emptytype = [emptytype] empty_arr_emptytype = EmptyImmutable[] -uninitialized_arr_emptytype = Vector{EmptyType}(1) +uninitialized_arr_emptytype = Vector{EmptyType}(undef, 1) struct EmptyII x::EmptyImmutable end @@ -197,9 +197,9 @@ end padding_test = PaddingTest[PaddingTest(i, i) for i = 1:8] # Empty arrays of various types and sizes empty_arr_1 = Int[] -empty_arr_2 = Matrix{Int}(56, 0) +empty_arr_2 = Matrix{Int}(undef, 56, 0) empty_arr_3 = Any[] -empty_arr_4 = Matrix{Any}(0, 97) +empty_arr_4 = Matrix{Any}(undef, 0, 97) # Moderately big dataset (which will be mmapped) bigdata = [1:1000000;] # BigFloats and BigInts @@ -215,12 +215,12 @@ bigfloatintobj = BigFloatIntObject(big(pi), big(typemax(UInt128))+1) # None none = Union{} nonearr = Vector{Union{}}(5) -# nothing/Void +# nothing/Nothing scalar_nothing = nothing -vector_nothing = Union{Int,Void}[1,nothing] +vector_nothing = Union{Int,Nothing}[1,nothing] # some data big enough to ensure that compression is used: -Abig = kron(eye(10), rand(20,20)) +Abig = kron(Matrix{Float64}(I, 10, 10), rand(20, 20)) Bbig = Any[i for i=1:3000] Sbig = "A test string "^1000 @@ -269,8 +269,8 @@ iseq(x::Core.SimpleVector, y::Core.SimpleVector) = collect(x) == collect(y) # Type that overloads != so that it is not boolean mutable struct NALikeType; end Base.:!=(::NALikeType, ::NALikeType) = NALikeType() -Base.:!=(::NALikeType, ::Void) = NALikeType() -Base.:!=(::Void, ::NALikeType) = NALikeType() +Base.:!=(::NALikeType, ::Nothing) = NALikeType() +Base.:!=(::Nothing, ::NALikeType) = NALikeType() natyperef = Any[NALikeType(), NALikeType()] # JLD2 issue #31 (lots of strings) @@ -283,16 +283,16 @@ function iseq(x::Array{EmptyType}, y::Array{EmptyType}) def = isassigned(x, i) def != isassigned(y, i) && return false if def - x[i] != y[i] && return false + iseq(x[i], y[i]) || return false end end return true end iseq(x::MyStruct, y::MyStruct) = (x.len == y.len && x.data == y.data) iseq(x::MyImmutable, y::MyImmutable) = (isequal(x.x, y.x) && isequal(x.y, y.y) && isequal(x.z, y.z)) -iseq(x::Union{EmptyTI,EmptyTT}, y::Union{EmptyTI,EmptyTT}) = isequal(x.x, y.x) +iseq(x::Union{EmptyTI,EmptyTT,EmptyIT}, y::Union{EmptyTI,EmptyTT,EmptyIT}) = iseq(x.x, y.x) iseq(x::NoneTypedField{Union{}}, y::NoneTypedField{Union{}}) = x.a === y.a -iseq(c1::Array{Base.Sys.CPUinfo}, c2::Array{Base.Sys.CPUinfo}) = length(c1) == length(c2) && all([iseq(c1[i], c2[i]) for i = 1:length(c1)]) +iseq(c1::Array, c2::Array) = length(c1) == length(c2) && all(p->iseq(p...), zip(c1, c2)) function iseq(c1::Base.Sys.CPUinfo, c2::Base.Sys.CPUinfo) for n in fieldnames(Base.Sys.CPUinfo) if getfield(c1, n) != getfield(c2, n) @@ -304,6 +304,8 @@ end iseq(x::MyUnicodeStruct☺, y::MyUnicodeStruct☺) = (x.α == y.α && x.∂ₓα == y.∂ₓα) iseq(x::Array{Union{}}, y::Array{Union{}}) = size(x) == size(y) iseq(x::BigFloatIntObject, y::BigFloatIntObject) = (x.bigfloat == y.bigfloat && x.bigint == y.bigint) +iseq(x::T, y::T) where {T<:Union{EmptyType,EmptyImmutable,NALikeType}} = true +iseq(x::BitsParams{T}, y::BitsParams{S}) where {T,S} = (T == S) macro check(fid, sym) ex = quote let tmp @@ -397,8 +399,8 @@ for ioty in [JLD2.MmapIO, IOStream], compress in [false, true] @write fid typevar_lb @write fid typevar_ub @write fid typevar_lb_ub - @write fid undef - @write fid undefs + @write fid arr_undef + @write fid arr_undefs @write fid ms_undef @test_throws JLD2.PointerException @write fid objwithpointer @write fid bt @@ -515,13 +517,13 @@ for ioty in [JLD2.MmapIO, IOStream], compress in [false, true] @check fidr typevar_lb_ub # Special cases for reading undefs - undef = read(fidr, "undef") - if !isa(undef, Array{Any, 1}) || length(undef) != 1 || isassigned(undef, 1) - error("For undef, read value does not agree with written value") + arr_undef = read(fidr, "arr_undef") + if !isa(arr_undef, Array{Any, 1}) || length(arr_undef) != 1 || isassigned(arr_undef, 1) + error("For arr_undef, read value does not agree with written value") end - undefs = read(fidr, "undefs") - if !isa(undefs, Array{Any, 2}) || length(undefs) != 4 || any(map(i->isassigned(undefs, i), 1:4)) - error("For undefs, read value does not agree with written value") + arr_undefs = read(fidr, "arr_undefs") + if !isa(arr_undefs, Array{Any, 2}) || length(arr_undefs) != 4 || any(map(i->isassigned(arr_undefs, i), 1:4)) + error("For arr_undefs, read value does not agree with written value") end ms_undef = read(fidr, "ms_undef") if !isa(ms_undef, MyStruct) || ms_undef.len != 0 || isdefined(ms_undef, :data)