mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-16 14:15:26 -06:00
2816 lines
95 KiB
C
2816 lines
95 KiB
C
/** @file mat73.c
|
|
* Matlab MAT version 7.3 file functions
|
|
* @ingroup MAT
|
|
*/
|
|
/*
|
|
* Copyright (c) 2005-2019, Christopher C. Hulbert
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
|
# define strdup _strdup
|
|
#endif
|
|
#include "matio_private.h"
|
|
|
|
#if defined(MAT73) && MAT73
|
|
#if HAVE_HDF5
|
|
|
|
#include "mat73.h"
|
|
|
|
static const char *ClassNames[] = {
|
|
"",
|
|
"cell",
|
|
"struct",
|
|
"object",
|
|
"char",
|
|
"sparse",
|
|
"double",
|
|
"single",
|
|
"int8",
|
|
"uint8",
|
|
"int16",
|
|
"uint16",
|
|
"int32",
|
|
"uint32",
|
|
"int64",
|
|
"uint64",
|
|
"function"
|
|
};
|
|
|
|
struct ReadNextIterData {
|
|
mat_t *mat;
|
|
matvar_t *matvar;
|
|
};
|
|
|
|
struct ReadGroupInfoIterData {
|
|
hsize_t nfields;
|
|
matvar_t *matvar;
|
|
};
|
|
|
|
#if H5_VERSION_GE(1,10,0)
|
|
#define H5RDEREFERENCE(obj_id, ref_type, _ref) H5Rdereference2((obj_id), H5P_DATASET_ACCESS_DEFAULT, (ref_type), (_ref))
|
|
#else
|
|
#define H5RDEREFERENCE(obj_id, ref_type, _ref) H5Rdereference((obj_id), (ref_type), (_ref))
|
|
#endif
|
|
|
|
#if H5_VERSION_GE(1,10,3)
|
|
#define H5OGET_INFO_BY_NAME(loc_id, name, oinfo, lapl_id) H5Oget_info_by_name2((loc_id), (name), (oinfo), H5O_INFO_BASIC, (lapl_id));
|
|
#else
|
|
#define H5OGET_INFO_BY_NAME(loc_id, name, oinfo, lapl_id) H5Oget_info_by_name((loc_id), (name), (oinfo), (lapl_id));
|
|
#endif
|
|
|
|
#if !defined(MAX_RANK)
|
|
/* Maximal number of dimensions for stack allocated temporary dimension arrays */
|
|
#define MAX_RANK (3)
|
|
#endif
|
|
|
|
/*===========================================================================
|
|
* Private functions
|
|
*===========================================================================
|
|
*/
|
|
static enum matio_classes ClassStr2ClassType(const char *name);
|
|
static enum matio_classes DataType2ClassType(enum matio_types type);
|
|
static hid_t ClassType2H5T(enum matio_classes class_type);
|
|
static hid_t DataType2H5T(enum matio_types data_type);
|
|
static hid_t SizeType2H5T(void);
|
|
static hid_t DataType(hid_t h5_type, int isComplex);
|
|
static void Mat_H5GetChunkSize(size_t rank,hsize_t *dims,hsize_t *chunk_dims);
|
|
static void Mat_H5ReadVarInfo(matvar_t *matvar,hid_t dset_id);
|
|
static size_t* Mat_H5ReadDims(hid_t dset_id, hsize_t *nelems, int *rank);
|
|
static void Mat_H5ReadFieldNames(matvar_t *matvar, hid_t dset_id, hsize_t *nfields);
|
|
static void Mat_H5ReadDatasetInfo(mat_t *mat,matvar_t *matvar,hid_t dset_id);
|
|
static void Mat_H5ReadGroupInfo(mat_t *mat,matvar_t *matvar,hid_t dset_id);
|
|
static void Mat_H5ReadNextReferenceInfo(hid_t ref_id,matvar_t *matvar,mat_t *mat);
|
|
static void Mat_H5ReadNextReferenceData(hid_t ref_id,matvar_t *matvar,mat_t *mat);
|
|
static int Mat_VarWriteEmpty(hid_t id,matvar_t *matvar,const char *name,
|
|
const char* class_name);
|
|
static int Mat_VarWriteCell73(hid_t id,matvar_t *matvar,const char *name,
|
|
hid_t *refs_id,hsize_t *dims);
|
|
static int Mat_VarWriteChar73(hid_t id,matvar_t *matvar,const char *name,hsize_t *dims);
|
|
static int Mat_WriteEmptyVariable73(hid_t id,const char *name,hsize_t rank,
|
|
size_t *dims);
|
|
static int Mat_VarWriteLogical73(hid_t id,matvar_t *matvar,const char *name,hsize_t *dims);
|
|
static int Mat_VarWriteNumeric73(hid_t id,matvar_t *matvar,const char *name,hsize_t *dims,
|
|
hsize_t* max_dims);
|
|
static int Mat_VarWriteAppendNumeric73(hid_t id,matvar_t *matvar,const char *name,
|
|
hsize_t *dims,int dim);
|
|
static int Mat_VarWriteSparse73(hid_t id,matvar_t *matvar,const char *name);
|
|
static int Mat_VarWriteStruct73(hid_t id,matvar_t *matvar,const char *name,
|
|
hid_t *refs_id,hsize_t *dims,hsize_t* max_dims);
|
|
static int Mat_VarWriteAppendStruct73(hid_t id,matvar_t *matvar,const char *name,
|
|
hid_t *refs_id,hsize_t *dims,int dim);
|
|
static int Mat_VarWriteNext73(hid_t id,matvar_t *matvar,const char *name,
|
|
hid_t *refs_id);
|
|
static int Mat_VarWriteAppendNext73(hid_t id,matvar_t *matvar,const char *name,
|
|
hid_t *refs_id,int dim);
|
|
static int Mat_VarWriteNextType73(hid_t id,matvar_t *matvar,const char *name,
|
|
hid_t *refs_id,hsize_t *dims);
|
|
static int Mat_VarWriteAppendNextType73(hid_t id,matvar_t *matvar,const char *name,
|
|
hid_t *refs_id,hsize_t *dims,int dim);
|
|
static herr_t Mat_VarReadNextInfoIterate(hid_t id, const char *name,
|
|
const H5L_info_t *info, void *op_data);
|
|
static herr_t Mat_H5ReadGroupInfoIterate(hid_t dset_id, const char *name,
|
|
const H5L_info_t *info, void *op_data);
|
|
static void Mat_H5ReadData(hid_t dset_id, hid_t h5_type, hid_t mem_space, hid_t dset_space,
|
|
int isComplex, void *data);
|
|
static int Mat_H5WriteData(hid_t dset_id, hid_t h5_type, hid_t mem_space, hid_t dset_space,
|
|
int isComplex, void *data);
|
|
static int Mat_H5WriteAppendData(hid_t id, hid_t h5_type, int mrank, const char *name,
|
|
const size_t* mdims, hsize_t *dims, int dim, int isComplex, void* data);
|
|
static int Mat_VarWriteRef(hid_t id, matvar_t* matvar, enum matio_compression compression,
|
|
hid_t *refs_id, hobj_ref_t* ref);
|
|
|
|
static enum matio_classes
|
|
ClassStr2ClassType(const char *name)
|
|
{
|
|
enum matio_classes id = MAT_C_EMPTY;
|
|
if ( NULL != name ) {
|
|
int k;
|
|
for ( k = 1; k < 17; k++ ) {
|
|
if ( 0 == strcmp(name,ClassNames[k]) ) {
|
|
id = (enum matio_classes)k;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
static enum matio_classes
|
|
DataType2ClassType(enum matio_types type)
|
|
{
|
|
switch ( type ) {
|
|
case MAT_T_DOUBLE:
|
|
return MAT_C_DOUBLE;
|
|
case MAT_T_SINGLE:
|
|
return MAT_C_SINGLE;
|
|
#ifdef HAVE_MAT_INT64_T
|
|
case MAT_T_INT64:
|
|
return MAT_C_INT64;
|
|
#endif
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
case MAT_T_UINT64:
|
|
return MAT_C_UINT64;
|
|
#endif
|
|
case MAT_T_INT32:
|
|
return MAT_C_INT32;
|
|
case MAT_T_UINT32:
|
|
return MAT_C_UINT32;
|
|
case MAT_T_INT16:
|
|
return MAT_C_INT16;
|
|
case MAT_T_UINT16:
|
|
return MAT_C_UINT16;
|
|
case MAT_T_INT8:
|
|
return MAT_C_INT8;
|
|
case MAT_T_UINT8:
|
|
return MAT_C_UINT8;
|
|
default:
|
|
return MAT_C_EMPTY;
|
|
}
|
|
}
|
|
|
|
static hid_t
|
|
ClassType2H5T(enum matio_classes class_type)
|
|
{
|
|
switch ( class_type ) {
|
|
case MAT_C_DOUBLE:
|
|
return H5T_NATIVE_DOUBLE;
|
|
case MAT_C_SINGLE:
|
|
return H5T_NATIVE_FLOAT;
|
|
case MAT_C_INT64:
|
|
# if CHAR_BIT*SIZEOF_SHORT == 64
|
|
return H5T_NATIVE_SHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 64
|
|
return H5T_NATIVE_INT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 64
|
|
return H5T_NATIVE_LONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 64
|
|
return H5T_NATIVE_LLONG;
|
|
# endif
|
|
case MAT_C_UINT64:
|
|
# if CHAR_BIT*SIZEOF_SHORT == 64
|
|
return H5T_NATIVE_USHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 64
|
|
return H5T_NATIVE_UINT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 64
|
|
return H5T_NATIVE_ULONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 64
|
|
return H5T_NATIVE_ULLONG;
|
|
# endif
|
|
case MAT_C_INT32:
|
|
# if CHAR_BIT == 32
|
|
return H5T_NATIVE_SCHAR;
|
|
# elif CHAR_BIT*SIZEOF_SHORT == 32
|
|
return H5T_NATIVE_SHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 32
|
|
return H5T_NATIVE_INT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 32
|
|
return H5T_NATIVE_LONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 32
|
|
return H5T_NATIVE_LLONG;
|
|
# endif
|
|
case MAT_C_UINT32:
|
|
# if CHAR_BIT == 32
|
|
return H5T_NATIVE_UCHAR;
|
|
# elif CHAR_BIT*SIZEOF_SHORT == 32
|
|
return H5T_NATIVE_USHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 32
|
|
return H5T_NATIVE_UINT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 32
|
|
return H5T_NATIVE_ULONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 32
|
|
return H5T_NATIVE_ULLONG;
|
|
# endif
|
|
case MAT_C_INT16:
|
|
# if CHAR_BIT == 16
|
|
return H5T_NATIVE_SCHAR;
|
|
# elif CHAR_BIT*SIZEOF_SHORT == 16
|
|
return H5T_NATIVE_SHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 16
|
|
return H5T_NATIVE_INT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 16
|
|
return H5T_NATIVE_LONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 16
|
|
return H5T_NATIVE_LLONG;
|
|
# endif
|
|
case MAT_C_UINT16:
|
|
# if CHAR_BIT == 16
|
|
return H5T_NATIVE_UCHAR;
|
|
# elif CHAR_BIT*SIZEOF_SHORT == 16
|
|
return H5T_NATIVE_USHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 16
|
|
return H5T_NATIVE_UINT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 16
|
|
return H5T_NATIVE_ULONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 16
|
|
return H5T_NATIVE_ULLONG;
|
|
# endif
|
|
case MAT_C_INT8:
|
|
# if CHAR_BIT == 8
|
|
return H5T_NATIVE_SCHAR;
|
|
# elif CHAR_BIT*SIZEOF_SHORT == 8
|
|
return H5T_NATIVE_SHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 8
|
|
return H5T_NATIVE_INT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 8
|
|
return H5T_NATIVE_LONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 8
|
|
return H5T_NATIVE_LLONG;
|
|
# endif
|
|
case MAT_C_UINT8:
|
|
# if CHAR_BIT == 8
|
|
return H5T_NATIVE_UCHAR;
|
|
# elif CHAR_BIT*SIZEOF_SHORT == 8
|
|
return H5T_NATIVE_USHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 8
|
|
return H5T_NATIVE_UINT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 8
|
|
return H5T_NATIVE_ULONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 8
|
|
return H5T_NATIVE_ULLONG;
|
|
# endif
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
static hid_t
|
|
DataType2H5T(enum matio_types data_type)
|
|
{
|
|
switch ( data_type ) {
|
|
case MAT_T_DOUBLE:
|
|
return H5T_NATIVE_DOUBLE;
|
|
case MAT_T_SINGLE:
|
|
return H5T_NATIVE_FLOAT;
|
|
case MAT_T_INT64:
|
|
# if CHAR_BIT*SIZEOF_SHORT == 64
|
|
return H5T_NATIVE_SHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 64
|
|
return H5T_NATIVE_INT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 64
|
|
return H5T_NATIVE_LONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 64
|
|
return H5T_NATIVE_LLONG;
|
|
# endif
|
|
case MAT_T_UINT64:
|
|
# if CHAR_BIT*SIZEOF_SHORT == 64
|
|
return H5T_NATIVE_USHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 64
|
|
return H5T_NATIVE_UINT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 64
|
|
return H5T_NATIVE_ULONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 64
|
|
return H5T_NATIVE_ULLONG;
|
|
# endif
|
|
case MAT_T_INT32:
|
|
# if CHAR_BIT == 32
|
|
return H5T_NATIVE_SCHAR;
|
|
# elif CHAR_BIT*SIZEOF_SHORT == 32
|
|
return H5T_NATIVE_SHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 32
|
|
return H5T_NATIVE_INT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 32
|
|
return H5T_NATIVE_LONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 32
|
|
return H5T_NATIVE_LLONG;
|
|
# endif
|
|
case MAT_T_UINT32:
|
|
# if CHAR_BIT == 32
|
|
return H5T_NATIVE_UCHAR;
|
|
# elif CHAR_BIT*SIZEOF_SHORT == 32
|
|
return H5T_NATIVE_USHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 32
|
|
return H5T_NATIVE_UINT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 32
|
|
return H5T_NATIVE_ULONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 32
|
|
return H5T_NATIVE_ULLONG;
|
|
# endif
|
|
case MAT_T_INT16:
|
|
# if CHAR_BIT == 16
|
|
return H5T_NATIVE_SCHAR;
|
|
# elif CHAR_BIT*SIZEOF_SHORT == 16
|
|
return H5T_NATIVE_SHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 16
|
|
return H5T_NATIVE_INT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 16
|
|
return H5T_NATIVE_LONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 16
|
|
return H5T_NATIVE_LLONG;
|
|
# endif
|
|
case MAT_T_UINT16:
|
|
case MAT_T_UTF16:
|
|
# if CHAR_BIT == 16
|
|
return H5T_NATIVE_UCHAR;
|
|
# elif CHAR_BIT*SIZEOF_SHORT == 16
|
|
return H5T_NATIVE_USHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 16
|
|
return H5T_NATIVE_UINT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 16
|
|
return H5T_NATIVE_ULONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 16
|
|
return H5T_NATIVE_ULLONG;
|
|
# endif
|
|
case MAT_T_INT8:
|
|
# if CHAR_BIT == 8
|
|
return H5T_NATIVE_SCHAR;
|
|
# elif CHAR_BIT*SIZEOF_SHORT == 8
|
|
return H5T_NATIVE_SHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 8
|
|
return H5T_NATIVE_INT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 8
|
|
return H5T_NATIVE_LONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 8
|
|
return H5T_NATIVE_LLONG;
|
|
# endif
|
|
case MAT_T_UINT8:
|
|
# if CHAR_BIT == 8
|
|
return H5T_NATIVE_UCHAR;
|
|
# elif CHAR_BIT*SIZEOF_SHORT == 8
|
|
return H5T_NATIVE_USHORT;
|
|
# elif CHAR_BIT*SIZEOF_INT == 8
|
|
return H5T_NATIVE_UINT;
|
|
# elif CHAR_BIT*SIZEOF_LONG == 8
|
|
return H5T_NATIVE_ULONG;
|
|
# elif CHAR_BIT*SIZEOF_LONG_LONG == 8
|
|
return H5T_NATIVE_ULLONG;
|
|
# endif
|
|
case MAT_T_UTF8:
|
|
return H5T_NATIVE_CHAR;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
static hid_t
|
|
SizeType2H5T(void)
|
|
{
|
|
if ( sizeof(size_t) == H5Tget_size(H5T_NATIVE_HSIZE) )
|
|
return H5T_NATIVE_HSIZE;
|
|
else if ( sizeof(size_t) == H5Tget_size(H5T_NATIVE_ULLONG) )
|
|
return H5T_NATIVE_ULLONG;
|
|
else if ( sizeof(size_t) == H5Tget_size(H5T_NATIVE_ULONG) )
|
|
return H5T_NATIVE_ULONG;
|
|
else if ( sizeof(size_t) == H5Tget_size(H5T_NATIVE_UINT) )
|
|
return H5T_NATIVE_UINT;
|
|
else if ( sizeof(size_t) == H5Tget_size(H5T_NATIVE_USHORT) )
|
|
return H5T_NATIVE_USHORT;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
static hid_t
|
|
DataType(hid_t h5_type, int isComplex)
|
|
{
|
|
hid_t h5_dtype;
|
|
if ( isComplex ) {
|
|
size_t h5_size = H5Tget_size(h5_type);
|
|
h5_dtype = H5Tcreate(H5T_COMPOUND, 2*h5_size);
|
|
H5Tinsert(h5_dtype,"real",0,h5_type);
|
|
H5Tinsert(h5_dtype,"imag",h5_size,h5_type);
|
|
} else {
|
|
h5_dtype = H5Tcopy(h5_type);
|
|
}
|
|
return h5_dtype;
|
|
}
|
|
|
|
static void
|
|
Mat_H5GetChunkSize(size_t rank,hsize_t *dims,hsize_t *chunk_dims)
|
|
{
|
|
hsize_t i, j, chunk_size = 1;
|
|
|
|
for ( i = 0; i < rank; i++ ) {
|
|
chunk_dims[i] = 1;
|
|
for ( j = 4096/chunk_size; j > 1; j >>= 1 ) {
|
|
if ( dims[i] >= j ) {
|
|
chunk_dims[i] = j;
|
|
break;
|
|
}
|
|
}
|
|
chunk_size *= chunk_dims[i];
|
|
}
|
|
}
|
|
|
|
static void
|
|
Mat_H5ReadVarInfo(matvar_t *matvar,hid_t dset_id)
|
|
{
|
|
hid_t attr_id, type_id;
|
|
ssize_t name_len;
|
|
|
|
/* Get the HDF5 name of the variable */
|
|
name_len = H5Iget_name(dset_id,NULL,0);
|
|
if ( name_len > 0 ) {
|
|
matvar->internal->hdf5_name = (char*)malloc(name_len+1);
|
|
(void)H5Iget_name(dset_id,matvar->internal->hdf5_name,name_len+1);
|
|
} else {
|
|
/* Can not get an internal name, so leave the identifier open */
|
|
matvar->internal->id = dset_id;
|
|
}
|
|
|
|
attr_id = H5Aopen_by_name(dset_id,".","MATLAB_class",H5P_DEFAULT,H5P_DEFAULT);
|
|
type_id = H5Aget_type(attr_id);
|
|
if ( H5T_STRING == H5Tget_class(type_id) ) {
|
|
char *class_str = (char*)calloc(H5Tget_size(type_id)+1,1);
|
|
if ( NULL != class_str ) {
|
|
hid_t class_id = H5Tcopy(H5T_C_S1);
|
|
H5Tset_size(class_id,H5Tget_size(type_id));
|
|
H5Aread(attr_id,class_id,class_str);
|
|
H5Tclose(class_id);
|
|
matvar->class_type = ClassStr2ClassType(class_str);
|
|
if ( MAT_C_EMPTY == matvar->class_type || MAT_C_CHAR == matvar->class_type ) {
|
|
int int_decode = 0;
|
|
if ( H5Aexists_by_name(dset_id,".","MATLAB_int_decode",H5P_DEFAULT) ) {
|
|
hid_t attr_id2 = H5Aopen_by_name(dset_id,".","MATLAB_int_decode",H5P_DEFAULT,H5P_DEFAULT);
|
|
/* FIXME: Check that dataspace is scalar */
|
|
H5Aread(attr_id2,H5T_NATIVE_INT,&int_decode);
|
|
H5Aclose(attr_id2);
|
|
}
|
|
switch ( int_decode ) {
|
|
case 2:
|
|
matvar->data_type = MAT_T_UINT16;
|
|
break;
|
|
case 1:
|
|
matvar->data_type = MAT_T_UINT8;
|
|
break;
|
|
case 4:
|
|
matvar->data_type = MAT_T_UINT32;
|
|
break;
|
|
default:
|
|
matvar->data_type = MAT_T_UNKNOWN;
|
|
break;
|
|
}
|
|
if ( MAT_C_EMPTY == matvar->class_type ) {
|
|
/* Check if this is a logical variable */
|
|
if ( 0 == strcmp(class_str, "logical") ) {
|
|
matvar->isLogical = MAT_F_LOGICAL;
|
|
}
|
|
matvar->class_type = DataType2ClassType(matvar->data_type);
|
|
} else if ( MAT_T_UNKNOWN == matvar->data_type ) {
|
|
matvar->data_type = MAT_T_UINT16;
|
|
}
|
|
} else {
|
|
matvar->data_type = ClassType2DataType(matvar->class_type);
|
|
}
|
|
free(class_str);
|
|
}
|
|
}
|
|
H5Tclose(type_id);
|
|
H5Aclose(attr_id);
|
|
|
|
/* Check if the variable is global */
|
|
if ( H5Aexists_by_name(dset_id,".","MATLAB_global",H5P_DEFAULT) ) {
|
|
attr_id = H5Aopen_by_name(dset_id,".","MATLAB_global",H5P_DEFAULT,H5P_DEFAULT);
|
|
/* FIXME: Check that dataspace is scalar */
|
|
H5Aread(attr_id,H5T_NATIVE_INT,&matvar->isGlobal);
|
|
H5Aclose(attr_id);
|
|
}
|
|
}
|
|
|
|
static size_t*
|
|
Mat_H5ReadDims(hid_t dset_id, hsize_t *nelems, int *rank)
|
|
{
|
|
hid_t space_id;
|
|
size_t* perm_dims;
|
|
|
|
*nelems = 0;
|
|
space_id = H5Dget_space(dset_id);
|
|
*rank = H5Sget_simple_extent_ndims(space_id);
|
|
if ( 0 > *rank ) {
|
|
*rank = 0;
|
|
H5Sclose(space_id);
|
|
return NULL;
|
|
}
|
|
perm_dims = (size_t*)malloc(*rank*sizeof(*perm_dims));
|
|
if ( NULL != perm_dims ) {
|
|
if ( MAX_RANK >= *rank ) {
|
|
hsize_t dims[MAX_RANK];
|
|
int k;
|
|
size_t tmp = 1;
|
|
(void)H5Sget_simple_extent_dims(space_id,dims,NULL);
|
|
/* Permute dimensions */
|
|
for ( k = 0; k < *rank; k++ ) {
|
|
perm_dims[k] = (size_t)dims[*rank - k - 1];
|
|
SafeMul(&tmp, tmp, perm_dims[k]);
|
|
}
|
|
*nelems = (hsize_t)tmp;
|
|
H5Sclose(space_id);
|
|
} else {
|
|
hsize_t* dims = (hsize_t*)malloc(*rank*sizeof(hsize_t));
|
|
if ( NULL != dims ) {
|
|
int k;
|
|
size_t tmp = 1;
|
|
(void)H5Sget_simple_extent_dims(space_id,dims,NULL);
|
|
/* Permute dimensions */
|
|
for ( k = 0; k < *rank; k++ ) {
|
|
perm_dims[k] = (size_t)dims[*rank - k - 1];
|
|
SafeMul(&tmp, tmp, perm_dims[k]);
|
|
}
|
|
*nelems = (hsize_t)tmp;
|
|
free(dims);
|
|
H5Sclose(space_id);
|
|
} else {
|
|
free(perm_dims);
|
|
perm_dims = NULL;
|
|
*rank = 0;
|
|
H5Sclose(space_id);
|
|
Mat_Critical("Error allocating memory for dims");
|
|
}
|
|
}
|
|
} else {
|
|
*rank = 0;
|
|
H5Sclose(space_id);
|
|
Mat_Critical("Error allocating memory for matvar->dims");
|
|
}
|
|
|
|
return perm_dims;
|
|
}
|
|
|
|
static void
|
|
Mat_H5ReadFieldNames(matvar_t *matvar, hid_t dset_id, hsize_t *nfields)
|
|
{
|
|
hsize_t i;
|
|
hid_t field_id, attr_id, space_id;
|
|
hvl_t *fieldnames_vl;
|
|
|
|
attr_id = H5Aopen_by_name(dset_id,".","MATLAB_fields",H5P_DEFAULT,H5P_DEFAULT);
|
|
space_id = H5Aget_space(attr_id);
|
|
(void)H5Sget_simple_extent_dims(space_id,nfields,NULL);
|
|
field_id = H5Aget_type(attr_id);
|
|
fieldnames_vl = (hvl_t*)malloc((size_t)(*nfields)*sizeof(*fieldnames_vl));
|
|
H5Aread(attr_id,field_id,fieldnames_vl);
|
|
|
|
matvar->internal->num_fields = (unsigned int)*nfields;
|
|
matvar->internal->fieldnames =
|
|
(char**)malloc((size_t)(*nfields)*sizeof(*matvar->internal->fieldnames));
|
|
for ( i = 0; i < *nfields; i++ ) {
|
|
matvar->internal->fieldnames[i] =
|
|
(char*)calloc(fieldnames_vl[i].len+1,1);
|
|
memcpy(matvar->internal->fieldnames[i],fieldnames_vl[i].p,
|
|
fieldnames_vl[i].len);
|
|
}
|
|
|
|
H5Dvlen_reclaim(field_id,space_id,H5P_DEFAULT,fieldnames_vl);
|
|
H5Sclose(space_id);
|
|
H5Tclose(field_id);
|
|
H5Aclose(attr_id);
|
|
free(fieldnames_vl);
|
|
}
|
|
|
|
static void
|
|
Mat_H5ReadDatasetInfo(mat_t *mat,matvar_t *matvar,hid_t dset_id)
|
|
{
|
|
hid_t attr_id,type_id;
|
|
hsize_t nelems;
|
|
|
|
Mat_H5ReadVarInfo(matvar, dset_id);
|
|
|
|
matvar->dims = Mat_H5ReadDims(dset_id, &nelems, &matvar->rank);
|
|
if ( NULL == matvar->dims ) {
|
|
return;
|
|
}
|
|
|
|
/* Check for attribute that indicates an empty array */
|
|
if ( H5Aexists_by_name(dset_id,".","MATLAB_empty",H5P_DEFAULT) ) {
|
|
int empty = 0;
|
|
attr_id = H5Aopen_by_name(dset_id,".","MATLAB_empty",H5P_DEFAULT,H5P_DEFAULT);
|
|
/* FIXME: Check that dataspace is scalar */
|
|
H5Aread(attr_id,H5T_NATIVE_INT,&empty);
|
|
H5Aclose(attr_id);
|
|
if ( empty ) {
|
|
matvar->rank = matvar->dims[0];
|
|
free(matvar->dims);
|
|
matvar->dims = (size_t*)calloc(matvar->rank,sizeof(*matvar->dims));
|
|
H5Dread(dset_id,SizeType2H5T(),H5S_ALL,H5S_ALL,H5P_DEFAULT,matvar->dims);
|
|
{
|
|
size_t tmp = 1;
|
|
SafeMulDims(matvar, &tmp);
|
|
nelems = (hsize_t)tmp;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Test if dataset type is compound and if so if it's complex */
|
|
type_id = H5Dget_type(dset_id);
|
|
if ( H5T_COMPOUND == H5Tget_class(type_id) ) {
|
|
/* FIXME: Any more checks? */
|
|
matvar->isComplex = MAT_F_COMPLEX;
|
|
}
|
|
H5Tclose(type_id);
|
|
|
|
/* If the dataset is a cell array read the info of the cells */
|
|
if ( MAT_C_CELL == matvar->class_type ) {
|
|
matvar_t **cells;
|
|
hobj_ref_t *ref_ids;
|
|
|
|
matvar->data_size = sizeof(matvar_t**);
|
|
SafeMul(&matvar->nbytes, nelems, matvar->data_size);
|
|
matvar->data = malloc(matvar->nbytes);
|
|
cells = (matvar_t**)matvar->data;
|
|
|
|
if ( nelems ) {
|
|
size_t i;
|
|
ref_ids = (hobj_ref_t*)malloc(nelems*sizeof(*ref_ids));
|
|
H5Dread(dset_id,H5T_STD_REF_OBJ,H5S_ALL,H5S_ALL,H5P_DEFAULT,ref_ids);
|
|
for ( i = 0; i < nelems; i++ ) {
|
|
hid_t ref_id;
|
|
cells[i] = Mat_VarCalloc();
|
|
cells[i]->internal->hdf5_ref = ref_ids[i];
|
|
/* Closing of ref_id is done in Mat_H5ReadNextReferenceInfo */
|
|
ref_id = H5RDEREFERENCE(dset_id,H5R_OBJECT,ref_ids+i);
|
|
cells[i]->internal->id = ref_id;
|
|
Mat_H5ReadNextReferenceInfo(ref_id,cells[i],mat);
|
|
}
|
|
free(ref_ids);
|
|
}
|
|
} else if ( MAT_C_STRUCT == matvar->class_type ) {
|
|
/* Empty structures can be a dataset */
|
|
|
|
/* Check if the structure defines its fields in MATLAB_fields */
|
|
if ( H5Aexists_by_name(dset_id,".","MATLAB_fields",H5P_DEFAULT) ) {
|
|
hsize_t nfields;
|
|
Mat_H5ReadFieldNames(matvar, dset_id, &nfields);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
Mat_H5ReadGroupInfo(mat_t *mat,matvar_t *matvar,hid_t dset_id)
|
|
{
|
|
int fields_are_variables = 1;
|
|
hsize_t nfields=0,nelems;
|
|
hid_t attr_id,field_id;
|
|
matvar_t **fields;
|
|
H5O_type_t obj_type;
|
|
|
|
Mat_H5ReadVarInfo(matvar,dset_id);
|
|
|
|
/* Check if the variable is sparse */
|
|
if ( H5Aexists_by_name(dset_id,".","MATLAB_sparse",H5P_DEFAULT) ) {
|
|
hid_t sparse_dset_id;
|
|
unsigned nrows = 0;
|
|
|
|
attr_id = H5Aopen_by_name(dset_id,".","MATLAB_sparse",H5P_DEFAULT,H5P_DEFAULT);
|
|
H5Aread(attr_id,H5T_NATIVE_UINT,&nrows);
|
|
H5Aclose(attr_id);
|
|
|
|
matvar->class_type = MAT_C_SPARSE;
|
|
|
|
sparse_dset_id = H5Dopen(dset_id,"jc",H5P_DEFAULT);
|
|
matvar->dims = Mat_H5ReadDims(sparse_dset_id, &nelems, &matvar->rank);
|
|
H5Dclose(sparse_dset_id);
|
|
if ( NULL != matvar->dims ) {
|
|
if ( 1 == matvar->rank ) {
|
|
size_t* dims = (size_t*)realloc(matvar->dims, 2*sizeof(*matvar->dims));
|
|
if ( NULL != dims ) {
|
|
matvar->rank = 2;
|
|
matvar->dims = dims;
|
|
}
|
|
}
|
|
if ( 2 == matvar->rank ) {
|
|
matvar->dims[1] = matvar->dims[0] - 1;
|
|
matvar->dims[0] = nrows;
|
|
}
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
/* Test if dataset type is compound and if so if it's complex */
|
|
if ( H5Lexists(dset_id,"data",H5P_DEFAULT) ) {
|
|
hid_t type_id;
|
|
sparse_dset_id = H5Dopen(dset_id,"data",H5P_DEFAULT);
|
|
type_id = H5Dget_type(sparse_dset_id);
|
|
if ( H5T_COMPOUND == H5Tget_class(type_id) ) {
|
|
/* FIXME: Any more checks? */
|
|
matvar->isComplex = MAT_F_COMPLEX;
|
|
}
|
|
H5Tclose(type_id);
|
|
H5Dclose(sparse_dset_id);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* Check if the structure defines its fields in MATLAB_fields */
|
|
if ( H5Aexists_by_name(dset_id,".","MATLAB_fields",H5P_DEFAULT) ) {
|
|
Mat_H5ReadFieldNames(matvar, dset_id, &nfields);
|
|
} else {
|
|
H5G_info_t group_info;
|
|
matvar->internal->num_fields = 0;
|
|
H5Gget_info(dset_id, &group_info);
|
|
if ( group_info.nlinks > 0 ) {
|
|
struct ReadGroupInfoIterData group_data = {0, NULL};
|
|
herr_t herr;
|
|
|
|
/* First iteration to retrieve number of relevant links */
|
|
herr = H5Literate_by_name(dset_id, matvar->internal->hdf5_name, H5_INDEX_NAME,
|
|
H5_ITER_NATIVE, NULL, Mat_H5ReadGroupInfoIterate,
|
|
(void *)&group_data, H5P_DEFAULT);
|
|
if ( herr > 0 && group_data.nfields > 0 ) {
|
|
matvar->internal->fieldnames =
|
|
(char**)calloc((size_t)(group_data.nfields),sizeof(*matvar->internal->fieldnames));
|
|
group_data.nfields = 0;
|
|
group_data.matvar = matvar;
|
|
if ( matvar->internal->fieldnames != NULL ) {
|
|
/* Second iteration to fill fieldnames */
|
|
H5Literate_by_name(dset_id, matvar->internal->hdf5_name, H5_INDEX_NAME,
|
|
H5_ITER_NATIVE, NULL, Mat_H5ReadGroupInfoIterate,
|
|
(void *)&group_data, H5P_DEFAULT);
|
|
}
|
|
matvar->internal->num_fields = (unsigned)group_data.nfields;
|
|
nfields = group_data.nfields;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( nfields > 0 ) {
|
|
H5O_info_t object_info;
|
|
H5OGET_INFO_BY_NAME(dset_id, matvar->internal->fieldnames[0], &object_info, H5P_DEFAULT);
|
|
obj_type = object_info.type;
|
|
} else {
|
|
obj_type = H5O_TYPE_UNKNOWN;
|
|
}
|
|
if ( obj_type == H5O_TYPE_DATASET ) {
|
|
hid_t field_type_id;
|
|
field_id = H5Dopen(dset_id,matvar->internal->fieldnames[0],H5P_DEFAULT);
|
|
field_type_id = H5Dget_type(field_id);
|
|
if ( H5T_REFERENCE == H5Tget_class(field_type_id) ) {
|
|
/* Check if the field has the MATLAB_class attribute. If so, it
|
|
* means the structure is a scalar. Otherwise, the dimensions of
|
|
* the field dataset is the dimensions of the structure
|
|
*/
|
|
if ( H5Aexists_by_name(field_id,".","MATLAB_class",H5P_DEFAULT) ) {
|
|
matvar->rank = 2;
|
|
matvar->dims = (size_t*)malloc(2*sizeof(*matvar->dims));
|
|
if ( NULL != matvar->dims ) {
|
|
matvar->dims[0] = 1;
|
|
matvar->dims[1] = 1;
|
|
nelems = 1;
|
|
} else {
|
|
H5Tclose(field_type_id);
|
|
H5Dclose(field_id);
|
|
Mat_Critical("Error allocating memory for matvar->dims");
|
|
return;
|
|
}
|
|
} else {
|
|
matvar->dims = Mat_H5ReadDims(field_id, &nelems, &matvar->rank);
|
|
if ( NULL != matvar->dims ) {
|
|
fields_are_variables = 0;
|
|
} else {
|
|
H5Tclose(field_type_id);
|
|
H5Dclose(field_id);
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
/* Structure should be a scalar */
|
|
matvar->rank = 2;
|
|
matvar->dims = (size_t*)malloc(2*sizeof(*matvar->dims));
|
|
if ( NULL != matvar->dims ) {
|
|
matvar->dims[0] = 1;
|
|
matvar->dims[1] = 1;
|
|
nelems = 1;
|
|
} else {
|
|
H5Tclose(field_type_id);
|
|
H5Dclose(field_id);
|
|
Mat_Critical("Error allocating memory for matvar->dims");
|
|
return;
|
|
}
|
|
}
|
|
H5Tclose(field_type_id);
|
|
H5Dclose(field_id);
|
|
} else {
|
|
/* Structure should be a scalar */
|
|
matvar->rank = 2;
|
|
matvar->dims = (size_t*)malloc(2*sizeof(*matvar->dims));
|
|
if ( NULL != matvar->dims ) {
|
|
matvar->dims[0] = 1;
|
|
matvar->dims[1] = 1;
|
|
nelems = 1;
|
|
} else {
|
|
Mat_Critical("Error allocating memory for matvar->dims");
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( nelems < 1 || nfields < 1 )
|
|
return;
|
|
|
|
matvar->data_size = sizeof(*fields);
|
|
{
|
|
size_t nelems_x_nfields;
|
|
SafeMul(&nelems_x_nfields, nelems, nfields);
|
|
SafeMul(&matvar->nbytes, nelems_x_nfields, matvar->data_size);
|
|
}
|
|
fields = (matvar_t**)malloc(matvar->nbytes);
|
|
matvar->data = fields;
|
|
if ( NULL != fields ) {
|
|
int k;
|
|
for ( k = 0; k < nfields; k++ ) {
|
|
H5O_info_t object_info;
|
|
fields[k] = NULL;
|
|
H5OGET_INFO_BY_NAME(dset_id, matvar->internal->fieldnames[k], &object_info, H5P_DEFAULT);
|
|
if ( object_info.type == H5O_TYPE_DATASET ) {
|
|
field_id = H5Dopen(dset_id,matvar->internal->fieldnames[k],
|
|
H5P_DEFAULT);
|
|
if ( !fields_are_variables ) {
|
|
int l;
|
|
hobj_ref_t *ref_ids = (hobj_ref_t*)malloc((size_t)nelems*sizeof(*ref_ids));
|
|
H5Dread(field_id,H5T_STD_REF_OBJ,H5S_ALL,H5S_ALL,
|
|
H5P_DEFAULT,ref_ids);
|
|
for ( l = 0; l < nelems; l++ ) {
|
|
hid_t ref_id;
|
|
ssize_t name_len;
|
|
fields[l*nfields+k] = Mat_VarCalloc();
|
|
fields[l*nfields+k]->name =
|
|
strdup(matvar->internal->fieldnames[k]);
|
|
fields[l*nfields+k]->internal->hdf5_ref=ref_ids[l];
|
|
/* Get the HDF5 name of the variable */
|
|
name_len = H5Iget_name(field_id,NULL,0);
|
|
if ( name_len > 0 ) {
|
|
fields[l*nfields+k]->internal->hdf5_name =
|
|
(char*)malloc(name_len+1);
|
|
(void)H5Iget_name(field_id,
|
|
fields[l*nfields+k]->internal->hdf5_name,
|
|
name_len+1);
|
|
}
|
|
/* Closing of ref_id is done in Mat_H5ReadNextReferenceInfo */
|
|
ref_id = H5RDEREFERENCE(field_id,H5R_OBJECT,ref_ids+l);
|
|
fields[l*nfields+k]->internal->id = ref_id;
|
|
Mat_H5ReadNextReferenceInfo(ref_id,fields[l*nfields+k],mat);
|
|
}
|
|
free(ref_ids);
|
|
} else {
|
|
fields[k] = Mat_VarCalloc();
|
|
fields[k]->name = strdup(matvar->internal->fieldnames[k]);
|
|
Mat_H5ReadDatasetInfo(mat,fields[k],field_id);
|
|
}
|
|
H5Dclose(field_id);
|
|
} else if ( object_info.type == H5O_TYPE_GROUP ) {
|
|
field_id = H5Gopen(dset_id,matvar->internal->fieldnames[k],
|
|
H5P_DEFAULT);
|
|
if ( -1 < field_id ) {
|
|
fields[k] = Mat_VarCalloc();
|
|
fields[k]->name = strdup(matvar->internal->fieldnames[k]);
|
|
Mat_H5ReadGroupInfo(mat,fields[k],field_id);
|
|
H5Gclose(field_id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static herr_t
|
|
Mat_H5ReadGroupInfoIterate(hid_t dset_id, const char *name, const H5L_info_t *info, void *op_data)
|
|
{
|
|
matvar_t *matvar;
|
|
H5O_info_t object_info;
|
|
struct ReadGroupInfoIterData *group_data;
|
|
|
|
/* FIXME: follow symlinks, datatypes? */
|
|
|
|
H5OGET_INFO_BY_NAME(dset_id, name, &object_info, H5P_DEFAULT);
|
|
if ( H5O_TYPE_DATASET != object_info.type && H5O_TYPE_GROUP != object_info.type )
|
|
return 0;
|
|
|
|
group_data = (struct ReadGroupInfoIterData *)op_data;
|
|
if ( group_data == NULL )
|
|
return -1;
|
|
matvar = group_data->matvar;
|
|
|
|
switch ( object_info.type ) {
|
|
case H5O_TYPE_GROUP:
|
|
/* Check that this is not the /#refs# group */
|
|
if ( 0 == strcmp(name,"#refs#") )
|
|
return 0;
|
|
/* Fall through */
|
|
case H5O_TYPE_DATASET:
|
|
if ( matvar != NULL ) {
|
|
matvar->internal->fieldnames[group_data->nfields] = strdup(name);
|
|
}
|
|
group_data->nfields++;
|
|
break;
|
|
default:
|
|
/* Not possible to get here */
|
|
break;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void
|
|
Mat_H5ReadNextReferenceInfo(hid_t ref_id,matvar_t *matvar,mat_t *mat)
|
|
{
|
|
if( ref_id < 0 || matvar == NULL)
|
|
return;
|
|
|
|
switch ( H5Iget_type(ref_id) ) {
|
|
case H5I_DATASET:
|
|
Mat_H5ReadDatasetInfo(mat,matvar,ref_id);
|
|
if ( matvar->internal->id != ref_id ) {
|
|
/* Close dataset and increment count */
|
|
H5Dclose(ref_id);
|
|
}
|
|
|
|
/*H5Dclose(ref_id);*/
|
|
break;
|
|
|
|
case H5I_GROUP:
|
|
Mat_H5ReadGroupInfo(mat,matvar,ref_id);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void
|
|
Mat_H5ReadData(hid_t dset_id, hid_t h5_type, hid_t mem_space, hid_t dset_space, int isComplex, void *data)
|
|
{
|
|
if ( !isComplex ) {
|
|
H5Dread(dset_id,h5_type,mem_space,dset_space,H5P_DEFAULT,data);
|
|
} else {
|
|
mat_complex_split_t *complex_data = (mat_complex_split_t*)data;
|
|
hid_t h5_complex;
|
|
size_t h5_size = H5Tget_size(h5_type);
|
|
|
|
h5_complex = H5Tcreate(H5T_COMPOUND, h5_size);
|
|
H5Tinsert(h5_complex,"real",0,h5_type);
|
|
H5Dread(dset_id,h5_complex,mem_space,dset_space,H5P_DEFAULT,
|
|
complex_data->Re);
|
|
H5Tclose(h5_complex);
|
|
|
|
h5_complex = H5Tcreate(H5T_COMPOUND, h5_size);
|
|
H5Tinsert(h5_complex,"imag",0,h5_type);
|
|
H5Dread(dset_id,h5_complex,mem_space,dset_space,H5P_DEFAULT,
|
|
complex_data->Im);
|
|
H5Tclose(h5_complex);
|
|
}
|
|
}
|
|
|
|
static void
|
|
Mat_H5ReadNextReferenceData(hid_t ref_id,matvar_t *matvar,mat_t *mat)
|
|
{
|
|
size_t nelems = 1;
|
|
|
|
if ( ref_id < 0 || matvar == NULL )
|
|
return;
|
|
|
|
/* If the datatype with references is a cell, we've already read info into
|
|
* the variable data, so just loop over each cell element and call
|
|
* Mat_H5ReadNextReferenceData on it.
|
|
*/
|
|
if ( MAT_C_CELL == matvar->class_type ) {
|
|
size_t i;
|
|
matvar_t **cells = (matvar_t**)matvar->data;
|
|
SafeMulDims(matvar, &nelems);
|
|
for ( i = 0; i < nelems; i++ )
|
|
Mat_H5ReadNextReferenceData(cells[i]->internal->id,cells[i],mat);
|
|
return;
|
|
}
|
|
|
|
switch ( H5Iget_type(ref_id) ) {
|
|
case H5I_DATASET:
|
|
{
|
|
hid_t data_type_id, dset_id;
|
|
SafeMulDims(matvar, &nelems);
|
|
|
|
if ( MAT_C_CHAR == matvar->class_type ) {
|
|
matvar->data_type = MAT_T_UINT8;
|
|
matvar->data_size = Mat_SizeOf(MAT_T_UINT8);
|
|
data_type_id = DataType2H5T(MAT_T_UINT8);
|
|
} else if ( MAT_C_STRUCT == matvar->class_type ) {
|
|
/* Empty structure array */
|
|
break;
|
|
} else {
|
|
matvar->data_size = Mat_SizeOfClass(matvar->class_type);
|
|
data_type_id = ClassType2H5T(matvar->class_type);
|
|
}
|
|
SafeMul(&matvar->nbytes, nelems, matvar->data_size);
|
|
|
|
if ( matvar->nbytes < 1 ) {
|
|
H5Dclose(ref_id);
|
|
break;
|
|
}
|
|
|
|
dset_id = ref_id;
|
|
|
|
if ( !matvar->isComplex ) {
|
|
matvar->data = malloc(matvar->nbytes);
|
|
} else {
|
|
matvar->data = ComplexMalloc(matvar->nbytes);
|
|
}
|
|
if ( NULL != matvar->data ) {
|
|
Mat_H5ReadData(dset_id, data_type_id,
|
|
H5S_ALL, H5S_ALL, matvar->isComplex, matvar->data);
|
|
}
|
|
H5Dclose(dset_id);
|
|
break;
|
|
}
|
|
case H5I_GROUP:
|
|
{
|
|
if ( MAT_C_SPARSE == matvar->class_type ) {
|
|
Mat_VarRead73(mat,matvar);
|
|
} else {
|
|
matvar_t **fields;
|
|
size_t i;
|
|
|
|
if ( !matvar->nbytes || !matvar->data_size || NULL == matvar->data )
|
|
break;
|
|
nelems = matvar->nbytes / matvar->data_size;
|
|
fields = (matvar_t**)matvar->data;
|
|
for ( i = 0; i < nelems; i++ ) {
|
|
if ( 0 < fields[i]->internal->hdf5_ref &&
|
|
-1 < fields[i]->internal->id ) {
|
|
/* Dataset of references */
|
|
Mat_H5ReadNextReferenceData(fields[i]->internal->id,fields[i],mat);
|
|
} else {
|
|
Mat_VarRead73(mat,fields[i]);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static int
|
|
Mat_H5WriteData(hid_t dset_id, hid_t h5_type, hid_t mem_space, hid_t dset_space, int isComplex, void *data)
|
|
{
|
|
int err = 0;
|
|
|
|
if ( !isComplex ) {
|
|
if ( 0 > H5Dwrite(dset_id,h5_type,mem_space,dset_space,H5P_DEFAULT,data) )
|
|
err = 5;
|
|
} else {
|
|
mat_complex_split_t *complex_data = (mat_complex_split_t*)data;
|
|
hid_t h5_complex;
|
|
size_t h5_size = H5Tget_size(h5_type);
|
|
|
|
/* Write real part of dataset */
|
|
h5_complex = H5Tcreate(H5T_COMPOUND, h5_size);
|
|
H5Tinsert(h5_complex, "real", 0, h5_type);
|
|
err = Mat_H5WriteData(dset_id, h5_complex, mem_space, dset_space, 0, complex_data->Re);
|
|
H5Tclose(h5_complex);
|
|
|
|
/* Write imaginary part of dataset */
|
|
h5_complex = H5Tcreate(H5T_COMPOUND, h5_size);
|
|
H5Tinsert(h5_complex,"imag", 0, h5_type);
|
|
err += Mat_H5WriteData(dset_id, h5_complex, mem_space, dset_space, 0, complex_data->Im);
|
|
H5Tclose(h5_complex);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
Mat_H5WriteAppendData(hid_t id, hid_t h5_type, int mrank, const char *name, const size_t* mdims, hsize_t *dims, int dim, int isComplex, void* data)
|
|
{
|
|
int err = 0;
|
|
hid_t dset_id, space_id;
|
|
int rank;
|
|
|
|
if ( dim < 1 || dim > mrank )
|
|
return -2;
|
|
|
|
dset_id = H5Dopen(id, name, H5P_DEFAULT);
|
|
space_id = H5Dget_space(dset_id);
|
|
rank = H5Sget_simple_extent_ndims(space_id);
|
|
if ( rank == mrank ) {
|
|
hsize_t* size_offset_dims;
|
|
size_offset_dims = (hsize_t*)malloc(rank*sizeof(*size_offset_dims));
|
|
if ( NULL != size_offset_dims ) {
|
|
hsize_t offset;
|
|
hid_t mspace_id;
|
|
int k;
|
|
|
|
(void)H5Sget_simple_extent_dims(space_id,size_offset_dims,NULL);
|
|
offset = size_offset_dims[rank - dim];
|
|
size_offset_dims[rank - dim] += mdims[dim - 1];
|
|
H5Dset_extent(dset_id, size_offset_dims);
|
|
for ( k = 0; k < rank; k++ ) {
|
|
size_offset_dims[k] = 0;
|
|
}
|
|
size_offset_dims[rank - dim] = offset;
|
|
/* Need to reopen */
|
|
H5Sclose(space_id);
|
|
space_id = H5Dget_space(dset_id);
|
|
H5Sselect_hyperslab(space_id, H5S_SELECT_SET, size_offset_dims,
|
|
NULL, dims, NULL);
|
|
free(size_offset_dims);
|
|
mspace_id = H5Screate_simple(rank, dims, NULL);
|
|
err = Mat_H5WriteData(dset_id, h5_type, mspace_id, space_id, isComplex, data);
|
|
H5Sclose(mspace_id);
|
|
} else {
|
|
err = -3;
|
|
}
|
|
} else {
|
|
err = -4;
|
|
}
|
|
H5Sclose(space_id);
|
|
H5Dclose(dset_id);
|
|
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
Mat_VarWriteRef(hid_t id, matvar_t* matvar, enum matio_compression compression, hid_t *refs_id, hobj_ref_t* ref)
|
|
{
|
|
int err;
|
|
char obj_name[64];
|
|
H5G_info_t group_info;
|
|
|
|
H5Gget_info(*refs_id, &group_info);
|
|
sprintf(obj_name,"%llu", group_info.nlinks);
|
|
if ( NULL != matvar )
|
|
matvar->compression = compression;
|
|
err = Mat_VarWriteNext73(*refs_id, matvar, obj_name, refs_id);
|
|
sprintf(obj_name, "/#refs#/%llu", group_info.nlinks);
|
|
H5Rcreate(ref, id, obj_name, H5R_OBJECT, -1);
|
|
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
Mat_VarWriteEmpty(hid_t id,matvar_t *matvar,const char *name,const char* class_name)
|
|
{
|
|
int err = 0;
|
|
hsize_t rank = matvar->rank;
|
|
unsigned empty = 1;
|
|
hid_t mspace_id, dset_id, attr_type_id, aspace_id, attr_id;
|
|
|
|
mspace_id = H5Screate_simple(1,&rank,NULL);
|
|
dset_id = H5Dcreate(id,name,H5T_NATIVE_HSIZE,mspace_id,
|
|
H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT);
|
|
attr_type_id = H5Tcopy(H5T_C_S1);
|
|
H5Tset_size(attr_type_id, strlen(class_name));
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(dset_id,"MATLAB_class",attr_type_id,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id, attr_type_id, class_name) )
|
|
err = 5;
|
|
H5Sclose(aspace_id);
|
|
H5Aclose(attr_id);
|
|
H5Tclose(attr_type_id);
|
|
|
|
if ( 0 == strcmp(class_name, "struct") ) {
|
|
/* Write the fields attribute */
|
|
hsize_t nfields = matvar->internal->num_fields;
|
|
if ( nfields ) {
|
|
hvl_t *fieldnames = (hvl_t*)malloc((size_t)nfields*sizeof(*fieldnames));
|
|
if ( NULL != fieldnames ) {
|
|
hid_t str_type_id,fieldnames_id;
|
|
hsize_t k;
|
|
|
|
str_type_id = H5Tcopy(H5T_C_S1);
|
|
for ( k = 0; k < nfields; k++ ) {
|
|
fieldnames[k].len =
|
|
strlen(matvar->internal->fieldnames[k]);
|
|
fieldnames[k].p = matvar->internal->fieldnames[k];
|
|
}
|
|
H5Tset_size(str_type_id,1);
|
|
fieldnames_id = H5Tvlen_create(str_type_id);
|
|
aspace_id = H5Screate_simple(1,&nfields,NULL);
|
|
attr_id = H5Acreate(dset_id,"MATLAB_fields",fieldnames_id,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id,fieldnames_id,fieldnames) )
|
|
err += 5;
|
|
H5Aclose(attr_id);
|
|
H5Sclose(aspace_id);
|
|
H5Tclose(fieldnames_id);
|
|
H5Tclose(str_type_id);
|
|
free(fieldnames);
|
|
} else {
|
|
err = 1;
|
|
}
|
|
}
|
|
} else if ( 0 == strcmp(class_name, "logical") ) {
|
|
/* Write the MATLAB_int_decode attribute */
|
|
int int_decode = 1;
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(dset_id,"MATLAB_int_decode",H5T_NATIVE_INT,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id,H5T_NATIVE_INT,&int_decode) )
|
|
err += 5;
|
|
H5Sclose(aspace_id);
|
|
H5Aclose(attr_id);
|
|
}
|
|
|
|
/* Write the empty attribute */
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(dset_id,"MATLAB_empty",H5T_NATIVE_UINT,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id,H5T_NATIVE_UINT,&empty) )
|
|
err += 5;
|
|
H5Sclose(aspace_id);
|
|
H5Aclose(attr_id);
|
|
|
|
/* Write the dimensions as the data */
|
|
if ( 0 > H5Dwrite(dset_id,SizeType2H5T(),H5S_ALL,H5S_ALL,
|
|
H5P_DEFAULT,matvar->dims) )
|
|
err += 5;
|
|
H5Dclose(dset_id);
|
|
H5Sclose(mspace_id);
|
|
|
|
return err;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Writes a cell array matlab variable to the specified HDF id with the
|
|
* given name
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param id HDF id of the parent object
|
|
* @param matvar pointer to the cell array variable
|
|
* @param name Name of the HDF dataset
|
|
* @param refs_id pointer to the id of the /#refs# group in HDF5
|
|
* @param dims array of permuted dimensions
|
|
* @retval 0 on success
|
|
* @endif
|
|
*/
|
|
static int
|
|
Mat_VarWriteCell73(hid_t id,matvar_t *matvar,const char *name,hid_t *refs_id,hsize_t *dims)
|
|
{
|
|
int k;
|
|
hsize_t nelems = 1;
|
|
matvar_t **cells;
|
|
int err = 0;
|
|
|
|
cells = (matvar_t**)matvar->data;
|
|
for ( k = 0; k < matvar->rank; k++ )
|
|
nelems *= dims[k];
|
|
|
|
if ( 0 == nelems || NULL == matvar->data ) {
|
|
err = Mat_VarWriteEmpty(id, matvar, name, ClassNames[matvar->class_type]);
|
|
} else {
|
|
if ( *refs_id < 0 ) {
|
|
if ( H5Lexists(id,"/#refs#",H5P_DEFAULT) ) {
|
|
*refs_id = H5Gopen(id,"/#refs#",H5P_DEFAULT);
|
|
} else {
|
|
*refs_id = H5Gcreate(id,"/#refs#",H5P_DEFAULT,
|
|
H5P_DEFAULT,H5P_DEFAULT);
|
|
}
|
|
}
|
|
if ( *refs_id > -1 ) {
|
|
hobj_ref_t *refs;
|
|
hid_t str_type_id,mspace_id,dset_id,attr_id,aspace_id;
|
|
|
|
refs = (hobj_ref_t*)malloc((size_t)nelems*sizeof(*refs));
|
|
mspace_id = H5Screate_simple(matvar->rank,dims,NULL);
|
|
dset_id = H5Dcreate(id,name,H5T_STD_REF_OBJ,mspace_id,
|
|
H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT);
|
|
|
|
for ( k = 0; k < nelems; k++ ) {
|
|
err += Mat_VarWriteRef(id, cells[k], matvar->compression,
|
|
refs_id, refs+k);
|
|
}
|
|
err += Mat_H5WriteData(dset_id, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL,
|
|
0, refs);
|
|
|
|
str_type_id = H5Tcopy(H5T_C_S1);
|
|
H5Tset_size(str_type_id,4);
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(dset_id,"MATLAB_class",str_type_id,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id,str_type_id,"cell") )
|
|
err += 5;
|
|
H5Aclose(attr_id);
|
|
H5Sclose(aspace_id);
|
|
H5Tclose(str_type_id);
|
|
H5Dclose(dset_id);
|
|
free(refs);
|
|
H5Sclose(mspace_id);
|
|
} else {
|
|
err = -1;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Writes a character matlab variable to the specified HDF id with the
|
|
* given name
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param id HDF id of the parent object
|
|
* @param matvar pointer to the character variable
|
|
* @param name Name of the HDF dataset
|
|
* @param dims array of permuted dimensions
|
|
* @retval 0 on success
|
|
* @endif
|
|
*/
|
|
static int
|
|
Mat_VarWriteChar73(hid_t id,matvar_t *matvar,const char *name,hsize_t *dims)
|
|
{
|
|
int err = 0, k;
|
|
hsize_t nelems = 1;
|
|
|
|
for ( k = 0; k < matvar->rank; k++ ) {
|
|
nelems *= dims[k];
|
|
}
|
|
|
|
if ( 0 == nelems || NULL == matvar->data ) {
|
|
err = Mat_VarWriteEmpty(id, matvar, name, ClassNames[matvar->class_type]);
|
|
} else {
|
|
int matlab_int_decode = 2;
|
|
hid_t mspace_id,dset_id,attr_type_id,attr_id,aspace_id;
|
|
|
|
mspace_id = H5Screate_simple(matvar->rank,dims,NULL);
|
|
switch ( matvar->data_type ) {
|
|
case MAT_T_UTF32:
|
|
case MAT_T_INT32:
|
|
case MAT_T_UINT32:
|
|
/* Not sure matlab will actually handle this */
|
|
dset_id = H5Dcreate(id,name,
|
|
ClassType2H5T(MAT_C_UINT32),
|
|
mspace_id,H5P_DEFAULT,H5P_DEFAULT,
|
|
H5P_DEFAULT);
|
|
break;
|
|
case MAT_T_UTF16:
|
|
case MAT_T_UTF8:
|
|
case MAT_T_INT16:
|
|
case MAT_T_UINT16:
|
|
case MAT_T_INT8:
|
|
case MAT_T_UINT8:
|
|
dset_id = H5Dcreate(id,name,
|
|
ClassType2H5T(MAT_C_UINT16),
|
|
mspace_id,H5P_DEFAULT,H5P_DEFAULT,
|
|
H5P_DEFAULT);
|
|
break;
|
|
default:
|
|
H5Sclose(mspace_id);
|
|
return -1;
|
|
}
|
|
attr_type_id = H5Tcopy(H5T_C_S1);
|
|
H5Tset_size(attr_type_id, strlen(ClassNames[matvar->class_type]));
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(dset_id,"MATLAB_class",attr_type_id,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id,attr_type_id,ClassNames[matvar->class_type]) )
|
|
err = 5;
|
|
H5Aclose(attr_id);
|
|
H5Tclose(attr_type_id);
|
|
|
|
attr_type_id = H5Tcopy(H5T_NATIVE_INT);
|
|
attr_id = H5Acreate(dset_id,"MATLAB_int_decode",attr_type_id,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id,attr_type_id,&matlab_int_decode) )
|
|
err += 5;
|
|
H5Aclose(attr_id);
|
|
H5Tclose(attr_type_id);
|
|
H5Sclose(aspace_id);
|
|
|
|
if ( 0 > H5Dwrite(dset_id,DataType2H5T(matvar->data_type),
|
|
H5S_ALL,H5S_ALL,H5P_DEFAULT,matvar->data) )
|
|
err += 5;
|
|
H5Dclose(dset_id);
|
|
H5Sclose(mspace_id);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
Mat_WriteEmptyVariable73(hid_t id,const char *name,hsize_t rank,size_t *dims)
|
|
{
|
|
int err = 0;
|
|
unsigned empty = 1;
|
|
hid_t mspace_id,dset_id;
|
|
|
|
mspace_id = H5Screate_simple(1,&rank,NULL);
|
|
dset_id = H5Dcreate(id,name,H5T_NATIVE_HSIZE,mspace_id,
|
|
H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( dset_id > -1 ) {
|
|
hid_t attr_type_id,attr_id,aspace_id;
|
|
|
|
attr_type_id = H5Tcopy(H5T_C_S1);
|
|
H5Tset_size(attr_type_id,6);
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(dset_id,"MATLAB_class",attr_type_id,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id,attr_type_id,"double") )
|
|
err = 5;
|
|
H5Sclose(aspace_id);
|
|
H5Aclose(attr_id);
|
|
H5Tclose(attr_type_id);
|
|
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(dset_id,"MATLAB_empty",H5T_NATIVE_UINT,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id,H5T_NATIVE_UINT,&empty) )
|
|
err += 5;
|
|
H5Sclose(aspace_id);
|
|
H5Aclose(attr_id);
|
|
|
|
/* Write the dimensions as the data */
|
|
if ( 0 > H5Dwrite(dset_id,SizeType2H5T(),H5S_ALL,H5S_ALL,
|
|
H5P_DEFAULT,dims) )
|
|
err += 5;
|
|
H5Dclose(dset_id);
|
|
} else {
|
|
err = -1;
|
|
}
|
|
H5Sclose(mspace_id);
|
|
|
|
return err;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Writes a logical matlab variable to the specified HDF id with the
|
|
* given name
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param id HDF id of the parent object
|
|
* @param matvar pointer to the logical variable
|
|
* @param name Name of the HDF dataset
|
|
* @param dims array of permuted dimensions
|
|
* @retval 0 on success
|
|
* @endif
|
|
*/
|
|
static int
|
|
Mat_VarWriteLogical73(hid_t id,matvar_t *matvar,const char *name,hsize_t *dims)
|
|
{
|
|
int err = 0, k;
|
|
hsize_t nelems = 1;
|
|
hid_t plist;
|
|
|
|
for ( k = 0; k < matvar->rank; k++ ) {
|
|
nelems *= dims[k];
|
|
}
|
|
|
|
if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
plist = H5Pcreate(H5P_DATASET_CREATE);
|
|
if ( MAX_RANK >= matvar->rank ) {
|
|
hsize_t chunk_dims[MAX_RANK];
|
|
Mat_H5GetChunkSize(matvar->rank, dims, chunk_dims);
|
|
H5Pset_chunk(plist, matvar->rank, chunk_dims);
|
|
} else {
|
|
hsize_t *chunk_dims = (hsize_t*)malloc(matvar->rank*sizeof(hsize_t));
|
|
if ( NULL != chunk_dims ) {
|
|
Mat_H5GetChunkSize(matvar->rank, dims, chunk_dims);
|
|
H5Pset_chunk(plist, matvar->rank, chunk_dims);
|
|
free(chunk_dims);
|
|
} else {
|
|
H5Pclose(plist);
|
|
return -1;
|
|
}
|
|
}
|
|
H5Pset_deflate(plist, 9);
|
|
} else {
|
|
plist = H5P_DEFAULT;
|
|
}
|
|
|
|
if ( 0 == nelems || NULL == matvar->data ) {
|
|
err = Mat_VarWriteEmpty(id, matvar, name, "logical");
|
|
} else {
|
|
int int_decode = 1;
|
|
hid_t mspace_id,dset_id,attr_type_id,attr_id,aspace_id;
|
|
|
|
mspace_id = H5Screate_simple(matvar->rank,dims,NULL);
|
|
/* Note that MATLAB only recognizes uint8 as logical */
|
|
dset_id = H5Dcreate(id,name,
|
|
ClassType2H5T(MAT_C_UINT8),
|
|
mspace_id,H5P_DEFAULT,plist,H5P_DEFAULT);
|
|
attr_type_id = H5Tcopy(H5T_C_S1);
|
|
H5Tset_size(attr_type_id,7);
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(dset_id,"MATLAB_class",attr_type_id,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id,attr_type_id,"logical") )
|
|
err = 5;
|
|
H5Sclose(aspace_id);
|
|
H5Aclose(attr_id);
|
|
H5Tclose(attr_type_id);
|
|
/* Write the MATLAB_int_decode attribute */
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(dset_id,"MATLAB_int_decode",H5T_NATIVE_INT,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id,H5T_NATIVE_INT,&int_decode) )
|
|
err += 5;
|
|
H5Sclose(aspace_id);
|
|
H5Aclose(attr_id);
|
|
|
|
if ( 0 > H5Dwrite(dset_id,DataType2H5T(matvar->data_type),
|
|
H5S_ALL,H5S_ALL,H5P_DEFAULT,matvar->data) )
|
|
err += 5;
|
|
H5Dclose(dset_id);
|
|
H5Sclose(mspace_id);
|
|
}
|
|
|
|
if ( H5P_DEFAULT != plist )
|
|
H5Pclose(plist);
|
|
|
|
return err;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Writes a numeric matlab variable to the specified HDF id with the
|
|
* given name
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param id HDF id of the parent object
|
|
* @param matvar pointer to the numeric variable
|
|
* @param name Name of the HDF dataset
|
|
* @param dims array of permuted dimensions
|
|
* @param max_dims maximum dimensions
|
|
* @retval 0 on success
|
|
* @endif
|
|
*/
|
|
static int
|
|
Mat_VarWriteNumeric73(hid_t id,matvar_t *matvar,const char *name,hsize_t *dims,hsize_t* max_dims)
|
|
{
|
|
int err = 0, k;
|
|
hsize_t nelems = 1;
|
|
hid_t plist;
|
|
|
|
for ( k = 0; k < matvar->rank; k++ ) {
|
|
nelems *= dims[k];
|
|
}
|
|
|
|
if ( matvar->compression || NULL != max_dims ) {
|
|
plist = H5Pcreate(H5P_DATASET_CREATE);
|
|
if ( MAX_RANK >= matvar->rank ) {
|
|
hsize_t chunk_dims[MAX_RANK];
|
|
Mat_H5GetChunkSize(matvar->rank, dims, chunk_dims);
|
|
H5Pset_chunk(plist, matvar->rank, chunk_dims);
|
|
} else {
|
|
hsize_t *chunk_dims = (hsize_t*)malloc(matvar->rank*sizeof(hsize_t));
|
|
if ( NULL != chunk_dims ) {
|
|
Mat_H5GetChunkSize(matvar->rank, dims, chunk_dims);
|
|
H5Pset_chunk(plist, matvar->rank, chunk_dims);
|
|
free(chunk_dims);
|
|
} else {
|
|
H5Pclose(plist);
|
|
return -1;
|
|
}
|
|
}
|
|
if ( matvar->compression == MAT_COMPRESSION_ZLIB )
|
|
H5Pset_deflate(plist, 9);
|
|
} else {
|
|
plist = H5P_DEFAULT;
|
|
}
|
|
|
|
if ( 0 == nelems || NULL == matvar->data ) {
|
|
err = Mat_VarWriteEmpty(id, matvar, name, ClassNames[matvar->class_type]);
|
|
} else {
|
|
hid_t mspace_id,dset_id,attr_type_id,attr_id,aspace_id;
|
|
hid_t h5_type = ClassType2H5T(matvar->class_type);
|
|
hid_t h5_dtype = DataType(h5_type, matvar->isComplex);
|
|
|
|
mspace_id = H5Screate_simple(matvar->rank,dims,max_dims);
|
|
dset_id = H5Dcreate(id,name,h5_dtype,mspace_id,
|
|
H5P_DEFAULT,plist,H5P_DEFAULT);
|
|
attr_type_id = H5Tcopy(H5T_C_S1);
|
|
H5Tset_size(attr_type_id, strlen(ClassNames[matvar->class_type]));
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(dset_id,"MATLAB_class",attr_type_id,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id, attr_type_id, ClassNames[matvar->class_type]) )
|
|
err = 5;
|
|
H5Sclose(aspace_id);
|
|
H5Aclose(attr_id);
|
|
H5Tclose(attr_type_id);
|
|
H5Tclose(h5_dtype);
|
|
err += Mat_H5WriteData(dset_id, h5_type, H5S_ALL, H5S_ALL,
|
|
matvar->isComplex, matvar->data);
|
|
H5Dclose(dset_id);
|
|
H5Sclose(mspace_id);
|
|
}
|
|
|
|
if ( H5P_DEFAULT != plist )
|
|
H5Pclose(plist);
|
|
|
|
return err;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Writes/appends a numeric matlab variable to the specified HDF id with the
|
|
* given name
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param id HDF id of the parent object
|
|
* @param matvar pointer to the numeric variable
|
|
* @param name Name of the HDF dataset
|
|
* @param dims array of permuted dimensions
|
|
* @param dim dimension to append data
|
|
* @retval 0 on success
|
|
* @endif
|
|
*/
|
|
static int
|
|
Mat_VarWriteAppendNumeric73(hid_t id,matvar_t *matvar,const char *name,hsize_t *dims,int dim)
|
|
{
|
|
int err = 0, k;
|
|
hsize_t nelems = 1;
|
|
|
|
for ( k = 0; k < matvar->rank; k++ ) {
|
|
nelems *= dims[k];
|
|
}
|
|
|
|
if ( 0 != nelems && NULL != matvar->data ) {
|
|
if ( H5Lexists(id, matvar->name, H5P_DEFAULT) ) {
|
|
err = Mat_H5WriteAppendData(id, ClassType2H5T(matvar->class_type), matvar->rank,
|
|
matvar->name, matvar->dims, dims, dim, matvar->isComplex, matvar->data);
|
|
} else {
|
|
/* Create with unlimited number of dimensions */
|
|
if ( MAX_RANK >= matvar->rank ) {
|
|
hsize_t max_dims[MAX_RANK];
|
|
for ( k = 0; k < matvar->rank; k++ ) {
|
|
max_dims[k] = H5S_UNLIMITED;
|
|
}
|
|
err = Mat_VarWriteNumeric73(id, matvar, name, dims, max_dims);
|
|
} else {
|
|
hsize_t* max_dims = (hsize_t*)malloc(matvar->rank*sizeof(hsize_t));
|
|
if ( NULL != max_dims ) {
|
|
for ( k = 0; k < matvar->rank; k++ ) {
|
|
max_dims[k] = H5S_UNLIMITED;
|
|
}
|
|
err = Mat_VarWriteNumeric73(id, matvar, name, dims, max_dims);
|
|
free(max_dims);
|
|
} else {
|
|
err = -1;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
err = -1;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Writes a sparse matrix variable to the specified HDF id with the
|
|
* given name
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param id HDF id of the parent object
|
|
* @param matvar pointer to the structure variable
|
|
* @param name Name of the HDF dataset
|
|
* @retval 0 on success
|
|
* @endif
|
|
*/
|
|
static int
|
|
Mat_VarWriteSparse73(hid_t id,matvar_t *matvar,const char *name)
|
|
{
|
|
int err = 0;
|
|
hid_t sparse_id;
|
|
|
|
sparse_id = H5Gcreate(id,name,H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( sparse_id < 0 ) {
|
|
Mat_Critical("Error creating group for sparse array %s",
|
|
matvar->name);
|
|
err = -1;
|
|
} else {
|
|
hid_t size_type_id,h5_type,h5_dtype;
|
|
hid_t mspace_id,dset_id,attr_type_id,attr_id,aspace_id;
|
|
mat_sparse_t *sparse;
|
|
hsize_t nir, njc, ndata;
|
|
mat_uint64_t sparse_attr_value;
|
|
enum matio_classes class_type;
|
|
|
|
sparse = (mat_sparse_t*)matvar->data;
|
|
class_type = DataType2ClassType(matvar->data_type);
|
|
attr_type_id = H5Tcopy(H5T_C_S1);
|
|
H5Tset_size(attr_type_id,
|
|
matvar->isLogical ? 7 : strlen(ClassNames[class_type]));
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(sparse_id,"MATLAB_class",attr_type_id,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id, attr_type_id,
|
|
matvar->isLogical ? "logical" : ClassNames[class_type]) )
|
|
err = 5;
|
|
H5Sclose(aspace_id);
|
|
H5Aclose(attr_id);
|
|
H5Tclose(attr_type_id);
|
|
|
|
if ( matvar->isLogical ) {
|
|
/* Write the MATLAB_int_decode attribute */
|
|
int int_decode = 1;
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(sparse_id, "MATLAB_int_decode", H5T_NATIVE_INT,
|
|
aspace_id, H5P_DEFAULT, H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id, H5T_NATIVE_INT, &int_decode) )
|
|
err += 5;
|
|
H5Sclose(aspace_id);
|
|
H5Aclose(attr_id);
|
|
}
|
|
|
|
sparse_attr_value = matvar->dims[0];
|
|
size_type_id = ClassType2H5T(MAT_C_UINT64);
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(sparse_id,"MATLAB_sparse",size_type_id,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id,size_type_id,&sparse_attr_value) )
|
|
err += 5;
|
|
H5Sclose(aspace_id);
|
|
H5Aclose(attr_id);
|
|
|
|
ndata = sparse->ndata;
|
|
h5_type = DataType2H5T(matvar->data_type);
|
|
h5_dtype = DataType(h5_type, matvar->isComplex);
|
|
mspace_id = H5Screate_simple(1,&ndata,NULL);
|
|
dset_id = H5Dcreate(sparse_id,"data",h5_dtype,mspace_id,
|
|
H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT);
|
|
H5Tclose(h5_dtype);
|
|
err += Mat_H5WriteData(dset_id, h5_type, H5S_ALL, H5S_ALL,
|
|
matvar->isComplex, sparse->data);
|
|
H5Dclose(dset_id);
|
|
H5Sclose(mspace_id);
|
|
|
|
nir = sparse->nir;
|
|
mspace_id = H5Screate_simple(1,&nir,NULL);
|
|
dset_id = H5Dcreate(sparse_id,"ir",size_type_id,mspace_id,
|
|
H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT);
|
|
err += Mat_H5WriteData(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
|
|
0, sparse->ir);
|
|
H5Dclose(dset_id);
|
|
H5Sclose(mspace_id);
|
|
|
|
njc = sparse->njc;
|
|
mspace_id = H5Screate_simple(1,&njc,NULL);
|
|
dset_id = H5Dcreate(sparse_id,"jc",size_type_id,mspace_id,
|
|
H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT);
|
|
err += Mat_H5WriteData(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
|
|
0, sparse->jc);
|
|
H5Dclose(dset_id);
|
|
H5Sclose(mspace_id);
|
|
H5Gclose(sparse_id);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Writes a structure matlab variable to the specified HDF id with the
|
|
* given name
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param id HDF id of the parent object
|
|
* @param matvar pointer to the structure variable
|
|
* @param name Name of the HDF dataset
|
|
* @param refs_id pointer to the id of the /#refs# group in HDF5
|
|
* @param dims array of permuted dimensions
|
|
* @param max_dims maximum dimensions
|
|
* @retval 0 on success
|
|
* @endif
|
|
*/
|
|
static int
|
|
Mat_VarWriteStruct73(hid_t id,matvar_t *matvar,const char *name,hid_t *refs_id,hsize_t *dims,hsize_t* max_dims)
|
|
{
|
|
int err = 0, k;
|
|
hsize_t nelems;
|
|
|
|
{
|
|
size_t tmp = 1;
|
|
SafeMulDims(matvar, &tmp);
|
|
nelems = (hsize_t)tmp;
|
|
}
|
|
|
|
if ( 0 == nelems || NULL == matvar->data ) {
|
|
err = Mat_VarWriteEmpty(id, matvar, name, ClassNames[matvar->class_type]);
|
|
} else {
|
|
hid_t struct_id = H5Gcreate(id,name,H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( struct_id < 0 ) {
|
|
Mat_Critical("Error creating group for struct %s",name);
|
|
err = -1;
|
|
} else {
|
|
hid_t attr_id,aspace_id;
|
|
hid_t str_type_id,fieldnames_id;
|
|
matvar_t **fields = (matvar_t**)matvar->data;
|
|
hvl_t *fieldnames;
|
|
hsize_t nfields = matvar->internal->num_fields;
|
|
|
|
str_type_id = H5Tcopy(H5T_C_S1);
|
|
H5Tset_size(str_type_id,6);
|
|
aspace_id = H5Screate(H5S_SCALAR);
|
|
attr_id = H5Acreate(struct_id,"MATLAB_class",str_type_id,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id,str_type_id,"struct") )
|
|
err = 5;
|
|
H5Aclose(attr_id);
|
|
H5Sclose(aspace_id);
|
|
|
|
/* Structure with no fields */
|
|
if ( nfields == 0 ) {
|
|
H5Gclose(struct_id);
|
|
H5Tclose(str_type_id);
|
|
return err;
|
|
}
|
|
|
|
fieldnames = (hvl_t*)malloc((size_t)nfields*sizeof(*fieldnames));
|
|
for ( k = 0; k < nfields; k++ ) {
|
|
fieldnames[k].len =
|
|
strlen(matvar->internal->fieldnames[k]);
|
|
fieldnames[k].p = matvar->internal->fieldnames[k];
|
|
}
|
|
H5Tset_size(str_type_id,1);
|
|
fieldnames_id = H5Tvlen_create(str_type_id);
|
|
aspace_id = H5Screate_simple(1,&nfields,NULL);
|
|
attr_id = H5Acreate(struct_id,"MATLAB_fields",fieldnames_id,
|
|
aspace_id,H5P_DEFAULT,H5P_DEFAULT);
|
|
if ( 0 > H5Awrite(attr_id,fieldnames_id,fieldnames) )
|
|
err += 5;
|
|
H5Aclose(attr_id);
|
|
H5Sclose(aspace_id);
|
|
H5Tclose(fieldnames_id);
|
|
H5Tclose(str_type_id);
|
|
free(fieldnames);
|
|
|
|
if ( 1 == nelems && NULL == max_dims ) {
|
|
for ( k = 0; k < nfields; k++ ) {
|
|
if ( NULL != fields[k] )
|
|
fields[k]->compression = matvar->compression;
|
|
if ( 0 != Mat_VarWriteNext73(struct_id,fields[k],
|
|
matvar->internal->fieldnames[k],refs_id) )
|
|
err += 5;
|
|
}
|
|
} else {
|
|
if ( *refs_id < 0 ) {
|
|
if ( H5Lexists(id,"/#refs#",H5P_DEFAULT) ) {
|
|
*refs_id = H5Gopen(id,"/#refs#",H5P_DEFAULT);
|
|
} else {
|
|
*refs_id = H5Gcreate(id,"/#refs#",H5P_DEFAULT,
|
|
H5P_DEFAULT,H5P_DEFAULT);
|
|
}
|
|
}
|
|
if ( *refs_id > -1 ) {
|
|
hobj_ref_t **refs;
|
|
int l;
|
|
hid_t plist,mspace_id,dset_id;
|
|
|
|
refs = (hobj_ref_t**)malloc((size_t)nfields*sizeof(*refs));
|
|
for ( l = 0; l < nfields; l++ )
|
|
refs[l] = (hobj_ref_t*)malloc((size_t)nelems*sizeof(*refs[l]));
|
|
|
|
for ( k = 0; k < nelems; k++ ) {
|
|
for ( l = 0; l < nfields; l++ ) {
|
|
err += Mat_VarWriteRef(id, fields[k*nfields+l], matvar->compression,
|
|
refs_id, refs[l]+k);
|
|
}
|
|
}
|
|
|
|
if ( NULL != max_dims ) {
|
|
plist = H5Pcreate(H5P_DATASET_CREATE);
|
|
if ( MAX_RANK >= matvar->rank ) {
|
|
hsize_t chunk_dims[MAX_RANK];
|
|
Mat_H5GetChunkSize(matvar->rank, dims, chunk_dims);
|
|
H5Pset_chunk(plist, matvar->rank, chunk_dims);
|
|
} else {
|
|
hsize_t *chunk_dims = (hsize_t*)malloc(matvar->rank*sizeof(hsize_t));
|
|
if ( NULL != chunk_dims ) {
|
|
Mat_H5GetChunkSize(matvar->rank, dims, chunk_dims);
|
|
H5Pset_chunk(plist, matvar->rank, chunk_dims);
|
|
free(chunk_dims);
|
|
} else {
|
|
H5Pclose(plist);
|
|
plist = H5P_DEFAULT;
|
|
}
|
|
}
|
|
} else {
|
|
plist = H5P_DEFAULT;
|
|
}
|
|
|
|
mspace_id = H5Screate_simple(matvar->rank,dims,max_dims);
|
|
for ( l = 0; l < nfields; l++ ) {
|
|
dset_id = H5Dcreate(struct_id,
|
|
matvar->internal->fieldnames[l],
|
|
H5T_STD_REF_OBJ,mspace_id,
|
|
H5P_DEFAULT,plist,H5P_DEFAULT);
|
|
err += Mat_H5WriteData(dset_id, H5T_STD_REF_OBJ, H5S_ALL,
|
|
H5S_ALL, 0, refs[l]);
|
|
H5Dclose(dset_id);
|
|
free(refs[l]);
|
|
}
|
|
free(refs);
|
|
H5Sclose(mspace_id);
|
|
if ( H5P_DEFAULT != plist )
|
|
H5Pclose(plist);
|
|
} else {
|
|
err = -1;
|
|
}
|
|
}
|
|
H5Gclose(struct_id);
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
Mat_VarWriteAppendStruct73(hid_t id,matvar_t *matvar,const char *name,hid_t *refs_id,hsize_t *dims,int dim)
|
|
{
|
|
int err = 0, k;
|
|
hsize_t nelems = 1;
|
|
|
|
for ( k = 0; k < matvar->rank; k++ ) {
|
|
nelems *= dims[k];
|
|
}
|
|
|
|
if ( 0 != nelems && NULL != matvar->data ) {
|
|
if ( H5Lexists(id, name, H5P_DEFAULT) ) {
|
|
hid_t struct_id;
|
|
hobj_ref_t **refs;
|
|
int l;
|
|
hsize_t nfields = matvar->internal->num_fields;
|
|
matvar_t** fields = (matvar_t**)matvar->data;
|
|
|
|
if ( *refs_id <= -1 )
|
|
return -3;
|
|
|
|
refs = (hobj_ref_t**)malloc((size_t)nfields*sizeof(*refs));
|
|
for ( l = 0; l < nfields; l++ )
|
|
refs[l] = (hobj_ref_t*)malloc((size_t)nelems*sizeof(*refs[l]));
|
|
|
|
for ( k = 0; k < nelems; k++ ) {
|
|
for ( l = 0; l < nfields; l++ ) {
|
|
err += Mat_VarWriteRef(id, fields[k*nfields+l], matvar->compression,
|
|
refs_id, refs[l]+k);
|
|
}
|
|
}
|
|
|
|
struct_id = H5Gopen(id, name, H5P_DEFAULT);
|
|
for ( l = 0; l < nfields; l++ ) {
|
|
err += Mat_H5WriteAppendData(struct_id, H5T_STD_REF_OBJ, matvar->rank,
|
|
matvar->internal->fieldnames[l], matvar->dims, dims, dim, 0, refs[l]);
|
|
free(refs[l]);
|
|
}
|
|
free(refs);
|
|
H5Gclose(struct_id);
|
|
} else {
|
|
/* Create with unlimited number of dimensions */
|
|
if ( MAX_RANK >= matvar->rank ) {
|
|
hsize_t max_dims[MAX_RANK];
|
|
for ( k = 0; k < matvar->rank; k++ ) {
|
|
max_dims[k] = H5S_UNLIMITED;
|
|
}
|
|
err = Mat_VarWriteStruct73(id,matvar,name,refs_id,dims,max_dims);
|
|
} else {
|
|
hsize_t* max_dims = (hsize_t*)malloc(matvar->rank*sizeof(hsize_t));
|
|
if ( NULL != max_dims ) {
|
|
for ( k = 0; k < matvar->rank; k++ ) {
|
|
max_dims[k] = H5S_UNLIMITED;
|
|
}
|
|
err = Mat_VarWriteStruct73(id,matvar,name,refs_id,dims,max_dims);
|
|
free(max_dims);
|
|
} else {
|
|
err = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
Mat_VarWriteNext73(hid_t id,matvar_t *matvar,const char *name,hid_t *refs_id)
|
|
{
|
|
int err = -1;
|
|
|
|
if ( NULL == matvar ) {
|
|
size_t dims[2] = {0,0};
|
|
return Mat_WriteEmptyVariable73(id,name,2,dims);
|
|
}
|
|
|
|
if ( MAX_RANK >= matvar->rank ) {
|
|
hsize_t perm_dims[MAX_RANK];
|
|
err = Mat_VarWriteNextType73(id, matvar, name, refs_id, perm_dims);
|
|
} else {
|
|
hsize_t *perm_dims = (hsize_t*)malloc(matvar->rank*sizeof(hsize_t));
|
|
if ( NULL != perm_dims ) {
|
|
err = Mat_VarWriteNextType73(id, matvar, name, refs_id, perm_dims);
|
|
free(perm_dims);
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
Mat_VarWriteAppendNext73(hid_t id,matvar_t *matvar,const char *name,hid_t *refs_id,int dim)
|
|
{
|
|
int err = -1;
|
|
|
|
if ( MAX_RANK >= matvar->rank ) {
|
|
hsize_t perm_dims[MAX_RANK];
|
|
err = Mat_VarWriteAppendNextType73(id, matvar, name, refs_id, perm_dims, dim);
|
|
} else {
|
|
hsize_t *perm_dims = (hsize_t*)malloc(matvar->rank*sizeof(hsize_t));
|
|
if ( NULL != perm_dims ) {
|
|
err = Mat_VarWriteAppendNextType73(id, matvar, name, refs_id, perm_dims, dim);
|
|
free(perm_dims);
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
Mat_VarWriteNextType73(hid_t id,matvar_t *matvar,const char *name,hid_t *refs_id,hsize_t *dims)
|
|
{
|
|
int err = -1, k;
|
|
|
|
/* Permute dimensions */
|
|
for ( k = 0; k < matvar->rank; k++ ) {
|
|
dims[k] = matvar->dims[matvar->rank - k - 1];
|
|
}
|
|
|
|
if ( matvar->isLogical && matvar->class_type != MAT_C_SPARSE ) {
|
|
err = Mat_VarWriteLogical73(id,matvar,name,dims);
|
|
} else {
|
|
switch ( matvar->class_type ) {
|
|
case MAT_C_DOUBLE:
|
|
case MAT_C_SINGLE:
|
|
case MAT_C_INT64:
|
|
case MAT_C_UINT64:
|
|
case MAT_C_INT32:
|
|
case MAT_C_UINT32:
|
|
case MAT_C_INT16:
|
|
case MAT_C_UINT16:
|
|
case MAT_C_INT8:
|
|
case MAT_C_UINT8:
|
|
err = Mat_VarWriteNumeric73(id,matvar,name,dims,NULL);
|
|
break;
|
|
case MAT_C_CHAR:
|
|
err = Mat_VarWriteChar73(id,matvar,name,dims);
|
|
break;
|
|
case MAT_C_STRUCT:
|
|
err = Mat_VarWriteStruct73(id,matvar,name,refs_id,dims,NULL);
|
|
break;
|
|
case MAT_C_CELL:
|
|
err = Mat_VarWriteCell73(id,matvar,name,refs_id,dims);
|
|
break;
|
|
case MAT_C_SPARSE:
|
|
err = Mat_VarWriteSparse73(id,matvar,name);
|
|
break;
|
|
case MAT_C_EMPTY:
|
|
err = Mat_WriteEmptyVariable73(id,name,matvar->rank,matvar->dims);
|
|
break;
|
|
case MAT_C_FUNCTION:
|
|
case MAT_C_OBJECT:
|
|
case MAT_C_OPAQUE:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
Mat_VarWriteAppendNextType73(hid_t id,matvar_t *matvar,const char *name,hid_t *refs_id,hsize_t *dims,int dim)
|
|
{
|
|
int err = -1, k;
|
|
|
|
/* Permute dimensions */
|
|
for ( k = 0; k < matvar->rank; k++ ) {
|
|
dims[k] = matvar->dims[matvar->rank - k - 1];
|
|
}
|
|
|
|
if ( !matvar->isLogical ) {
|
|
switch ( matvar->class_type ) {
|
|
case MAT_C_DOUBLE:
|
|
case MAT_C_SINGLE:
|
|
case MAT_C_INT64:
|
|
case MAT_C_UINT64:
|
|
case MAT_C_INT32:
|
|
case MAT_C_UINT32:
|
|
case MAT_C_INT16:
|
|
case MAT_C_UINT16:
|
|
case MAT_C_INT8:
|
|
case MAT_C_UINT8:
|
|
err = Mat_VarWriteAppendNumeric73(id,matvar,name,dims,dim);
|
|
break;
|
|
case MAT_C_STRUCT:
|
|
err = Mat_VarWriteAppendStruct73(id,matvar,name,refs_id,dims,dim);
|
|
break;
|
|
case MAT_C_EMPTY:
|
|
case MAT_C_CHAR:
|
|
case MAT_C_CELL:
|
|
case MAT_C_SPARSE:
|
|
case MAT_C_FUNCTION:
|
|
case MAT_C_OBJECT:
|
|
case MAT_C_OPAQUE:
|
|
err = Mat_VarWriteNextType73(id,matvar,name,refs_id,dims);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Creates a new Matlab MAT version 7.3 file
|
|
*
|
|
* Tries to create a new Matlab MAT file with the given name and optional
|
|
* header string. If no header string is given, the default string
|
|
* is used containing the software, version, and date in it. If a header
|
|
* string is given, at most the first 116 characters is written to the file.
|
|
* The given header string need not be the full 116 characters, but MUST be
|
|
* NULL terminated.
|
|
* @ingroup mat_internal
|
|
* @param matname Name of MAT file to create
|
|
* @param hdr_str Optional header string, NULL to use default
|
|
* @return A pointer to the MAT file or NULL if it failed. This is not a
|
|
* simple FILE * and should not be used as one.
|
|
* @endif
|
|
*/
|
|
mat_t *
|
|
Mat_Create73(const char *matname,const char *hdr_str)
|
|
{
|
|
FILE *fp;
|
|
mat_int16_t endian = 0, version;
|
|
mat_t *mat = NULL;
|
|
size_t err;
|
|
time_t t;
|
|
hid_t plist_id,fid,plist_ap;
|
|
|
|
plist_id = H5Pcreate(H5P_FILE_CREATE);
|
|
H5Pset_userblock(plist_id,512);
|
|
plist_ap = H5Pcreate(H5P_FILE_ACCESS);
|
|
#if H5_VERSION_GE(1,10,2)
|
|
H5Pset_libver_bounds(plist_ap,H5F_LIBVER_EARLIEST,H5F_LIBVER_V18);
|
|
#endif
|
|
fid = H5Fcreate(matname,H5F_ACC_TRUNC,plist_id,plist_ap);
|
|
H5Fclose(fid);
|
|
H5Pclose(plist_id);
|
|
|
|
fp = fopen(matname,"r+b");
|
|
if ( !fp ) {
|
|
H5Pclose(plist_ap);
|
|
return NULL;
|
|
}
|
|
|
|
(void)fseek(fp,0,SEEK_SET);
|
|
|
|
mat = (mat_t*)malloc(sizeof(*mat));
|
|
if ( mat == NULL ) {
|
|
fclose(fp);
|
|
H5Pclose(plist_ap);
|
|
return NULL;
|
|
}
|
|
|
|
mat->fp = NULL;
|
|
mat->header = NULL;
|
|
mat->subsys_offset = NULL;
|
|
mat->filename = NULL;
|
|
mat->version = 0;
|
|
mat->byteswap = 0;
|
|
mat->mode = 0;
|
|
mat->bof = 128;
|
|
mat->next_index = 0;
|
|
mat->num_datasets = 0;
|
|
mat->refs_id = -1;
|
|
mat->dir = NULL;
|
|
|
|
t = time(NULL);
|
|
mat->filename = strdup_printf("%s",matname);
|
|
mat->mode = MAT_ACC_RDWR;
|
|
mat->byteswap = 0;
|
|
mat->header = (char*)malloc(128*sizeof(char));
|
|
mat->subsys_offset = (char*)malloc(8*sizeof(char));
|
|
memset(mat->header,' ',128);
|
|
if ( hdr_str == NULL ) {
|
|
err = mat_snprintf(mat->header,116,"MATLAB 7.3 MAT-file, Platform: %s, "
|
|
"Created by: libmatio v%d.%d.%d on %s HDF5 schema 0.5",
|
|
MATIO_PLATFORM, MATIO_MAJOR_VERSION, MATIO_MINOR_VERSION,
|
|
MATIO_RELEASE_LEVEL, ctime(&t));
|
|
} else {
|
|
err = mat_snprintf(mat->header,116,"%s",hdr_str);
|
|
}
|
|
if ( err >= 116 )
|
|
mat->header[115] = '\0'; /* Just to make sure it's NULL terminated */
|
|
memset(mat->subsys_offset,' ',8);
|
|
mat->version = (int)0x0200;
|
|
endian = 0x4d49;
|
|
|
|
version = 0x0200;
|
|
|
|
fwrite(mat->header,1,116,fp);
|
|
fwrite(mat->subsys_offset,1,8,fp);
|
|
fwrite(&version,2,1,fp);
|
|
fwrite(&endian,2,1,fp);
|
|
|
|
fclose(fp);
|
|
|
|
fid = H5Fopen(matname,H5F_ACC_RDWR,plist_ap);
|
|
H5Pclose(plist_ap);
|
|
|
|
mat->fp = malloc(sizeof(hid_t));
|
|
*(hid_t*)mat->fp = fid;
|
|
|
|
return mat;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Reads the MAT variable identified by matvar
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar MAT variable pointer
|
|
* @endif
|
|
*/
|
|
void
|
|
Mat_VarRead73(mat_t *mat,matvar_t *matvar)
|
|
{
|
|
hid_t fid,dset_id,ref_id;
|
|
|
|
if ( NULL == mat || NULL == matvar )
|
|
return;
|
|
else if ( NULL == matvar->internal->hdf5_name && 0 > matvar->internal->id )
|
|
return;
|
|
|
|
fid = *(hid_t*)mat->fp;
|
|
|
|
switch ( matvar->class_type ) {
|
|
case MAT_C_DOUBLE:
|
|
case MAT_C_SINGLE:
|
|
case MAT_C_INT64:
|
|
case MAT_C_UINT64:
|
|
case MAT_C_INT32:
|
|
case MAT_C_UINT32:
|
|
case MAT_C_INT16:
|
|
case MAT_C_UINT16:
|
|
case MAT_C_INT8:
|
|
case MAT_C_UINT8:
|
|
{
|
|
size_t nelems = 1;
|
|
SafeMulDims(matvar, &nelems);
|
|
matvar->data_size = Mat_SizeOfClass(matvar->class_type);
|
|
SafeMul(&matvar->nbytes, nelems, matvar->data_size);
|
|
|
|
if ( nelems < 1 )
|
|
break;
|
|
|
|
if ( NULL != matvar->internal->hdf5_name ) {
|
|
ref_id = H5Dopen(fid,matvar->internal->hdf5_name,H5P_DEFAULT);
|
|
} else {
|
|
ref_id = matvar->internal->id;
|
|
H5Iinc_ref(ref_id);
|
|
}
|
|
if ( 0 < matvar->internal->hdf5_ref ) {
|
|
dset_id = H5RDEREFERENCE(ref_id,H5R_OBJECT,&matvar->internal->hdf5_ref);
|
|
} else {
|
|
dset_id = ref_id;
|
|
H5Iinc_ref(dset_id);
|
|
}
|
|
|
|
if ( !matvar->isComplex ) {
|
|
matvar->data = malloc(matvar->nbytes);
|
|
} else {
|
|
matvar->data = ComplexMalloc(matvar->nbytes);
|
|
}
|
|
if ( NULL != matvar->data ) {
|
|
Mat_H5ReadData(dset_id, ClassType2H5T(matvar->class_type),
|
|
H5S_ALL, H5S_ALL, matvar->isComplex, matvar->data);
|
|
}
|
|
H5Dclose(dset_id);
|
|
H5Dclose(ref_id);
|
|
break;
|
|
}
|
|
case MAT_C_CHAR:
|
|
{
|
|
size_t nelems = 1;
|
|
SafeMulDims(matvar, &nelems);
|
|
matvar->data_size = Mat_SizeOf(matvar->data_type);
|
|
SafeMul(&matvar->nbytes, nelems, matvar->data_size);
|
|
|
|
if ( NULL != matvar->internal->hdf5_name ) {
|
|
dset_id = H5Dopen(fid,matvar->internal->hdf5_name,H5P_DEFAULT);
|
|
} else {
|
|
dset_id = matvar->internal->id;
|
|
H5Iinc_ref(dset_id);
|
|
}
|
|
if ( matvar->nbytes > 0 ) {
|
|
matvar->data = malloc(matvar->nbytes);
|
|
if ( NULL != matvar->data ) {
|
|
H5Dread(dset_id,DataType2H5T(matvar->data_type),
|
|
H5S_ALL,H5S_ALL,H5P_DEFAULT,matvar->data);
|
|
}
|
|
}
|
|
H5Dclose(dset_id);
|
|
break;
|
|
}
|
|
case MAT_C_STRUCT:
|
|
{
|
|
matvar_t **fields;
|
|
size_t i, nelems_x_nfields, nelems = 1;
|
|
|
|
if ( !matvar->internal->num_fields || NULL == matvar->data )
|
|
break;
|
|
SafeMulDims(matvar, &nelems);
|
|
SafeMul(&nelems_x_nfields, nelems, matvar->internal->num_fields);
|
|
fields = (matvar_t**)matvar->data;
|
|
for ( i = 0; i < nelems_x_nfields; i++ ) {
|
|
if ( 0 < fields[i]->internal->hdf5_ref &&
|
|
-1 < fields[i]->internal->id ) {
|
|
/* Dataset of references */
|
|
Mat_H5ReadNextReferenceData(fields[i]->internal->id,fields[i],mat);
|
|
} else {
|
|
Mat_VarRead73(mat,fields[i]);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case MAT_C_CELL:
|
|
{
|
|
matvar_t **cells;
|
|
size_t i, nelems = 0;
|
|
|
|
nelems = matvar->nbytes / matvar->data_size;
|
|
cells = (matvar_t**)matvar->data;
|
|
|
|
for ( i = 0; i < nelems; i++ )
|
|
Mat_H5ReadNextReferenceData(cells[i]->internal->id,cells[i],mat);
|
|
break;
|
|
}
|
|
case MAT_C_SPARSE:
|
|
{
|
|
hid_t sparse_dset_id;
|
|
mat_sparse_t *sparse_data = (mat_sparse_t *)calloc(1,
|
|
sizeof(*sparse_data));
|
|
|
|
if ( NULL != matvar->internal->hdf5_name ) {
|
|
dset_id = H5Gopen(fid,matvar->internal->hdf5_name,H5P_DEFAULT);
|
|
} else {
|
|
dset_id = matvar->internal->id;
|
|
H5Iinc_ref(dset_id);
|
|
}
|
|
|
|
if ( H5Lexists(dset_id,"ir",H5P_DEFAULT) ) {
|
|
size_t *dims;
|
|
hsize_t nelems;
|
|
int rank;
|
|
|
|
sparse_dset_id = H5Dopen(dset_id,"ir",H5P_DEFAULT);
|
|
dims = Mat_H5ReadDims(sparse_dset_id, &nelems, &rank);
|
|
if ( NULL != dims ) {
|
|
sparse_data->nir = dims[0];
|
|
free(dims);
|
|
sparse_data->ir = (int*)malloc(sparse_data->nir*
|
|
sizeof(*sparse_data->ir));
|
|
H5Dread(sparse_dset_id,H5T_NATIVE_INT,
|
|
H5S_ALL,H5S_ALL,H5P_DEFAULT,sparse_data->ir);
|
|
}
|
|
H5Dclose(sparse_dset_id);
|
|
}
|
|
|
|
if ( H5Lexists(dset_id,"jc",H5P_DEFAULT) ) {
|
|
size_t *dims;
|
|
hsize_t nelems;
|
|
int rank;
|
|
|
|
sparse_dset_id = H5Dopen(dset_id,"jc",H5P_DEFAULT);
|
|
dims = Mat_H5ReadDims(sparse_dset_id, &nelems, &rank);
|
|
if ( NULL != dims ) {
|
|
sparse_data->njc = dims[0];
|
|
free(dims);
|
|
sparse_data->jc = (int*)malloc(sparse_data->njc*
|
|
sizeof(*sparse_data->jc));
|
|
H5Dread(sparse_dset_id,H5T_NATIVE_INT,
|
|
H5S_ALL,H5S_ALL,H5P_DEFAULT,sparse_data->jc);
|
|
}
|
|
H5Dclose(sparse_dset_id);
|
|
}
|
|
|
|
if ( H5Lexists(dset_id,"data",H5P_DEFAULT) ) {
|
|
size_t *dims;
|
|
hsize_t nelems;
|
|
int rank;
|
|
|
|
sparse_dset_id = H5Dopen(dset_id,"data",H5P_DEFAULT);
|
|
dims = Mat_H5ReadDims(sparse_dset_id, &nelems, &rank);
|
|
if ( NULL != dims ) {
|
|
size_t ndata_bytes;
|
|
sparse_data->nzmax = dims[0];
|
|
sparse_data->ndata = dims[0];
|
|
free(dims);
|
|
matvar->data_size = sizeof(mat_sparse_t);
|
|
matvar->nbytes = matvar->data_size;
|
|
|
|
ndata_bytes = sparse_data->nzmax*Mat_SizeOf(matvar->data_type);
|
|
if ( !matvar->isComplex ) {
|
|
sparse_data->data = malloc(ndata_bytes);
|
|
} else {
|
|
sparse_data->data = ComplexMalloc(ndata_bytes);
|
|
}
|
|
if ( NULL != sparse_data->data ) {
|
|
Mat_H5ReadData(sparse_dset_id, DataType2H5T(matvar->data_type),
|
|
H5S_ALL, H5S_ALL, matvar->isComplex, sparse_data->data);
|
|
}
|
|
}
|
|
H5Dclose(sparse_dset_id);
|
|
}
|
|
H5Gclose(dset_id);
|
|
matvar->data = sparse_data;
|
|
break;
|
|
}
|
|
case MAT_C_EMPTY:
|
|
case MAT_C_FUNCTION:
|
|
case MAT_C_OBJECT:
|
|
case MAT_C_OPAQUE:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Reads a slab of data from the mat variable @c matvar
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar pointer to the mat variable
|
|
* @param data pointer to store the read data in (must be of size
|
|
* edge[0]*...edge[rank-1]*Mat_SizeOfClass(matvar->class_type))
|
|
* @param start index to start reading data in each dimension
|
|
* @param stride write data every @c stride elements in each dimension
|
|
* @param edge number of elements to read in each dimension
|
|
* @retval 0 on success
|
|
* @endif
|
|
*/
|
|
int
|
|
Mat_VarReadData73(mat_t *mat,matvar_t *matvar,void *data,
|
|
int *start,int *stride,int *edge)
|
|
{
|
|
int err = -1, k;
|
|
hid_t fid,dset_id,ref_id,dset_space,mem_space;
|
|
hsize_t *dset_start_stride_edge;
|
|
hsize_t *dset_start, *dset_stride, *dset_edge;
|
|
|
|
if ( NULL == mat || NULL == matvar || NULL == data || NULL == start ||
|
|
NULL == stride || NULL == edge )
|
|
return err;
|
|
else if ( NULL == matvar->internal->hdf5_name && 0 > matvar->internal->id )
|
|
return err;
|
|
|
|
fid = *(hid_t*)mat->fp;
|
|
|
|
dset_start_stride_edge = (hsize_t*)malloc(matvar->rank*3*sizeof(hsize_t));
|
|
if ( NULL == dset_start_stride_edge ) {
|
|
return err;
|
|
}
|
|
dset_start = &dset_start_stride_edge[0];
|
|
dset_stride = &dset_start_stride_edge[matvar->rank];
|
|
dset_edge = &dset_start_stride_edge[2*matvar->rank];
|
|
|
|
for ( k = 0; k < matvar->rank; k++ ) {
|
|
dset_start[k] = start[matvar->rank-k-1];
|
|
dset_stride[k] = stride[matvar->rank-k-1];
|
|
dset_edge[k] = edge[matvar->rank-k-1];
|
|
}
|
|
mem_space = H5Screate_simple(matvar->rank, dset_edge, NULL);
|
|
|
|
switch ( matvar->class_type ) {
|
|
case MAT_C_DOUBLE:
|
|
case MAT_C_SINGLE:
|
|
case MAT_C_INT64:
|
|
case MAT_C_UINT64:
|
|
case MAT_C_INT32:
|
|
case MAT_C_UINT32:
|
|
case MAT_C_INT16:
|
|
case MAT_C_UINT16:
|
|
case MAT_C_INT8:
|
|
case MAT_C_UINT8:
|
|
if ( NULL != matvar->internal->hdf5_name ) {
|
|
ref_id = H5Dopen(fid,matvar->internal->hdf5_name,H5P_DEFAULT);
|
|
} else {
|
|
ref_id = matvar->internal->id;
|
|
H5Iinc_ref(ref_id);
|
|
}
|
|
if ( 0 < matvar->internal->hdf5_ref ) {
|
|
dset_id = H5RDEREFERENCE(ref_id,H5R_OBJECT,&matvar->internal->hdf5_ref);
|
|
} else {
|
|
dset_id = ref_id;
|
|
H5Iinc_ref(dset_id);
|
|
}
|
|
|
|
dset_space = H5Dget_space(dset_id);
|
|
H5Sselect_hyperslab(dset_space, H5S_SELECT_SET, dset_start,
|
|
dset_stride, dset_edge, NULL);
|
|
Mat_H5ReadData(dset_id, ClassType2H5T(matvar->class_type), mem_space,
|
|
dset_space, matvar->isComplex, data);
|
|
H5Sclose(dset_space);
|
|
H5Dclose(dset_id);
|
|
H5Dclose(ref_id);
|
|
err = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
H5Sclose(mem_space);
|
|
free(dset_start_stride_edge);
|
|
|
|
return err;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Reads a subset of a MAT variable using a 1-D indexing
|
|
*
|
|
* Reads data from a MAT variable using a linear (1-D) indexing mode. The
|
|
* variable must have been read by Mat_VarReadInfo.
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar pointer to the mat variable
|
|
* @param data pointer to store the read data in (must be of size
|
|
* edge*Mat_SizeOfClass(matvar->class_type))
|
|
* @param start starting index
|
|
* @param stride stride of data
|
|
* @param edge number of elements to read
|
|
* @retval 0 on success
|
|
* @endif
|
|
*/
|
|
int
|
|
Mat_VarReadDataLinear73(mat_t *mat,matvar_t *matvar,void *data,
|
|
int start,int stride,int edge)
|
|
{
|
|
int err = -1, k;
|
|
hid_t fid,dset_id,dset_space,mem_space;
|
|
hsize_t *points, dset_edge, *dimp;
|
|
|
|
if ( NULL == mat || NULL == matvar || NULL == data )
|
|
return err;
|
|
else if ( NULL == matvar->internal->hdf5_name && 0 > matvar->internal->id )
|
|
return err;
|
|
|
|
fid = *(hid_t*)mat->fp;
|
|
|
|
dset_edge = edge;
|
|
mem_space = H5Screate_simple(1, &dset_edge, NULL);
|
|
|
|
switch ( matvar->class_type ) {
|
|
case MAT_C_DOUBLE:
|
|
case MAT_C_SINGLE:
|
|
case MAT_C_INT64:
|
|
case MAT_C_UINT64:
|
|
case MAT_C_INT32:
|
|
case MAT_C_UINT32:
|
|
case MAT_C_INT16:
|
|
case MAT_C_UINT16:
|
|
case MAT_C_INT8:
|
|
case MAT_C_UINT8:
|
|
points = (hsize_t*)malloc(matvar->rank*(size_t)dset_edge*sizeof(*points));
|
|
if ( NULL == points ) {
|
|
err = -2;
|
|
break;
|
|
}
|
|
dimp = (hsize_t*)malloc(matvar->rank*sizeof(hsize_t));
|
|
if ( NULL == dimp ) {
|
|
err = -2;
|
|
free(points);
|
|
break;
|
|
}
|
|
dimp[0] = 1;
|
|
for ( k = 1; k < matvar->rank; k++ )
|
|
dimp[k] = dimp[k-1]*matvar->dims[k-1];
|
|
for ( k = 0; k < edge; k++ ) {
|
|
size_t l, coord;
|
|
coord = (size_t)(start + k*stride);
|
|
for ( l = matvar->rank; l--; ) {
|
|
size_t idx = (size_t)(coord / dimp[l]);
|
|
points[matvar->rank*(k+1)-1-l] = idx;
|
|
coord -= idx*(size_t)dimp[l];
|
|
}
|
|
}
|
|
free(dimp);
|
|
|
|
if ( NULL != matvar->internal->hdf5_name ) {
|
|
dset_id = H5Dopen(fid,matvar->internal->hdf5_name,H5P_DEFAULT);
|
|
} else {
|
|
dset_id = matvar->internal->id;
|
|
H5Iinc_ref(dset_id);
|
|
}
|
|
dset_space = H5Dget_space(dset_id);
|
|
H5Sselect_elements(dset_space,H5S_SELECT_SET,(size_t)dset_edge,points);
|
|
free(points);
|
|
Mat_H5ReadData(dset_id, ClassType2H5T(matvar->class_type), mem_space,
|
|
dset_space, matvar->isComplex, data);
|
|
H5Sclose(dset_space);
|
|
H5Dclose(dset_id);
|
|
err = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
H5Sclose(mem_space);
|
|
|
|
return err;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Reads the header information for the next MAT variable
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @return pointer to the MAT variable or NULL
|
|
* @endif
|
|
*/
|
|
matvar_t *
|
|
Mat_VarReadNextInfo73( mat_t *mat )
|
|
{
|
|
hid_t id;
|
|
hsize_t idx;
|
|
herr_t herr;
|
|
struct ReadNextIterData mat_data;
|
|
|
|
if ( mat == NULL )
|
|
return NULL;
|
|
|
|
if ( mat->next_index >= mat->num_datasets )
|
|
return NULL;
|
|
|
|
id = *(hid_t*)mat->fp;
|
|
idx = (hsize_t)mat->next_index;
|
|
mat_data.mat = mat;
|
|
mat_data.matvar = NULL;
|
|
herr = H5Literate(id, H5_INDEX_NAME, H5_ITER_NATIVE, &idx, Mat_VarReadNextInfoIterate, (void*)&mat_data);
|
|
if ( herr > 0 )
|
|
mat->next_index = (size_t)idx;
|
|
return mat_data.matvar;
|
|
}
|
|
|
|
static herr_t
|
|
Mat_VarReadNextInfoIterate(hid_t id, const char *name, const H5L_info_t *info, void *op_data)
|
|
{
|
|
mat_t *mat;
|
|
matvar_t *matvar;
|
|
H5O_info_t object_info;
|
|
struct ReadNextIterData *mat_data;
|
|
|
|
/* FIXME: follow symlinks, datatypes? */
|
|
|
|
/* Check that this is not the /#refs# or /"#subsystem#" group */
|
|
if ( 0 == strcmp(name, "#refs#") || 0 == strcmp(name, "#subsystem#") )
|
|
return 0;
|
|
|
|
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;
|
|
|
|
mat_data = (struct ReadNextIterData *)op_data;
|
|
if ( NULL == mat_data )
|
|
return -1;
|
|
mat = mat_data->mat;
|
|
|
|
matvar = Mat_VarCalloc();
|
|
if ( NULL == matvar )
|
|
return -1;
|
|
|
|
matvar->name = strdup(name);
|
|
if ( NULL == matvar->name ) {
|
|
Mat_VarFree(matvar);
|
|
return -1;
|
|
}
|
|
|
|
switch ( object_info.type ) {
|
|
case H5O_TYPE_DATASET:
|
|
{
|
|
hid_t dset_id = H5Dopen(id,matvar->name,H5P_DEFAULT);
|
|
|
|
Mat_H5ReadDatasetInfo(mat,matvar,dset_id);
|
|
if ( matvar->internal->id != dset_id ) {
|
|
/* Close dataset and increment count */
|
|
H5Dclose(dset_id);
|
|
}
|
|
mat_data->matvar = matvar;
|
|
break;
|
|
}
|
|
case H5O_TYPE_GROUP:
|
|
{
|
|
hid_t dset_id = H5Gopen(id,matvar->name,H5P_DEFAULT);
|
|
|
|
Mat_H5ReadGroupInfo(mat,matvar,dset_id);
|
|
H5Gclose(dset_id);
|
|
mat_data->matvar = matvar;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Writes a matlab variable to a version 7.3 matlab file
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar pointer to the mat variable
|
|
* @param compress option to compress the variable
|
|
* (only works for numeric types)
|
|
* @retval 0 on success
|
|
* @endif
|
|
*/
|
|
int
|
|
Mat_VarWrite73(mat_t *mat,matvar_t *matvar,int compress)
|
|
{
|
|
hid_t id;
|
|
|
|
if ( NULL == mat || NULL == matvar )
|
|
return -1;
|
|
|
|
matvar->compression = (enum matio_compression)compress;
|
|
|
|
id = *(hid_t*)mat->fp;
|
|
return Mat_VarWriteNext73(id,matvar,matvar->name,&(mat->refs_id));
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Writes/appends a matlab variable to a version 7.3 matlab file
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar pointer to the mat variable
|
|
* @param compress option to compress the variable
|
|
* (only works for numeric types)
|
|
* @param dim dimension to append data
|
|
* (only works for numeric types)
|
|
* @retval 0 on success
|
|
* @endif
|
|
*/
|
|
int
|
|
Mat_VarWriteAppend73(mat_t *mat,matvar_t *matvar,int compress,int dim)
|
|
{
|
|
hid_t id;
|
|
|
|
if ( NULL == mat || NULL == matvar )
|
|
return -1;
|
|
|
|
matvar->compression = (enum matio_compression)compress;
|
|
|
|
id = *(hid_t*)mat->fp;
|
|
return Mat_VarWriteAppendNext73(id,matvar,matvar->name,&(mat->refs_id),dim);
|
|
}
|
|
|
|
#endif
|
|
#endif
|