Skip to content

Commit

Permalink
Exit early when obtaining variables names of HDF5 MAT file
Browse files Browse the repository at this point in the history
As reported by #157
  • Loading branch information
tbeu committed Oct 20, 2023
1 parent ad9cc50 commit 2da57ab
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 40 deletions.
18 changes: 10 additions & 8 deletions src/mat.c
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ Mat_GetDir(mat_t *mat, size_t *n)
}
mat->next_index = 0;
while ( mat->next_index < mat->num_datasets ) {
matvar = Mat_VarReadNextInfo(mat);
matvar = Mat_VarReadNextInfo73(mat, NULL, NULL, 1);
if ( NULL != matvar ) {
if ( NULL != matvar->name ) {
mat->dir[i++] = strdup(matvar->name);
Expand Down Expand Up @@ -2587,7 +2587,7 @@ Mat_VarReadDataLinear(mat_t *mat, matvar_t *matvar, void *data, int start, int s
/** @brief Reads the information of the next variable in a MAT file
*
* Reads the next variable's information (class,flags-complex/global/logical,
* rank,dimensions, name, etc) from the Matlab MAT file. After reading, the MAT
* rank,dimensions, name, etc) from the Matlab MAT file. After reading, the MAT
* file is positioned past the current variable.
* @ingroup MAT
* @param mat Pointer to the MAT file
Expand All @@ -2604,11 +2604,13 @@ Mat_VarReadNextInfo(mat_t *mat)
*
* Reads the next variable's information (class,flags-complex/global/logical,
* rank,dimensions, name, etc) from the Matlab MAT file. Calls a user callback
* to check where the variable has to be fully read of skipped.
* to check where the variable has to be fully read or skipped.
* If skipped tries to read next till accepted or EOF.
* After reading, the MAT file is positioned past the current variable.
* @ingroup MAT
* @param mat Pointer to the MAT file
* @param pred User callback function
* @param user_data User data to be passed to the callback function
* @return Pointer to the @ref matvar_t structure containing the MAT
* variable information
*/
Expand All @@ -2625,7 +2627,7 @@ Mat_VarReadNextInfoPredicate(mat_t *mat, mat_iter_pred_t pred, const void *user_
break;
case MAT_FT_MAT73:
#if defined(MAT73) && MAT73
matvar = Mat_VarReadNextInfo73(mat, pred, user_data);
matvar = Mat_VarReadNextInfo73(mat, pred, user_data, 0);
#else
matvar = NULL;
#endif
Expand All @@ -2644,8 +2646,8 @@ Mat_VarReadNextInfoPredicate(mat_t *mat, mat_iter_pred_t pred, const void *user_
static int
Mat_IteratorNameAcceptor(const char *name, const void *user_data)
{
const char *required_name = user_data;
return name && required_name && strcmp(name, required_name) == 0;
const char *required_name = (const char *)user_data;
return (NULL != name) && (NULL != required_name) && 0 == strcmp(name, required_name);
}

/** @brief Reads the information of a variable with the given name from a MAT file
Expand Down Expand Up @@ -2816,8 +2818,8 @@ Mat_VarReadNextPredicate(mat_t *mat, mat_iter_pred_t pred, const void *user_data
}
break;
}
} while ( pred && pred(matvar->name, user_data) ==
0 ); /* for 7.3 the predicate will be called one extra time */
} while ( (NULL != pred) && 0 == pred(matvar->name, user_data) );
/* for 7.3 the predicate will be called one extra time */

return matvar;
}
Expand Down
71 changes: 40 additions & 31 deletions src/mat73.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ struct ReadNextIterData
matvar_t *matvar;
mat_iter_pred_t pred;
const void *pred_user_data;
int only_root_name;
};

struct ReadGroupInfoIterData
Expand Down Expand Up @@ -3157,16 +3158,19 @@ Mat_VarReadDataLinear73(mat_t *mat, matvar_t *matvar, void *data, int start, int
*
* @ingroup mat_internal
* @param mat MAT file pointer
* @param pred User callback function
* @param user_data User data to be passed to the callback function
* @param only_root_name Flag to only iterate on root level
* @return pointer to the MAT variable or NULL
* @endif
*/
matvar_t *
Mat_VarReadNextInfo73(mat_t *mat, mat_iter_pred_t pred, const void *user_data)
Mat_VarReadNextInfo73(mat_t *mat, mat_iter_pred_t pred, const void *user_data, int only_root_name)
{
hid_t id;
hsize_t idx;
herr_t herr;
struct ReadNextIterData mat_data;
struct ReadNextIterData iter_data;

if ( mat == NULL )
return NULL;
Expand All @@ -3176,43 +3180,44 @@ Mat_VarReadNextInfo73(mat_t *mat, mat_iter_pred_t pred, const void *user_data)

id = *(hid_t *)mat->fp;
idx = (hsize_t)mat->next_index;
mat_data.mat = mat;
mat_data.matvar = NULL;
mat_data.pred = pred;
mat_data.pred_user_data = user_data;
iter_data.mat = mat;
iter_data.matvar = NULL;
iter_data.pred = pred;
iter_data.pred_user_data = user_data;
iter_data.only_root_name = only_root_name;
herr = H5Literate(id, H5_INDEX_NAME, H5_ITER_NATIVE, &idx, Mat_VarReadNextInfoIterate,
(void *)&mat_data);
(void *)&iter_data);
if ( herr > 0 )
mat->next_index = (size_t)idx;
return mat_data.matvar;
return iter_data.matvar;
}

static herr_t
Mat_VarReadNextInfoIterate(hid_t id, const char *name, const H5L_info_t *info, void *op_data)
{
mat_t *mat;
H5O_INFO_T object_info;
struct ReadNextIterData *mat_data;
struct ReadNextIterData *iter_data;

/* FIXME: follow symlinks, datatypes? */

mat_data = (struct ReadNextIterData *)op_data;
iter_data = (struct ReadNextIterData *)op_data;

/* Check that this is not the /#refs# or /"#subsystem#" group */
if ( 0 == strcmp(name, "#refs#") || 0 == strcmp(name, "#subsystem#") )
return 0;
if ( mat_data && mat_data->pred &&
mat_data->pred(name, mat_data->pred_user_data) == 0 ) /* do we need to skip it? */
if ( (NULL != iter_data) && (NULL != iter_data->pred) &&
0 == iter_data->pred(name, iter_data->pred_user_data) ) /* do we need to skip it? */
return 0;

object_info.type = H5O_TYPE_UNKNOWN;
H5OGET_INFO_BY_NAME(id, name, &object_info, H5P_DEFAULT);
if ( H5O_TYPE_DATASET != object_info.type && H5O_TYPE_GROUP != object_info.type )
return 0;

if ( NULL == mat_data )
if ( NULL == iter_data )
return -1;
mat = mat_data->mat;
mat = iter_data->mat;

switch ( object_info.type ) {
case H5O_TYPE_DATASET: {
Expand All @@ -3228,17 +3233,19 @@ Mat_VarReadNextInfoIterate(hid_t id, const char *name, const H5L_info_t *info, v
return -1;
}

dset_id = H5Dopen(id, name, H5P_DEFAULT);
err = Mat_H5ReadDatasetInfo(mat, matvar, dset_id);
if ( matvar->internal->id != dset_id ) {
/* Close dataset and increment count */
H5Dclose(dset_id);
}
if ( err ) {
Mat_VarFree(matvar);
return -1;
if ( !iter_data->only_root_name ) {
dset_id = H5Dopen(id, name, H5P_DEFAULT);
err = Mat_H5ReadDatasetInfo(mat, matvar, dset_id);
if ( matvar->internal->id != dset_id ) {
/* Close dataset and increment count */
H5Dclose(dset_id);
}
if ( err ) {
Mat_VarFree(matvar);
return -1;
}
}
mat_data->matvar = matvar;
iter_data->matvar = matvar;
break;
}
case H5O_TYPE_GROUP: {
Expand All @@ -3254,14 +3261,16 @@ Mat_VarReadNextInfoIterate(hid_t id, const char *name, const H5L_info_t *info, v
return -1;
}

dset_id = H5Gopen(id, name, H5P_DEFAULT);
err = Mat_H5ReadGroupInfo(mat, matvar, dset_id);
H5Gclose(dset_id);
if ( err ) {
Mat_VarFree(matvar);
return -1;
if ( !iter_data->only_root_name ) {
dset_id = H5Gopen(id, name, H5P_DEFAULT);
err = Mat_H5ReadGroupInfo(mat, matvar, dset_id);
H5Gclose(dset_id);
if ( err ) {
Mat_VarFree(matvar);
return -1;
}
}
mat_data->matvar = matvar;
iter_data->matvar = matvar;
break;
}
default:
Expand Down
3 changes: 2 additions & 1 deletion src/mat73.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ EXTERN int Mat_VarReadData73(mat_t *mat, matvar_t *matvar, void *data, int *star
int *edge);
EXTERN int Mat_VarReadDataLinear73(mat_t *mat, matvar_t *matvar, void *data, int start, int stride,
int edge);
EXTERN matvar_t *Mat_VarReadNextInfo73(mat_t *mat, mat_iter_pred_t pred, const void *user_data);
EXTERN matvar_t *Mat_VarReadNextInfo73(mat_t *mat, mat_iter_pred_t pred, const void *user_data,
int only_root_name);
EXTERN int Mat_VarWrite73(mat_t *mat, matvar_t *matvar, int compress);
EXTERN int Mat_VarWriteAppend73(mat_t *mat, matvar_t *matvar, int compress, int dim);

Expand Down

0 comments on commit 2da57ab

Please sign in to comment.