Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

An assortment of minor changes #692

Merged
merged 8 commits into from
Oct 7, 2020
Merged
7 changes: 7 additions & 0 deletions gen/api_defs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
@bind h5_free_memory(buf::Ptr{Cvoid})::herr_t "Error freeing memory"
@bind h5_garbage_collect()::herr_t "Error on garbage collect"
@bind h5_get_libversion(majnum::Ref{Cuint}, minnum::Ref{Cuint}, relnum::Ref{Cuint})::herr_t "Error getting HDF5 library version"
@bind h5_is_library_threadsafe(is_ts::Ref{Cuint})::herr_t "Error determining thread safety"
@bind h5_open()::herr_t "Error initializing the HDF5 library"
@bind h5_set_free_list_limits(reg_global_lim::Cint, reg_list_lim::Cint, arr_global_lim::Cint, arr_list_lim::Cint, blk_global_lim::Cint, blk_list_lim::Cint)::herr_t "Error setting limits on free lists"

Expand Down Expand Up @@ -113,6 +114,7 @@
@bind h5i_get_name(obj_id::hid_t, buf::Ptr{UInt8}, buf_size::Csize_t)::Cssize_t "Error getting object name"
@bind h5i_get_ref(obj_id::hid_t)::Cint "Error getting reference count"
@bind h5i_get_type(obj_id::hid_t)::Cint "Error getting type"
@bind h5i_inc_ref(obj_id::hid_t)::Cint "Error incrementing identifier refcount"
@bind h5i_is_valid(obj_id::hid_t)::htri_t "Cannot determine whether object is valid"

###
Expand Down Expand Up @@ -221,6 +223,8 @@
@bind h5t_get_array_ndims(dtype_id::hid_t)::Cint "Error getting ndims of array"
@bind h5t_get_class(dtype_id::hid_t)::Cint "Error getting class"
@bind h5t_get_cset(dtype_id::hid_t)::Cint "Error getting character set encoding"
@bind h5t_get_ebias(dtype_id::hid_t)::Csize_t "Error getting datatype floating point exponent bias"
@bind h5t_get_fields(dtype_id::hid_t, spos::Ref{Csize_t}, epos::Ref{Csize_t}, esize::Ref{Csize_t}, mpos::Ref{Csize_t}, msize::Ref{Csize_t})::herr_t "Error getting datatype floating point bit positions"
@bind h5t_get_member_class(dtype_id::hid_t, index::Cuint)::Cint error("Error getting class of compound datatype member #", index)
@bind h5t_get_member_index(dtype_id::hid_t, membername::Ptr{UInt8})::Cint error("Error getting index of compound datatype member \"", membername, "\"")
@bind h5t_get_member_offset(dtype_id::hid_t, index::Cuint)::Csize_t # does not error
Expand All @@ -233,8 +237,11 @@
@bind h5t_get_super(dtype_id::hid_t)::hid_t "Error getting super type"
@bind h5t_insert(dtype_id::hid_t, fieldname::Ptr{UInt8}, offset::Csize_t, field_id::hid_t)::herr_t error("Error adding field ", fieldname, " to compound datatype")
@bind h5t_is_variable_str(type_id::hid_t)::htri_t "Error determining whether string is of variable length"
@bind h5t_lock(type_id::hid_t)::herr_t "Error locking type"
@bind h5t_open(loc_id::hid_t, name::Ptr{UInt8}, tapl_id::hid_t)::hid_t error("Error opening type ", h5i_get_name(loc_id), "/", name)
@bind h5t_set_cset(dtype_id::hid_t, cset::Cint)::herr_t "Error setting character set in datatype"
@bind h5t_set_ebias(dtype_id::hid_t, ebias::Csize_t)::herr_t "Error setting datatype floating point exponent bias"
@bind h5t_set_fields(dtype_id::hid_t, spos::Csize_t, epos::Csize_t, esize::Csize_t, mpos::Csize_t, msize::Csize_t)::herr_t "Error setting datatype floating point bit positions"
@bind h5t_set_precision(dtype_id::hid_t, sz::Csize_t)::herr_t "Error setting precision of datatype"
@bind h5t_set_size(dtype_id::hid_t, sz::Csize_t)::herr_t "Error setting size of datatype"
@bind h5t_set_strpad(dtype_id::hid_t, sz::Cint)::herr_t "Error setting size of datatype"
Expand Down
48 changes: 32 additions & 16 deletions src/HDF5.jl
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,32 @@ mutable struct Datatype
end
end
convert(::Type{hid_t}, dtype::Datatype) = dtype.id
show(io::IO, dtype::Datatype) = print(io, "HDF5 datatype: ", h5lt_dtype_to_text(dtype.id))
hash(dtype::Datatype, h::UInt) =
(dtype.id % UInt + h) ^ (0xadaf9b66bc962084 % UInt)
==(dt1::Datatype, dt2::Datatype) = h5t_equal(dt1, dt2) > 0
function show(io::IO, dtype::Datatype)
print(io, "HDF5 datatype: ")
if isvalid(dtype)
print(io, h5lt_dtype_to_text(dtype.id))
else
# Note that h5i_is_valid returns `false` on the built-in datatypes (e.g.
# H5T_NATIVE_INT), apparently because they have refcounts of 0 yet are always
# valid. Just temporarily turn off error printing and try the call to probe if
# dtype is valid since H5LTdtype_to_text special-cases all of the built-in types
# internally.
old_func, old_client_data = h5e_get_auto(H5E_DEFAULT)
h5e_set_auto(H5E_DEFAULT, C_NULL, C_NULL)
local text
try
text = h5lt_dtype_to_text(dtype.id)
catch
text = "(invalid)"
finally
h5e_set_auto(H5E_DEFAULT, old_func, old_client_data)
end
print(io, text)
end
end

