Skip to content

Commit

Permalink
Unpad fixed length strings in compound datatypes (#614)
Browse files Browse the repository at this point in the history
* wrap H5Tset_strpad

* add test for unpadding strings inside compound datasets

* unpad fixed strings in compound datasets
  • Loading branch information
kleinhenz authored Apr 2, 2020
1 parent 8c5a15e commit ff0c780
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 8 deletions.
15 changes: 10 additions & 5 deletions src/HDF5.jl
Original file line number Diff line number Diff line change
Expand Up @@ -483,10 +483,13 @@ size(x::T) where T <: FixedArray = size(T)
eltype(::Type{FixedArray{T,D,L}}) where {T,D,L} = T
eltype(x::T) where T <: FixedArray = eltype(T)

struct FixedString{N}
struct FixedString{N, PAD}
data::NTuple{N, Cchar}
end
length(::Type{FixedString{N}}) where N = N
length(::Type{FixedString{N, PAD}}) where {N, PAD} = N
length(x::T) where T <: FixedString = length(T)
pad(::Type{FixedString{N, PAD}}) where {N, PAD} = PAD
pad(x::T) where T <: FixedString = pad(T)

struct VariableArray{T}
len::Csize_t
Expand Down Expand Up @@ -1471,7 +1474,7 @@ end
normalize_types(x) = x
normalize_types(x::NamedTuple{T}) where T = NamedTuple{T}(map(normalize_types, values(x)))
normalize_types(x::Cstring) = unsafe_string(x)
normalize_types(x::FixedString) = join(Char.(x.data))
normalize_types(x::FixedString) = unpad(join(Char.(x.data)), pad(x))
normalize_types(x::FixedArray) = reshape(collect(x.data), size(x)...)
normalize_types(x::VariableArray) = copy(unsafe_wrap(Array, convert(Ptr{eltype(x)}, x.p), x.len, own=false))

Expand Down Expand Up @@ -1780,7 +1783,7 @@ _dropint() = ()

# Write to a subset of a dataset using array slices: dataset[:,:,10] = array

setindex!(dset::HDF5Dataset, x, I::Union{AbstractRange,Integer,Colon}...) =
setindex!(dset::HDF5Dataset, x, I::Union{AbstractRange,Integer,Colon}...) =
_setindex!(dset, x, Base.to_indices(dset, I)...)
function _setindex!(dset::HDF5Dataset, X::Array, I::Union{AbstractRange{Int},Int}...)
T = hdf5_to_julia(dset)
Expand Down Expand Up @@ -2001,7 +2004,8 @@ function hdf5_to_julia_eltype(objtype)
return Cstring
else
n = h5t_get_size(dtype.id)
return FixedString{Int(n)}
pad = h5t_get_strpad(dtype.id)
return FixedString{Int(n), pad}
end
elseif ci == H5T_VLEN
superid = h5t_get_super(dtype.id)
Expand Down Expand Up @@ -2187,6 +2191,7 @@ for (jlname, h5name, outtype, argtypes, argsyms, msg) in
(:h5t_close, :H5Tclose, Herr, (Hid,), (:dtype_id,), "Error closing datatype"),
(:h5t_set_cset, :H5Tset_cset, Herr, (Hid, Cint), (:dtype_id, :cset), "Error setting character set in datatype"),
(:h5t_set_size, :H5Tset_size, Herr, (Hid, Csize_t), (:dtype_id, :sz), "Error setting size of datatype"),
(:h5t_set_strpad, :H5Tset_strpad, Herr, (Hid, Cint), (:dtype_id, :sz), "Error setting size of datatype"),
(:h5t_set_precision, :H5Tset_precision, Herr, (Hid, Csize_t), (:dtype_id, :sz), "Error setting precision of datatype"),
)

Expand Down
7 changes: 4 additions & 3 deletions test/compound.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ end
struct foo_hdf5
a::Float64
b::Cstring
c::NTuple{10, Cchar}
c::NTuple{20, Cchar}
d::NTuple{9, ComplexF64}
e::HDF5.Hvl_t
end

function unsafe_convert(::Type{foo_hdf5}, x::foo)
foo_hdf5(x.a,
Base.unsafe_convert(Cstring, x.b),
ntuple(i -> x.c[i], length(x.c)),
ntuple(i -> i <= length(x.c) ? x.c[i] : '\0', 20),
ntuple(i -> x.d[i], length(x.d)),
HDF5.Hvl_t(length(x.e), pointer(x.e))
)
Expand All @@ -38,8 +38,9 @@ function datatype(::Type{foo_hdf5})
HDF5.h5t_insert(dtype, "b", fieldoffset(foo_hdf5, 2), vlenstr_dtype)

fixedstr_dtype = HDF5.h5t_copy(HDF5.H5T_C_S1)
HDF5.h5t_set_size(fixedstr_dtype, 10 * sizeof(Cchar))
HDF5.h5t_set_size(fixedstr_dtype, 20 * sizeof(Cchar))
HDF5.h5t_set_cset(fixedstr_dtype, HDF5.H5T_CSET_UTF8)
HDF5.h5t_set_strpad(fixedstr_dtype, HDF5.H5T_STR_NULLPAD)
HDF5.h5t_insert(dtype, "c", fieldoffset(foo_hdf5, 3), fixedstr_dtype)

hsz = HDF5.Hsize[3,3]
Expand Down

0 comments on commit ff0c780

Please sign in to comment.