11function refs = export(obj , fid , fullpath , refs )
2- % Check for compound data type refs
2+
3+ % If exporting to the same file this DataStub originates from, skip export.
34 src_fid = H5F .open(obj .filename );
4- % if filenames are the same, then do nothing
55 src_filename = H5F .get_name(src_fid );
66 dest_filename = H5F .get_name(fid );
77 if strcmp(src_filename , dest_filename )
1010
1111 src_did = H5D .open(src_fid , obj .path );
1212 src_tid = H5D .get_type(src_did );
13- src_sid = H5D .get_space(src_did );
14- ref_i = false ;
15- char_i = false ;
16- member_name = {};
17- ref_tid = {};
13+
14+ % Check for compound data type refs
1815 if H5T .get_class(src_tid ) == H5ML .get_constant_value(' H5T_COMPOUND' )
19- ncol = H5T .get_nmembers(src_tid );
20- ref_i = false(ncol , 1 );
21- member_name = cell(ncol , 1 );
22- char_i = false(ncol , 1 );
23- ref_tid = cell(ncol , 1 );
24- refTypeConst = H5ML .get_constant_value(' H5T_REFERENCE' );
25- strTypeConst = H5ML .get_constant_value(' H5T_STRING' );
26- for i = 1 : ncol
27- member_name{i } = H5T .get_member_name(src_tid , i - 1 );
28- subclass = H5T .get_member_class(src_tid , i - 1 );
29- subtid = H5T .get_member_type(src_tid , i - 1 );
30- char_i(i ) = subclass == strTypeConst && ...
31- ~H5T .is_variable_str(subtid );
32- if subclass == refTypeConst
33- ref_i(i ) = true ;
34- ref_tid{i } = subtid ;
35- end
36- end
16+ isCompoundDatasetWithReference = isCompoundWithReference(src_tid );
17+ else
18+ isCompoundDatasetWithReference = false ;
3719 end
38-
39- % manually load the data struct
40- if any(ref_i )
41- % This requires loading the entire table.
42- % Due to this HDF5 library's inability to delete/update
43- % dataset data, this is unfortunately required.
44- ref_tid = ref_tid(~cellfun(' isempty' , ref_tid ));
20+
21+ % If dataset is compound and contains reference types, data needs to be
22+ % manually read and written to the new file. This is due to a bug in
23+ % the hdf5 library (see e.g. https://github.com/HDFGroup/hdf5/issues/3429)
24+ if isCompoundDatasetWithReference
25+ % This requires loading the entire table.
26+ % Due to this HDF5 library's inability to delete/update
27+ % dataset data, this is unfortunately required.
4528 data = H5D .read(src_did );
46-
47- refNames = member_name(ref_i );
48- for i= 1 : length(refNames )
49- data.(refNames{i }) = io .parseReference(src_did , ref_tid{i }, ...
50- data.(refNames{i }));
51- end
52-
53- strNames = member_name(char_i );
54- for i= 1 : length(strNames )
55- s = data.(strNames{i }) .' ;
56- data.(strNames{i }) = mat2cell(s , ones(size(s ,1 ),1 ));
57- end
58-
29+
30+ % Use io.parseCompound to consistently handle references, character arrays, and logical types,
31+ % ensuring all data types are properly postprocessed in line with the rest of the codebase.
32+ data = io .parseCompound(src_did , data );
5933 io .writeCompound(fid , fullpath , data );
34+
6035 elseif ~H5L .exists(fid , fullpath , ' H5P_DEFAULT' )
6136 % copy data over and return destination.
6237 ocpl = H5P .create(' H5P_OBJECT_COPY' );
6641 H5P .close(lcpl );
6742 end
6843 H5T .close(src_tid );
69- H5S .close(src_sid );
7044 H5D .close(src_did );
7145 H5F .close(src_fid );
72- end
46+ end
47+
48+ function hasReference = isCompoundWithReference(src_tid )
49+ hasReference = false ;
50+
51+ ncol = H5T .get_nmembers(src_tid );
52+ refTypeConst = H5ML .get_constant_value(' H5T_REFERENCE' );
53+
54+ for i = 1 : ncol
55+ subclass = H5T .get_member_class(src_tid , i - 1 );
56+ if subclass == refTypeConst
57+ hasReference = true ;
58+ return
59+ end
60+ end
61+ end
0 commit comments