# Define an H5O Object type
const Object = Union{Group, Dataset, Datatype}
Expand Down Expand Up @@ -261,7 +283,7 @@ end
convert(::Type{hid_t}, attr::Attribute) = attr.id
show(io::IO, attr::Attribute) = isvalid(attr) ? print(io, "HDF5 attribute: ", name(attr)) : print(io, "HDF5 attribute (invalid)")

mutable struct Attributes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the only mutable struct -> struct audited?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't check thoroughly — I noticed it while browsing through your rename PR and this one was the only one that stood out to me as not needing to be mutable since it doesn't add a finalizer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the only candidate, though:

$ git grep 'mutable struct'
src/HDF5.jl:mutable struct File <: DataFile
src/HDF5.jl:mutable struct Group <: DataFile
src/HDF5.jl:mutable struct Properties
src/HDF5.jl:mutable struct Dataset
src/HDF5.jl:mutable struct Datatype
src/HDF5.jl:mutable struct Dataspace
src/HDF5.jl:mutable struct Attribute

struct Attributes
parent::Union{File,Group,Dataset}
end
attrs(p::Union{File,Group,Dataset}) = Attributes(p)
Expand Down Expand Up @@ -605,15 +627,11 @@ ishdf5(name::AbstractString) = h5f_is_hdf5(name)

# Extract the file
file(f::File) = f
file(g::Group) = g.file
file(dset::Dataset) = dset.file
file(dtype::Datatype) = dtype.file
file(a::Attribute) = a.file
file(o::Union{Object,Attribute}) = o.file
fd(obj::Object) = h5i_get_file_id(checkvalid(obj).id)

# Flush buffers
flush(f::Union{Object,Attribute,Datatype,File}, scope) = h5f_flush(checkvalid(f).id, scope)
flush(f::Union{Object,Attribute,Datatype,File}) = flush(f, H5F_SCOPE_GLOBAL)
flush(f::Union{Object,Attribute,Datatype,File}, scope = H5F_SCOPE_GLOBAL) = h5f_flush(checkvalid(f).id, scope)

