mirror of
https://github.com/TREX-CoE/trexio.git
synced 2025-04-26 18:34:44 +02:00
26 KiB
26 KiB
HDF5 back end
- HDF5 back end
- Template for HDF5 definitions
- Template for HDF5 structures
- Template for HDF5 init/deinit
- Template for HDF5 has/read/write the numerical attribute
- Template for HDF5 has/read/write the dataset of numerical data
- Template for HDF5 has/read/write the dataset of sparse data
- Template for HDF5 has/read/write the dataset of strings
- Template for HDF5 has/read/write the string attribute
HDF5 back end
Template for HDF5 definitions
#define $GROUP$_GROUP_NAME "$group$"
#define $GROUP_NUM$_NAME "$group_num$"
#define $GROUP_DSET$_NAME "$group_dset$"
#define $GROUP_STR$_NAME "$group_str$"
Template for HDF5 structures
typedef struct trexio_hdf5_s {
trexio_t parent ;
hid_t file_id;
hid_t $group$_group;
} trexio_hdf5_t;
Template for HDF5 init/deinit
trexio_exit_code
trexio_hdf5_init (trexio_t* const file)
{
trexio_hdf5_t* const f = (trexio_hdf5_t*) file;
/* If file doesn't exist, create it */
int f_exists = 0;
struct stat st;
if (stat(file->file_name, &st) == 0) f_exists = 1;
if (f_exists == 1) {
switch (file->mode) {
case 'r':
// reading the existing file -> open as RDONLY
f->file_id = H5Fopen(file->file_name, H5F_ACC_RDONLY, H5P_DEFAULT);
break;
case 'w':
// writing the existing file -> open as RDWRITE
f->file_id = H5Fopen(file->file_name, H5F_ACC_RDWR, H5P_DEFAULT);
break;
}
} else {
switch (file->mode) {
case 'r':
// reading non-existing file -> error
return TREXIO_FAILURE;
case 'w':
// writing non-existing file -> create it
f->file_id = H5Fcreate(file->file_name, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT);
break;
}
}
/* Create or open groups in the hdf5 file assuming that they exist if file exists */
switch (file->mode) {
case 'r':
f->$group$_group = H5Gopen(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT);
break;
case 'w':
if (f_exists == 1) {
f->$group$_group = H5Gopen(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT);
} else {
f->$group$_group = H5Gcreate(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
}
break;
}
if (f->$group$_group <= 0L) return TREXIO_INVALID_ID;
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_hdf5_deinit (trexio_t* const file)
{
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
H5Gclose(f->$group$_group);
f->$group$_group = 0;
H5Fclose(f->file_id);
f->file_id = 0;
return TREXIO_SUCCESS;
}
Template for HDF5 has/read/write the numerical attribute
trexio_exit_code
trexio_hdf5_read_$group_num$ (trexio_t* const file, $group_num_dtype_double$* const num)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (num == NULL) return TREXIO_INVALID_ARG_2;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
/* Quit if the dimensioning attribute is missing in the file */
if (H5Aexists(f->$group$_group, $GROUP_NUM$_NAME) == 0) return TREXIO_FAILURE;
/* Read the $group_num$ attribute of $group$ group */
const hid_t num_id = H5Aopen(f->$group$_group, $GROUP_NUM$_NAME, H5P_DEFAULT);
if (num_id <= 0) return TREXIO_INVALID_ID;
const herr_t status = H5Aread(num_id, H5T_$GROUP_NUM_H5_DTYPE$, num);
H5Aclose(num_id);
if (status < 0) return TREXIO_FAILURE;
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_hdf5_write_$group_num$ (trexio_t* const file, const $group_num_dtype_double$ num)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
trexio_hdf5_t* const f = (trexio_hdf5_t*) file;
/* Write the dimensioning variables */
const hid_t dtype = H5Tcopy(H5T_$GROUP_NUM_H5_DTYPE$);
const hid_t dspace = H5Screate(H5S_SCALAR);
const hid_t num_id = H5Acreate(f->$group$_group, $GROUP_NUM$_NAME,
dtype, dspace, H5P_DEFAULT, H5P_DEFAULT);
if (num_id <= 0) {
H5Sclose(dspace);
H5Tclose(dtype);
return TREXIO_INVALID_ID;
}
const herr_t status = H5Awrite(num_id, dtype, &(num));
if (status < 0) {
H5Aclose(num_id);
H5Sclose(dspace);
H5Tclose(dtype);
return TREXIO_FAILURE;
}
H5Sclose(dspace);
H5Aclose(num_id);
H5Tclose(dtype);
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_hdf5_has_$group_num$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
htri_t status = H5Aexists(f->$group$_group, $GROUP_NUM$_NAME);
/* H5Aexists returns positive value if attribute exists, 0 if does not, negative if error */
if (status > 0){
return TREXIO_SUCCESS;
} else if (status == 0) {
return TREXIO_HAS_NOT;
} else {
return TREXIO_FAILURE;
}
}
Template for HDF5 has/read/write the dataset of numerical data
trexio_exit_code
trexio_hdf5_read_$group_dset$ (trexio_t* const file, $group_dset_dtype$* const $group_dset$, const uint32_t rank, const uint64_t* dims)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
// open the dataset to get its dimensions
hid_t dset_id = H5Dopen(f->$group$_group, $GROUP_DSET$_NAME, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
// allocate space for the dimensions to be read
hsize_t* ddims = CALLOC( (int) rank, hsize_t);
if (ddims == NULL) return TREXIO_FAILURE;
// get the dataspace of the dataset
hid_t dspace_id = H5Dget_space(dset_id);
// get the rank and dimensions of the dataset
int rrank = H5Sget_simple_extent_dims(dspace_id, ddims, NULL);
// check that dimensions are consistent
if (rrank != (int) rank) {
FREE(ddims);
H5Sclose(dspace_id);
H5Dclose(dset_id);
return TREXIO_INVALID_ARG_3;
}
for (uint32_t i=0; i<rank; ++i){
if (ddims[i] != dims[i]) {
FREE(ddims);
H5Sclose(dspace_id);
H5Dclose(dset_id);
return TREXIO_INVALID_ARG_4;
}
}
FREE(ddims);
H5Sclose(dspace_id);
H5Dclose(dset_id);
/* High-level H5LT API. No need to deal with dataspaces and datatypes */
herr_t status = H5LTread_dataset(f->$group$_group,
$GROUP_DSET$_NAME,
H5T_$GROUP_DSET_H5_DTYPE$,
$group_dset$);
if (status < 0) return TREXIO_FAILURE;
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_hdf5_write_$group_dset$ (trexio_t* const file, const $group_dset_dtype$* $group_dset$, const uint32_t rank, const uint64_t* dims)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
if ( H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME) != 1 ) {
const herr_t status = H5LTmake_dataset(f->$group$_group,
$GROUP_DSET$_NAME,
(int) rank, (const hsize_t*) dims,
H5T_$GROUP_DSET_H5_DTYPE$,
$group_dset$);
if (status < 0) return TREXIO_FAILURE;
} else {
hid_t dset_id = H5Dopen(f->$group$_group, $GROUP_DSET$_NAME, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
const herr_t status = H5Dwrite(dset_id,
H5T_$GROUP_DSET_H5_DTYPE$,
H5S_ALL, H5S_ALL, H5P_DEFAULT,
$group_dset$);
H5Dclose(dset_id);
if (status < 0) return TREXIO_FAILURE;
}
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_hdf5_has_$group_dset$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
herr_t status = H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME);
/* H5LTfind_dataset returns 1 if dataset exists, 0 otherwise */
if (status == 1){
return TREXIO_SUCCESS;
} else if (status == 0) {
return TREXIO_HAS_NOT;
} else {
return TREXIO_FAILURE;
}
}
Template for HDF5 has/read/write the dataset of sparse data
Sparse data is stored using extensible datasets of HDF5. Extensibility is required due to the fact that the sparse data will be written in chunks of user-defined size.
trexio_exit_code
trexio_hdf5_write_$group_dset$ (trexio_t* const file,
const int64_t offset_file,
const int64_t size,
const int64_t size_max,
const int32_t* index_sparse,
const double* value_sparse)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
const uint32_t h5_rank = 1;
const hsize_t chunk_dims[1] = {size * $group_dset_rank$};
const hsize_t maxdims[1] = {H5S_UNLIMITED};
if ( H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME) != 1 ) {
hid_t dspace = H5Screate_simple(h5_rank, chunk_dims, maxdims);
hid_t prop = H5Pcreate(H5P_DATASET_CREATE);
herr_t status = H5Pset_chunk(prop, h5_rank, chunk_dims);
hid_t dset_id = H5Dcreate(f->$group$_group,
$GROUP_DSET$_NAME,
H5T_NATIVE_INT32,
dspace,
H5P_DEFAULT,
prop,
H5P_DEFAULT);
assert(dset_id >= 0);
status = H5Dwrite(dset_id, H5T_NATIVE_INT32, H5S_ALL, H5S_ALL, H5P_DEFAULT, index_sparse);
/*const herr_t status = H5LTmake_dataset(f->$group$_group,
$GROUP_DSET$_NAME,
(int) rank, (const hsize_t*) dims,
H5T_$GROUP_DSET_H5_DTYPE$,
$group_dset$);
if (status < 0) return TREXIO_FAILURE;*/
H5Pclose(prop);
H5Dclose(dset_id);
H5Sclose(dspace);
} else {
hid_t dset_id = H5Dopen(f->$group$_group, $GROUP_DSET$_NAME, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
hid_t fspace = H5Dget_space(dset_id);
hsize_t offset[1] = {(hsize_t) offset_file * $group_dset_rank$};
// allocate space for the dimensions to be read
hsize_t ddims[1] = {0};
// get the rank and dimensions of the dataset
int rrank = H5Sget_simple_extent_dims(fspace, ddims, NULL);
ddims[0] += chunk_dims[0];
// extend the dset size
herr_t status = H5Dset_extent(dset_id, ddims);
H5Sclose(fspace);
fspace = H5Dget_space(dset_id);
status = H5Sselect_hyperslab(fspace, H5S_SELECT_SET, offset, NULL, chunk_dims, NULL);
hid_t dspace = H5Screate_simple(h5_rank, chunk_dims, NULL);
status = H5Dwrite(dset_id,
H5T_NATIVE_INT32,
dspace, fspace, H5P_DEFAULT,
index_sparse);
assert(status >= 0);
H5Dclose(dset_id);
H5Sclose(dspace);
H5Sclose(fspace);
if (status < 0) return TREXIO_FAILURE;
}
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_hdf5_read_$group_dset$ (trexio_t* const file,
const int64_t offset_file,
const int64_t size,
const int64_t size_max,
uint64_t* const eof_read_size,
int32_t* const index_read,
double* const value_read)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (eof_read_size == NULL) return TREXIO_INVALID_ARG_5;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
// open the dataset to get its dimensions
hid_t dset_id = H5Dopen(f->$group$_group, $GROUP_DSET$_NAME, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
// get the dataspace of the dataset
hid_t fspace_id = H5Dget_space(dset_id);
// TODO: check for possible overflow HERE ?
hsize_t offset[1] = {(hsize_t) offset_file * $group_dset_rank$};
hsize_t count[1] = {(hsize_t) size * $group_dset_rank$};
/* get dimensions of the dataset in the file to check whether reading with user-provided chunk size
will reach end of the dataset (i.e. EOF in TEXT back end)
,*/
hsize_t ddims[1] = {0};
int rrank = H5Sget_simple_extent_dims(fspace_id, ddims, NULL);
hsize_t max_offset = offset[0] + count[0];
int eof_reachable = 0;
if (max_offset > ddims[0]) {
eof_reachable = 1;
// lower the value of count to reduce the number of elements which will be read
count[0] -= max_offset - ddims[0];
// modify the eof_read_size accordingly
*eof_read_size = (uint64_t) (count[0] / $group_dset_rank$UL);
}
herr_t status = H5Sselect_hyperslab(fspace_id, H5S_SELECT_SET, offset, NULL, count, NULL);
hid_t memspace_id = H5Screate_simple(1, count, NULL);
status = H5Dread(dset_id, H5T_NATIVE_INT32, memspace_id, fspace_id, H5P_DEFAULT, index_read);
H5Sclose(fspace_id);
H5Sclose(memspace_id);
H5Dclose(dset_id);
assert (status >= 0);
if (eof_reachable == 1) return TREXIO_END;
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_hdf5_read_$group_dset$_size (trexio_t* const file, int64_t* const size_max)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
hid_t dset_id = H5Dopen(f->$group$_group, $GROUP_DSET$_NAME, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
hid_t fspace_id = H5Dget_space(dset_id);
// allocate space for the dimensions to be read
hsize_t ddims[1] = {0};
// get the rank and dimensions of the dataset
int rrank = H5Sget_simple_extent_dims(fspace_id, ddims, NULL);
H5Dclose(dset_id);
H5Sclose(fspace_id);
int mod_$group_dset_rank$ = (int) (ddims[0] % $group_dset_rank$);
if (mod_$group_dset_rank$ != 0) return TREXIO_FAILURE;
*size_max = ((int64_t) ddims[0]) / $group_dset_rank$L;
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_hdf5_has_$group_dset$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
herr_t status = H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME);
/* H5LTfind_dataset returns 1 if dataset exists, 0 otherwise */
if (status == 1){
return TREXIO_SUCCESS;
} else if (status == 0) {
return TREXIO_HAS_NOT;
} else {
return TREXIO_FAILURE;
}
}
Template for HDF5 has/read/write the dataset of strings
trexio_exit_code
trexio_hdf5_read_$group_dset$ (trexio_t* const file, char* const $group_dset$, const uint32_t rank, const uint64_t* dims, const uint32_t max_str_len)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
herr_t status;
// open the dataset to get its dimensions
hid_t dset_id = H5Dopen(f->$group$_group, $GROUP_DSET$_NAME, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
// allocate space for the dimensions to be read
hsize_t* ddims = CALLOC( (int) rank, hsize_t);
if (ddims == NULL) {
H5Dclose(dset_id);
return TREXIO_ALLOCATION_FAILED;
}
hid_t dspace = H5Dget_space(dset_id);
if (dset_id <= 0) {
FREE(ddims);
H5Dclose(dset_id);
return TREXIO_INVALID_ID;
}
// get the rank of the dataset in a file
int rrank = H5Sget_simple_extent_dims(dspace, ddims, NULL);
if (rrank != (int) rank) {
FREE(ddims);
H5Dclose(dset_id);
H5Sclose(dspace);
return TREXIO_INVALID_ARG_3;
}
for (int i=0; i<rrank; i++) {
if (ddims[i] != dims[i]) {
H5Dclose(dset_id);
H5Sclose(dspace);
FREE(ddims);
return TREXIO_INVALID_ARG_4;
}
}
FREE(ddims);
hid_t memtype = H5Tcopy (H5T_C_S1);
status = H5Tset_size(memtype, H5T_VARIABLE);
if (status < 0 || memtype <= 0) {
H5Dclose(dset_id);
H5Sclose(dspace);
return TREXIO_FAILURE;
}
char** rdata = CALLOC(dims[0], char*);
if (rdata == NULL) {
H5Dclose(dset_id);
H5Sclose(dspace);
H5Tclose(memtype);
return TREXIO_ALLOCATION_FAILED;
}
status = H5Dread(dset_id, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata);
if (status < 0) {
FREE(rdata);
H5Dclose(dset_id);
H5Sclose(dspace);
H5Tclose(memtype);
return TREXIO_FAILURE;
}
// copy contents of temporary rdata buffer into the group_dset otherwise they are lost
// after calling H5Treclaim or H5Dvlen_reclaim functions
strcpy($group_dset$, "");
for (uint64_t i=0; i<dims[0]; i++) {
strncat($group_dset$, rdata[i], max_str_len);
strcat($group_dset$, TREXIO_DELIM);
}
// H5Dvlen_reclaim is deprecated and replaced by H5Treclaim in HDF5 v.1.12.0
#if (H5_VERS_MAJOR <= 1 && H5_VERS_MINOR < 12)
status = H5Dvlen_reclaim(memtype, dspace, H5P_DEFAULT, rdata);
#else
status = H5Treclaim(memtype, dspace, H5P_DEFAULT, rdata);
#endif
if (status < 0) {
FREE(rdata);
H5Dclose(dset_id);
H5Sclose(dspace);
H5Tclose(memtype);
return TREXIO_FAILURE;
}
FREE(rdata);
H5Dclose(dset_id);
H5Sclose(dspace);
H5Tclose(memtype);
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_hdf5_write_$group_dset$ (trexio_t* const file, const char** $group_dset$, const uint32_t rank, const uint64_t* dims)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
herr_t status;
hid_t dset_id;
/* we are going to write variable-length strings */
hid_t memtype = H5Tcopy (H5T_C_S1);
if (memtype <= 0) return TREXIO_INVALID_ID;
status = H5Tset_size (memtype, H5T_VARIABLE);
if (status < 0) return TREXIO_FAILURE;
if ( H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME) != 1 ) {
/* code to create dataset */
hid_t filetype = H5Tcopy (H5T_FORTRAN_S1);
if (filetype <= 0) return TREXIO_INVALID_ID;
status = H5Tset_size (filetype, H5T_VARIABLE);
if (status < 0) return TREXIO_FAILURE;
hid_t dspace = H5Screate_simple( (int) rank, (const hsize_t*) dims, NULL);
if (dspace <= 0) return TREXIO_INVALID_ID;
dset_id = H5Dcreate (f->$group$_group, $GROUP_DSET$_NAME, filetype, dspace,
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
status = H5Dwrite (dset_id, memtype,
H5S_ALL, H5S_ALL, H5P_DEFAULT,
$group_dset$);
H5Dclose (dset_id);
H5Sclose (dspace);
H5Tclose (filetype);
H5Tclose (memtype);
if (status < 0) return TREXIO_FAILURE;
} else {
dset_id = H5Dopen(f->$group$_group, $GROUP_DSET$_NAME, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
/* code to write dataset */
status = H5Dwrite(dset_id, memtype,
H5S_ALL, H5S_ALL, H5P_DEFAULT,
$group_dset$);
H5Dclose(dset_id);
H5Tclose(memtype);
if (status < 0) return TREXIO_FAILURE;
}
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_hdf5_has_$group_dset$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
herr_t status = H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME);
/* H5LTfind_dataset returns 1 if dataset exists, 0 otherwise */
if (status == 1){
return TREXIO_SUCCESS;
} else if (status == 0) {
return TREXIO_HAS_NOT;
} else {
return TREXIO_FAILURE;
}
}
Template for HDF5 has/read/write the string attribute
trexio_exit_code
trexio_hdf5_read_$group_str$ (trexio_t* const file, char* const str, const uint32_t max_str_len)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (str == NULL) return TREXIO_INVALID_ARG_2;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
/* Quit if the string attribute is missing in the file */
if (H5Aexists(f->$group$_group, $GROUP_STR$_NAME) == 0) return TREXIO_HAS_NOT;
/* Read the $group_str$ attribute of $group$ group */
const hid_t str_id = H5Aopen(f->$group$_group, $GROUP_STR$_NAME, H5P_DEFAULT);
if (str_id <= 0) return TREXIO_INVALID_ID;
const hid_t ftype_id = H5Aget_type(str_id);
if (ftype_id <= 0) return TREXIO_INVALID_ID;
uint64_t sdim = H5Tget_size(ftype_id);
if (sdim <= 0) return TREXIO_FAILURE;
sdim++; /* Make room for null terminator */
const hid_t mem_id = H5Tcopy(H5T_C_S1);
if (mem_id <= 0) return TREXIO_INVALID_ID;
herr_t status;
status = (max_str_len+1) > sdim ? H5Tset_size(mem_id, sdim) : H5Tset_size(mem_id, max_str_len+1) ;
if (status < 0) return TREXIO_FAILURE;
status = H5Aread(str_id, mem_id, str);
if (status < 0) return TREXIO_FAILURE;
H5Aclose(str_id);
H5Tclose(mem_id);
H5Tclose(ftype_id);
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_hdf5_write_$group_str$ (trexio_t* const file, const char* str)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (str == NULL) return TREXIO_INVALID_ARG_2;
trexio_hdf5_t* const f = (trexio_hdf5_t*) file;
/* Setup the dataspace */
const hid_t dtype_id = H5Tcopy(H5T_C_S1);
if (dtype_id <= 0) return TREXIO_INVALID_ID;
size_t str_attr_len = strlen(str) + 1;
herr_t status;
status = H5Tset_size(dtype_id, str_attr_len);
if (status < 0) return TREXIO_FAILURE;
status = H5Tset_strpad(dtype_id, H5T_STR_NULLTERM);
if (status < 0) return TREXIO_FAILURE;
const hid_t dspace_id = H5Screate(H5S_SCALAR);
if (dspace_id <= 0) return TREXIO_INVALID_ID;
/* Create the $group_str$ attribute of $group$ group */
const hid_t str_id = H5Acreate(f->$group$_group, $GROUP_STR$_NAME, dtype_id, dspace_id,
H5P_DEFAULT, H5P_DEFAULT);
if (str_id <= 0) {
H5Sclose(dspace_id);
H5Tclose(dtype_id);
return TREXIO_INVALID_ID;
}
status = H5Awrite(str_id, dtype_id, str);
if (status < 0) {
H5Aclose(str_id);
H5Sclose(dspace_id);
H5Tclose(dtype_id);
return TREXIO_FAILURE;
}
H5Aclose(str_id);
H5Sclose(dspace_id);
H5Tclose(dtype_id);
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_hdf5_has_$group_str$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
htri_t status = H5Aexists(f->$group$_group, $GROUP_STR$_NAME);
/* H5Aexists returns positive value if attribute exists, 0 if does not, negative if error */
if (status > 0){
return TREXIO_SUCCESS;
} else if (status == 0) {
return TREXIO_HAS_NOT;
} else {
return TREXIO_FAILURE;
}
}