/** @brief Finds a field of a structure by the field's index * * Returns a pointer to the structure field at the given 0-relative index. * @ingroup MAT * @param matvar Pointer to the Structure MAT variable * @param field_index 0-relative index of the field. * @param index linear index of the structure array * @return Pointer to the structure field on success, NULL on error */ matvar_t * Mat_VarGetStructFieldByIndex(matvar_t *matvar,size_t field_index,size_t index) { int i, nfields; matvar_t *field = NULL; size_t nmemb = 1; if ( matvar == NULL || matvar->class_type != MAT_C_STRUCT || matvar->data_size == 0 ) return field; nmemb = 1; for ( i = 0; i < matvar->rank; i++ ) nmemb *= matvar->dims[i]; nfields = matvar->internal->num_fields; if ( nmemb > 0 && index >= nmemb ) { Mat_Critical("Mat_VarGetStructField: structure index out of bounds"); } else if ( nfields > 0 ) { if ( field_index > nfields ) { Mat_Critical("Mat_VarGetStructField: field index out of bounds"); } else { field = *((matvar_t **)matvar->data+index*nfields+field_index); } } return field; }
/** @brief Inflates the data * * buf must hold at least @c nBytes bytes * @ingroup mat_internal * @param mat Pointer to the MAT file * @param z zlib compression stream * @param buf Pointer to store the data type * @param nBytes Number of bytes to inflate * @return Number of bytes read from the file */ size_t InflateData(mat_t *mat, z_streamp z, void *buf, int nBytes) { mat_uint8_t comp_buf[1024]; int err; size_t bytesread = 0; if ( buf == NULL ) return 0; if ( nBytes < 1 ) { return bytesread; } if ( !z->avail_in ) { if ( nBytes > 1024 ) { z->avail_in = fread(comp_buf,1,1024,(FILE*)mat->fp); } else { z->avail_in = fread(comp_buf,1,nBytes,(FILE*)mat->fp); } bytesread += z->avail_in; z->next_in = comp_buf; } z->avail_out = nBytes; z->next_out = (Bytef*)buf; err = inflate(z,Z_FULL_FLUSH); if ( err == Z_STREAM_END ) { return bytesread; } else if ( err != Z_OK ) { Mat_Critical("InflateData: inflate returned %s",zError( err == Z_NEED_DICT ? Z_DATA_ERROR : err )); return bytesread; } while ( z->avail_out && !z->avail_in ) { if ( nBytes > 1024 + bytesread ) { z->avail_in = fread(comp_buf,1,1024,(FILE*)mat->fp); } else if ( nBytes < 1 + bytesread ) { /* Read a byte at a time */ z->avail_in = fread(comp_buf,1,1,(FILE*)mat->fp); } else { z->avail_in = fread(comp_buf,1,nBytes-bytesread,(FILE*)mat->fp); } bytesread += z->avail_in; z->next_in = comp_buf; err = inflate(z,Z_FULL_FLUSH); if ( err == Z_STREAM_END ) { break; } else if ( err != Z_OK && err != Z_BUF_ERROR ) { Mat_Critical("InflateData: inflate returned %s",zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); break; } } if ( z->avail_in ) { long offset = -(long)z->avail_in; (void)fseek((FILE*)mat->fp,offset,SEEK_CUR); bytesread -= z->avail_in; z->avail_in = 0; } return bytesread; }
/** @brief Inflate the data until @c nbytes of compressed data has been * inflated * * @ingroup mat_internal * @param mat Pointer to the MAT file * @param z zlib compression stream * @param nbytes Number of uncompressed bytes to skip * @return Number of bytes read from the file */ size_t InflateSkip2(mat_t *mat, matvar_t *matvar, int nbytes) { mat_uint8_t comp_buf[32],uncomp_buf[32]; int err, cnt = 0; size_t bytesread = 0; if ( !matvar->internal->z->avail_in ) { matvar->internal->z->avail_in = 1; matvar->internal->z->next_in = comp_buf; bytesread += fread(comp_buf,1,1,(FILE*)mat->fp); } matvar->internal->z->avail_out = 1; matvar->internal->z->next_out = uncomp_buf; err = inflate(matvar->internal->z,Z_NO_FLUSH); if ( err != Z_OK ) { Mat_Critical("InflateSkip2: %s - inflate returned %s",matvar->name,zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); return bytesread; } if ( !matvar->internal->z->avail_out ) { matvar->internal->z->avail_out = 1; matvar->internal->z->next_out = uncomp_buf; } while ( cnt < nbytes ) { if ( !matvar->internal->z->avail_in ) { matvar->internal->z->avail_in = 1; matvar->internal->z->next_in = comp_buf; bytesread += fread(comp_buf,1,1,(FILE*)mat->fp); cnt++; } err = inflate(matvar->internal->z,Z_NO_FLUSH); if ( err != Z_OK ) { Mat_Critical("InflateSkip2: %s - inflate returned %s",matvar->name,zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); return bytesread; } if ( !matvar->internal->z->avail_out ) { matvar->internal->z->avail_out = 1; matvar->internal->z->next_out = uncomp_buf; } } if ( matvar->internal->z->avail_in ) { (void)fseek((FILE*)mat->fp,-(int)matvar->internal->z->avail_in,SEEK_CUR); bytesread -= matvar->internal->z->avail_in; matvar->internal->z->avail_in = 0; } return bytesread; }
/** @brief Finds a field of a structure by the field's name * * Returns a pointer to the structure field at the given 0-relative index. * @ingroup MAT * @param matvar Pointer to the Structure MAT variable * @param name Name of the structure field * @param index linear index of the structure array * @return Pointer to the structure field on success, NULL on error */ matvar_t * Mat_VarGetStructFieldByName(matvar_t *matvar,const char *field_name, size_t index) { int i, nfields, field_index; matvar_t *field = NULL; size_t nmemb; if ( matvar == NULL || matvar->class_type != MAT_C_STRUCT || matvar->data_size == 0 ) return field; nmemb = 1; for ( i = 0; i < matvar->rank; i++ ) nmemb *= matvar->dims[i]; nfields = matvar->internal->num_fields; field_index = -1; for ( i = 0; i < nfields; i++ ) { if ( !strcmp(matvar->internal->fieldnames[i],field_name) ) { field_index = i; break; } } if ( index >= nmemb ) { Mat_Critical("Mat_VarGetStructField: structure index out of bounds"); } else if ( field_index >= 0 ) { field = *((matvar_t **)matvar->data+index*nfields+field_index); } return field; }
/** @brief Inflates the data's tag * * buf must hold at least 8 bytes * @ingroup mat_internal * @param mat Pointer to the MAT file * @param matvar Pointer to the MAT variable * @param buf Pointer to store the data tag * @return Number of bytes read from the file */ size_t InflateDataTag(mat_t *mat, matvar_t *matvar, void *buf) { mat_uint8_t comp_buf[32]; int err; size_t bytesread = 0; if ( buf == NULL ) return 0; if ( !matvar->internal->z->avail_in ) { matvar->internal->z->avail_in = 1; matvar->internal->z->next_in = comp_buf; bytesread += fread(comp_buf,1,1,(FILE*)mat->fp); } matvar->internal->z->avail_out = 8; matvar->internal->z->next_out = (Bytef*)buf; err = inflate(matvar->internal->z,Z_NO_FLUSH); if ( err == Z_STREAM_END ) { return bytesread; } else if ( err != Z_OK ) { Mat_Critical("InflateDataTag: %s - inflate returned %s",matvar->name,zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); return bytesread; } while ( matvar->internal->z->avail_out && !matvar->internal->z->avail_in ) { matvar->internal->z->avail_in = 1; matvar->internal->z->next_in = comp_buf; bytesread += fread(comp_buf,1,1,(FILE*)mat->fp); err = inflate(matvar->internal->z,Z_NO_FLUSH); if ( err == Z_STREAM_END ) { break; } else if ( err != Z_OK ) { Mat_Critical("InflateDataTag: %s - inflate returned %s",matvar->name,zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); return bytesread; } } if ( matvar->internal->z->avail_in ) { (void)fseek((FILE*)mat->fp,-(int)matvar->internal->z->avail_in,SEEK_CUR); bytesread -= matvar->internal->z->avail_in; matvar->internal->z->avail_in = 0; } return bytesread; }
/** @brief Inflates the structure's fieldnames * * buf must hold at least @c nfields * @c fieldname_length bytes * @ingroup mat_internal * @param mat Pointer to the MAT file * @param matvar Pointer to the MAT variable * @param buf Pointer to store the fieldnames * @param nfields Number of fields * @param fieldname_length Maximum length in bytes of each field * @param padding Number of padding bytes * @return Number of bytes read from the file */ size_t InflateFieldNames(mat_t *mat,matvar_t *matvar,void *buf,int nfields, int fieldname_length,int padding) { mat_uint8_t comp_buf[32]; int err; size_t bytesread = 0; if ( buf == NULL ) return 0; if ( !matvar->internal->z->avail_in ) { matvar->internal->z->avail_in = 1; matvar->internal->z->next_in = comp_buf; bytesread += fread(comp_buf,1,1,(FILE*)mat->fp); } matvar->internal->z->avail_out = nfields*fieldname_length+padding; matvar->internal->z->next_out = (Bytef*)buf; err = inflate(matvar->internal->z,Z_NO_FLUSH); if ( err != Z_OK ) { Mat_Critical("InflateFieldNames: inflate returned %s",zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); return bytesread; } while ( matvar->internal->z->avail_out && !matvar->internal->z->avail_in ) { matvar->internal->z->avail_in = 1; matvar->internal->z->next_in = comp_buf; bytesread += fread(comp_buf,1,1,(FILE*)mat->fp); err = inflate(matvar->internal->z,Z_NO_FLUSH); if ( err != Z_OK ) { Mat_Critical("InflateFieldNames: inflate returned %s",zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); return bytesread; } } if ( matvar->internal->z->avail_in ) { (void)fseek((FILE*)mat->fp,-(int)matvar->internal->z->avail_in,SEEK_CUR); bytesread -= matvar->internal->z->avail_in; matvar->internal->z->avail_in = 0; } return bytesread; }
/** @brief Inflates the data's type * * buf must hold at least 4 bytes * @ingroup mat_internal * @param mat Pointer to the MAT file * @param matvar Pointer to the MAT variable * @param buf Pointer to store the data type * @return Number of bytes read from the file */ size_t InflateDataType(mat_t *mat, z_streamp z, void *buf) { mat_uint8_t comp_buf[32]; int err; size_t bytesread = 0; if ( buf == NULL ) return 0; if ( !z->avail_in ) { z->avail_in = 1; z->next_in = comp_buf; bytesread += fread(comp_buf,1,1,(FILE*)mat->fp); } z->avail_out = 4; z->next_out = (Bytef*)buf; err = inflate(z,Z_NO_FLUSH); if ( err != Z_OK ) { Mat_Critical("InflateDataType: inflate returned %s",zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); return bytesread; } while ( z->avail_out && !z->avail_in ) { z->avail_in = 1; z->next_in = comp_buf; bytesread += fread(comp_buf,1,1,(FILE*)mat->fp); err = inflate(z,Z_NO_FLUSH); if ( err != Z_OK ) { Mat_Critical("InflateDataType: inflate returned %s",zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); return bytesread; } } if ( z->avail_in ) { (void)fseek((FILE*)mat->fp,-(int)z->avail_in,SEEK_CUR); bytesread -= z->avail_in; z->avail_in = 0; } return bytesread; }
/** @if mat_devman * @brief Reads the data of a version 4 MAT file variable * * @ingroup mat_internal * @param mat MAT file pointer * @param matvar MAT variable pointer to read the data * @endif */ void Read4(mat_t *mat,matvar_t *matvar) { unsigned int N; if ( fseek(mat->fp,matvar->internal->datapos,SEEK_SET) ) return; N = matvar->dims[0]*matvar->dims[1]; switch ( matvar->data_type ) { case MAT_T_DOUBLE: matvar->data_size = sizeof(double); if ( matvar->isComplex ) { struct ComplexSplit *complex_data; matvar->nbytes = N*sizeof(double); complex_data = malloc(sizeof(*complex_data)); complex_data->Re = malloc(matvar->nbytes); complex_data->Im = malloc(matvar->nbytes); matvar->data = complex_data; if ( complex_data != NULL && complex_data->Re != NULL && complex_data->Im != NULL ) { fread(complex_data->Re,N,sizeof(double),mat->fp); fread(complex_data->Im,N,sizeof(double),mat->fp); } } else { matvar->nbytes = N*sizeof(double); matvar->data = malloc(matvar->nbytes); if ( matvar->data != NULL ) fread(matvar->data,N,sizeof(double),mat->fp); } break; case MAT_T_SINGLE: matvar->data_size = sizeof(float); if ( matvar->isComplex ) { struct ComplexSplit *complex_data; matvar->nbytes = N*sizeof(float); complex_data = malloc(sizeof(*complex_data)); complex_data->Re = malloc(matvar->nbytes); complex_data->Im = malloc(matvar->nbytes); matvar->data = complex_data; if ( complex_data != NULL && complex_data->Re != NULL && complex_data->Im != NULL ) { fread(complex_data->Re,N,sizeof(float),mat->fp); fread(complex_data->Im,N,sizeof(float),mat->fp); } } else { matvar->nbytes = N*sizeof(float); matvar->data = malloc(matvar->nbytes); if ( matvar->data != NULL ) fread(matvar->data,N,sizeof(float),mat->fp); } break; case MAT_T_INT32: matvar->data_size = sizeof(mat_int32_t); if ( matvar->isComplex ) { struct ComplexSplit *complex_data; matvar->nbytes = N*sizeof(mat_int32_t); complex_data = malloc(sizeof(*complex_data)); complex_data->Re = malloc(matvar->nbytes); complex_data->Im = malloc(matvar->nbytes); matvar->data = complex_data; if ( complex_data != NULL && complex_data->Re != NULL && complex_data->Im != NULL ) { fread(complex_data->Re,N,sizeof(mat_int32_t),mat->fp); fread(complex_data->Im,N,sizeof(mat_int32_t),mat->fp); } } else { matvar->nbytes = N*sizeof(mat_int32_t); matvar->data = malloc(matvar->nbytes); if ( matvar->data != NULL ) fread(matvar->data,N,sizeof(mat_int32_t),mat->fp); } break; case MAT_T_INT16: matvar->data_size = sizeof(mat_int16_t); if ( matvar->isComplex ) { struct ComplexSplit *complex_data; matvar->nbytes = N*sizeof(mat_int16_t); complex_data = malloc(sizeof(*complex_data)); complex_data->Re = malloc(matvar->nbytes); complex_data->Im = malloc(matvar->nbytes); matvar->data = complex_data; if ( complex_data != NULL && complex_data->Re != NULL && complex_data->Im != NULL ) { fread(complex_data->Re,N,sizeof(mat_int16_t),mat->fp); fread(complex_data->Im,N,sizeof(mat_int16_t),mat->fp); } } else { matvar->nbytes = N*sizeof(mat_int16_t); matvar->data = malloc(matvar->nbytes); if ( matvar->data != NULL ) fread(matvar->data,N,sizeof(mat_int16_t),mat->fp); } break; case MAT_T_UINT16: matvar->data_size = sizeof(mat_uint16_t); if ( matvar->isComplex ) { struct ComplexSplit *complex_data; matvar->nbytes = N*sizeof(mat_uint16_t); complex_data = malloc(sizeof(*complex_data)); complex_data->Re = malloc(matvar->nbytes); complex_data->Im = malloc(matvar->nbytes); matvar->data = complex_data; if ( complex_data != NULL && complex_data->Re != NULL && complex_data->Im != NULL ) { fread(complex_data->Re,N,sizeof(mat_uint16_t),mat->fp); fread(complex_data->Im,N,sizeof(mat_uint16_t),mat->fp); } } else { matvar->nbytes = N*sizeof(mat_uint16_t); matvar->data = malloc(matvar->nbytes); if ( matvar->data != NULL ) fread(matvar->data,N,sizeof(mat_uint16_t),mat->fp); } break; case MAT_T_UINT8: matvar->data_size = sizeof(mat_uint8_t); if ( matvar->isComplex ) { struct ComplexSplit *complex_data; matvar->nbytes = N*sizeof(mat_uint8_t); complex_data = malloc(sizeof(*complex_data)); complex_data->Re = malloc(matvar->nbytes); complex_data->Im = malloc(matvar->nbytes); matvar->data = complex_data; if ( complex_data != NULL && complex_data->Re != NULL && complex_data->Im != NULL ) { fread(complex_data->Re,N,sizeof(mat_uint8_t),mat->fp); fread(complex_data->Im,N,sizeof(mat_uint8_t),mat->fp); } } else { matvar->nbytes = N*sizeof(mat_uint8_t); matvar->data = malloc(matvar->nbytes); if ( matvar->data != NULL ) fread(matvar->data,N,sizeof(mat_uint8_t),mat->fp); } break; default: Mat_Critical("MAT V4 data type error"); return; } return; }
/** @brief Inflate the data until @c nbytes of uncompressed data has been * inflated * * @ingroup mat_internal * @param mat Pointer to the MAT file * @param z zlib compression stream * @param nbytes Number of uncompressed bytes to skip * @return Number of bytes read from the file */ size_t InflateSkip(mat_t *mat, z_streamp z, int nbytes) { mat_uint8_t comp_buf[512],uncomp_buf[512]; int n, err, cnt = 0; size_t bytesread = 0; if ( nbytes < 1 ) return 0; n = (nbytes<512) ? nbytes : 512; if ( !z->avail_in ) { z->next_in = comp_buf; z->avail_in += fread(comp_buf,1,n,(FILE*)mat->fp); bytesread += z->avail_in; } z->avail_out = n; z->next_out = uncomp_buf; err = inflate(z,Z_FULL_FLUSH); if ( err == Z_STREAM_END ) { return bytesread; } else if ( err != Z_OK ) { Mat_Critical("InflateSkip: inflate returned %s",zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); return bytesread; } if ( !z->avail_out ) { cnt += n; n = ((nbytes-cnt)<512) ? nbytes-cnt : 512; z->avail_out = n; z->next_out = uncomp_buf; } while ( cnt < nbytes ) { if ( !z->avail_in ) { z->next_in = comp_buf; z->avail_in += fread(comp_buf,1,n,(FILE*)mat->fp); bytesread += z->avail_in; } err = inflate(z,Z_FULL_FLUSH); if ( err == Z_STREAM_END ) { break; } else if ( err != Z_OK ) { Mat_Critical("InflateSkip: inflate returned %s",zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); break; } if ( !z->avail_out ) { cnt += n; n = ((nbytes-cnt)<512) ? nbytes-cnt : 512; z->avail_out = n; z->next_out = uncomp_buf; } } if ( z->avail_in ) { long offset = -(long)z->avail_in; (void)fseek((FILE*)mat->fp,offset,SEEK_CUR); bytesread -= z->avail_in; z->avail_in = 0; } return bytesread; }
/** @brief Inflates the dimensions tag and the dimensions data * * @c buf must hold at least (8+4*rank) bytes where rank is the number of * dimensions. If the end of the dimensions data is not aligned on an 8-byte * boundary, this function eats up those bytes and stores then in @c buf. * @ingroup mat_internal * @param mat Pointer to the MAT file * @param matvar Pointer to the MAT variable * @param buf Pointer to store the dimensions flag and data * @return Number of bytes read from the file */ size_t InflateDimensions(mat_t *mat, matvar_t *matvar, void *buf) { mat_uint8_t comp_buf[32]; mat_int32_t tag[2]; int err, rank, i; size_t bytesread = 0; if ( buf == NULL ) return 0; if ( !matvar->internal->z->avail_in ) { matvar->internal->z->avail_in = 1; matvar->internal->z->next_in = comp_buf; bytesread += fread(comp_buf,1,1,(FILE*)mat->fp); } matvar->internal->z->avail_out = 8; matvar->internal->z->next_out = (Bytef*)buf; err = inflate(matvar->internal->z,Z_NO_FLUSH); if ( err != Z_OK ) { Mat_Critical("InflateDimensions: inflate returned %s",zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); return bytesread; } while ( matvar->internal->z->avail_out && !matvar->internal->z->avail_in ) { matvar->internal->z->avail_in = 1; matvar->internal->z->next_in = comp_buf; bytesread += fread(comp_buf,1,1,(FILE*)mat->fp); err = inflate(matvar->internal->z,Z_NO_FLUSH); if ( err != Z_OK ) { Mat_Critical("InflateDimensions: inflate returned %s",zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); return bytesread; } } tag[0] = *(int *)buf; tag[1] = *((int *)buf+1); if ( mat->byteswap ) { Mat_int32Swap(tag); Mat_int32Swap(tag+1); } if ( (tag[0] & 0x0000ffff) != MAT_T_INT32 ) { Mat_Critical("InflateDimensions: Reading dimensions expected type MAT_T_INT32"); return bytesread; } rank = tag[1]; if ( rank % 8 != 0 ) i = 8-(rank %8); else i = 0; rank+=i; if ( !matvar->internal->z->avail_in ) { matvar->internal->z->avail_in = 1; matvar->internal->z->next_in = comp_buf; bytesread += fread(comp_buf,1,1,(FILE*)mat->fp); } matvar->internal->z->avail_out = rank; matvar->internal->z->next_out = (Bytef*)((mat_int32_t *)buf+2); err = inflate(matvar->internal->z,Z_NO_FLUSH); if ( err != Z_OK ) { Mat_Critical("InflateDimensions: inflate returned %s",zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); return bytesread; } while ( matvar->internal->z->avail_out && !matvar->internal->z->avail_in ) { matvar->internal->z->avail_in = 1; matvar->internal->z->next_in = comp_buf; bytesread += fread(comp_buf,1,1,(FILE*)mat->fp); err = inflate(matvar->internal->z,Z_NO_FLUSH); if ( err != Z_OK ) { Mat_Critical("InflateDimensions: inflate returned %s",zError(err == Z_NEED_DICT ? Z_DATA_ERROR : err)); return bytesread; } } if ( matvar->internal->z->avail_in ) { (void)fseek((FILE*)mat->fp,-(int)matvar->internal->z->avail_in,SEEK_CUR); bytesread -= matvar->internal->z->avail_in; matvar->internal->z->avail_in = 0; } return bytesread; }