# Open objects
g_open(parent::Union{File,Group}, name::String, apl::Properties=DEFAULT_PROPERTIES) = Group(h5g_open(checkvalid(parent).id, name, apl.id), file(parent))
Expand Down Expand Up @@ -1030,7 +1048,7 @@ dataspace(attr::Attribute) = Dataspace(h5a_get_space(checkvalid(attr).id))
# Create a dataspace from in-memory types
dataspace(x::Union{T, Complex{T}}) where {T<:HDF5Scalar} = Dataspace(h5s_create(H5S_SCALAR))

function _dataspace(sz::Tuple{Vararg{Int}}, max_dims::Union{Dims, Tuple{}}=())
function _dataspace(sz::Dims{N}, max_dims::Union{Dims{N}, Tuple{}}=()) where N
dims = Vector{hsize_t}(undef,length(sz))
any_zero = false
for i = 1:length(sz)
Expand All @@ -1042,15 +1060,13 @@ function _dataspace(sz::Tuple{Vararg{Int}}, max_dims::Union{Dims, Tuple{}}=())
space_id = h5s_create(H5S_NULL)
else
if isempty(max_dims)
space_id = h5s_create_simple(length(dims), dims, dims)
maxd = dims
else
# This allows max_dims to be specified as -1 without
# triggering an overflow exception due to the signed->
# unsigned conversion.
space_id = h5s_create_simple(length(dims), dims,
reinterpret(hsize_t, convert(Vector{hssize_t},
[reverse(max_dims)...])))
# This allows max_dims to be specified as -1 without triggering an overflow
# exception due to the signed -> unsigned conversion.
maxd = [(hssize_t.(reverse(max_dims)) .% hsize_t)...]
end
space_id = h5s_create_simple(length(dims), dims, maxd)
end
Dataspace(space_id)
end
Expand Down
42 changes: 42 additions & 0 deletions src/api.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ function h5_get_libversion(majnum, minnum, relnum)
return nothing
end

function h5_is_library_threadsafe(is_ts)
var"#status#" = ccall((:H5is_library_threadsafe, libhdf5), herr_t, (Ref{Cuint},), is_ts)
var"#status#" < 0 && error("Error determining thread safety")
return nothing
end

function h5_open()
var"#status#" = ccall((:H5open, libhdf5), herr_t, ())
var"#status#" < 0 && error("Error initializing the HDF5 library")
Expand Down Expand Up @@ -393,6 +399,12 @@ function h5i_get_type(obj_id)
return var"#status#"
end

function h5i_inc_ref(obj_id)
var"#status#" = ccall((:H5Iinc_ref, libhdf5), Cint, (hid_t,), obj_id)
var"#status#" < 0 && error("Error incrementing identifier refcount")
return var"#status#"
end

function h5i_is_valid(obj_id)
var"#status#" = ccall((:H5Iis_valid, libhdf5), htri_t, (hid_t,), obj_id)
var"#status#" < 0 && error("Cannot determine whether object is valid")
Expand Down Expand Up @@ -860,6 +872,18 @@ function h5t_get_cset(dtype_id)
return var"#status#"
end

function h5t_get_ebias(dtype_id)
var"#status#" = ccall((:H5Tget_ebias, libhdf5), Csize_t, (hid_t,), dtype_id)
var"#status#" < 0 && error("Error getting datatype floating point exponent bias")
return var"#status#"
end

function h5t_get_fields(dtype_id, spos, epos, esize, mpos, msize)
var"#status#" = ccall((:H5Tget_fields, libhdf5), herr_t, (hid_t, Ref{Csize_t}, Ref{Csize_t}, Ref{Csize_t}, Ref{Csize_t}, Ref{Csize_t}), dtype_id, spos, epos, esize, mpos, msize)
var"#status#" < 0 && error("Error getting datatype floating point bit positions")
return nothing
end

function h5t_get_member_class(dtype_id, index)
var"#status#" = ccall((:H5Tget_member_class, libhdf5), Cint, (hid_t, Cuint), dtype_id, index)
var"#status#" < 0 && error("Error getting class of compound datatype member #", index)
Expand Down Expand Up @@ -931,6 +955,12 @@ function h5t_is_variable_str(type_id)
return var"#status#" > 0
end

function h5t_lock(type_id)
var"#status#" = ccall((:H5Tlock, libhdf5), herr_t, (hid_t,), type_id)
var"#status#" < 0 && error("Error locking type")
return nothing
end

function h5t_open(loc_id, name, tapl_id)
var"#status#" = ccall((:H5Topen2, libhdf5), hid_t, (hid_t, Ptr{UInt8}, hid_t), loc_id, name, tapl_id)
var"#status#" < 0 && error("Error opening type ", h5i_get_name(loc_id), "/", name)
Expand All @@ -943,6 +973,18 @@ function h5t_set_cset(dtype_id, cset)
return nothing
end

function h5t_set_ebias(dtype_id, ebias)
var"#status#" = ccall((:H5Tset_ebias, libhdf5), herr_t, (hid_t, Csize_t), dtype_id, ebias)
var"#status#" < 0 && error("Error setting datatype floating point exponent bias")
return nothing
end

function h5t_set_fields(dtype_id, spos, epos, esize, mpos, msize)
var"#status#" = ccall((:H5Tset_fields, libhdf5), herr_t, (hid_t, Csize_t, Csize_t, Csize_t, Csize_t, Csize_t), dtype_id, spos, epos, esize, mpos, msize)
var"#status#" < 0 && error("Error setting datatype floating point bit positions")
return nothing
end

function h5t_set_precision(dtype_id, sz)
var"#status#" = ccall((:H5Tset_precision, libhdf5), herr_t, (hid_t, Csize_t), dtype_id, sz)
var"#status#" < 0 && error("Error setting precision of datatype")
Expand Down
37 changes: 21 additions & 16 deletions src/api_helpers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ function h5_get_libversion()
VersionNumber(majnum[], minnum[], relnum[])
end

function h5_is_library_threadsafe()
is_ts = Ref{Cuint}()
h5_is_library_threadsafe(is_ts)
return is_ts[] > 0
end

###
### Attribute Interface
###
Expand Down Expand Up @@ -238,6 +244,16 @@ function h5t_get_array_dims(type_id)
return dims
end

function h5t_get_fields(type_id)
spos = Ref{Csize_t}()
epos = Ref{Csize_t}()
esize = Ref{Csize_t}()
mpos = Ref{Csize_t}()
msize = Ref{Csize_t}()
h5t_get_fields(type_id, spos, epos, esize, mpos, msize)
return (spos[], epos[], esize[], mpos[], msize[])
end

# Note: The following two functions implement direct ccalls because the binding generator
# cannot (yet) do the string wrapping and memory freeing.
function h5t_get_member_name(type_id, index)
Expand Down Expand Up @@ -269,22 +285,11 @@ end
###

function h5lt_dtype_to_text(dtype_id)
# Note we can't use h5i_is_valid to check if dtype is valid because
# ref counts aren't incremented for basic atomic types (e.g. H5T_NATIVE_INT).
# Instead just temporarily turn off error printing and try call to probe if dtype is valid.
old_func, old_client_data = h5e_get_auto(H5E_DEFAULT)
h5e_set_auto(H5E_DEFAULT, C_NULL, C_NULL)
try
len = Ref{Csize_t}()
h5lt_dtype_to_text(dtype_id, C_NULL, 0, len)
buf = StringVector(len[] - 1)
h5lt_dtype_to_text(dtype_id, buf, 0, len)
return String(buf)
catch
return "(invalid)"
finally
h5e_set_auto(H5E_DEFAULT, old_func, old_client_data)
end
len = Ref{Csize_t}()
h5lt_dtype_to_text(dtype_id, C_NULL, 0, len)
buf = StringVector(len[] - 1)
h5lt_dtype_to_text(dtype_id, buf, 0, len)
return String(buf)
end

###
Expand Down