mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-16 14:15:26 -06:00
4861 lines
179 KiB
C
4861 lines
179 KiB
C
/** @file mat5.c
|
|
* Matlab MAT version 5 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.
|
|
*/
|
|
|
|
/* FIXME: Implement Unicode support */
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
|
# define SIZE_T_FMTSTR "Iu"
|
|
# define strdup _strdup
|
|
#else
|
|
# define SIZE_T_FMTSTR "zu"
|
|
#endif
|
|
#include "matio_private.h"
|
|
#include "mat5.h"
|
|
|
|
/** Get type from tag */
|
|
#define TYPE_FROM_TAG(a) ( ((a) & 0x000000ff) <= MAT_T_FUNCTION ) ? (enum matio_types)((a) & 0x000000ff) : MAT_T_UNKNOWN
|
|
/** Get class from array flag */
|
|
#define CLASS_FROM_ARRAY_FLAGS(a) ( ((a) & 0x000000ff) <= MAT_C_OPAQUE ) ? ((enum matio_classes)((a) & 0x000000ff)) : MAT_C_EMPTY
|
|
/** Class type mask */
|
|
#define CLASS_TYPE_MASK 0x000000ff
|
|
|
|
static mat_complex_split_t null_complex_data = {NULL,NULL};
|
|
|
|
/*===========================================================================
|
|
* Private functions
|
|
*===========================================================================
|
|
*/
|
|
static size_t GetTypeBufSize(matvar_t *matvar);
|
|
static size_t GetStructFieldBufSize(matvar_t *matvar);
|
|
static size_t GetCellArrayFieldBufSize(matvar_t *matvar);
|
|
#if defined(HAVE_ZLIB)
|
|
static size_t GetMatrixMaxBufSize(matvar_t *matvar);
|
|
#endif
|
|
static size_t GetEmptyMatrixMaxBufSize(const char *name,int rank);
|
|
static size_t WriteCharData(mat_t *mat, void *data, int N,enum matio_types data_type);
|
|
static size_t ReadNextCell( mat_t *mat, matvar_t *matvar );
|
|
static size_t ReadNextStructField( mat_t *mat, matvar_t *matvar );
|
|
static size_t ReadNextFunctionHandle(mat_t *mat, matvar_t *matvar);
|
|
static size_t ReadRankDims(mat_t *mat, matvar_t *matvar, enum matio_types data_type,
|
|
mat_uint32_t nbytes);
|
|
static int WriteType(mat_t *mat,matvar_t *matvar);
|
|
static int WriteCellArrayField(mat_t *mat,matvar_t *matvar );
|
|
static int WriteStructField(mat_t *mat,matvar_t *matvar);
|
|
static int WriteData(mat_t *mat,void *data,int N,enum matio_types data_type);
|
|
static size_t Mat_WriteEmptyVariable5(mat_t *mat,const char *name,int rank,
|
|
size_t *dims);
|
|
static void Mat_VarReadNumeric5(mat_t *mat,matvar_t *matvar,void *data,size_t N);
|
|
#if defined(HAVE_ZLIB)
|
|
static size_t WriteCompressedCharData(mat_t *mat,z_streamp z,void *data,int N,
|
|
enum matio_types data_type);
|
|
static size_t WriteCompressedData(mat_t *mat,z_streamp z,void *data,int N,
|
|
enum matio_types data_type);
|
|
static size_t WriteCompressedTypeArrayFlags(mat_t *mat,matvar_t *matvar,
|
|
z_streamp z);
|
|
static size_t WriteCompressedType(mat_t *mat,matvar_t *matvar,z_streamp z);
|
|
static size_t WriteCompressedCellArrayField(mat_t *mat,matvar_t *matvar,
|
|
z_streamp z);
|
|
static size_t WriteCompressedStructField(mat_t *mat,matvar_t *matvar,
|
|
z_streamp z);
|
|
static size_t Mat_WriteCompressedEmptyVariable5(mat_t *mat,const char *name,
|
|
int rank,size_t *dims,z_streamp z);
|
|
#endif
|
|
|
|
/** @brief determines the number of bytes for a given class type
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param matvar MAT variable
|
|
* @return the number of bytes needed to store the MAT variable
|
|
*/
|
|
static size_t
|
|
GetTypeBufSize(matvar_t *matvar)
|
|
{
|
|
size_t nBytes = 0, data_bytes;
|
|
size_t tag_size = 8;
|
|
size_t nelems = 1;
|
|
|
|
SafeMulDims(matvar, &nelems);
|
|
|
|
/* Add rank and dimensions, padded to an 8 byte block */
|
|
if ( matvar->rank % 2 )
|
|
nBytes += tag_size + matvar->rank*4 + 4;
|
|
else
|
|
nBytes += tag_size + matvar->rank*4;
|
|
|
|
switch ( matvar->class_type ) {
|
|
case MAT_C_STRUCT:
|
|
{
|
|
matvar_t **fields = (matvar_t**)matvar->data;
|
|
size_t nfields = matvar->internal->num_fields;
|
|
size_t maxlen = 0, i;
|
|
|
|
for ( i = 0; i < nfields; i++ ) {
|
|
char *fieldname = matvar->internal->fieldnames[i];
|
|
if ( NULL != fieldname && strlen(fieldname) > maxlen )
|
|
maxlen = strlen(fieldname);
|
|
}
|
|
maxlen++;
|
|
while ( nfields*maxlen % 8 != 0 )
|
|
maxlen++;
|
|
|
|
nBytes += tag_size + tag_size + maxlen*nfields;
|
|
|
|
/* FIXME: Add bytes for the fieldnames */
|
|
if ( NULL != fields && nfields > 0 ) {
|
|
size_t nelems_x_nfields = 1;
|
|
SafeMul(&nelems_x_nfields, nelems, nfields);
|
|
for ( i = 0; i < nelems_x_nfields; i++ )
|
|
nBytes += tag_size + GetStructFieldBufSize(fields[i]);
|
|
}
|
|
break;
|
|
}
|
|
case MAT_C_CELL:
|
|
{
|
|
matvar_t **cells = (matvar_t**)matvar->data;
|
|
|
|
if ( matvar->nbytes == 0 || matvar->data_size == 0 )
|
|
break;
|
|
|
|
nelems = matvar->nbytes / matvar->data_size;
|
|
if ( NULL != cells && nelems > 0 ) {
|
|
size_t i;
|
|
for ( i = 0; i < nelems; i++ )
|
|
nBytes += tag_size + GetCellArrayFieldBufSize(cells[i]);
|
|
}
|
|
break;
|
|
}
|
|
case MAT_C_SPARSE:
|
|
{
|
|
mat_sparse_t *sparse = (mat_sparse_t*)matvar->data;
|
|
|
|
SafeMul(&data_bytes, sparse->nir, sizeof(mat_int32_t));
|
|
if ( data_bytes % 8 )
|
|
data_bytes += (8 - (data_bytes % 8));
|
|
nBytes += tag_size + data_bytes;
|
|
|
|
SafeMul(&data_bytes, sparse->njc, sizeof(mat_int32_t));
|
|
if ( data_bytes % 8 )
|
|
data_bytes += (8 - (data_bytes % 8));
|
|
nBytes += tag_size + data_bytes;
|
|
|
|
SafeMul(&data_bytes, sparse->ndata, Mat_SizeOf(matvar->data_type));
|
|
if ( data_bytes % 8 )
|
|
data_bytes += (8 - (data_bytes % 8));
|
|
nBytes += tag_size + data_bytes;
|
|
|
|
if ( matvar->isComplex )
|
|
nBytes += tag_size + data_bytes;
|
|
|
|
break;
|
|
}
|
|
case MAT_C_CHAR:
|
|
if ( MAT_T_UINT8 == matvar->data_type ||
|
|
MAT_T_INT8 == matvar->data_type )
|
|
SafeMul(&data_bytes, nelems, Mat_SizeOf(MAT_T_UINT16));
|
|
else
|
|
SafeMul(&data_bytes, nelems, Mat_SizeOf(matvar->data_type));
|
|
if ( data_bytes % 8 )
|
|
data_bytes += (8 - (data_bytes % 8));
|
|
nBytes += tag_size + data_bytes;
|
|
if ( matvar->isComplex )
|
|
nBytes += tag_size + data_bytes;
|
|
break;
|
|
default:
|
|
SafeMul(&data_bytes, nelems, Mat_SizeOf(matvar->data_type));
|
|
if ( data_bytes % 8 )
|
|
data_bytes += (8 - (data_bytes % 8));
|
|
nBytes += tag_size + data_bytes;
|
|
if ( matvar->isComplex )
|
|
nBytes += tag_size + data_bytes;
|
|
} /* switch ( matvar->class_type ) */
|
|
|
|
return nBytes;
|
|
}
|
|
|
|
/** @brief determines the number of bytes needed to store the given struct field
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param matvar field of a structure
|
|
* @return the number of bytes needed to store the struct field
|
|
*/
|
|
static size_t
|
|
GetStructFieldBufSize(matvar_t *matvar)
|
|
{
|
|
size_t nBytes = 0;
|
|
size_t tag_size = 8, array_flags_size = 8;
|
|
|
|
if ( matvar == NULL )
|
|
return GetEmptyMatrixMaxBufSize(NULL, 2);
|
|
|
|
/* Add the Array Flags tag and space to the number of bytes */
|
|
nBytes += tag_size + array_flags_size;
|
|
|
|
/* In a struct field, the name is just a tag with 0 bytes */
|
|
nBytes += tag_size;
|
|
|
|
nBytes += GetTypeBufSize(matvar);
|
|
|
|
return nBytes;
|
|
}
|
|
|
|
/** @brief determines the number of bytes needed to store the cell array element
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param matvar MAT variable
|
|
* @return the number of bytes needed to store the variable
|
|
*/
|
|
static size_t
|
|
GetCellArrayFieldBufSize(matvar_t *matvar)
|
|
{
|
|
size_t nBytes = 0;
|
|
size_t tag_size = 8, array_flags_size = 8;
|
|
|
|
if ( matvar == NULL )
|
|
return nBytes;
|
|
|
|
/* Add the Array Flags tag and space to the number of bytes */
|
|
nBytes += tag_size + array_flags_size;
|
|
|
|
/* In an element of a cell array, the name is just a tag with 0 bytes */
|
|
nBytes += tag_size;
|
|
|
|
nBytes += GetTypeBufSize(matvar);
|
|
|
|
return nBytes;
|
|
}
|
|
|
|
/** @brief determines the number of bytes needed to store the given variable
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param matvar MAT variable
|
|
* @return the number of bytes needed to store the variable
|
|
*/
|
|
static size_t
|
|
GetEmptyMatrixMaxBufSize(const char *name,int rank)
|
|
{
|
|
size_t nBytes = 0, len;
|
|
size_t tag_size = 8, array_flags_size = 8;
|
|
|
|
/* Add the Array Flags tag and space to the number of bytes */
|
|
nBytes += tag_size + array_flags_size;
|
|
|
|
/* Get size of variable name, pad it to an 8 byte block, and add it to nBytes */
|
|
if ( NULL != name )
|
|
len = strlen(name);
|
|
else
|
|
len = 4;
|
|
|
|
if ( len <= 4 ) {
|
|
nBytes += tag_size;
|
|
} else {
|
|
if ( len % 8 )
|
|
len = len + (8 - len % 8);
|
|
nBytes += tag_size + len;
|
|
}
|
|
|
|
/* Add rank and dimensions, padded to an 8 byte block */
|
|
if ( rank % 2 )
|
|
nBytes += tag_size + rank*4 + 4;
|
|
else
|
|
nBytes += tag_size + rank*4;
|
|
|
|
/* Data tag */
|
|
nBytes += tag_size;
|
|
|
|
return nBytes;
|
|
}
|
|
|
|
#if defined(HAVE_ZLIB)
|
|
/** @brief determines the number of bytes needed to store the given variable
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param matvar MAT variable
|
|
* @return the number of bytes needed to store the variable
|
|
*/
|
|
static size_t
|
|
GetMatrixMaxBufSize(matvar_t *matvar)
|
|
{
|
|
size_t nBytes = 0, len;
|
|
size_t tag_size = 8, array_flags_size = 8;
|
|
|
|
if ( matvar == NULL )
|
|
return nBytes;
|
|
|
|
/* Add the Array Flags tag and space to the number of bytes */
|
|
nBytes += tag_size + array_flags_size;
|
|
|
|
/* Get size of variable name, pad it to an 8 byte block, and add it to nBytes */
|
|
if ( NULL != matvar->name )
|
|
len = strlen(matvar->name);
|
|
else
|
|
len=4;
|
|
|
|
if ( len <= 4 ) {
|
|
nBytes += tag_size;
|
|
} else {
|
|
if ( len % 8 )
|
|
len = len + (8 - len % 8);
|
|
nBytes += tag_size + len;
|
|
}
|
|
|
|
nBytes += GetTypeBufSize(matvar);
|
|
|
|
return nBytes;
|
|
}
|
|
#endif
|
|
|
|
/** @if mat_devman
|
|
* @brief Creates a new Matlab MAT version 5 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
|
|
* @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_Create5(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;
|
|
|
|
fp = fopen(matname,"w+b");
|
|
if ( !fp )
|
|
return NULL;
|
|
|
|
mat = (mat_t*)malloc(sizeof(*mat));
|
|
if ( mat == NULL ) {
|
|
fclose(fp);
|
|
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;
|
|
#if defined(MAT73) && MAT73
|
|
mat->refs_id = -1;
|
|
#endif
|
|
mat->dir = NULL;
|
|
|
|
t = time(NULL);
|
|
mat->fp = fp;
|
|
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 5.0 MAT-file, Platform: %s, "
|
|
"Created by: libmatio v%d.%d.%d on %s", 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)0x0100;
|
|
endian = 0x4d49;
|
|
|
|
version = 0x0100;
|
|
|
|
fwrite(mat->header,1,116,(FILE*)mat->fp);
|
|
fwrite(mat->subsys_offset,1,8,(FILE*)mat->fp);
|
|
fwrite(&version,2,1,(FILE*)mat->fp);
|
|
fwrite(&endian,2,1,(FILE*)mat->fp);
|
|
|
|
return mat;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Writes @c data as character data
|
|
*
|
|
* This function uses the knowledge that the data is part of a character class
|
|
* to avoid some pitfalls with Matlab listed below.
|
|
* @li Matlab character data cannot be unsigned 8-bit integers, it needs at
|
|
* least unsigned 16-bit integers
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param data character data to write
|
|
* @param N Number of elements to write
|
|
* @param data_type character data type (enum matio_types)
|
|
* @return number of bytes written
|
|
* @endif
|
|
*/
|
|
static size_t
|
|
WriteCharData(mat_t *mat, void *data, int N,enum matio_types data_type)
|
|
{
|
|
int nBytes = 0, i;
|
|
size_t byteswritten = 0;
|
|
mat_int8_t pad1 = 0;
|
|
|
|
switch ( data_type ) {
|
|
case MAT_T_UINT16:
|
|
{
|
|
nBytes = N*2;
|
|
fwrite(&data_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
if ( NULL != data && N > 0 )
|
|
fwrite(data,2,N,(FILE*)mat->fp);
|
|
if ( nBytes % 8 )
|
|
for ( i = nBytes % 8; i < 8; i++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
break;
|
|
}
|
|
case MAT_T_INT8:
|
|
case MAT_T_UINT8:
|
|
{
|
|
mat_uint8_t *ptr;
|
|
mat_uint16_t c;
|
|
|
|
/* Matlab can't read MAT_C_CHAR as uint8, needs uint16 */
|
|
nBytes = N*2;
|
|
data_type = MAT_T_UINT16;
|
|
fwrite(&data_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
ptr = (mat_uint8_t*)data;
|
|
if ( NULL == ptr )
|
|
break;
|
|
for ( i = 0; i < N; i++ ) {
|
|
c = (mat_uint16_t)*(char *)ptr;
|
|
fwrite(&c,2,1,(FILE*)mat->fp);
|
|
ptr++;
|
|
}
|
|
if ( nBytes % 8 )
|
|
for ( i = nBytes % 8; i < 8; i++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
break;
|
|
}
|
|
case MAT_T_UTF8:
|
|
{
|
|
mat_uint8_t *ptr;
|
|
|
|
nBytes = N;
|
|
fwrite(&data_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
ptr = (mat_uint8_t*)data;
|
|
if ( NULL != ptr && nBytes > 0 )
|
|
fwrite(ptr,1,nBytes,(FILE*)mat->fp);
|
|
if ( nBytes % 8 )
|
|
for ( i = nBytes % 8; i < 8; i++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
break;
|
|
}
|
|
case MAT_T_UNKNOWN:
|
|
{
|
|
/* Sometimes empty char data will have MAT_T_UNKNOWN, so just write
|
|
* a data tag
|
|
*/
|
|
nBytes = N*2;
|
|
data_type = MAT_T_UINT16;
|
|
fwrite(&data_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
byteswritten += nBytes;
|
|
return byteswritten;
|
|
}
|
|
|
|
#if defined(HAVE_ZLIB)
|
|
/** @brief Writes @c data as compressed character data
|
|
*
|
|
* This function uses the knowledge that the data is part of a character class
|
|
* to avoid some pitfalls with Matlab listed below.
|
|
* @li Matlab character data cannot be unsigned 8-bit integers, it needs at
|
|
* least unsigned 16-bit integers
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param z pointer to the zlib compression stream
|
|
* @param data character data to write
|
|
* @param N Number of elements to write
|
|
* @param data_type character data type (enum matio_types)
|
|
* @return number of bytes written
|
|
*/
|
|
static size_t
|
|
WriteCompressedCharData(mat_t *mat,z_streamp z,void *data,int N,
|
|
enum matio_types data_type)
|
|
{
|
|
int data_size, data_tag[2], byteswritten = 0;
|
|
int buf_size = 1024;
|
|
mat_uint8_t buf[1024], pad[8] = {0,};
|
|
|
|
if ( mat == NULL || mat->fp == NULL )
|
|
return 0;
|
|
|
|
switch ( data_type ) {
|
|
case MAT_T_UINT8:
|
|
case MAT_T_UINT16:
|
|
case MAT_T_UTF8:
|
|
case MAT_T_UTF16:
|
|
data_size = Mat_SizeOf(data_type);
|
|
data_tag[0] = MAT_T_UINT8 == data_type ? MAT_T_UTF8 : data_type;
|
|
data_tag[1] = N*data_size;
|
|
z->next_in = ZLIB_BYTE_PTR(data_tag);
|
|
z->avail_in = 8;
|
|
do {
|
|
z->next_out = buf;
|
|
z->avail_out = buf_size;
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(buf,1,buf_size-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
|
|
/* exit early if this is an empty data */
|
|
if ( NULL == data || N < 1 )
|
|
break;
|
|
|
|
z->next_in = (Bytef*)data;
|
|
z->avail_in = data_size*N;
|
|
do {
|
|
z->next_out = buf;
|
|
z->avail_out = buf_size;
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(buf,1,buf_size-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
/* Add/Compress padding to pad to 8-byte boundary */
|
|
if ( N*data_size % 8 ) {
|
|
z->next_in = pad;
|
|
z->avail_in = 8 - (N*data_size % 8);
|
|
do {
|
|
z->next_out = buf;
|
|
z->avail_out = buf_size;
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(buf,1,buf_size-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
}
|
|
break;
|
|
case MAT_T_UNKNOWN:
|
|
/* Sometimes empty char data will have MAT_T_UNKNOWN, so just write a data tag */
|
|
data_size = 2;
|
|
data_tag[0] = MAT_T_UINT16;
|
|
data_tag[1] = N*data_size;
|
|
z->next_in = ZLIB_BYTE_PTR(data_tag);
|
|
z->avail_in = 8;
|
|
do {
|
|
z->next_out = buf;
|
|
z->avail_out = buf_size;
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(buf,1,buf_size-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return byteswritten;
|
|
}
|
|
#endif
|
|
|
|
/** @brief Writes the data buffer to the file
|
|
*
|
|
* @param mat MAT file pointer
|
|
* @param data pointer to the data to write
|
|
* @param N number of elements to write
|
|
* @param data_type data type of the data
|
|
* @return number of bytes written
|
|
*/
|
|
static int
|
|
WriteData(mat_t *mat,void *data,int N,enum matio_types data_type)
|
|
{
|
|
int nBytes = 0, data_size;
|
|
|
|
if ( mat == NULL || mat->fp == NULL )
|
|
return 0;
|
|
|
|
data_size = Mat_SizeOf(data_type);
|
|
nBytes = N*data_size;
|
|
fwrite(&data_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
|
|
if ( data != NULL && N > 0 )
|
|
fwrite(data,data_size,N,(FILE*)mat->fp);
|
|
|
|
return nBytes;
|
|
}
|
|
|
|
#if defined(HAVE_ZLIB)
|
|
/* Compresses the data buffer and writes it to the file */
|
|
static size_t
|
|
WriteCompressedData(mat_t *mat,z_streamp z,void *data,int N,
|
|
enum matio_types data_type)
|
|
{
|
|
int nBytes = 0, data_size, data_tag[2], byteswritten = 0;
|
|
int buf_size = 1024;
|
|
mat_uint8_t buf[1024], pad[8] = {0,};
|
|
|
|
if ( mat == NULL || mat->fp == NULL )
|
|
return 0;
|
|
|
|
data_size = Mat_SizeOf(data_type);
|
|
data_tag[0] = data_type;
|
|
data_tag[1] = data_size*N;
|
|
z->next_in = ZLIB_BYTE_PTR(data_tag);
|
|
z->avail_in = 8;
|
|
do {
|
|
z->next_out = buf;
|
|
z->avail_out = buf_size;
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(buf,1,buf_size-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
|
|
/* exit early if this is an empty data */
|
|
if ( NULL == data || N < 1 )
|
|
return byteswritten;
|
|
|
|
z->next_in = (Bytef*)data;
|
|
z->avail_in = N*data_size;
|
|
do {
|
|
z->next_out = buf;
|
|
z->avail_out = buf_size;
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(buf,1,buf_size-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
/* Add/Compress padding to pad to 8-byte boundary */
|
|
if ( N*data_size % 8 ) {
|
|
z->next_in = pad;
|
|
z->avail_in = 8 - (N*data_size % 8);
|
|
do {
|
|
z->next_out = buf;
|
|
z->avail_out = buf_size;
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(buf,1,buf_size-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
}
|
|
nBytes = byteswritten;
|
|
return nBytes;
|
|
}
|
|
#endif
|
|
|
|
/** @brief Reads the next cell of the cell array in @c matvar
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar MAT variable pointer
|
|
* @return Number of bytes read
|
|
*/
|
|
static size_t
|
|
ReadNextCell( mat_t *mat, matvar_t *matvar )
|
|
{
|
|
size_t bytesread = 0, i;
|
|
int err;
|
|
matvar_t **cells = NULL;
|
|
size_t nelems = 1;
|
|
|
|
err = SafeMulDims(matvar, &nelems);
|
|
if ( err ) {
|
|
Mat_Critical("Integer multiplication overflow");
|
|
return bytesread;
|
|
}
|
|
matvar->data_size = sizeof(matvar_t *);
|
|
err = SafeMul(&matvar->nbytes, nelems, matvar->data_size);
|
|
if ( err ) {
|
|
Mat_Critical("Integer multiplication overflow");
|
|
return bytesread;
|
|
}
|
|
|
|
matvar->data = calloc(nelems, matvar->data_size);
|
|
if ( NULL == matvar->data ) {
|
|
if ( NULL != matvar->name )
|
|
Mat_Critical("Couldn't allocate memory for %s->data", matvar->name);
|
|
return bytesread;
|
|
}
|
|
cells = (matvar_t **)matvar->data;
|
|
|
|
if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
#if defined(HAVE_ZLIB)
|
|
mat_uint32_t uncomp_buf[16] = {0,};
|
|
int nbytes;
|
|
mat_uint32_t array_flags;
|
|
|
|
for ( i = 0; i < nelems; i++ ) {
|
|
cells[i] = Mat_VarCalloc();
|
|
if ( NULL == cells[i] ) {
|
|
Mat_Critical("Couldn't allocate memory for cell %" SIZE_T_FMTSTR, i);
|
|
continue;
|
|
}
|
|
|
|
/* Read variable tag for cell */
|
|
uncomp_buf[0] = 0;
|
|
uncomp_buf[1] = 0;
|
|
bytesread += InflateVarTag(mat,matvar,uncomp_buf);
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(uncomp_buf);
|
|
(void)Mat_uint32Swap(uncomp_buf+1);
|
|
}
|
|
nbytes = uncomp_buf[1];
|
|
if ( 0 == nbytes ) {
|
|
/* Empty cell: Memory optimization */
|
|
free(cells[i]->internal);
|
|
cells[i]->internal = NULL;
|
|
continue;
|
|
} else if ( uncomp_buf[0] != MAT_T_MATRIX ) {
|
|
Mat_VarFree(cells[i]);
|
|
cells[i] = NULL;
|
|
Mat_Critical("cells[%" SIZE_T_FMTSTR "], Uncompressed type not MAT_T_MATRIX", i);
|
|
break;
|
|
}
|
|
cells[i]->compression = MAT_COMPRESSION_ZLIB;
|
|
bytesread += InflateArrayFlags(mat,matvar,uncomp_buf);
|
|
nbytes -= 16;
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(uncomp_buf);
|
|
(void)Mat_uint32Swap(uncomp_buf+1);
|
|
(void)Mat_uint32Swap(uncomp_buf+2);
|
|
(void)Mat_uint32Swap(uncomp_buf+3);
|
|
}
|
|
/* Array Flags */
|
|
if ( uncomp_buf[0] == MAT_T_UINT32 ) {
|
|
array_flags = uncomp_buf[2];
|
|
cells[i]->class_type = CLASS_FROM_ARRAY_FLAGS(array_flags);
|
|
cells[i]->isComplex = (array_flags & MAT_F_COMPLEX);
|
|
cells[i]->isGlobal = (array_flags & MAT_F_GLOBAL);
|
|
cells[i]->isLogical = (array_flags & MAT_F_LOGICAL);
|
|
if ( cells[i]->class_type == MAT_C_SPARSE ) {
|
|
/* Need to find a more appropriate place to store nzmax */
|
|
cells[i]->nbytes = uncomp_buf[3];
|
|
}
|
|
} else {
|
|
Mat_Critical("Expected MAT_T_UINT32 for array tags, got %d",
|
|
uncomp_buf[0]);
|
|
bytesread+=InflateSkip(mat,matvar->internal->z,nbytes);
|
|
}
|
|
if ( cells[i]->class_type != MAT_C_OPAQUE ) {
|
|
mat_uint32_t* dims = NULL;
|
|
int do_clean = 0;
|
|
bytesread += InflateRankDims(mat,matvar,uncomp_buf,sizeof(uncomp_buf),&dims);
|
|
if ( NULL == dims )
|
|
dims = uncomp_buf + 2;
|
|
else
|
|
do_clean = 1;
|
|
nbytes -= 8;
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(uncomp_buf);
|
|
(void)Mat_uint32Swap(uncomp_buf+1);
|
|
}
|
|
/* Rank and Dimension */
|
|
if ( uncomp_buf[0] == MAT_T_INT32 ) {
|
|
int j;
|
|
cells[i]->rank = uncomp_buf[1];
|
|
nbytes -= cells[i]->rank;
|
|
cells[i]->rank /= 4;
|
|
cells[i]->dims = (size_t*)malloc(cells[i]->rank*sizeof(*cells[i]->dims));
|
|
if ( mat->byteswap ) {
|
|
for ( j = 0; j < cells[i]->rank; j++ )
|
|
cells[i]->dims[j] = Mat_uint32Swap(dims + j);
|
|
} else {
|
|
for ( j = 0; j < cells[i]->rank; j++ )
|
|
cells[i]->dims[j] = dims[j];
|
|
}
|
|
if ( cells[i]->rank % 2 != 0 )
|
|
nbytes -= 4;
|
|
}
|
|
if ( do_clean )
|
|
free(dims);
|
|
bytesread += InflateVarNameTag(mat,matvar,uncomp_buf);
|
|
nbytes -= 8;
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(uncomp_buf);
|
|
(void)Mat_uint32Swap(uncomp_buf+1);
|
|
}
|
|
/* Handle cell elements written with a variable name */
|
|
if ( uncomp_buf[1] > 0 ) {
|
|
/* Name of variable */
|
|
if ( uncomp_buf[0] == MAT_T_INT8 ) { /* Name not in tag */
|
|
mat_uint32_t len = uncomp_buf[1];
|
|
|
|
if ( len % 8 > 0 )
|
|
len = len+(8-(len % 8));
|
|
cells[i]->name = (char*)malloc(len+1);
|
|
nbytes -= len;
|
|
if ( NULL != cells[i]->name ) {
|
|
/* Inflate variable name */
|
|
bytesread += InflateVarName(mat,matvar,cells[i]->name,len);
|
|
cells[i]->name[len] = '\0';
|
|
}
|
|
} else {
|
|
mat_uint32_t len = (uncomp_buf[0] & 0xffff0000) >> 16;
|
|
if ( ((uncomp_buf[0] & 0x0000ffff) == MAT_T_INT8) && len > 0 && len <= 4 ) {
|
|
/* Name packed in tag */
|
|
cells[i]->name = (char*)malloc(len+1);
|
|
if ( NULL != cells[i]->name ) {
|
|
memcpy(cells[i]->name,uncomp_buf+1,len);
|
|
cells[i]->name[len] = '\0';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
cells[i]->internal->z = (z_streamp)calloc(1,sizeof(z_stream));
|
|
if ( cells[i]->internal->z != NULL ) {
|
|
err = inflateCopy(cells[i]->internal->z,matvar->internal->z);
|
|
if ( err == Z_OK ) {
|
|
cells[i]->internal->datapos = ftell((FILE*)mat->fp);
|
|
if ( cells[i]->internal->datapos != -1L ) {
|
|
cells[i]->internal->datapos -= matvar->internal->z->avail_in;
|
|
if ( cells[i]->class_type == MAT_C_STRUCT )
|
|
bytesread+=ReadNextStructField(mat,cells[i]);
|
|
else if ( cells[i]->class_type == MAT_C_CELL )
|
|
bytesread+=ReadNextCell(mat,cells[i]);
|
|
else if ( nbytes <= (1 << MAX_WBITS) ) {
|
|
/* Memory optimization: Read data if less in size
|
|
than the zlib inflate state (approximately) */
|
|
Mat_VarRead5(mat,cells[i]);
|
|
cells[i]->internal->data = cells[i]->data;
|
|
cells[i]->data = NULL;
|
|
}
|
|
(void)fseek((FILE*)mat->fp,cells[i]->internal->datapos,SEEK_SET);
|
|
} else {
|
|
Mat_Critical("Couldn't determine file position");
|
|
}
|
|
if ( cells[i]->internal->data != NULL ||
|
|
cells[i]->class_type == MAT_C_STRUCT ||
|
|
cells[i]->class_type == MAT_C_CELL ) {
|
|
/* Memory optimization: Free inflate state */
|
|
inflateEnd(cells[i]->internal->z);
|
|
free(cells[i]->internal->z);
|
|
cells[i]->internal->z = NULL;
|
|
}
|
|
} else {
|
|
Mat_Critical("inflateCopy returned error %s",zError(err));
|
|
}
|
|
} else {
|
|
Mat_Critical("Couldn't allocate memory");
|
|
}
|
|
}
|
|
bytesread+=InflateSkip(mat,matvar->internal->z,nbytes);
|
|
}
|
|
#else
|
|
Mat_Critical("Not compiled with zlib support");
|
|
#endif
|
|
|
|
} else {
|
|
mat_uint32_t buf[6];
|
|
int nBytes;
|
|
mat_uint32_t array_flags;
|
|
|
|
for ( i = 0; i < nelems; i++ ) {
|
|
int cell_bytes_read,name_len;
|
|
cells[i] = Mat_VarCalloc();
|
|
if ( !cells[i] ) {
|
|
Mat_Critical("Couldn't allocate memory for cell %" SIZE_T_FMTSTR, i);
|
|
continue;
|
|
}
|
|
|
|
/* Read variable tag for cell */
|
|
cell_bytes_read = fread(buf,4,2,(FILE*)mat->fp);
|
|
|
|
/* Empty cells at the end of a file may cause an EOF */
|
|
if ( !cell_bytes_read )
|
|
continue;
|
|
bytesread += cell_bytes_read;
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(buf);
|
|
(void)Mat_uint32Swap(buf+1);
|
|
}
|
|
nBytes = buf[1];
|
|
if ( 0 == nBytes ) {
|
|
/* Empty cell: Memory optimization */
|
|
free(cells[i]->internal);
|
|
cells[i]->internal = NULL;
|
|
continue;
|
|
} else if ( buf[0] != MAT_T_MATRIX ) {
|
|
Mat_VarFree(cells[i]);
|
|
cells[i] = NULL;
|
|
Mat_Critical("cells[%" SIZE_T_FMTSTR "] not MAT_T_MATRIX, fpos = %ld", i,
|
|
ftell((FILE*)mat->fp));
|
|
break;
|
|
}
|
|
|
|
/* Read array flags and the dimensions tag */
|
|
bytesread += fread(buf,4,6,(FILE*)mat->fp);
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(buf);
|
|
(void)Mat_uint32Swap(buf+1);
|
|
(void)Mat_uint32Swap(buf+2);
|
|
(void)Mat_uint32Swap(buf+3);
|
|
(void)Mat_uint32Swap(buf+4);
|
|
(void)Mat_uint32Swap(buf+5);
|
|
}
|
|
nBytes-=24;
|
|
/* Array flags */
|
|
if ( buf[0] == MAT_T_UINT32 ) {
|
|
array_flags = buf[2];
|
|
cells[i]->class_type = CLASS_FROM_ARRAY_FLAGS(array_flags);
|
|
cells[i]->isComplex = (array_flags & MAT_F_COMPLEX);
|
|
cells[i]->isGlobal = (array_flags & MAT_F_GLOBAL);
|
|
cells[i]->isLogical = (array_flags & MAT_F_LOGICAL);
|
|
if ( cells[i]->class_type == MAT_C_SPARSE ) {
|
|
/* Need to find a more appropriate place to store nzmax */
|
|
cells[i]->nbytes = buf[3];
|
|
}
|
|
}
|
|
/* Rank and dimension */
|
|
{
|
|
size_t nbytes = ReadRankDims(mat, cells[i], (enum matio_types)buf[4], buf[5]);
|
|
bytesread += nbytes;
|
|
nBytes -= nbytes;
|
|
}
|
|
/* Variable name tag */
|
|
bytesread+=fread(buf,1,8,(FILE*)mat->fp);
|
|
nBytes-=8;
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(buf);
|
|
(void)Mat_uint32Swap(buf+1);
|
|
}
|
|
name_len = 0;
|
|
if ( buf[1] > 0 ) {
|
|
/* Name of variable */
|
|
if ( buf[0] == MAT_T_INT8 ) { /* Name not in tag */
|
|
name_len = buf[1];
|
|
if ( name_len % 8 > 0 )
|
|
name_len = name_len+(8-(name_len % 8));
|
|
nBytes -= name_len;
|
|
(void)fseek((FILE*)mat->fp,name_len,SEEK_CUR);
|
|
}
|
|
}
|
|
cells[i]->internal->datapos = ftell((FILE*)mat->fp);
|
|
if ( cells[i]->internal->datapos != -1L ) {
|
|
if ( cells[i]->class_type == MAT_C_STRUCT )
|
|
bytesread+=ReadNextStructField(mat,cells[i]);
|
|
if ( cells[i]->class_type == MAT_C_CELL )
|
|
bytesread+=ReadNextCell(mat,cells[i]);
|
|
(void)fseek((FILE*)mat->fp,cells[i]->internal->datapos+nBytes,SEEK_SET);
|
|
} else {
|
|
Mat_Critical("Couldn't determine file position");
|
|
}
|
|
}
|
|
}
|
|
|
|
return bytesread;
|
|
}
|
|
|
|
/** @brief Reads the next struct field of the structure in @c matvar
|
|
*
|
|
* Reads the next struct fields (fieldname length,names,data headers for all
|
|
* the fields
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar MAT variable pointer
|
|
* @return Number of bytes read
|
|
*/
|
|
static size_t
|
|
ReadNextStructField( mat_t *mat, matvar_t *matvar )
|
|
{
|
|
mat_uint32_t fieldname_size;
|
|
int err;
|
|
size_t bytesread = 0, nfields, i;
|
|
matvar_t **fields = NULL;
|
|
size_t nelems = 1, nelems_x_nfields;
|
|
|
|
err = SafeMulDims(matvar, &nelems);
|
|
if ( err ) {
|
|
Mat_Critical("Integer multiplication overflow");
|
|
return bytesread;
|
|
}
|
|
if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
#if defined(HAVE_ZLIB)
|
|
mat_uint32_t uncomp_buf[16] = {0,};
|
|
int nbytes;
|
|
mat_uint32_t array_flags;
|
|
|
|
/* Inflate Field name length */
|
|
bytesread += InflateFieldNameLength(mat,matvar,uncomp_buf);
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(uncomp_buf);
|
|
(void)Mat_uint32Swap(uncomp_buf+1);
|
|
}
|
|
if ( (uncomp_buf[0] & 0x0000ffff) == MAT_T_INT32 ) {
|
|
fieldname_size = uncomp_buf[1];
|
|
} else {
|
|
Mat_Critical("Error getting fieldname size");
|
|
return bytesread;
|
|
}
|
|
|
|
bytesread += InflateFieldNamesTag(mat,matvar,uncomp_buf);
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(uncomp_buf);
|
|
(void)Mat_uint32Swap(uncomp_buf+1);
|
|
}
|
|
nfields = uncomp_buf[1] / fieldname_size;
|
|
matvar->data_size = sizeof(matvar_t *);
|
|
|
|
if ( nfields*fieldname_size % 8 != 0 )
|
|
i = 8-(nfields*fieldname_size % 8);
|
|
else
|
|
i = 0;
|
|
if ( nfields ) {
|
|
char *ptr = (char*)malloc(nfields*fieldname_size+i);
|
|
if ( NULL != ptr ) {
|
|
bytesread += InflateFieldNames(mat,matvar,ptr,nfields,fieldname_size,i);
|
|
matvar->internal->num_fields = nfields;
|
|
matvar->internal->fieldnames =
|
|
(char**)calloc(nfields,sizeof(*matvar->internal->fieldnames));
|
|
if ( NULL != matvar->internal->fieldnames ) {
|
|
for ( i = 0; i < nfields; i++ ) {
|
|
matvar->internal->fieldnames[i] = (char*)malloc(fieldname_size);
|
|
if ( NULL != matvar->internal->fieldnames[i] ) {
|
|
memcpy(matvar->internal->fieldnames[i], ptr+i*fieldname_size, fieldname_size);
|
|
matvar->internal->fieldnames[i][fieldname_size-1] = '\0';
|
|
}
|
|
}
|
|
}
|
|
free(ptr);
|
|
}
|
|
} else {
|
|
matvar->internal->num_fields = 0;
|
|
matvar->internal->fieldnames = NULL;
|
|
}
|
|
|
|
err = SafeMul(&nelems_x_nfields, nelems, nfields);
|
|
if ( err ) {
|
|
Mat_Critical("Integer multiplication overflow");
|
|
return bytesread;
|
|
}
|
|
err = SafeMul(&matvar->nbytes, nelems_x_nfields, matvar->data_size);
|
|
if ( err ) {
|
|
Mat_Critical("Integer multiplication overflow");
|
|
return bytesread;
|
|
}
|
|
if ( !matvar->nbytes )
|
|
return bytesread;
|
|
|
|
matvar->data = calloc(nelems_x_nfields, matvar->data_size);
|
|
if ( NULL == matvar->data ) {
|
|
Mat_Critical("Couldn't allocate memory for the data");
|
|
return bytesread;
|
|
}
|
|
|
|
fields = (matvar_t**)matvar->data;
|
|
for ( i = 0; i < nelems; i++ ) {
|
|
size_t k;
|
|
for ( k = 0; k < nfields; k++ ) {
|
|
fields[i*nfields+k] = Mat_VarCalloc();
|
|
}
|
|
}
|
|
if ( NULL != matvar->internal->fieldnames ) {
|
|
for ( i = 0; i < nelems; i++ ) {
|
|
size_t k;
|
|
for ( k = 0; k < nfields; k++ ) {
|
|
if ( NULL != matvar->internal->fieldnames[k] ) {
|
|
fields[i*nfields+k]->name = strdup(matvar->internal->fieldnames[k]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( i = 0; i < nelems_x_nfields; i++ ) {
|
|
/* Read variable tag for struct field */
|
|
bytesread += InflateVarTag(mat,matvar,uncomp_buf);
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(uncomp_buf);
|
|
(void)Mat_uint32Swap(uncomp_buf+1);
|
|
}
|
|
nbytes = uncomp_buf[1];
|
|
if ( uncomp_buf[0] != MAT_T_MATRIX ) {
|
|
Mat_VarFree(fields[i]);
|
|
fields[i] = NULL;
|
|
Mat_Critical("fields[%" SIZE_T_FMTSTR "], Uncompressed type not MAT_T_MATRIX", i);
|
|
continue;
|
|
} else if ( 0 == nbytes ) {
|
|
/* Empty field: Memory optimization */
|
|
free(fields[i]->internal);
|
|
fields[i]->internal = NULL;
|
|
continue;
|
|
}
|
|
fields[i]->compression = MAT_COMPRESSION_ZLIB;
|
|
bytesread += InflateArrayFlags(mat,matvar,uncomp_buf);
|
|
nbytes -= 16;
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(uncomp_buf);
|
|
(void)Mat_uint32Swap(uncomp_buf+1);
|
|
(void)Mat_uint32Swap(uncomp_buf+2);
|
|
(void)Mat_uint32Swap(uncomp_buf+3);
|
|
}
|
|
/* Array flags */
|
|
if ( uncomp_buf[0] == MAT_T_UINT32 ) {
|
|
array_flags = uncomp_buf[2];
|
|
fields[i]->class_type = CLASS_FROM_ARRAY_FLAGS(array_flags);
|
|
fields[i]->isComplex = (array_flags & MAT_F_COMPLEX);
|
|
fields[i]->isGlobal = (array_flags & MAT_F_GLOBAL);
|
|
fields[i]->isLogical = (array_flags & MAT_F_LOGICAL);
|
|
if ( fields[i]->class_type == MAT_C_SPARSE ) {
|
|
/* Need to find a more appropriate place to store nzmax */
|
|
fields[i]->nbytes = uncomp_buf[3];
|
|
}
|
|
} else {
|
|
Mat_Critical("Expected MAT_T_UINT32 for array tags, got %d",
|
|
uncomp_buf[0]);
|
|
bytesread+=InflateSkip(mat,matvar->internal->z,nbytes);
|
|
}
|
|
if ( fields[i]->class_type != MAT_C_OPAQUE ) {
|
|
mat_uint32_t* dims = NULL;
|
|
int do_clean = 0;
|
|
bytesread += InflateRankDims(mat,matvar,uncomp_buf,sizeof(uncomp_buf),&dims);
|
|
if ( NULL == dims )
|
|
dims = uncomp_buf + 2;
|
|
else
|
|
do_clean = 1;
|
|
nbytes -= 8;
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(uncomp_buf);
|
|
(void)Mat_uint32Swap(uncomp_buf+1);
|
|
}
|
|
/* Rank and dimension */
|
|
if ( uncomp_buf[0] == MAT_T_INT32 ) {
|
|
int j;
|
|
fields[i]->rank = uncomp_buf[1];
|
|
nbytes -= fields[i]->rank;
|
|
fields[i]->rank /= 4;
|
|
fields[i]->dims = (size_t*)malloc(fields[i]->rank*
|
|
sizeof(*fields[i]->dims));
|
|
if ( mat->byteswap ) {
|
|
for ( j = 0; j < fields[i]->rank; j++ )
|
|
fields[i]->dims[j] = Mat_uint32Swap(dims+j);
|
|
} else {
|
|
for ( j = 0; j < fields[i]->rank; j++ )
|
|
fields[i]->dims[j] = dims[j];
|
|
}
|
|
if ( fields[i]->rank % 2 != 0 )
|
|
nbytes -= 4;
|
|
}
|
|
if ( do_clean )
|
|
free(dims);
|
|
bytesread += InflateVarNameTag(mat,matvar,uncomp_buf);
|
|
nbytes -= 8;
|
|
fields[i]->internal->z = (z_streamp)calloc(1,sizeof(z_stream));
|
|
if ( fields[i]->internal->z != NULL ) {
|
|
err = inflateCopy(fields[i]->internal->z,matvar->internal->z);
|
|
if ( err == Z_OK ) {
|
|
fields[i]->internal->datapos = ftell((FILE*)mat->fp);
|
|
if ( fields[i]->internal->datapos != -1L ) {
|
|
fields[i]->internal->datapos -= matvar->internal->z->avail_in;
|
|
if ( fields[i]->class_type == MAT_C_STRUCT )
|
|
bytesread+=ReadNextStructField(mat,fields[i]);
|
|
else if ( fields[i]->class_type == MAT_C_CELL )
|
|
bytesread+=ReadNextCell(mat,fields[i]);
|
|
else if ( nbytes <= (1 << MAX_WBITS) ) {
|
|
/* Memory optimization: Read data if less in size
|
|
than the zlib inflate state (approximately) */
|
|
Mat_VarRead5(mat,fields[i]);
|
|
fields[i]->internal->data = fields[i]->data;
|
|
fields[i]->data = NULL;
|
|
}
|
|
(void)fseek((FILE*)mat->fp,fields[i]->internal->datapos,SEEK_SET);
|
|
} else {
|
|
Mat_Critical("Couldn't determine file position");
|
|
}
|
|
if ( fields[i]->internal->data != NULL ||
|
|
fields[i]->class_type == MAT_C_STRUCT ||
|
|
fields[i]->class_type == MAT_C_CELL ) {
|
|
/* Memory optimization: Free inflate state */
|
|
inflateEnd(fields[i]->internal->z);
|
|
free(fields[i]->internal->z);
|
|
fields[i]->internal->z = NULL;
|
|
}
|
|
} else {
|
|
Mat_Critical("inflateCopy returned error %s",zError(err));
|
|
}
|
|
} else {
|
|
Mat_Critical("Couldn't allocate memory");
|
|
}
|
|
}
|
|
bytesread+=InflateSkip(mat,matvar->internal->z,nbytes);
|
|
}
|
|
#else
|
|
Mat_Critical("Not compiled with zlib support");
|
|
#endif
|
|
} else {
|
|
mat_uint32_t buf[6];
|
|
int nBytes;
|
|
mat_uint32_t array_flags;
|
|
|
|
bytesread+=fread(buf,4,2,(FILE*)mat->fp);
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(buf);
|
|
(void)Mat_uint32Swap(buf+1);
|
|
}
|
|
if ( (buf[0] & 0x0000ffff) == MAT_T_INT32 ) {
|
|
fieldname_size = buf[1];
|
|
} else {
|
|
Mat_Critical("Error getting fieldname size");
|
|
return bytesread;
|
|
}
|
|
bytesread+=fread(buf,4,2,(FILE*)mat->fp);
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(buf);
|
|
(void)Mat_uint32Swap(buf+1);
|
|
}
|
|
nfields = buf[1] / fieldname_size;
|
|
matvar->data_size = sizeof(matvar_t *);
|
|
|
|
if ( nfields ) {
|
|
matvar->internal->num_fields = nfields;
|
|
matvar->internal->fieldnames =
|
|
(char**)calloc(nfields,sizeof(*matvar->internal->fieldnames));
|
|
if ( NULL != matvar->internal->fieldnames ) {
|
|
for ( i = 0; i < nfields; i++ ) {
|
|
matvar->internal->fieldnames[i] = (char*)malloc(fieldname_size);
|
|
if ( NULL != matvar->internal->fieldnames[i] ) {
|
|
bytesread+=fread(matvar->internal->fieldnames[i],1,fieldname_size,(FILE*)mat->fp);
|
|
matvar->internal->fieldnames[i][fieldname_size-1] = '\0';
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
matvar->internal->num_fields = 0;
|
|
matvar->internal->fieldnames = NULL;
|
|
}
|
|
|
|
if ( (nfields*fieldname_size) % 8 ) {
|
|
(void)fseek((FILE*)mat->fp,8-((nfields*fieldname_size) % 8),SEEK_CUR);
|
|
bytesread+=8-((nfields*fieldname_size) % 8);
|
|
}
|
|
|
|
err = SafeMul(&nelems_x_nfields, nelems, nfields);
|
|
if ( err ) {
|
|
Mat_Critical("Integer multiplication overflow");
|
|
return bytesread;
|
|
}
|
|
err = SafeMul(&matvar->nbytes, nelems_x_nfields, matvar->data_size);
|
|
if ( err ) {
|
|
Mat_Critical("Integer multiplication overflow");
|
|
return bytesread;
|
|
}
|
|
if ( !matvar->nbytes )
|
|
return bytesread;
|
|
|
|
matvar->data = malloc(matvar->nbytes);
|
|
if ( NULL == matvar->data )
|
|
return bytesread;
|
|
|
|
fields = (matvar_t**)matvar->data;
|
|
for ( i = 0; i < nelems; i++ ) {
|
|
size_t k;
|
|
for ( k = 0; k < nfields; k++ ) {
|
|
fields[i*nfields+k] = Mat_VarCalloc();
|
|
}
|
|
}
|
|
if ( NULL != matvar->internal->fieldnames ) {
|
|
for ( i = 0; i < nelems; i++ ) {
|
|
size_t k;
|
|
for ( k = 0; k < nfields; k++ ) {
|
|
if ( NULL != matvar->internal->fieldnames[k] ) {
|
|
fields[i*nfields+k]->name = strdup(matvar->internal->fieldnames[k]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( i = 0; i < nelems_x_nfields; i++ ) {
|
|
/* Read variable tag for struct field */
|
|
bytesread += fread(buf,4,2,(FILE*)mat->fp);
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(buf);
|
|
(void)Mat_uint32Swap(buf+1);
|
|
}
|
|
nBytes = buf[1];
|
|
if ( buf[0] != MAT_T_MATRIX ) {
|
|
Mat_VarFree(fields[i]);
|
|
fields[i] = NULL;
|
|
Mat_Critical("fields[%" SIZE_T_FMTSTR "] not MAT_T_MATRIX, fpos = %ld", i,
|
|
ftell((FILE*)mat->fp));
|
|
return bytesread;
|
|
} else if ( 0 == nBytes ) {
|
|
/* Empty field: Memory optimization */
|
|
free(fields[i]->internal);
|
|
fields[i]->internal = NULL;
|
|
continue;
|
|
}
|
|
|
|
/* Read array flags and the dimensions tag */
|
|
bytesread += fread(buf,4,6,(FILE*)mat->fp);
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(buf);
|
|
(void)Mat_uint32Swap(buf+1);
|
|
(void)Mat_uint32Swap(buf+2);
|
|
(void)Mat_uint32Swap(buf+3);
|
|
(void)Mat_uint32Swap(buf+4);
|
|
(void)Mat_uint32Swap(buf+5);
|
|
}
|
|
nBytes-=24;
|
|
/* Array flags */
|
|
if ( buf[0] == MAT_T_UINT32 ) {
|
|
array_flags = buf[2];
|
|
fields[i]->class_type = CLASS_FROM_ARRAY_FLAGS(array_flags);
|
|
fields[i]->isComplex = (array_flags & MAT_F_COMPLEX);
|
|
fields[i]->isGlobal = (array_flags & MAT_F_GLOBAL);
|
|
fields[i]->isLogical = (array_flags & MAT_F_LOGICAL);
|
|
if ( fields[i]->class_type == MAT_C_SPARSE ) {
|
|
/* Need to find a more appropriate place to store nzmax */
|
|
fields[i]->nbytes = buf[3];
|
|
}
|
|
}
|
|
/* Rank and dimension */
|
|
{
|
|
size_t nbytes = ReadRankDims(mat, fields[i], (enum matio_types)buf[4], buf[5]);
|
|
bytesread += nbytes;
|
|
nBytes -= nbytes;
|
|
}
|
|
/* Variable name tag */
|
|
bytesread+=fread(buf,1,8,(FILE*)mat->fp);
|
|
nBytes-=8;
|
|
fields[i]->internal->datapos = ftell((FILE*)mat->fp);
|
|
if ( fields[i]->internal->datapos != -1L ) {
|
|
if ( fields[i]->class_type == MAT_C_STRUCT )
|
|
bytesread+=ReadNextStructField(mat,fields[i]);
|
|
else if ( fields[i]->class_type == MAT_C_CELL )
|
|
bytesread+=ReadNextCell(mat,fields[i]);
|
|
(void)fseek((FILE*)mat->fp,fields[i]->internal->datapos+nBytes,SEEK_SET);
|
|
} else {
|
|
Mat_Critical("Couldn't determine file position");
|
|
}
|
|
}
|
|
}
|
|
|
|
return bytesread;
|
|
}
|
|
|
|
/** @brief Reads the function handle data of the function handle in @c matvar
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar MAT variable pointer
|
|
* @return Number of bytes read
|
|
*/
|
|
static size_t
|
|
ReadNextFunctionHandle(mat_t *mat, matvar_t *matvar)
|
|
{
|
|
size_t nelems = 1;
|
|
|
|
SafeMulDims(matvar, &nelems);
|
|
matvar->data_size = sizeof(matvar_t *);
|
|
SafeMul(&matvar->nbytes, nelems, matvar->data_size);
|
|
matvar->data = malloc(matvar->nbytes);
|
|
if ( matvar->data != NULL ) {
|
|
size_t i;
|
|
matvar_t **functions = (matvar_t**)matvar->data;;
|
|
for ( i = 0; i < nelems; i++ )
|
|
functions[i] = Mat_VarReadNextInfo(mat);
|
|
} else {
|
|
matvar->data_size = 0;
|
|
matvar->nbytes = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/** @brief Reads the rank and dimensions in @c matvar
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar MAT variable pointer
|
|
* @param data_type data type of dimension array
|
|
* @param nbytes len of dimension array in bytes
|
|
* @return Number of bytes read
|
|
*/
|
|
static size_t
|
|
ReadRankDims(mat_t *mat, matvar_t *matvar, enum matio_types data_type, mat_uint32_t nbytes)
|
|
{
|
|
size_t bytesread = 0;
|
|
/* Rank and dimension */
|
|
if ( data_type == MAT_T_INT32 ) {
|
|
matvar->rank = nbytes / sizeof(mat_uint32_t);
|
|
matvar->dims = (size_t*)malloc(matvar->rank*sizeof(*matvar->dims));
|
|
if ( NULL != matvar->dims ) {
|
|
int i;
|
|
mat_uint32_t buf;
|
|
|
|
for ( i = 0; i < matvar->rank; i++) {
|
|
size_t readresult = fread(&buf, sizeof(mat_uint32_t), 1, (FILE*)mat->fp);
|
|
if ( 1 == readresult ) {
|
|
bytesread += sizeof(mat_uint32_t);
|
|
if ( mat->byteswap ) {
|
|
matvar->dims[i] = Mat_uint32Swap(&buf);
|
|
} else {
|
|
matvar->dims[i] = buf;
|
|
}
|
|
} else {
|
|
free(matvar->dims);
|
|
matvar->dims = NULL;
|
|
matvar->rank = 0;
|
|
Mat_Critical("An error occurred in reading the MAT file");
|
|
return bytesread;
|
|
}
|
|
}
|
|
|
|
if ( matvar->rank % 2 != 0 ) {
|
|
size_t readresult = fread(&buf, sizeof(mat_uint32_t), 1, (FILE*)mat->fp);
|
|
if ( 1 == readresult ) {
|
|
bytesread += sizeof(mat_uint32_t);
|
|
} else {
|
|
Mat_Critical("An error occurred in reading the MAT file");
|
|
}
|
|
}
|
|
} else {
|
|
matvar->rank = 0;
|
|
Mat_Critical("Error allocating memory for dims");
|
|
}
|
|
}
|
|
return bytesread;
|
|
}
|
|
|
|
/** @brief Writes the header and data for a given type
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar pointer to the mat variable
|
|
* @retval 0 on success
|
|
*/
|
|
static int
|
|
WriteType(mat_t *mat,matvar_t *matvar)
|
|
{
|
|
mat_int16_t array_name_type = MAT_T_INT8;
|
|
mat_int8_t pad1 = 0;
|
|
int nBytes, j;
|
|
size_t nelems = 1;
|
|
|
|
SafeMulDims(matvar, &nelems);
|
|
|
|
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 ( matvar->isComplex ) {
|
|
mat_complex_split_t *complex_data = (mat_complex_split_t*)matvar->data;
|
|
|
|
if ( NULL == matvar->data )
|
|
complex_data = &null_complex_data;
|
|
|
|
nBytes=WriteData(mat,complex_data->Re,nelems,matvar->data_type);
|
|
if ( nBytes % 8 )
|
|
for ( j = nBytes % 8; j < 8; j++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
nBytes=WriteData(mat,complex_data->Im,nelems,matvar->data_type);
|
|
if ( nBytes % 8 )
|
|
for ( j = nBytes % 8; j < 8; j++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
} else {
|
|
nBytes=WriteData(mat,matvar->data,nelems,matvar->data_type);
|
|
if ( nBytes % 8 )
|
|
for ( j = nBytes % 8; j < 8; j++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
}
|
|
break;
|
|
}
|
|
case MAT_C_CHAR:
|
|
nBytes=WriteCharData(mat,matvar->data,nelems,matvar->data_type);
|
|
break;
|
|
case MAT_C_CELL:
|
|
{
|
|
size_t i;
|
|
matvar_t **cells = (matvar_t **)matvar->data;
|
|
|
|
/* Check for an empty cell array */
|
|
if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
|
|
matvar->data == NULL )
|
|
break;
|
|
nelems = matvar->nbytes / matvar->data_size;
|
|
for ( i = 0; i < nelems; i++ )
|
|
WriteCellArrayField(mat,cells[i]);
|
|
break;
|
|
}
|
|
case MAT_C_STRUCT:
|
|
{
|
|
mat_int16_t fieldname_type = MAT_T_INT32;
|
|
mat_int16_t fieldname_data_size = 4;
|
|
char *padzero;
|
|
int fieldname_size;
|
|
size_t maxlen = 0, nfields, i, nelems_x_nfields;
|
|
matvar_t **fields = (matvar_t **)matvar->data;
|
|
unsigned fieldname;
|
|
|
|
/* nelems*matvar->data_size can be zero when saving a struct that
|
|
* contains an empty struct in one of its fields
|
|
* (e.g. x.y = struct('z', {})). If it's zero, we would divide
|
|
* by zero.
|
|
*/
|
|
nfields = matvar->internal->num_fields;
|
|
/* Check for a structure with no fields */
|
|
if ( nfields < 1 ) {
|
|
#if 0
|
|
fwrite(&fieldname_type,2,1,(FILE*)mat->fp);
|
|
fwrite(&fieldname_data_size,2,1,(FILE*)mat->fp);
|
|
#else
|
|
fieldname = (fieldname_data_size<<16) | fieldname_type;
|
|
fwrite(&fieldname,4,1,(FILE*)mat->fp);
|
|
#endif
|
|
fieldname_size = 1;
|
|
fwrite(&fieldname_size,4,1,(FILE*)mat->fp);
|
|
fwrite(&array_name_type,2,1,(FILE*)mat->fp);
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
nBytes = 0;
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
break;
|
|
}
|
|
|
|
for ( i = 0; i < nfields; i++ ) {
|
|
size_t len = strlen(matvar->internal->fieldnames[i]);
|
|
if ( len > maxlen )
|
|
maxlen = len;
|
|
}
|
|
maxlen++;
|
|
fieldname_size = maxlen;
|
|
while ( nfields*fieldname_size % 8 != 0 )
|
|
fieldname_size++;
|
|
#if 0
|
|
fwrite(&fieldname_type,2,1,(FILE*)mat->fp);
|
|
fwrite(&fieldname_data_size,2,1,(FILE*)mat->fp);
|
|
#else
|
|
fieldname = (fieldname_data_size<<16) | fieldname_type;
|
|
fwrite(&fieldname,4,1,(FILE*)mat->fp);
|
|
#endif
|
|
fwrite(&fieldname_size,4,1,(FILE*)mat->fp);
|
|
fwrite(&array_name_type,2,1,(FILE*)mat->fp);
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
nBytes = nfields*fieldname_size;
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
padzero = (char*)calloc(fieldname_size,1);
|
|
for ( i = 0; i < nfields; i++ ) {
|
|
size_t len = strlen(matvar->internal->fieldnames[i]);
|
|
fwrite(matvar->internal->fieldnames[i],1,len,(FILE*)mat->fp);
|
|
fwrite(padzero,1,fieldname_size-len,(FILE*)mat->fp);
|
|
}
|
|
free(padzero);
|
|
SafeMul(&nelems_x_nfields, nelems, nfields);
|
|
for ( i = 0; i < nelems_x_nfields; i++ )
|
|
WriteStructField(mat,fields[i]);
|
|
break;
|
|
}
|
|
case MAT_C_SPARSE:
|
|
{
|
|
mat_sparse_t *sparse = (mat_sparse_t*)matvar->data;
|
|
|
|
nBytes = WriteData(mat,sparse->ir,sparse->nir,MAT_T_INT32);
|
|
if ( nBytes % 8 )
|
|
for ( j = nBytes % 8; j < 8; j++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
nBytes = WriteData(mat,sparse->jc,sparse->njc,MAT_T_INT32);
|
|
if ( nBytes % 8 )
|
|
for ( j = nBytes % 8; j < 8; j++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
if ( matvar->isComplex ) {
|
|
mat_complex_split_t *complex_data = (mat_complex_split_t*)sparse->data;
|
|
nBytes = WriteData(mat,complex_data->Re,sparse->ndata,
|
|
matvar->data_type);
|
|
if ( nBytes % 8 )
|
|
for ( j = nBytes % 8; j < 8; j++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
nBytes = WriteData(mat,complex_data->Im,sparse->ndata,
|
|
matvar->data_type);
|
|
if ( nBytes % 8 )
|
|
for ( j = nBytes % 8; j < 8; j++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
} else {
|
|
nBytes = WriteData(mat,sparse->data,sparse->ndata,
|
|
matvar->data_type);
|
|
if ( nBytes % 8 )
|
|
for ( j = nBytes % 8; j < 8; j++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
}
|
|
}
|
|
case MAT_C_FUNCTION:
|
|
case MAT_C_OBJECT:
|
|
case MAT_C_EMPTY:
|
|
case MAT_C_OPAQUE:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/** @brief Writes the header and data for an element of a cell array
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar pointer to the mat variable
|
|
* @retval 0 on success
|
|
*/
|
|
static int
|
|
WriteCellArrayField(mat_t *mat,matvar_t *matvar)
|
|
{
|
|
mat_uint32_t array_flags;
|
|
mat_int16_t array_name_type = MAT_T_INT8;
|
|
int array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
|
|
int array_flags_size = 8, pad4 = 0, matrix_type = MAT_T_MATRIX;
|
|
const mat_int8_t pad1 = 0;
|
|
int nBytes, i, nzmax = 0;
|
|
long start = 0, end = 0;
|
|
|
|
if ( matvar == NULL || mat == NULL )
|
|
return 1;
|
|
|
|
#if 0
|
|
nBytes = GetMatrixMaxBufSize(matvar);
|
|
#endif
|
|
|
|
fwrite(&matrix_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&pad4,4,1,(FILE*)mat->fp);
|
|
if ( MAT_C_EMPTY == matvar->class_type ) {
|
|
/* exit early if this is an empty data */
|
|
return 0;
|
|
}
|
|
start = ftell((FILE*)mat->fp);
|
|
|
|
/* Array Flags */
|
|
array_flags = matvar->class_type & CLASS_TYPE_MASK;
|
|
if ( matvar->isComplex )
|
|
array_flags |= MAT_F_COMPLEX;
|
|
if ( matvar->isGlobal )
|
|
array_flags |= MAT_F_GLOBAL;
|
|
if ( matvar->isLogical )
|
|
array_flags |= MAT_F_LOGICAL;
|
|
if ( matvar->class_type == MAT_C_SPARSE )
|
|
nzmax = ((mat_sparse_t *)matvar->data)->nzmax;
|
|
|
|
if ( mat->byteswap )
|
|
array_flags = Mat_int32Swap((mat_int32_t*)&array_flags);
|
|
fwrite(&array_flags_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&array_flags_size,4,1,(FILE*)mat->fp);
|
|
fwrite(&array_flags,4,1,(FILE*)mat->fp);
|
|
fwrite(&nzmax,4,1,(FILE*)mat->fp);
|
|
/* Rank and Dimension */
|
|
nBytes = matvar->rank * 4;
|
|
fwrite(&dims_array_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
for ( i = 0; i < matvar->rank; i++ ) {
|
|
mat_int32_t dim;
|
|
dim = matvar->dims[i];
|
|
fwrite(&dim,4,1,(FILE*)mat->fp);
|
|
}
|
|
if ( matvar->rank % 2 != 0 )
|
|
fwrite(&pad4,4,1,(FILE*)mat->fp);
|
|
/* Name of variable */
|
|
if ( !matvar->name ) {
|
|
fwrite(&array_name_type,2,1,(FILE*)mat->fp);
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
fwrite(&pad4,4,1,(FILE*)mat->fp);
|
|
} else if ( strlen(matvar->name) <= 4 ) {
|
|
mat_int16_t array_name_len = (mat_int16_t)strlen(matvar->name);
|
|
fwrite(&array_name_type,2,1,(FILE*)mat->fp);
|
|
fwrite(&array_name_len,2,1,(FILE*)mat->fp);
|
|
fwrite(matvar->name,1,array_name_len,(FILE*)mat->fp);
|
|
for ( i = array_name_len; i < 4; i++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
} else {
|
|
mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
|
|
fwrite(&array_name_type,2,1,(FILE*)mat->fp);
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
fwrite(&array_name_len,4,1,(FILE*)mat->fp);
|
|
fwrite(matvar->name,1,array_name_len,(FILE*)mat->fp);
|
|
if ( array_name_len % 8 )
|
|
for ( i = array_name_len % 8; i < 8; i++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
}
|
|
|
|
WriteType(mat,matvar);
|
|
end = ftell((FILE*)mat->fp);
|
|
if ( start != -1L && end != -1L ) {
|
|
nBytes = (int)(end-start);
|
|
(void)fseek((FILE*)mat->fp,(long)-(nBytes+4),SEEK_CUR);
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
(void)fseek((FILE*)mat->fp,end,SEEK_SET);
|
|
} else {
|
|
Mat_Critical("Couldn't determine file position");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if defined(HAVE_ZLIB)
|
|
/** @brief Writes the header and data for a given class type
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar pointer to the mat variable
|
|
* @return number of bytes written to the MAT file
|
|
*/
|
|
static size_t
|
|
WriteCompressedTypeArrayFlags(mat_t *mat,matvar_t *matvar,z_streamp z)
|
|
{
|
|
mat_uint32_t array_flags;
|
|
mat_int16_t array_name_type = MAT_T_INT8;
|
|
int array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
|
|
int array_flags_size = 8;
|
|
int nBytes, i, nzmax = 0;
|
|
|
|
mat_uint32_t comp_buf[512];
|
|
mat_uint32_t uncomp_buf[512] = {0,};
|
|
int buf_size = 512;
|
|
size_t byteswritten = 0;
|
|
|
|
if ( MAT_C_EMPTY == matvar->class_type ) {
|
|
/* exit early if this is an empty data */
|
|
return byteswritten;
|
|
}
|
|
|
|
/* Array Flags */
|
|
array_flags = matvar->class_type & CLASS_TYPE_MASK;
|
|
if ( matvar->isComplex )
|
|
array_flags |= MAT_F_COMPLEX;
|
|
if ( matvar->isGlobal )
|
|
array_flags |= MAT_F_GLOBAL;
|
|
if ( matvar->isLogical )
|
|
array_flags |= MAT_F_LOGICAL;
|
|
if ( matvar->class_type == MAT_C_SPARSE )
|
|
nzmax = ((mat_sparse_t *)matvar->data)->nzmax;
|
|
uncomp_buf[0] = array_flags_type;
|
|
uncomp_buf[1] = array_flags_size;
|
|
uncomp_buf[2] = array_flags;
|
|
uncomp_buf[3] = nzmax;
|
|
/* Rank and Dimension */
|
|
nBytes = matvar->rank * 4;
|
|
uncomp_buf[4] = dims_array_type;
|
|
uncomp_buf[5] = nBytes;
|
|
for ( i = 0; i < matvar->rank; i++ ) {
|
|
mat_int32_t dim;
|
|
dim = matvar->dims[i];
|
|
uncomp_buf[6+i] = dim;
|
|
}
|
|
if ( matvar->rank % 2 != 0 ) {
|
|
int pad4 = 0;
|
|
uncomp_buf[6+i] = pad4;
|
|
i++;
|
|
}
|
|
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = (6+i)*sizeof(*uncomp_buf);
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size*sizeof(*comp_buf);
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
|
|
(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
/* Name of variable */
|
|
uncomp_buf[0] = array_name_type;
|
|
uncomp_buf[1] = 0;
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = 8;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size*sizeof(*comp_buf);
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
|
|
(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
|
|
matvar->internal->datapos = ftell((FILE*)mat->fp);
|
|
if ( matvar->internal->datapos == -1L ) {
|
|
Mat_Critical("Couldn't determine file position");
|
|
}
|
|
|
|
byteswritten += WriteCompressedType(mat,matvar,z);
|
|
return byteswritten;
|
|
}
|
|
|
|
/** @brief Writes the header and data for a given class type
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar pointer to the mat variable
|
|
* @return number of bytes written to the MAT file
|
|
*/
|
|
static size_t
|
|
WriteCompressedType(mat_t *mat,matvar_t *matvar,z_streamp z)
|
|
{
|
|
mat_uint32_t comp_buf[512];
|
|
mat_uint32_t uncomp_buf[512] = {0,};
|
|
size_t byteswritten = 0, nelems = 1;
|
|
|
|
if ( MAT_C_EMPTY == matvar->class_type ) {
|
|
/* exit early if this is an empty data */
|
|
return byteswritten;
|
|
}
|
|
|
|
SafeMulDims(matvar, &nelems);
|
|
|
|
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:
|
|
{
|
|
/* WriteCompressedData makes sure uncompressed data is aligned
|
|
* on an 8-byte boundary */
|
|
if ( matvar->isComplex ) {
|
|
mat_complex_split_t *complex_data = (mat_complex_split_t*)matvar->data;
|
|
|
|
if ( NULL == matvar->data )
|
|
complex_data = &null_complex_data;
|
|
|
|
byteswritten += WriteCompressedData(mat,z,
|
|
complex_data->Re,nelems,matvar->data_type);
|
|
byteswritten += WriteCompressedData(mat,z,
|
|
complex_data->Im,nelems,matvar->data_type);
|
|
} else {
|
|
byteswritten += WriteCompressedData(mat,z,
|
|
matvar->data,nelems,matvar->data_type);
|
|
}
|
|
break;
|
|
}
|
|
case MAT_C_CHAR:
|
|
{
|
|
byteswritten += WriteCompressedCharData(mat,z,matvar->data,
|
|
nelems,matvar->data_type);
|
|
break;
|
|
}
|
|
case MAT_C_CELL:
|
|
{
|
|
size_t i;
|
|
matvar_t **cells = (matvar_t **)matvar->data;
|
|
|
|
/* Check for an empty cell array */
|
|
if ( matvar->nbytes == 0 || matvar->data_size == 0 ||
|
|
matvar->data == NULL )
|
|
break;
|
|
nelems = matvar->nbytes / matvar->data_size;
|
|
for ( i = 0; i < nelems; i++ )
|
|
WriteCompressedCellArrayField(mat,cells[i],z);
|
|
break;
|
|
}
|
|
case MAT_C_STRUCT:
|
|
{
|
|
int buf_size = 512;
|
|
mat_int16_t fieldname_type = MAT_T_INT32;
|
|
mat_int16_t fieldname_data_size = 4;
|
|
unsigned char *padzero;
|
|
int fieldname_size;
|
|
size_t maxlen = 0, nfields, i, nelems_x_nfields;
|
|
mat_int32_t array_name_type = MAT_T_INT8;
|
|
matvar_t **fields = (matvar_t **)matvar->data;
|
|
|
|
nfields = matvar->internal->num_fields;
|
|
/* Check for a structure with no fields */
|
|
if ( nfields < 1 ) {
|
|
fieldname_size = 1;
|
|
uncomp_buf[0] = (fieldname_data_size << 16) | fieldname_type;
|
|
uncomp_buf[1] = fieldname_size;
|
|
uncomp_buf[2] = array_name_type;
|
|
uncomp_buf[3] = 0;
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = 16;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size*sizeof(*comp_buf);
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,buf_size*
|
|
sizeof(*comp_buf)-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
break;
|
|
}
|
|
|
|
for ( i = 0; i < nfields; i++ ) {
|
|
size_t len = strlen(matvar->internal->fieldnames[i]);
|
|
if ( len > maxlen )
|
|
maxlen = len;
|
|
}
|
|
maxlen++;
|
|
fieldname_size = maxlen;
|
|
while ( nfields*fieldname_size % 8 != 0 )
|
|
fieldname_size++;
|
|
uncomp_buf[0] = (fieldname_data_size << 16) | fieldname_type;
|
|
uncomp_buf[1] = fieldname_size;
|
|
uncomp_buf[2] = array_name_type;
|
|
uncomp_buf[3] = nfields*fieldname_size;
|
|
|
|
padzero = (unsigned char*)calloc(fieldname_size,1);
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = 16;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size*sizeof(*comp_buf);
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,
|
|
buf_size*sizeof(*comp_buf)-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
for ( i = 0; i < nfields; i++ ) {
|
|
size_t len = strlen(matvar->internal->fieldnames[i]);
|
|
memset(padzero,'\0',fieldname_size);
|
|
memcpy(padzero,matvar->internal->fieldnames[i],len);
|
|
z->next_in = ZLIB_BYTE_PTR(padzero);
|
|
z->avail_in = fieldname_size;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size*sizeof(*comp_buf);
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,
|
|
buf_size*sizeof(*comp_buf)-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
}
|
|
free(padzero);
|
|
SafeMul(&nelems_x_nfields, nelems, nfields);
|
|
for ( i = 0; i < nelems_x_nfields; i++ )
|
|
byteswritten += WriteCompressedStructField(mat,fields[i],z);
|
|
break;
|
|
}
|
|
case MAT_C_SPARSE:
|
|
{
|
|
mat_sparse_t *sparse = (mat_sparse_t*)matvar->data;
|
|
|
|
byteswritten += WriteCompressedData(mat,z,sparse->ir,
|
|
sparse->nir,MAT_T_INT32);
|
|
byteswritten += WriteCompressedData(mat,z,sparse->jc,
|
|
sparse->njc,MAT_T_INT32);
|
|
if ( matvar->isComplex ) {
|
|
mat_complex_split_t *complex_data = (mat_complex_split_t*)sparse->data;
|
|
byteswritten += WriteCompressedData(mat,z,
|
|
complex_data->Re,sparse->ndata,matvar->data_type);
|
|
byteswritten += WriteCompressedData(mat,z,
|
|
complex_data->Im,sparse->ndata,matvar->data_type);
|
|
} else {
|
|
byteswritten += WriteCompressedData(mat,z,
|
|
sparse->data,sparse->ndata,matvar->data_type);
|
|
}
|
|
break;
|
|
}
|
|
case MAT_C_FUNCTION:
|
|
case MAT_C_OBJECT:
|
|
case MAT_C_EMPTY:
|
|
case MAT_C_OPAQUE:
|
|
break;
|
|
}
|
|
|
|
return byteswritten;
|
|
}
|
|
|
|
/** @brief Writes the header and data for a field of a compressed cell array
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar pointer to the mat variable
|
|
* @return number of bytes written to the MAT file
|
|
*/
|
|
static size_t
|
|
WriteCompressedCellArrayField(mat_t *mat,matvar_t *matvar,z_streamp z)
|
|
{
|
|
mat_uint32_t comp_buf[512];
|
|
mat_uint32_t uncomp_buf[512] = {0,};
|
|
int buf_size = 512;
|
|
size_t byteswritten = 0;
|
|
|
|
if ( NULL == matvar || NULL == mat || NULL == z)
|
|
return 0;
|
|
|
|
uncomp_buf[0] = MAT_T_MATRIX;
|
|
if ( MAT_C_EMPTY != matvar->class_type ) {
|
|
uncomp_buf[1] = (int)GetCellArrayFieldBufSize(matvar);
|
|
} else {
|
|
uncomp_buf[1] = 0;
|
|
}
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = 8;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size*sizeof(*comp_buf);
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
|
|
(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
|
|
byteswritten += WriteCompressedTypeArrayFlags(mat,matvar,z);
|
|
return byteswritten;
|
|
}
|
|
#endif
|
|
|
|
/** @brief Writes the header and data for a field of a struct array
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar pointer to the mat variable
|
|
* @retval 0 on success
|
|
*/
|
|
static int
|
|
WriteStructField(mat_t *mat,matvar_t *matvar)
|
|
{
|
|
mat_uint32_t array_flags;
|
|
mat_int32_t array_name_type = MAT_T_INT8;
|
|
int array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
|
|
int array_flags_size = 8, pad4 = 0, matrix_type = MAT_T_MATRIX;
|
|
int nBytes, i, nzmax = 0;
|
|
long start = 0, end = 0;
|
|
|
|
if ( mat == NULL )
|
|
return 1;
|
|
|
|
if ( NULL == matvar ) {
|
|
size_t dims[2] = {0,0};
|
|
Mat_WriteEmptyVariable5(mat, NULL, 2, dims);
|
|
return 0;
|
|
}
|
|
|
|
fwrite(&matrix_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&pad4,4,1,(FILE*)mat->fp);
|
|
if ( MAT_C_EMPTY == matvar->class_type ) {
|
|
/* exit early if this is an empty data */
|
|
return 0;
|
|
}
|
|
start = ftell((FILE*)mat->fp);
|
|
|
|
/* Array Flags */
|
|
array_flags = matvar->class_type & CLASS_TYPE_MASK;
|
|
if ( matvar->isComplex )
|
|
array_flags |= MAT_F_COMPLEX;
|
|
if ( matvar->isGlobal )
|
|
array_flags |= MAT_F_GLOBAL;
|
|
if ( matvar->isLogical )
|
|
array_flags |= MAT_F_LOGICAL;
|
|
if ( matvar->class_type == MAT_C_SPARSE )
|
|
nzmax = ((mat_sparse_t *)matvar->data)->nzmax;
|
|
|
|
if ( mat->byteswap )
|
|
array_flags = Mat_int32Swap((mat_int32_t*)&array_flags);
|
|
fwrite(&array_flags_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&array_flags_size,4,1,(FILE*)mat->fp);
|
|
fwrite(&array_flags,4,1,(FILE*)mat->fp);
|
|
fwrite(&nzmax,4,1,(FILE*)mat->fp);
|
|
/* Rank and Dimension */
|
|
nBytes = matvar->rank * 4;
|
|
fwrite(&dims_array_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
for ( i = 0; i < matvar->rank; i++ ) {
|
|
mat_int32_t dim;
|
|
dim = matvar->dims[i];
|
|
fwrite(&dim,4,1,(FILE*)mat->fp);
|
|
}
|
|
if ( matvar->rank % 2 != 0 )
|
|
fwrite(&pad4,4,1,(FILE*)mat->fp);
|
|
|
|
/* Name of variable */
|
|
fwrite(&array_name_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&pad4,4,1,(FILE*)mat->fp);
|
|
|
|
WriteType(mat,matvar);
|
|
end = ftell((FILE*)mat->fp);
|
|
if ( start != -1L && end != -1L ) {
|
|
nBytes = (int)(end-start);
|
|
(void)fseek((FILE*)mat->fp,(long)-(nBytes+4),SEEK_CUR);
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
(void)fseek((FILE*)mat->fp,end,SEEK_SET);
|
|
} else {
|
|
Mat_Critical("Couldn't determine file position");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if defined(HAVE_ZLIB)
|
|
/** @brief Writes the header and data for a field of a compressed struct array
|
|
*
|
|
* @ingroup mat_internal
|
|
* @fixme Currently does not work for cell arrays or sparse data
|
|
* @param mat MAT file pointer
|
|
* @param matvar pointer to the mat variable
|
|
* @return number of bytes written to the MAT file
|
|
*/
|
|
static size_t
|
|
WriteCompressedStructField(mat_t *mat,matvar_t *matvar,z_streamp z)
|
|
{
|
|
mat_uint32_t comp_buf[512];
|
|
mat_uint32_t uncomp_buf[512] = {0,};
|
|
int buf_size = 512;
|
|
size_t byteswritten = 0;
|
|
|
|
if ( NULL == mat || NULL == z)
|
|
return 0;
|
|
|
|
if ( NULL == matvar ) {
|
|
size_t dims[2] = {0,0};
|
|
byteswritten = Mat_WriteCompressedEmptyVariable5(mat, NULL, 2, dims, z);
|
|
return byteswritten;
|
|
}
|
|
|
|
uncomp_buf[0] = MAT_T_MATRIX;
|
|
if ( MAT_C_EMPTY != matvar->class_type ) {
|
|
uncomp_buf[1] = (int)GetStructFieldBufSize(matvar);
|
|
} else {
|
|
uncomp_buf[1] = 0;
|
|
}
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = 8;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size*sizeof(*comp_buf);
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,buf_size*sizeof(*comp_buf)-z->avail_out,
|
|
(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
|
|
byteswritten += WriteCompressedTypeArrayFlags(mat,matvar,z);
|
|
return byteswritten;
|
|
}
|
|
#endif
|
|
|
|
static size_t
|
|
Mat_WriteEmptyVariable5(mat_t *mat,const char *name,int rank,size_t *dims)
|
|
{
|
|
mat_uint32_t array_flags;
|
|
mat_int32_t array_name_type = MAT_T_INT8, matrix_type = MAT_T_MATRIX;
|
|
int array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
|
|
int array_flags_size = 8, pad4 = 0, nBytes, i;
|
|
const mat_int8_t pad1 = 0;
|
|
size_t byteswritten = 0;
|
|
long start = 0, end = 0;
|
|
|
|
fwrite(&matrix_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&pad4,4,1,(FILE*)mat->fp);
|
|
start = ftell((FILE*)mat->fp);
|
|
|
|
/* Array Flags */
|
|
array_flags = MAT_C_DOUBLE;
|
|
|
|
if ( mat->byteswap )
|
|
array_flags = Mat_int32Swap((mat_int32_t*)&array_flags);
|
|
byteswritten += fwrite(&array_flags_type,4,1,(FILE*)mat->fp);
|
|
byteswritten += fwrite(&array_flags_size,4,1,(FILE*)mat->fp);
|
|
byteswritten += fwrite(&array_flags,4,1,(FILE*)mat->fp);
|
|
byteswritten += fwrite(&pad4,4,1,(FILE*)mat->fp);
|
|
/* Rank and Dimension */
|
|
nBytes = rank * 4;
|
|
byteswritten += fwrite(&dims_array_type,4,1,(FILE*)mat->fp);
|
|
byteswritten += fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
for ( i = 0; i < rank; i++ ) {
|
|
mat_int32_t dim;
|
|
dim = dims[i];
|
|
byteswritten += fwrite(&dim,4,1,(FILE*)mat->fp);
|
|
}
|
|
if ( rank % 2 != 0 )
|
|
byteswritten += fwrite(&pad4,4,1,(FILE*)mat->fp);
|
|
|
|
if ( NULL == name ) {
|
|
/* Name of variable */
|
|
byteswritten += fwrite(&array_name_type,4,1,(FILE*)mat->fp);
|
|
byteswritten += fwrite(&pad4,4,1,(FILE*)mat->fp);
|
|
} else {
|
|
mat_int32_t array_name_len = (mat_int32_t)strlen(name);
|
|
/* Name of variable */
|
|
if ( array_name_len <= 4 ) {
|
|
array_name_type = (array_name_len << 16) | array_name_type;
|
|
byteswritten += fwrite(&array_name_type,4,1,(FILE*)mat->fp);
|
|
byteswritten += fwrite(name,1,array_name_len,(FILE*)mat->fp);
|
|
for ( i = array_name_len; i < 4; i++ )
|
|
byteswritten += fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
} else {
|
|
byteswritten += fwrite(&array_name_type,4,1,(FILE*)mat->fp);
|
|
byteswritten += fwrite(&array_name_len,4,1,(FILE*)mat->fp);
|
|
byteswritten += fwrite(name,1,array_name_len,(FILE*)mat->fp);
|
|
if ( array_name_len % 8 )
|
|
for ( i = array_name_len % 8; i < 8; i++ )
|
|
byteswritten += fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
}
|
|
}
|
|
|
|
nBytes = WriteData(mat,NULL,0,MAT_T_DOUBLE);
|
|
byteswritten += nBytes;
|
|
if ( nBytes % 8 )
|
|
for ( i = nBytes % 8; i < 8; i++ )
|
|
byteswritten += fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
|
|
end = ftell((FILE*)mat->fp);
|
|
if ( start != -1L && end != -1L ) {
|
|
nBytes = (int)(end-start);
|
|
(void)fseek((FILE*)mat->fp,(long)-(nBytes+4),SEEK_CUR);
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
(void)fseek((FILE*)mat->fp,end,SEEK_SET);
|
|
} else {
|
|
Mat_Critical("Couldn't determine file position");
|
|
}
|
|
|
|
return byteswritten;
|
|
}
|
|
|
|
#if defined(HAVE_ZLIB)
|
|
static size_t
|
|
Mat_WriteCompressedEmptyVariable5(mat_t *mat,const char *name,int rank,
|
|
size_t *dims,z_streamp z)
|
|
{
|
|
mat_uint32_t array_flags;
|
|
int array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
|
|
int array_flags_size = 8;
|
|
int nBytes, i;
|
|
|
|
mat_uint32_t comp_buf[512];
|
|
mat_uint32_t uncomp_buf[512] = {0,};
|
|
int buf_size = 512;
|
|
size_t byteswritten = 0, buf_size_bytes;
|
|
|
|
if ( NULL == mat || NULL == z)
|
|
return 1;
|
|
|
|
buf_size_bytes = buf_size*sizeof(*comp_buf);
|
|
|
|
/* Array Flags */
|
|
array_flags = MAT_C_DOUBLE;
|
|
|
|
uncomp_buf[0] = MAT_T_MATRIX;
|
|
uncomp_buf[1] = (int)GetEmptyMatrixMaxBufSize(name,rank);
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = 8;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size_bytes;
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,buf_size_bytes-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
uncomp_buf[0] = array_flags_type;
|
|
uncomp_buf[1] = array_flags_size;
|
|
uncomp_buf[2] = array_flags;
|
|
uncomp_buf[3] = 0;
|
|
/* Rank and Dimension */
|
|
nBytes = rank * 4;
|
|
uncomp_buf[4] = dims_array_type;
|
|
uncomp_buf[5] = nBytes;
|
|
for ( i = 0; i < rank; i++ ) {
|
|
mat_int32_t dim;
|
|
dim = dims[i];
|
|
uncomp_buf[6+i] = dim;
|
|
}
|
|
if ( rank % 2 != 0 ) {
|
|
int pad4 = 0;
|
|
uncomp_buf[6+i] = pad4;
|
|
i++;
|
|
}
|
|
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = (6+i)*sizeof(*uncomp_buf);
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size_bytes;
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,buf_size_bytes-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
/* Name of variable */
|
|
if ( NULL == name ) {
|
|
mat_int16_t array_name_type = MAT_T_INT8;
|
|
uncomp_buf[0] = array_name_type;
|
|
uncomp_buf[1] = 0;
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = 8;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size_bytes;
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,buf_size_bytes-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
} else if ( strlen(name) <= 4 ) {
|
|
mat_int16_t array_name_len = (mat_int16_t)strlen(name);
|
|
mat_int16_t array_name_type = MAT_T_INT8;
|
|
|
|
memset(uncomp_buf,0,8);
|
|
uncomp_buf[0] = (array_name_len << 16) | array_name_type;
|
|
memcpy(uncomp_buf+1,name,array_name_len);
|
|
if ( array_name_len % 4 )
|
|
array_name_len += 4-(array_name_len % 4);
|
|
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = 8;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size_bytes;
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,buf_size_bytes-z->avail_out,
|
|
(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
} else {
|
|
mat_int32_t array_name_len = (mat_int32_t)strlen(name);
|
|
mat_int32_t array_name_type = MAT_T_INT8;
|
|
|
|
memset(uncomp_buf,0,buf_size*sizeof(*uncomp_buf));
|
|
uncomp_buf[0] = array_name_type;
|
|
uncomp_buf[1] = array_name_len;
|
|
memcpy(uncomp_buf+2,name,array_name_len);
|
|
if ( array_name_len % 8 )
|
|
array_name_len += 8-(array_name_len % 8);
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = 8+array_name_len;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size_bytes;
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,buf_size_bytes-z->avail_out,
|
|
(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
}
|
|
|
|
byteswritten += WriteCompressedData(mat,z,NULL,0,MAT_T_DOUBLE);
|
|
return byteswritten;
|
|
}
|
|
#endif
|
|
|
|
/** @if mat_devman
|
|
* @brief Reads a data element including tag and data
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar MAT variable pointer
|
|
* @param data Pointer to store the data
|
|
* @param N number of data elements allocated for the pointer
|
|
* @endif
|
|
*/
|
|
static void
|
|
Mat_VarReadNumeric5(mat_t *mat,matvar_t *matvar,void *data,size_t N)
|
|
{
|
|
int nBytes = 0, data_in_tag = 0;
|
|
enum matio_types packed_type = MAT_T_UNKNOWN;
|
|
mat_uint32_t tag[2];
|
|
|
|
if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
#if defined(HAVE_ZLIB)
|
|
matvar->internal->z->avail_in = 0;
|
|
InflateDataType(mat,matvar->internal->z,tag);
|
|
if ( mat->byteswap )
|
|
(void)Mat_uint32Swap(tag);
|
|
|
|
packed_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
|
|
data_in_tag = 1;
|
|
nBytes = (tag[0] & 0xffff0000) >> 16;
|
|
} else {
|
|
data_in_tag = 0;
|
|
InflateDataType(mat,matvar->internal->z,tag+1);
|
|
if ( mat->byteswap )
|
|
(void)Mat_uint32Swap(tag+1);
|
|
nBytes = tag[1];
|
|
}
|
|
#endif
|
|
} else {
|
|
size_t bytesread = fread(tag,4,1,(FILE*)mat->fp);
|
|
if ( mat->byteswap )
|
|
(void)Mat_uint32Swap(tag);
|
|
packed_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
|
|
data_in_tag = 1;
|
|
nBytes = (tag[0] & 0xffff0000) >> 16;
|
|
} else {
|
|
data_in_tag = 0;
|
|
bytesread += fread(tag+1,4,1,(FILE*)mat->fp);
|
|
if ( mat->byteswap )
|
|
(void)Mat_uint32Swap(tag+1);
|
|
nBytes = tag[1];
|
|
}
|
|
}
|
|
if ( nBytes == 0 ) {
|
|
matvar->nbytes = 0;
|
|
return;
|
|
}
|
|
|
|
if ( matvar->compression == MAT_COMPRESSION_NONE ) {
|
|
switch ( matvar->class_type ) {
|
|
case MAT_C_DOUBLE:
|
|
nBytes = ReadDoubleData(mat,(double*)data,packed_type,N);
|
|
break;
|
|
case MAT_C_SINGLE:
|
|
nBytes = ReadSingleData(mat,(float*)data,packed_type,N);
|
|
break;
|
|
case MAT_C_INT64:
|
|
#ifdef HAVE_MAT_INT64_T
|
|
nBytes = ReadInt64Data(mat,(mat_int64_t*)data,packed_type,N);
|
|
#endif
|
|
break;
|
|
case MAT_C_UINT64:
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
nBytes = ReadUInt64Data(mat,(mat_uint64_t*)data,packed_type,N);
|
|
#endif
|
|
break;
|
|
case MAT_C_INT32:
|
|
nBytes = ReadInt32Data(mat,(mat_int32_t*)data,packed_type,N);
|
|
break;
|
|
case MAT_C_UINT32:
|
|
nBytes = ReadUInt32Data(mat,(mat_uint32_t*)data,packed_type,N);
|
|
break;
|
|
case MAT_C_INT16:
|
|
nBytes = ReadInt16Data(mat,(mat_int16_t*)data,packed_type,N);
|
|
break;
|
|
case MAT_C_UINT16:
|
|
nBytes = ReadUInt16Data(mat,(mat_uint16_t*)data,packed_type,N);
|
|
break;
|
|
case MAT_C_INT8:
|
|
nBytes = ReadInt8Data(mat,(mat_int8_t*)data,packed_type,N);
|
|
break;
|
|
case MAT_C_UINT8:
|
|
nBytes = ReadUInt8Data(mat,(mat_uint8_t*)data,packed_type,N);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
/*
|
|
* If the data was in the tag we started on a 4-byte
|
|
* boundary so add 4 to make it an 8-byte
|
|
*/
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
(void)fseek((FILE*)mat->fp,8-(nBytes % 8),SEEK_CUR);
|
|
#if defined(HAVE_ZLIB)
|
|
} else if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
switch ( matvar->class_type ) {
|
|
case MAT_C_DOUBLE:
|
|
nBytes = ReadCompressedDoubleData(mat,matvar->internal->z,(double*)data,
|
|
packed_type,N);
|
|
break;
|
|
case MAT_C_SINGLE:
|
|
nBytes = ReadCompressedSingleData(mat,matvar->internal->z,(float*)data,
|
|
packed_type,N);
|
|
break;
|
|
case MAT_C_INT64:
|
|
#ifdef HAVE_MAT_INT64_T
|
|
nBytes = ReadCompressedInt64Data(mat,matvar->internal->z,(mat_int64_t*)data,
|
|
packed_type,N);
|
|
#endif
|
|
break;
|
|
case MAT_C_UINT64:
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
nBytes = ReadCompressedUInt64Data(mat,matvar->internal->z,(mat_uint64_t*)data,
|
|
packed_type,N);
|
|
#endif
|
|
break;
|
|
case MAT_C_INT32:
|
|
nBytes = ReadCompressedInt32Data(mat,matvar->internal->z,(mat_int32_t*)data,
|
|
packed_type,N);
|
|
break;
|
|
case MAT_C_UINT32:
|
|
nBytes = ReadCompressedUInt32Data(mat,matvar->internal->z,(mat_uint32_t*)data,
|
|
packed_type,N);
|
|
break;
|
|
case MAT_C_INT16:
|
|
nBytes = ReadCompressedInt16Data(mat,matvar->internal->z,(mat_int16_t*)data,
|
|
packed_type,N);
|
|
break;
|
|
case MAT_C_UINT16:
|
|
nBytes = ReadCompressedUInt16Data(mat,matvar->internal->z,(mat_uint16_t*)data,
|
|
packed_type,N);
|
|
break;
|
|
case MAT_C_INT8:
|
|
nBytes = ReadCompressedInt8Data(mat,matvar->internal->z,(mat_int8_t*)data,
|
|
packed_type,N);
|
|
break;
|
|
case MAT_C_UINT8:
|
|
nBytes = ReadCompressedUInt8Data(mat,matvar->internal->z,(mat_uint8_t*)data,
|
|
packed_type,N);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
/*
|
|
* If the data was in the tag we started on a 4-byte
|
|
* boundary so add 4 to make it an 8-byte
|
|
*/
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
InflateSkip(mat,matvar->internal->z,8-(nBytes % 8));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Reads the data of a version 5 MAT variable
|
|
*
|
|
* @ingroup mat_internal
|
|
* @param mat MAT file pointer
|
|
* @param matvar MAT variable pointer to read the data
|
|
* @endif
|
|
*/
|
|
void
|
|
Mat_VarRead5(mat_t *mat, matvar_t *matvar)
|
|
{
|
|
int nBytes = 0, byteswap, data_in_tag = 0, err;
|
|
size_t nelems = 1;
|
|
enum matio_types packed_type = MAT_T_UNKNOWN;
|
|
long fpos;
|
|
mat_uint32_t tag[2];
|
|
size_t bytesread = 0;
|
|
|
|
if ( matvar == NULL )
|
|
return;
|
|
else if ( matvar->rank == 0 ) /* An empty data set */
|
|
return;
|
|
#if defined(HAVE_ZLIB)
|
|
else if ( NULL != matvar->internal->data ) {
|
|
/* Data already read in ReadNextStructField or ReadNextCell */
|
|
matvar->data = matvar->internal->data;
|
|
matvar->internal->data = NULL;
|
|
return;
|
|
}
|
|
#endif
|
|
fpos = ftell((FILE*)mat->fp);
|
|
if ( fpos == -1L ) {
|
|
Mat_Critical("Couldn't determine file position");
|
|
return;
|
|
}
|
|
err = SafeMulDims(matvar, &nelems);
|
|
if ( err ) {
|
|
Mat_Critical("Integer multiplication overflow");
|
|
return;
|
|
}
|
|
byteswap = mat->byteswap;
|
|
switch ( matvar->class_type ) {
|
|
case MAT_C_EMPTY:
|
|
matvar->nbytes = 0;
|
|
matvar->data_size = sizeof(double);
|
|
matvar->data_type = MAT_T_DOUBLE;
|
|
matvar->rank = 2;
|
|
matvar->dims = (size_t*)malloc(matvar->rank*sizeof(*(matvar->dims)));
|
|
matvar->dims[0] = 0;
|
|
matvar->dims[1] = 0;
|
|
break;
|
|
case MAT_C_DOUBLE:
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
matvar->data_size = sizeof(double);
|
|
matvar->data_type = MAT_T_DOUBLE;
|
|
break;
|
|
case MAT_C_SINGLE:
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
matvar->data_size = sizeof(float);
|
|
matvar->data_type = MAT_T_SINGLE;
|
|
break;
|
|
case MAT_C_INT64:
|
|
#ifdef HAVE_MAT_INT64_T
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
matvar->data_size = sizeof(mat_int64_t);
|
|
matvar->data_type = MAT_T_INT64;
|
|
#endif
|
|
break;
|
|
case MAT_C_UINT64:
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
matvar->data_size = sizeof(mat_uint64_t);
|
|
matvar->data_type = MAT_T_UINT64;
|
|
#endif
|
|
break;
|
|
case MAT_C_INT32:
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
matvar->data_size = sizeof(mat_int32_t);
|
|
matvar->data_type = MAT_T_INT32;
|
|
break;
|
|
case MAT_C_UINT32:
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
matvar->data_size = sizeof(mat_uint32_t);
|
|
matvar->data_type = MAT_T_UINT32;
|
|
break;
|
|
case MAT_C_INT16:
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
matvar->data_size = sizeof(mat_int16_t);
|
|
matvar->data_type = MAT_T_INT16;
|
|
break;
|
|
case MAT_C_UINT16:
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
matvar->data_size = sizeof(mat_uint16_t);
|
|
matvar->data_type = MAT_T_UINT16;
|
|
break;
|
|
case MAT_C_INT8:
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
matvar->data_size = sizeof(mat_int8_t);
|
|
matvar->data_type = MAT_T_INT8;
|
|
break;
|
|
case MAT_C_UINT8:
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
matvar->data_size = sizeof(mat_uint8_t);
|
|
matvar->data_type = MAT_T_UINT8;
|
|
break;
|
|
case MAT_C_CHAR:
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
#if defined(HAVE_ZLIB)
|
|
matvar->internal->z->avail_in = 0;
|
|
InflateDataType(mat,matvar->internal->z,tag);
|
|
if ( byteswap )
|
|
(void)Mat_uint32Swap(tag);
|
|
packed_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
|
|
data_in_tag = 1;
|
|
nBytes = (tag[0] & 0xffff0000) >> 16;
|
|
} else {
|
|
data_in_tag = 0;
|
|
InflateDataType(mat,matvar->internal->z,tag+1);
|
|
if ( byteswap )
|
|
(void)Mat_uint32Swap(tag+1);
|
|
nBytes = tag[1];
|
|
}
|
|
#endif
|
|
matvar->data_type = packed_type;
|
|
matvar->data_size = Mat_SizeOf(matvar->data_type);
|
|
matvar->nbytes = nBytes;
|
|
} else {
|
|
bytesread += fread(tag,4,1,(FILE*)mat->fp);
|
|
if ( byteswap )
|
|
(void)Mat_uint32Swap(tag);
|
|
packed_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
|
|
data_in_tag = 1;
|
|
/* nBytes = (tag[0] & 0xffff0000) >> 16; */
|
|
} else {
|
|
data_in_tag = 0;
|
|
bytesread += fread(tag+1,4,1,(FILE*)mat->fp);
|
|
if ( byteswap )
|
|
(void)Mat_uint32Swap(tag+1);
|
|
/* nBytes = tag[1]; */
|
|
}
|
|
matvar->data_type = MAT_T_UINT8;
|
|
matvar->data_size = Mat_SizeOf(MAT_T_UINT8);
|
|
err = SafeMul(&matvar->nbytes, nelems, matvar->data_size);
|
|
if ( err ) {
|
|
Mat_Critical("Integer multiplication overflow");
|
|
break;
|
|
}
|
|
}
|
|
if ( matvar->isComplex ) {
|
|
break;
|
|
}
|
|
matvar->data = calloc(matvar->nbytes+1,1);
|
|
if ( NULL == matvar->data ) {
|
|
Mat_Critical("Couldn't allocate memory for the data");
|
|
break;
|
|
}
|
|
if ( 0 == matvar->nbytes ) {
|
|
break;
|
|
}
|
|
{
|
|
size_t nbytes;
|
|
err = SafeMul(&nbytes, nelems, matvar->data_size);
|
|
if ( err || nbytes > matvar->nbytes ) {
|
|
break;
|
|
}
|
|
}
|
|
if ( matvar->compression == MAT_COMPRESSION_NONE ) {
|
|
nBytes = ReadCharData(mat,(char*)matvar->data,packed_type,(int)nelems);
|
|
/*
|
|
* If the data was in the tag we started on a 4-byte
|
|
* boundary so add 4 to make it an 8-byte
|
|
*/
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
(void)fseek((FILE*)mat->fp,8-(nBytes % 8),SEEK_CUR);
|
|
#if defined(HAVE_ZLIB)
|
|
} else if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
nBytes = ReadCompressedCharData(mat,matvar->internal->z,
|
|
(char*)matvar->data,packed_type,(int)nelems);
|
|
/*
|
|
* If the data was in the tag we started on a 4-byte
|
|
* boundary so add 4 to make it an 8-byte
|
|
*/
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
InflateSkip(mat,matvar->internal->z,8-(nBytes % 8));
|
|
#endif
|
|
}
|
|
break;
|
|
case MAT_C_STRUCT:
|
|
{
|
|
matvar_t **fields;
|
|
size_t i, nelems_x_nfields;
|
|
|
|
matvar->data_type = MAT_T_STRUCT;
|
|
if ( !matvar->nbytes || !matvar->data_size || NULL == matvar->data )
|
|
break;
|
|
SafeMul(&nelems_x_nfields, nelems, matvar->internal->num_fields);
|
|
fields = (matvar_t **)matvar->data;
|
|
for ( i = 0; i < nelems_x_nfields; i++ ) {
|
|
if ( NULL != fields[i] ) {
|
|
Mat_VarRead5(mat,fields[i]);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case MAT_C_CELL:
|
|
{
|
|
matvar_t **cells;
|
|
size_t i;
|
|
|
|
if ( NULL == matvar->data ) {
|
|
Mat_Critical("Data is NULL for cell array %s",matvar->name);
|
|
break;
|
|
}
|
|
cells = (matvar_t **)matvar->data;
|
|
for ( i = 0; i < nelems; i++ ) {
|
|
if ( NULL != cells[i] ) {
|
|
Mat_VarRead5(mat, cells[i]);
|
|
}
|
|
}
|
|
/* FIXME: */
|
|
matvar->data_type = MAT_T_CELL;
|
|
break;
|
|
}
|
|
case MAT_C_SPARSE:
|
|
{
|
|
mat_int32_t N = 0;
|
|
mat_sparse_t *data;
|
|
|
|
matvar->data_size = sizeof(mat_sparse_t);
|
|
matvar->data = malloc(matvar->data_size);
|
|
if ( matvar->data == NULL ) {
|
|
Mat_Critical("Mat_VarRead5: Allocation of data pointer failed");
|
|
break;
|
|
}
|
|
data = (mat_sparse_t*)matvar->data;
|
|
data->nzmax = matvar->nbytes;
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
/* Read ir */
|
|
if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
#if defined(HAVE_ZLIB)
|
|
matvar->internal->z->avail_in = 0;
|
|
InflateDataType(mat,matvar->internal->z,tag);
|
|
if ( mat->byteswap )
|
|
(void)Mat_uint32Swap(tag);
|
|
|
|
packed_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
|
|
data_in_tag = 1;
|
|
N = (tag[0] & 0xffff0000) >> 16;
|
|
} else {
|
|
data_in_tag = 0;
|
|
(void)ReadCompressedInt32Data(mat,matvar->internal->z,
|
|
(mat_int32_t*)&N,MAT_T_INT32,1);
|
|
}
|
|
#endif
|
|
} else {
|
|
bytesread += fread(tag,4,1,(FILE*)mat->fp);
|
|
if ( mat->byteswap )
|
|
(void)Mat_uint32Swap(tag);
|
|
packed_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
|
|
data_in_tag = 1;
|
|
N = (tag[0] & 0xffff0000) >> 16;
|
|
} else {
|
|
data_in_tag = 0;
|
|
bytesread += fread(&N,4,1,(FILE*)mat->fp);
|
|
if ( mat->byteswap )
|
|
Mat_int32Swap(&N);
|
|
}
|
|
}
|
|
data->nir = N / 4;
|
|
data->ir = (mat_int32_t*)malloc(data->nir*sizeof(mat_int32_t));
|
|
if ( data->ir != NULL ) {
|
|
if ( matvar->compression == MAT_COMPRESSION_NONE ) {
|
|
nBytes = ReadInt32Data(mat,data->ir,packed_type,data->nir);
|
|
/*
|
|
* If the data was in the tag we started on a 4-byte
|
|
* boundary so add 4 to make it an 8-byte
|
|
*/
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
(void)fseek((FILE*)mat->fp,8-(nBytes % 8),SEEK_CUR);
|
|
#if defined(HAVE_ZLIB)
|
|
} else if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
nBytes = ReadCompressedInt32Data(mat,matvar->internal->z,
|
|
data->ir,packed_type,data->nir);
|
|
/*
|
|
* If the data was in the tag we started on a 4-byte
|
|
* boundary so add 4 to make it an 8-byte
|
|
*/
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
InflateSkip(mat,matvar->internal->z,8-(nBytes % 8));
|
|
#endif
|
|
}
|
|
} else {
|
|
Mat_Critical("Mat_VarRead5: Allocation of ir pointer failed");
|
|
break;
|
|
}
|
|
/* Read jc */
|
|
if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
#if defined(HAVE_ZLIB)
|
|
matvar->internal->z->avail_in = 0;
|
|
InflateDataType(mat,matvar->internal->z,tag);
|
|
if ( mat->byteswap )
|
|
Mat_uint32Swap(tag);
|
|
packed_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
|
|
data_in_tag = 1;
|
|
N = (tag[0] & 0xffff0000) >> 16;
|
|
} else {
|
|
data_in_tag = 0;
|
|
(void)ReadCompressedInt32Data(mat,matvar->internal->z,
|
|
(mat_int32_t*)&N,MAT_T_INT32,1);
|
|
}
|
|
#endif
|
|
} else {
|
|
bytesread += fread(tag,4,1,(FILE*)mat->fp);
|
|
if ( mat->byteswap )
|
|
Mat_uint32Swap(tag);
|
|
packed_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
|
|
data_in_tag = 1;
|
|
N = (tag[0] & 0xffff0000) >> 16;
|
|
} else {
|
|
data_in_tag = 0;
|
|
bytesread += fread(&N,4,1,(FILE*)mat->fp);
|
|
if ( mat->byteswap )
|
|
Mat_int32Swap(&N);
|
|
}
|
|
}
|
|
data->njc = N / 4;
|
|
data->jc = (mat_int32_t*)malloc(data->njc*sizeof(mat_int32_t));
|
|
if ( data->jc != NULL ) {
|
|
if ( matvar->compression == MAT_COMPRESSION_NONE ) {
|
|
nBytes = ReadInt32Data(mat,data->jc,packed_type,data->njc);
|
|
/*
|
|
* If the data was in the tag we started on a 4-byte
|
|
* boundary so add 4 to make it an 8-byte
|
|
*/
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
(void)fseek((FILE*)mat->fp,8-(nBytes % 8),SEEK_CUR);
|
|
#if defined(HAVE_ZLIB)
|
|
} else if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
nBytes = ReadCompressedInt32Data(mat,matvar->internal->z,
|
|
data->jc,packed_type,data->njc);
|
|
/*
|
|
* If the data was in the tag we started on a 4-byte
|
|
* boundary so add 4 to make it an 8-byte
|
|
*/
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
InflateSkip(mat,matvar->internal->z,8-(nBytes % 8));
|
|
#endif
|
|
}
|
|
} else {
|
|
Mat_Critical("Mat_VarRead5: Allocation of jc pointer failed");
|
|
break;
|
|
}
|
|
/* Read data */
|
|
if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
#if defined(HAVE_ZLIB)
|
|
matvar->internal->z->avail_in = 0;
|
|
InflateDataType(mat,matvar->internal->z,tag);
|
|
if ( mat->byteswap )
|
|
Mat_uint32Swap(tag);
|
|
packed_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
|
|
data_in_tag = 1;
|
|
N = (tag[0] & 0xffff0000) >> 16;
|
|
} else {
|
|
data_in_tag = 0;
|
|
(void)ReadCompressedInt32Data(mat,matvar->internal->z,
|
|
(mat_int32_t*)&N,MAT_T_INT32,1);
|
|
}
|
|
#endif
|
|
} else {
|
|
bytesread += fread(tag,4,1,(FILE*)mat->fp);
|
|
if ( mat->byteswap )
|
|
Mat_uint32Swap(tag);
|
|
packed_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
|
|
data_in_tag = 1;
|
|
N = (tag[0] & 0xffff0000) >> 16;
|
|
} else {
|
|
data_in_tag = 0;
|
|
bytesread += fread(&N,4,1,(FILE*)mat->fp);
|
|
if ( mat->byteswap )
|
|
Mat_int32Swap(&N);
|
|
}
|
|
}
|
|
if ( matvar->isLogical && packed_type == MAT_T_DOUBLE ) {
|
|
/* For some reason, MAT says the data type is a double,
|
|
* but it appears to be written as 8-bit unsigned integer.
|
|
*/
|
|
packed_type = MAT_T_UINT8;
|
|
}
|
|
#if defined(EXTENDED_SPARSE)
|
|
matvar->data_type = packed_type;
|
|
#else
|
|
matvar->data_type = MAT_T_DOUBLE;
|
|
#endif
|
|
{
|
|
size_t s_type = Mat_SizeOf(packed_type);
|
|
if ( s_type == 0 )
|
|
break;
|
|
data->ndata = N / s_type;
|
|
}
|
|
if ( matvar->isComplex ) {
|
|
mat_complex_split_t *complex_data =
|
|
ComplexMalloc(data->ndata*Mat_SizeOf(matvar->data_type));
|
|
if ( NULL == complex_data ) {
|
|
Mat_Critical("Couldn't allocate memory for the complex sparse data");
|
|
break;
|
|
}
|
|
if ( matvar->compression == MAT_COMPRESSION_NONE ) {
|
|
#if defined(EXTENDED_SPARSE)
|
|
switch ( matvar->data_type ) {
|
|
case MAT_T_DOUBLE:
|
|
nBytes = ReadDoubleData(mat,(double*)complex_data->Re,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_SINGLE:
|
|
nBytes = ReadSingleData(mat,(float*)complex_data->Re,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT64:
|
|
#ifdef HAVE_MAT_INT64_T
|
|
nBytes = ReadInt64Data(mat,(mat_int64_t*)complex_data->Re,
|
|
packed_type,data->ndata);
|
|
#endif
|
|
break;
|
|
case MAT_T_UINT64:
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
nBytes = ReadUInt64Data(mat,(mat_uint64_t*)complex_data->Re,
|
|
packed_type,data->ndata);
|
|
#endif
|
|
break;
|
|
case MAT_T_INT32:
|
|
nBytes = ReadInt32Data(mat,(mat_int32_t*)complex_data->Re,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT32:
|
|
nBytes = ReadUInt32Data(mat,(mat_uint32_t*)complex_data->Re,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT16:
|
|
nBytes = ReadInt16Data(mat,(mat_int16_t*)complex_data->Re,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT16:
|
|
nBytes = ReadUInt16Data(mat,(mat_uint16_t*)complex_data->Re,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT8:
|
|
nBytes = ReadInt8Data(mat,(mat_int8_t*)complex_data->Re,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT8:
|
|
nBytes = ReadUInt8Data(mat,(mat_uint8_t*)complex_data->Re,
|
|
packed_type,data->ndata);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#else
|
|
nBytes = ReadDoubleData(mat,(double*)complex_data->Re,
|
|
packed_type,data->ndata);
|
|
#endif
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
(void)fseek((FILE*)mat->fp,8-(nBytes % 8),SEEK_CUR);
|
|
|
|
/* Complex Data Tag */
|
|
bytesread += fread(tag,4,1,(FILE*)mat->fp);
|
|
if ( byteswap )
|
|
(void)Mat_uint32Swap(tag);
|
|
packed_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
|
|
data_in_tag = 1;
|
|
nBytes = (tag[0] & 0xffff0000) >> 16;
|
|
} else {
|
|
data_in_tag = 0;
|
|
bytesread += fread(tag+1,4,1,(FILE*)mat->fp);
|
|
if ( byteswap )
|
|
(void)Mat_uint32Swap(tag+1);
|
|
nBytes = tag[1];
|
|
}
|
|
#if defined(EXTENDED_SPARSE)
|
|
switch ( matvar->data_type ) {
|
|
case MAT_T_DOUBLE:
|
|
nBytes = ReadDoubleData(mat,(double*)complex_data->Im,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_SINGLE:
|
|
nBytes = ReadSingleData(mat,(float*)complex_data->Im,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT64:
|
|
#ifdef HAVE_MAT_INT64_T
|
|
nBytes = ReadInt64Data(mat,(mat_int64_t*)complex_data->Im,
|
|
packed_type,data->ndata);
|
|
#endif
|
|
break;
|
|
case MAT_T_UINT64:
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
nBytes = ReadUInt64Data(mat,(mat_uint64_t*)complex_data->Im,
|
|
packed_type,data->ndata);
|
|
#endif
|
|
break;
|
|
case MAT_T_INT32:
|
|
nBytes = ReadInt32Data(mat,(mat_int32_t*)complex_data->Im,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT32:
|
|
nBytes = ReadUInt32Data(mat,(mat_uint32_t*)complex_data->Im,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT16:
|
|
nBytes = ReadInt16Data(mat,(mat_int16_t*)complex_data->Im,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT16:
|
|
nBytes = ReadUInt16Data(mat,(mat_uint16_t*)complex_data->Im,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT8:
|
|
nBytes = ReadInt8Data(mat,(mat_int8_t*)complex_data->Im,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT8:
|
|
nBytes = ReadUInt8Data(mat,(mat_uint8_t*)complex_data->Im,
|
|
packed_type,data->ndata);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#else /* EXTENDED_SPARSE */
|
|
nBytes = ReadDoubleData(mat,(double*)complex_data->Im,
|
|
packed_type,data->ndata);
|
|
#endif /* EXTENDED_SPARSE */
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
(void)fseek((FILE*)mat->fp,8-(nBytes % 8),SEEK_CUR);
|
|
#if defined(HAVE_ZLIB)
|
|
} else if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
#if defined(EXTENDED_SPARSE)
|
|
switch ( matvar->data_type ) {
|
|
case MAT_T_DOUBLE:
|
|
nBytes = ReadCompressedDoubleData(mat,matvar->internal->z,
|
|
(double*)complex_data->Re,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_SINGLE:
|
|
nBytes = ReadCompressedSingleData(mat,matvar->internal->z,
|
|
(float*)complex_data->Re,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT64:
|
|
#ifdef HAVE_MAT_INT64_T
|
|
nBytes = ReadCompressedInt64Data(mat,
|
|
matvar->internal->z,(mat_int64_t*)complex_data->Re,
|
|
packed_type,data->ndata);
|
|
#endif
|
|
break;
|
|
case MAT_T_UINT64:
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
nBytes = ReadCompressedUInt64Data(mat,
|
|
matvar->internal->z,(mat_uint64_t*)complex_data->Re,
|
|
packed_type,data->ndata);
|
|
#endif
|
|
break;
|
|
case MAT_T_INT32:
|
|
nBytes = ReadCompressedInt32Data(mat,matvar->internal->z,
|
|
(mat_int32_t*)complex_data->Re,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT32:
|
|
nBytes = ReadCompressedUInt32Data(mat,matvar->internal->z,
|
|
(mat_uint32_t*)complex_data->Re,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT16:
|
|
nBytes = ReadCompressedInt16Data(mat,matvar->internal->z,
|
|
(mat_int16_t*)complex_data->Re,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT16:
|
|
nBytes = ReadCompressedUInt16Data(mat,matvar->internal->z,
|
|
(mat_uint16_t*)complex_data->Re,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT8:
|
|
nBytes = ReadCompressedInt8Data(mat,matvar->internal->z,
|
|
(mat_int8_t*)complex_data->Re,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT8:
|
|
nBytes = ReadCompressedUInt8Data(mat,matvar->internal->z,
|
|
(mat_uint8_t*)complex_data->Re,packed_type,data->ndata);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#else /* EXTENDED_SPARSE */
|
|
nBytes = ReadCompressedDoubleData(mat,matvar->internal->z,
|
|
(double*)complex_data->Re,packed_type,data->ndata);
|
|
#endif /* EXTENDED_SPARSE */
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
InflateSkip(mat,matvar->internal->z,8-(nBytes % 8));
|
|
|
|
/* Complex Data Tag */
|
|
InflateDataType(mat,matvar->internal->z,tag);
|
|
if ( byteswap )
|
|
(void)Mat_uint32Swap(tag);
|
|
|
|
packed_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is in the tag */
|
|
data_in_tag = 1;
|
|
nBytes = (tag[0] & 0xffff0000) >> 16;
|
|
} else {
|
|
data_in_tag = 0;
|
|
InflateDataType(mat,matvar->internal->z,tag+1);
|
|
if ( byteswap )
|
|
(void)Mat_uint32Swap(tag+1);
|
|
nBytes = tag[1];
|
|
}
|
|
#if defined(EXTENDED_SPARSE)
|
|
switch ( matvar->data_type ) {
|
|
case MAT_T_DOUBLE:
|
|
nBytes = ReadCompressedDoubleData(mat,matvar->internal->z,
|
|
(double*)complex_data->Im,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_SINGLE:
|
|
nBytes = ReadCompressedSingleData(mat,matvar->internal->z,
|
|
(float*)complex_data->Im,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT64:
|
|
#ifdef HAVE_MAT_INT64_T
|
|
nBytes = ReadCompressedInt64Data(mat,
|
|
matvar->internal->z,(mat_int64_t*)complex_data->Im,
|
|
packed_type,data->ndata);
|
|
#endif
|
|
break;
|
|
case MAT_T_UINT64:
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
nBytes = ReadCompressedUInt64Data(mat,
|
|
matvar->internal->z,(mat_uint64_t*)complex_data->Im,
|
|
packed_type,data->ndata);
|
|
#endif
|
|
break;
|
|
case MAT_T_INT32:
|
|
nBytes = ReadCompressedInt32Data(mat,matvar->internal->z,
|
|
(mat_int32_t*)complex_data->Im,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT32:
|
|
nBytes = ReadCompressedUInt32Data(mat,matvar->internal->z,
|
|
(mat_uint32_t*)complex_data->Im,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT16:
|
|
nBytes = ReadCompressedInt16Data(mat,matvar->internal->z,
|
|
(mat_int16_t*)complex_data->Im,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT16:
|
|
nBytes = ReadCompressedUInt16Data(mat,matvar->internal->z,
|
|
(mat_uint16_t*)complex_data->Im,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT8:
|
|
nBytes = ReadCompressedInt8Data(mat,matvar->internal->z,
|
|
(mat_int8_t*)complex_data->Im,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT8:
|
|
nBytes = ReadCompressedUInt8Data(mat,matvar->internal->z,
|
|
(mat_uint8_t*)complex_data->Im,packed_type,data->ndata);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#else /* EXTENDED_SPARSE */
|
|
nBytes = ReadCompressedDoubleData(mat,matvar->internal->z,
|
|
(double*)complex_data->Im,packed_type,data->ndata);
|
|
#endif /* EXTENDED_SPARSE */
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
InflateSkip(mat,matvar->internal->z,8-(nBytes % 8));
|
|
#endif /* HAVE_ZLIB */
|
|
}
|
|
data->data = complex_data;
|
|
} else { /* isComplex */
|
|
data->data = malloc(data->ndata*Mat_SizeOf(matvar->data_type));
|
|
if ( data->data == NULL ) {
|
|
Mat_Critical("Couldn't allocate memory for the sparse data");
|
|
break;
|
|
}
|
|
if ( matvar->compression == MAT_COMPRESSION_NONE ) {
|
|
#if defined(EXTENDED_SPARSE)
|
|
switch ( matvar->data_type ) {
|
|
case MAT_T_DOUBLE:
|
|
nBytes = ReadDoubleData(mat,(double*)data->data,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_SINGLE:
|
|
nBytes = ReadSingleData(mat,(float*)data->data,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT64:
|
|
#ifdef HAVE_MAT_INT64_T
|
|
nBytes = ReadInt64Data(mat,(mat_int64_t*)data->data,
|
|
packed_type,data->ndata);
|
|
#endif
|
|
break;
|
|
case MAT_T_UINT64:
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
nBytes = ReadUInt64Data(mat,(mat_uint64_t*)data->data,
|
|
packed_type,data->ndata);
|
|
#endif
|
|
break;
|
|
case MAT_T_INT32:
|
|
nBytes = ReadInt32Data(mat,(mat_int32_t*)data->data,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT32:
|
|
nBytes = ReadUInt32Data(mat,(mat_uint32_t*)data->data,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT16:
|
|
nBytes = ReadInt16Data(mat,(mat_int16_t*)data->data,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT16:
|
|
nBytes = ReadUInt16Data(mat,(mat_uint16_t*)data->data,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT8:
|
|
nBytes = ReadInt8Data(mat,(mat_int8_t*)data->data,
|
|
packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT8:
|
|
nBytes = ReadUInt8Data(mat,(mat_uint8_t*)data->data,
|
|
packed_type,data->ndata);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#else
|
|
nBytes = ReadDoubleData(mat,(double*)data->data,packed_type,
|
|
data->ndata);
|
|
#endif
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
(void)fseek((FILE*)mat->fp,8-(nBytes % 8),SEEK_CUR);
|
|
#if defined(HAVE_ZLIB)
|
|
} else if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
#if defined(EXTENDED_SPARSE)
|
|
switch ( matvar->data_type ) {
|
|
case MAT_T_DOUBLE:
|
|
nBytes = ReadCompressedDoubleData(mat,matvar->internal->z,
|
|
(double*)data->data,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_SINGLE:
|
|
nBytes = ReadCompressedSingleData(mat,matvar->internal->z,
|
|
(float*)data->data,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT64:
|
|
#ifdef HAVE_MAT_INT64_T
|
|
nBytes = ReadCompressedInt64Data(mat,
|
|
matvar->internal->z,(mat_int64_t*)data->data,packed_type,
|
|
data->ndata);
|
|
#endif
|
|
break;
|
|
case MAT_T_UINT64:
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
nBytes = ReadCompressedUInt64Data(mat,
|
|
matvar->internal->z,(mat_uint64_t*)data->data,packed_type,
|
|
data->ndata);
|
|
#endif
|
|
break;
|
|
case MAT_T_INT32:
|
|
nBytes = ReadCompressedInt32Data(mat,matvar->internal->z,
|
|
(mat_int32_t*)data->data,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT32:
|
|
nBytes = ReadCompressedUInt32Data(mat,matvar->internal->z,
|
|
(mat_uint32_t*)data->data,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT16:
|
|
nBytes = ReadCompressedInt16Data(mat,matvar->internal->z,
|
|
(mat_int16_t*)data->data,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT16:
|
|
nBytes = ReadCompressedUInt16Data(mat,matvar->internal->z,
|
|
(mat_uint16_t*)data->data,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_INT8:
|
|
nBytes = ReadCompressedInt8Data(mat,matvar->internal->z,
|
|
(mat_int8_t*)data->data,packed_type,data->ndata);
|
|
break;
|
|
case MAT_T_UINT8:
|
|
nBytes = ReadCompressedUInt8Data(mat,matvar->internal->z,
|
|
(mat_uint8_t*)data->data,packed_type,data->ndata);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#else /* EXTENDED_SPARSE */
|
|
nBytes = ReadCompressedDoubleData(mat,matvar->internal->z,
|
|
(double*)data->data,packed_type,data->ndata);
|
|
#endif /* EXTENDED_SPARSE */
|
|
if ( data_in_tag )
|
|
nBytes+=4;
|
|
if ( (nBytes % 8) != 0 )
|
|
InflateSkip(mat,matvar->internal->z,8-(nBytes % 8));
|
|
#endif /* HAVE_ZLIB */
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case MAT_C_FUNCTION:
|
|
{
|
|
matvar_t **functions;
|
|
size_t nfunctions = 0;
|
|
|
|
if ( !matvar->nbytes || !matvar->data_size )
|
|
break;
|
|
nfunctions = matvar->nbytes / matvar->data_size;
|
|
functions = (matvar_t **)matvar->data;
|
|
if ( NULL != functions ) {
|
|
size_t i;
|
|
for ( i = 0; i < nfunctions; i++ ) {
|
|
Mat_VarRead5(mat,functions[i]);
|
|
}
|
|
}
|
|
/* FIXME: */
|
|
matvar->data_type = MAT_T_FUNCTION;
|
|
break;
|
|
}
|
|
default:
|
|
Mat_Critical("Mat_VarRead5: %d is not a supported class", matvar->class_type);
|
|
}
|
|
switch ( matvar->class_type ) {
|
|
case MAT_C_DOUBLE:
|
|
case MAT_C_SINGLE:
|
|
#ifdef HAVE_MAT_INT64_T
|
|
case MAT_C_INT64:
|
|
#endif
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
case MAT_C_UINT64:
|
|
#endif
|
|
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 ( matvar->isComplex ) {
|
|
mat_complex_split_t *complex_data;
|
|
|
|
SafeMul(&matvar->nbytes, nelems, matvar->data_size);
|
|
complex_data = ComplexMalloc(matvar->nbytes);
|
|
if ( NULL == complex_data ) {
|
|
Mat_Critical("Couldn't allocate memory for the complex data");
|
|
break;
|
|
}
|
|
Mat_VarReadNumeric5(mat,matvar,complex_data->Re,nelems);
|
|
Mat_VarReadNumeric5(mat,matvar,complex_data->Im,nelems);
|
|
matvar->data = complex_data;
|
|
} else {
|
|
SafeMul(&matvar->nbytes, nelems, matvar->data_size);
|
|
matvar->data = malloc(matvar->nbytes);
|
|
if ( NULL == matvar->data ) {
|
|
Mat_Critical("Couldn't allocate memory for the data");
|
|
break;
|
|
}
|
|
Mat_VarReadNumeric5(mat,matvar,matvar->data,nelems);
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
(void)fseek((FILE*)mat->fp,fpos,SEEK_SET);
|
|
|
|
return;
|
|
}
|
|
|
|
#if defined(HAVE_ZLIB)
|
|
#define GET_DATA_SLABN_RANK_LOOP \
|
|
do { \
|
|
for ( j = 1; j < rank; j++ ) { \
|
|
cnt[j]++; \
|
|
if ( (cnt[j] % edge[j]) == 0 ) { \
|
|
cnt[j] = 0; \
|
|
if ( (I % dimp[j]) != 0 ) { \
|
|
ptr_in += dimp[j]-(I % dimp[j])+dimp[j-1]*start[j]; \
|
|
I += dimp[j]-(I % dimp[j]) + dimp[j-1]*start[j]; \
|
|
} else if ( start[j] ) { \
|
|
ptr_in += dimp[j-1]*start[j]; \
|
|
I += dimp[j-1]*start[j]; \
|
|
} \
|
|
} else { \
|
|
I += inc[j]; \
|
|
ptr_in += inc[j]; \
|
|
break; \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
#define GET_DATA_SLAB2(T) \
|
|
do { \
|
|
ptr_in += start[1]*dims[0] + start[0]; \
|
|
for ( i = 0; i < edge[1]; i++ ) { \
|
|
for ( j = 0; j < edge[0]; j++ ) { \
|
|
*ptr = (T)(*(ptr_in+j*stride[0])); \
|
|
ptr++; \
|
|
} \
|
|
ptr_in += stride[1]*dims[0]; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define GET_DATA_SLABN(T) \
|
|
do { \
|
|
inc[0] = stride[0]-1; \
|
|
dimp[0] = dims[0]; \
|
|
N = edge[0]; \
|
|
I = 0; /* start[0]; */ \
|
|
for ( i = 1; i < rank; i++ ) { \
|
|
inc[i] = stride[i]-1; \
|
|
dimp[i] = dims[i-1]; \
|
|
for ( j = i; j--; ) { \
|
|
inc[i] *= dims[j]; \
|
|
dimp[i] *= dims[j+1]; \
|
|
} \
|
|
N *= edge[i]; \
|
|
I += dimp[i-1]*start[i]; \
|
|
} \
|
|
ptr_in += I; \
|
|
if ( stride[0] == 1 ) { \
|
|
for ( i = 0; i < N; i+=edge[0] ) { \
|
|
int k; \
|
|
if ( start[0] ) { \
|
|
ptr_in += start[0]; \
|
|
I += start[0]; \
|
|
} \
|
|
for ( k = 0; k < edge[0]; k++ ) { \
|
|
*(ptr+i+k) = (T)(*(ptr_in+k)); \
|
|
} \
|
|
I += dims[0]-start[0]; \
|
|
ptr_in += dims[0]-start[0]; \
|
|
GET_DATA_SLABN_RANK_LOOP; \
|
|
} \
|
|
} else { \
|
|
for ( i = 0; i < N; i+=edge[0] ) { \
|
|
if ( start[0] ) { \
|
|
ptr_in += start[0]; \
|
|
I += start[0]; \
|
|
} \
|
|
for ( j = 0; j < edge[0]; j++ ) { \
|
|
*(ptr+i+j) = (T)(*ptr_in); \
|
|
ptr_in += stride[0]; \
|
|
I += stride[0]; \
|
|
} \
|
|
I += dims[0]-(ptrdiff_t)edge[0]*stride[0]-start[0]; \
|
|
ptr_in += dims[0]-(ptrdiff_t)edge[0]*stride[0]-start[0]; \
|
|
GET_DATA_SLABN_RANK_LOOP; \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
#ifdef HAVE_MAT_INT64_T
|
|
#define GET_DATA_SLAB2_INT64(T) \
|
|
do { \
|
|
if ( MAT_T_INT64 == data_type ) { \
|
|
mat_int64_t *ptr_in = (mat_int64_t *)data_in; \
|
|
GET_DATA_SLAB2(T); \
|
|
err = 0; \
|
|
} \
|
|
} while (0)
|
|
#else
|
|
#define GET_DATA_SLAB2_INT64(T)
|
|
#endif /* HAVE_MAT_INT64_T */
|
|
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
#define GET_DATA_SLAB2_UINT64(T) \
|
|
do { \
|
|
if ( MAT_T_UINT64 == data_type ) { \
|
|
mat_uint64_t *ptr_in = (mat_uint64_t *)data_in; \
|
|
GET_DATA_SLAB2(T); \
|
|
err = 0; \
|
|
} \
|
|
} while (0)
|
|
#else
|
|
#define GET_DATA_SLAB2_UINT64(T)
|
|
#endif /* HAVE_MAT_UINT64_T */
|
|
|
|
#define GET_DATA_SLAB2_TYPE(T) \
|
|
do { \
|
|
switch ( data_type ) { \
|
|
case MAT_T_DOUBLE: \
|
|
{ \
|
|
double *ptr_in = (double *)data_in; \
|
|
GET_DATA_SLAB2(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_SINGLE: \
|
|
{ \
|
|
float *ptr_in = (float *)data_in; \
|
|
GET_DATA_SLAB2(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_INT32: \
|
|
{ \
|
|
mat_int32_t *ptr_in = (mat_int32_t *)data_in; \
|
|
GET_DATA_SLAB2(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_UINT32: \
|
|
{ \
|
|
mat_uint32_t *ptr_in = (mat_uint32_t *)data_in; \
|
|
GET_DATA_SLAB2(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_INT16: \
|
|
{ \
|
|
mat_int16_t *ptr_in = (mat_int16_t *)data_in; \
|
|
GET_DATA_SLAB2(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_UINT16: \
|
|
{ \
|
|
mat_uint16_t *ptr_in = (mat_uint16_t *)data_in; \
|
|
GET_DATA_SLAB2(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_INT8: \
|
|
{ \
|
|
mat_int8_t *ptr_in = (mat_int8_t *)data_in; \
|
|
GET_DATA_SLAB2(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_UINT8: \
|
|
{ \
|
|
mat_uint8_t *ptr_in = (mat_uint8_t *)data_in; \
|
|
GET_DATA_SLAB2(T); \
|
|
break; \
|
|
} \
|
|
default: \
|
|
err = 1; \
|
|
GET_DATA_SLAB2_INT64(T); \
|
|
GET_DATA_SLAB2_UINT64(T); \
|
|
break; \
|
|
} \
|
|
} while (0)
|
|
|
|
#ifdef HAVE_MAT_INT64_T
|
|
#define GET_DATA_SLABN_INT64(T) \
|
|
do { \
|
|
if ( MAT_T_INT64 == data_type ) { \
|
|
mat_int64_t *ptr_in = (mat_int64_t *)data_in; \
|
|
GET_DATA_SLABN(T); \
|
|
err = 0; \
|
|
} \
|
|
} while (0)
|
|
#else
|
|
#define GET_DATA_SLABN_INT64(T)
|
|
#endif /* HAVE_MAT_INT64_T */
|
|
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
#define GET_DATA_SLABN_UINT64(T) \
|
|
do { \
|
|
if ( MAT_T_UINT64 == data_type ) { \
|
|
mat_uint64_t *ptr_in = (mat_uint64_t *)data_in; \
|
|
GET_DATA_SLABN(T); \
|
|
err = 0; \
|
|
} \
|
|
} while (0)
|
|
#else
|
|
#define GET_DATA_SLABN_UINT64(T)
|
|
#endif /* HAVE_MAT_UINT64_T */
|
|
|
|
#define GET_DATA_SLABN_TYPE(T) \
|
|
do { \
|
|
switch ( data_type ) { \
|
|
case MAT_T_DOUBLE: \
|
|
{ \
|
|
double *ptr_in = (double *)data_in; \
|
|
GET_DATA_SLABN(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_SINGLE: \
|
|
{ \
|
|
float *ptr_in = (float *)data_in; \
|
|
GET_DATA_SLABN(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_INT32: \
|
|
{ \
|
|
mat_int32_t *ptr_in = (mat_int32_t *)data_in; \
|
|
GET_DATA_SLABN(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_UINT32: \
|
|
{ \
|
|
mat_uint32_t *ptr_in = (mat_uint32_t *)data_in; \
|
|
GET_DATA_SLABN(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_INT16: \
|
|
{ \
|
|
mat_int16_t *ptr_in = (mat_int16_t *)data_in; \
|
|
GET_DATA_SLABN(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_UINT16: \
|
|
{ \
|
|
mat_uint16_t *ptr_in = (mat_uint16_t *)data_in; \
|
|
GET_DATA_SLABN(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_INT8: \
|
|
{ \
|
|
mat_int8_t *ptr_in = (mat_int8_t *)data_in; \
|
|
GET_DATA_SLABN(T); \
|
|
break; \
|
|
} \
|
|
case MAT_T_UINT8: \
|
|
{ \
|
|
mat_uint8_t *ptr_in = (mat_uint8_t *)data_in; \
|
|
GET_DATA_SLABN(T); \
|
|
break; \
|
|
} \
|
|
default: \
|
|
err = 1; \
|
|
GET_DATA_SLABN_INT64(T); \
|
|
GET_DATA_SLABN_UINT64(T); \
|
|
break; \
|
|
} \
|
|
} while (0)
|
|
|
|
static int
|
|
GetDataSlab(void *data_in, void *data_out, enum matio_classes class_type,
|
|
enum matio_types data_type, size_t *dims, int *start, int *stride, int *edge,
|
|
int rank, size_t nbytes)
|
|
{
|
|
int err = 0;
|
|
int same_type = 0;
|
|
if (( class_type == MAT_C_DOUBLE && data_type == MAT_T_DOUBLE ) ||
|
|
( class_type == MAT_C_SINGLE && data_type == MAT_T_SINGLE ) ||
|
|
( class_type == MAT_C_INT16 && data_type == MAT_T_INT16 ) ||
|
|
( class_type == MAT_C_INT32 && data_type == MAT_T_INT32 ) ||
|
|
( class_type == MAT_C_INT64 && data_type == MAT_T_INT64 ) ||
|
|
( class_type == MAT_C_INT8 && data_type == MAT_T_INT8 ) ||
|
|
( class_type == MAT_C_UINT16 && data_type == MAT_T_UINT16 ) ||
|
|
( class_type == MAT_C_UINT32 && data_type == MAT_T_UINT32 ) ||
|
|
( class_type == MAT_C_UINT64 && data_type == MAT_T_UINT64 ) ||
|
|
( class_type == MAT_C_UINT8 && data_type == MAT_T_UINT8 ))
|
|
same_type = 1;
|
|
|
|
if ( rank == 2 ) {
|
|
if ( (size_t)stride[0]*(edge[0]-1)+start[0]+1 > dims[0] )
|
|
err = 1;
|
|
else if ( (size_t)stride[1]*(edge[1]-1)+start[1]+1 > dims[1] )
|
|
err = 1;
|
|
else if ( ( stride[0] == 1 && edge[0] == dims[0] ) &&
|
|
( stride[1] == 1 ) && ( same_type == 1 ) )
|
|
memcpy(data_out, data_in, nbytes);
|
|
else {
|
|
int i, j;
|
|
|
|
switch ( class_type ) {
|
|
case MAT_C_DOUBLE:
|
|
{
|
|
double *ptr = (double *)data_out;
|
|
GET_DATA_SLAB2_TYPE(double);
|
|
break;
|
|
}
|
|
case MAT_C_SINGLE:
|
|
{
|
|
float *ptr = (float *)data_out;
|
|
GET_DATA_SLAB2_TYPE(float);
|
|
break;
|
|
}
|
|
#ifdef HAVE_MAT_INT64_T
|
|
case MAT_C_INT64:
|
|
{
|
|
mat_int64_t *ptr = (mat_int64_t *)data_out;
|
|
GET_DATA_SLAB2_TYPE(mat_int64_t);
|
|
break;
|
|
}
|
|
#endif /* HAVE_MAT_INT64_T */
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
case MAT_C_UINT64:
|
|
{
|
|
mat_uint64_t *ptr = (mat_uint64_t *)data_out;
|
|
GET_DATA_SLAB2_TYPE(mat_uint64_t);
|
|
break;
|
|
}
|
|
#endif /* HAVE_MAT_UINT64_T */
|
|
case MAT_C_INT32:
|
|
{
|
|
mat_int32_t *ptr = (mat_int32_t *)data_out;
|
|
GET_DATA_SLAB2_TYPE(mat_int32_t);
|
|
break;
|
|
}
|
|
case MAT_C_UINT32:
|
|
{
|
|
mat_uint32_t *ptr = (mat_uint32_t *)data_out;
|
|
GET_DATA_SLAB2_TYPE(mat_uint32_t);
|
|
break;
|
|
}
|
|
case MAT_C_INT16:
|
|
{
|
|
mat_int16_t *ptr = (mat_int16_t *)data_out;
|
|
GET_DATA_SLAB2_TYPE(mat_int16_t);
|
|
break;
|
|
}
|
|
case MAT_C_UINT16:
|
|
{
|
|
mat_uint16_t *ptr = (mat_uint16_t *)data_out;
|
|
GET_DATA_SLAB2_TYPE(mat_uint16_t);
|
|
break;
|
|
}
|
|
case MAT_C_INT8:
|
|
{
|
|
mat_int8_t *ptr = (mat_int8_t *)data_out;
|
|
GET_DATA_SLAB2_TYPE(mat_int8_t);
|
|
break;
|
|
}
|
|
case MAT_C_UINT8:
|
|
{
|
|
mat_uint8_t *ptr = (mat_uint8_t *)data_out;
|
|
GET_DATA_SLAB2_TYPE(mat_uint8_t);
|
|
break;
|
|
}
|
|
default:
|
|
err = 1;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
int i, j, N, I = 0;
|
|
int inc[10] = {0,}, cnt[10] = {0,}, dimp[10] = {0,};
|
|
|
|
switch ( class_type ) {
|
|
case MAT_C_DOUBLE:
|
|
{
|
|
double *ptr = (double *)data_out;
|
|
GET_DATA_SLABN_TYPE(double);
|
|
break;
|
|
}
|
|
case MAT_C_SINGLE:
|
|
{
|
|
float *ptr = (float *)data_out;
|
|
GET_DATA_SLABN_TYPE(float);
|
|
break;
|
|
}
|
|
#ifdef HAVE_MAT_INT64_T
|
|
case MAT_C_INT64:
|
|
{
|
|
mat_int64_t *ptr = (mat_int64_t *)data_out;
|
|
GET_DATA_SLABN_TYPE(mat_int64_t);
|
|
break;
|
|
}
|
|
#endif /* HAVE_MAT_INT64_T */
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
case MAT_C_UINT64:
|
|
{
|
|
mat_uint64_t *ptr = (mat_uint64_t *)data_out;
|
|
GET_DATA_SLABN_TYPE(mat_uint64_t);
|
|
break;
|
|
}
|
|
#endif /* HAVE_MAT_UINT64_T */
|
|
case MAT_C_INT32:
|
|
{
|
|
mat_int32_t *ptr = (mat_int32_t *)data_out;
|
|
GET_DATA_SLABN_TYPE(mat_int32_t);
|
|
break;
|
|
}
|
|
case MAT_C_UINT32:
|
|
{
|
|
mat_uint32_t *ptr = (mat_uint32_t *)data_out;
|
|
GET_DATA_SLABN_TYPE(mat_uint32_t);
|
|
break;
|
|
}
|
|
case MAT_C_INT16:
|
|
{
|
|
mat_int16_t *ptr = (mat_int16_t *)data_out;
|
|
GET_DATA_SLABN_TYPE(mat_int16_t);
|
|
break;
|
|
}
|
|
case MAT_C_UINT16:
|
|
{
|
|
mat_uint16_t *ptr = (mat_uint16_t *)data_out;
|
|
GET_DATA_SLABN_TYPE(mat_uint16_t);
|
|
break;
|
|
}
|
|
case MAT_C_INT8:
|
|
{
|
|
mat_int8_t *ptr = (mat_int8_t *)data_out;
|
|
GET_DATA_SLABN_TYPE(mat_int8_t);
|
|
break;
|
|
}
|
|
case MAT_C_UINT8:
|
|
{
|
|
mat_uint8_t *ptr = (mat_uint8_t *)data_out;
|
|
GET_DATA_SLABN_TYPE(mat_uint8_t);
|
|
break;
|
|
}
|
|
default:
|
|
err = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
#undef GET_DATA_SLAB2
|
|
#undef GET_DATA_SLAB2_TYPE
|
|
#undef GET_DATA_SLAB2_INT64
|
|
#undef GET_DATA_SLAB2_UINT64
|
|
#undef GET_DATA_SLABN
|
|
#undef GET_DATA_SLABN_TYPE
|
|
#undef GET_DATA_SLABN_INT64
|
|
#undef GET_DATA_SLABN_UINT64
|
|
#undef GET_DATA_SLABN_RANK_LOOP
|
|
|
|
#define GET_DATA_LINEAR \
|
|
do { \
|
|
ptr_in += start; \
|
|
if ( !stride ) { \
|
|
memcpy(ptr, ptr_in, (size_t)edge*data_size); \
|
|
} else { \
|
|
int i; \
|
|
for ( i = 0; i < edge; i++ ) \
|
|
memcpy(ptr++, ptr_in+i*stride, data_size); \
|
|
} \
|
|
} while (0)
|
|
|
|
static int
|
|
GetDataLinear(void *data_in, void *data_out, enum matio_classes class_type,
|
|
enum matio_types data_type, int start, int stride, int edge)
|
|
{
|
|
int err = 0;
|
|
size_t data_size = Mat_SizeOf(data_type);
|
|
|
|
switch ( class_type ) {
|
|
case MAT_C_DOUBLE:
|
|
{
|
|
double *ptr = (double *)data_out;
|
|
double *ptr_in = (double*)data_in;
|
|
GET_DATA_LINEAR;
|
|
break;
|
|
}
|
|
case MAT_C_SINGLE:
|
|
{
|
|
float *ptr = (float *)data_out;
|
|
float *ptr_in = (float*)data_in;
|
|
GET_DATA_LINEAR;
|
|
break;
|
|
}
|
|
#ifdef HAVE_MAT_INT64_T
|
|
case MAT_C_INT64:
|
|
{
|
|
mat_int64_t *ptr = (mat_int64_t *)data_out;
|
|
mat_int64_t *ptr_in = (mat_int64_t*)data_in;
|
|
GET_DATA_LINEAR;
|
|
break;
|
|
}
|
|
#endif /* HAVE_MAT_INT64_T */
|
|
#ifdef HAVE_MAT_UINT64_T
|
|
case MAT_C_UINT64:
|
|
{
|
|
mat_uint64_t *ptr = (mat_uint64_t *)data_out;
|
|
mat_uint64_t *ptr_in = (mat_uint64_t*)data_in;
|
|
GET_DATA_LINEAR;
|
|
break;
|
|
}
|
|
#endif /* HAVE_MAT_UINT64_T */
|
|
case MAT_C_INT32:
|
|
{
|
|
mat_int32_t *ptr = (mat_int32_t *)data_out;
|
|
mat_int32_t *ptr_in = (mat_int32_t*)data_in;
|
|
GET_DATA_LINEAR;
|
|
break;
|
|
}
|
|
case MAT_C_UINT32:
|
|
{
|
|
mat_uint32_t *ptr = (mat_uint32_t *)data_out;
|
|
mat_uint32_t *ptr_in = (mat_uint32_t*)data_in;
|
|
GET_DATA_LINEAR;
|
|
break;
|
|
}
|
|
case MAT_C_INT16:
|
|
{
|
|
mat_int16_t *ptr = (mat_int16_t *)data_out;
|
|
mat_int16_t *ptr_in = (mat_int16_t*)data_in;
|
|
GET_DATA_LINEAR;
|
|
break;
|
|
}
|
|
case MAT_C_UINT16:
|
|
{
|
|
mat_uint16_t *ptr = (mat_uint16_t *)data_out;
|
|
mat_uint16_t *ptr_in = (mat_uint16_t*)data_in;
|
|
GET_DATA_LINEAR;
|
|
break;
|
|
}
|
|
case MAT_C_INT8:
|
|
{
|
|
mat_int8_t *ptr = (mat_int8_t *)data_out;
|
|
mat_int8_t *ptr_in = (mat_int8_t*)data_in;
|
|
GET_DATA_LINEAR;
|
|
break;
|
|
}
|
|
case MAT_C_UINT8:
|
|
{
|
|
mat_uint8_t *ptr = (mat_uint8_t *)data_out;
|
|
mat_uint8_t *ptr_in = (mat_uint8_t*)data_in;
|
|
GET_DATA_LINEAR;
|
|
break;
|
|
}
|
|
default:
|
|
err = 1;
|
|
break;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
#undef GET_DATA_LINEAR
|
|
#endif
|
|
|
|
/** @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_VarReadData5(mat_t *mat,matvar_t *matvar,void *data,
|
|
int *start,int *stride,int *edge)
|
|
{
|
|
int err = 0,real_bytes = 0;
|
|
mat_int32_t tag[2];
|
|
#if defined(HAVE_ZLIB)
|
|
z_stream z;
|
|
#endif
|
|
size_t bytesread = 0;
|
|
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
if ( matvar->compression == MAT_COMPRESSION_NONE ) {
|
|
bytesread += fread(tag,4,2,(FILE*)mat->fp);
|
|
if ( mat->byteswap ) {
|
|
Mat_int32Swap(tag);
|
|
Mat_int32Swap(tag+1);
|
|
}
|
|
matvar->data_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
|
|
(void)fseek((FILE*)mat->fp,-4,SEEK_CUR);
|
|
real_bytes = 4+(tag[0] >> 16);
|
|
} else {
|
|
real_bytes = 8+tag[1];
|
|
}
|
|
#if defined(HAVE_ZLIB)
|
|
} else if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
if ( NULL != matvar->internal->data ) {
|
|
/* Data already read in ReadNextStructField or ReadNextCell */
|
|
if ( matvar->isComplex ) {
|
|
mat_complex_split_t *ci, *co;
|
|
|
|
co = (mat_complex_split_t*)data;
|
|
ci = (mat_complex_split_t*)matvar->internal->data;
|
|
err = GetDataSlab(ci->Re, co->Re, matvar->class_type,
|
|
matvar->data_type, matvar->dims, start, stride, edge,
|
|
matvar->rank, matvar->nbytes);
|
|
if ( err == 0 )
|
|
err = GetDataSlab(ci->Im, co->Im, matvar->class_type,
|
|
matvar->data_type, matvar->dims, start, stride, edge,
|
|
matvar->rank, matvar->nbytes);
|
|
return err;
|
|
} else {
|
|
return GetDataSlab(matvar->internal->data, data, matvar->class_type,
|
|
matvar->data_type, matvar->dims, start, stride, edge,
|
|
matvar->rank, matvar->nbytes);
|
|
}
|
|
}
|
|
|
|
err = inflateCopy(&z,matvar->internal->z);
|
|
if ( err != Z_OK ) {
|
|
Mat_Critical("inflateCopy returned error %s",zError(err));
|
|
return -1;
|
|
}
|
|
z.avail_in = 0;
|
|
InflateDataType(mat,&z,tag);
|
|
if ( mat->byteswap ) {
|
|
Mat_int32Swap(tag);
|
|
}
|
|
matvar->data_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( !(tag[0] & 0xffff0000) ) {/* Data is NOT packed in the tag */
|
|
/* We're cheating, but InflateDataType just inflates 4 bytes */
|
|
InflateDataType(mat,&z,tag+1);
|
|
if ( mat->byteswap ) {
|
|
Mat_int32Swap(tag+1);
|
|
}
|
|
real_bytes = 8+tag[1];
|
|
} else {
|
|
real_bytes = 4+(tag[0] >> 16);
|
|
}
|
|
#endif
|
|
}
|
|
if ( real_bytes % 8 )
|
|
real_bytes += (8-(real_bytes % 8));
|
|
|
|
if ( matvar->rank == 2 ) {
|
|
if ( (size_t)stride[0]*(edge[0]-1)+start[0]+1 > matvar->dims[0] )
|
|
err = 1;
|
|
else if ( (size_t)stride[1]*(edge[1]-1)+start[1]+1 > matvar->dims[1] )
|
|
err = 1;
|
|
else if ( matvar->compression == MAT_COMPRESSION_NONE ) {
|
|
if ( matvar->isComplex ) {
|
|
mat_complex_split_t *complex_data = (mat_complex_split_t*)data;
|
|
|
|
ReadDataSlab2(mat,complex_data->Re,matvar->class_type,
|
|
matvar->data_type,matvar->dims,start,stride,edge);
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos+real_bytes,SEEK_SET);
|
|
bytesread += fread(tag,4,2,(FILE*)mat->fp);
|
|
if ( mat->byteswap ) {
|
|
Mat_int32Swap(tag);
|
|
Mat_int32Swap(tag+1);
|
|
}
|
|
matvar->data_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
|
|
(void)fseek((FILE*)mat->fp,-4,SEEK_CUR);
|
|
}
|
|
ReadDataSlab2(mat,complex_data->Im,matvar->class_type,
|
|
matvar->data_type,matvar->dims,start,stride,edge);
|
|
} else {
|
|
ReadDataSlab2(mat,data,matvar->class_type,
|
|
matvar->data_type,matvar->dims,start,stride,edge);
|
|
}
|
|
}
|
|
#if defined(HAVE_ZLIB)
|
|
else if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
if ( matvar->isComplex ) {
|
|
mat_complex_split_t *complex_data = (mat_complex_split_t*)data;
|
|
|
|
ReadCompressedDataSlab2(mat,&z,complex_data->Re,
|
|
matvar->class_type,matvar->data_type,matvar->dims,
|
|
start,stride,edge);
|
|
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
|
|
/* Reset zlib knowledge to before reading real tag */
|
|
inflateEnd(&z);
|
|
err = inflateCopy(&z,matvar->internal->z);
|
|
if ( err != Z_OK ) {
|
|
Mat_Critical("inflateCopy returned error %s",zError(err));
|
|
}
|
|
InflateSkip(mat,&z,real_bytes);
|
|
z.avail_in = 0;
|
|
InflateDataType(mat,&z,tag);
|
|
if ( mat->byteswap ) {
|
|
Mat_int32Swap(tag);
|
|
}
|
|
matvar->data_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( !(tag[0] & 0xffff0000) ) {/*Data is NOT packed in the tag*/
|
|
InflateSkip(mat,&z,4);
|
|
}
|
|
ReadCompressedDataSlab2(mat,&z,complex_data->Im,
|
|
matvar->class_type,matvar->data_type,matvar->dims,
|
|
start,stride,edge);
|
|
} else {
|
|
ReadCompressedDataSlab2(mat,&z,data,matvar->class_type,
|
|
matvar->data_type,matvar->dims,start,stride,edge);
|
|
}
|
|
inflateEnd(&z);
|
|
}
|
|
#endif
|
|
} else {
|
|
if ( matvar->compression == MAT_COMPRESSION_NONE ) {
|
|
if ( matvar->isComplex ) {
|
|
mat_complex_split_t *complex_data = (mat_complex_split_t*)data;
|
|
|
|
ReadDataSlabN(mat,complex_data->Re,matvar->class_type,
|
|
matvar->data_type,matvar->rank,matvar->dims,
|
|
start,stride,edge);
|
|
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos+real_bytes,SEEK_SET);
|
|
bytesread += fread(tag,4,2,(FILE*)mat->fp);
|
|
if ( mat->byteswap ) {
|
|
Mat_int32Swap(tag);
|
|
Mat_int32Swap(tag+1);
|
|
}
|
|
matvar->data_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
|
|
(void)fseek((FILE*)mat->fp,-4,SEEK_CUR);
|
|
}
|
|
ReadDataSlabN(mat,complex_data->Im,matvar->class_type,
|
|
matvar->data_type,matvar->rank,matvar->dims,
|
|
start,stride,edge);
|
|
} else {
|
|
ReadDataSlabN(mat,data,matvar->class_type,matvar->data_type,
|
|
matvar->rank,matvar->dims,start,stride,edge);
|
|
}
|
|
}
|
|
#if defined(HAVE_ZLIB)
|
|
else if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
if ( matvar->isComplex ) {
|
|
mat_complex_split_t *complex_data = (mat_complex_split_t*)data;
|
|
|
|
ReadCompressedDataSlabN(mat,&z,complex_data->Re,
|
|
matvar->class_type,matvar->data_type,matvar->rank,
|
|
matvar->dims,start,stride,edge);
|
|
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
/* Reset zlib knowledge to before reading real tag */
|
|
inflateEnd(&z);
|
|
err = inflateCopy(&z,matvar->internal->z);
|
|
if ( err != Z_OK ) {
|
|
Mat_Critical("inflateCopy returned error %s",zError(err));
|
|
}
|
|
InflateSkip(mat,&z,real_bytes);
|
|
z.avail_in = 0;
|
|
InflateDataType(mat,&z,tag);
|
|
if ( mat->byteswap ) {
|
|
Mat_int32Swap(tag);
|
|
}
|
|
matvar->data_type = TYPE_FROM_TAG(tag[0]);
|
|
if ( !(tag[0] & 0xffff0000) ) {/*Data is NOT packed in the tag*/
|
|
InflateSkip(mat,&z,4);
|
|
}
|
|
ReadCompressedDataSlabN(mat,&z,complex_data->Im,
|
|
matvar->class_type,matvar->data_type,matvar->rank,
|
|
matvar->dims,start,stride,edge);
|
|
} else {
|
|
ReadCompressedDataSlabN(mat,&z,data,matvar->class_type,
|
|
matvar->data_type,matvar->rank,matvar->dims,
|
|
start,stride,edge);
|
|
}
|
|
inflateEnd(&z);
|
|
}
|
|
#endif
|
|
}
|
|
if ( err == 0 ) {
|
|
matvar->data_type = ClassType2DataType(matvar->class_type);
|
|
matvar->data_size = Mat_SizeOfClass(matvar->class_type);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
/** @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
|
|
* @param mat MAT file to read data from
|
|
* @param matvar MAT variable information
|
|
* @param data pointer to store data in (must be pre-allocated)
|
|
* @param start starting index
|
|
* @param stride stride of data
|
|
* @param edge number of elements to read
|
|
* @retval 0 on success
|
|
*/
|
|
int
|
|
Mat_VarReadDataLinear5(mat_t *mat,matvar_t *matvar,void *data,int start,
|
|
int stride,int edge)
|
|
{
|
|
int err = 0, real_bytes = 0;
|
|
mat_int32_t tag[2];
|
|
#if defined(HAVE_ZLIB)
|
|
z_stream z;
|
|
#endif
|
|
size_t bytesread = 0, nelems = 1;
|
|
|
|
if ( mat->version == MAT_FT_MAT4 )
|
|
return -1;
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
if ( matvar->compression == MAT_COMPRESSION_NONE ) {
|
|
bytesread += fread(tag,4,2,(FILE*)mat->fp);
|
|
if ( mat->byteswap ) {
|
|
Mat_int32Swap(tag);
|
|
Mat_int32Swap(tag+1);
|
|
}
|
|
matvar->data_type = (enum matio_types)(tag[0] & 0x000000ff);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
|
|
(void)fseek((FILE*)mat->fp,-4,SEEK_CUR);
|
|
real_bytes = 4+(tag[0] >> 16);
|
|
} else {
|
|
real_bytes = 8+tag[1];
|
|
}
|
|
#if defined(HAVE_ZLIB)
|
|
} else if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
if ( NULL != matvar->internal->data ) {
|
|
/* Data already read in ReadNextStructField or ReadNextCell */
|
|
if ( matvar->isComplex ) {
|
|
mat_complex_split_t *ci, *co;
|
|
|
|
co = (mat_complex_split_t*)data;
|
|
ci = (mat_complex_split_t*)matvar->internal->data;
|
|
err = GetDataLinear(ci->Re, co->Re, matvar->class_type,
|
|
matvar->data_type, start, stride, edge);
|
|
if ( err == 0 )
|
|
err = GetDataLinear(ci->Im, co->Im, matvar->class_type,
|
|
matvar->data_type, start, stride, edge);
|
|
return err;
|
|
} else {
|
|
return GetDataLinear(matvar->internal->data, data, matvar->class_type,
|
|
matvar->data_type, start, stride, edge);
|
|
}
|
|
}
|
|
|
|
matvar->internal->z->avail_in = 0;
|
|
err = inflateCopy(&z,matvar->internal->z);
|
|
if ( err != Z_OK ) {
|
|
Mat_Critical("inflateCopy returned error %s",zError(err));
|
|
return -1;
|
|
}
|
|
InflateDataType(mat,&z,tag);
|
|
if ( mat->byteswap ) {
|
|
Mat_int32Swap(tag);
|
|
Mat_int32Swap(tag+1);
|
|
}
|
|
matvar->data_type = (enum matio_types)(tag[0] & 0x000000ff);
|
|
if ( !(tag[0] & 0xffff0000) ) {/* Data is NOT packed in the tag */
|
|
/* We're cheating, but InflateDataType just inflates 4 bytes */
|
|
InflateDataType(mat,&z,tag+1);
|
|
if ( mat->byteswap ) {
|
|
Mat_int32Swap(tag+1);
|
|
}
|
|
real_bytes = 8+tag[1];
|
|
} else {
|
|
real_bytes = 4+(tag[0] >> 16);
|
|
}
|
|
#endif
|
|
}
|
|
if ( real_bytes % 8 )
|
|
real_bytes += (8-(real_bytes % 8));
|
|
|
|
err = SafeMulDims(matvar, &nelems);
|
|
if ( err ) {
|
|
Mat_Critical("Integer multiplication overflow");
|
|
}
|
|
|
|
if ( (size_t)stride*(edge-1)+start+1 > nelems ) {
|
|
err = 1;
|
|
} else if ( matvar->compression == MAT_COMPRESSION_NONE ) {
|
|
if ( matvar->isComplex ) {
|
|
mat_complex_split_t *complex_data = (mat_complex_split_t*)data;
|
|
|
|
ReadDataSlab1(mat,complex_data->Re,matvar->class_type,
|
|
matvar->data_type,start,stride,edge);
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos+real_bytes,SEEK_SET);
|
|
bytesread += fread(tag,4,2,(FILE*)mat->fp);
|
|
if ( mat->byteswap ) {
|
|
Mat_int32Swap(tag);
|
|
Mat_int32Swap(tag+1);
|
|
}
|
|
matvar->data_type = (enum matio_types)(tag[0] & 0x000000ff);
|
|
if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
|
|
(void)fseek((FILE*)mat->fp,-4,SEEK_CUR);
|
|
}
|
|
ReadDataSlab1(mat,complex_data->Im,matvar->class_type,
|
|
matvar->data_type,start,stride,edge);
|
|
} else {
|
|
ReadDataSlab1(mat,data,matvar->class_type,
|
|
matvar->data_type,start,stride,edge);
|
|
}
|
|
#if defined(HAVE_ZLIB)
|
|
} else if ( matvar->compression == MAT_COMPRESSION_ZLIB ) {
|
|
if ( matvar->isComplex ) {
|
|
mat_complex_split_t *complex_data = (mat_complex_split_t*)data;
|
|
|
|
ReadCompressedDataSlab1(mat,&z,complex_data->Re,
|
|
matvar->class_type,matvar->data_type,start,stride,edge);
|
|
|
|
(void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET);
|
|
|
|
/* Reset zlib knowledge to before reading real tag */
|
|
inflateEnd(&z);
|
|
err = inflateCopy(&z,matvar->internal->z);
|
|
if ( err != Z_OK ) {
|
|
Mat_Critical("inflateCopy returned error %s",zError(err));
|
|
}
|
|
InflateSkip(mat,&z,real_bytes);
|
|
z.avail_in = 0;
|
|
InflateDataType(mat,&z,tag);
|
|
if ( mat->byteswap ) {
|
|
Mat_int32Swap(tag);
|
|
}
|
|
matvar->data_type = (enum matio_types)(tag[0] & 0x000000ff);
|
|
if ( !(tag[0] & 0xffff0000) ) {/*Data is NOT packed in the tag*/
|
|
InflateSkip(mat,&z,4);
|
|
}
|
|
ReadCompressedDataSlab1(mat,&z,complex_data->Im,
|
|
matvar->class_type,matvar->data_type,start,stride,edge);
|
|
} else {
|
|
ReadCompressedDataSlab1(mat,&z,data,matvar->class_type,
|
|
matvar->data_type,start,stride,edge);
|
|
}
|
|
inflateEnd(&z);
|
|
#endif
|
|
}
|
|
|
|
matvar->data_type = ClassType2DataType(matvar->class_type);
|
|
matvar->data_size = Mat_SizeOfClass(matvar->class_type);
|
|
|
|
return err;
|
|
}
|
|
|
|
/** @if mat_devman
|
|
* @brief Writes a matlab variable to a version 5 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_VarWrite5(mat_t *mat,matvar_t *matvar,int compress)
|
|
{
|
|
mat_uint32_t array_flags;
|
|
int array_flags_type = MAT_T_UINT32, dims_array_type = MAT_T_INT32;
|
|
int array_flags_size = 8, pad4 = 0, matrix_type = MAT_T_MATRIX;
|
|
int nBytes, i, nzmax = 0;
|
|
long start = 0, end = 0;
|
|
|
|
if ( NULL == mat )
|
|
return -1;
|
|
|
|
/* FIXME: SEEK_END is not Guaranteed by the C standard */
|
|
(void)fseek((FILE*)mat->fp,0,SEEK_END); /* Always write at end of file */
|
|
|
|
if ( NULL == matvar || NULL == matvar->name )
|
|
return -1;
|
|
|
|
#if defined(HAVE_ZLIB)
|
|
if ( compress == MAT_COMPRESSION_NONE ) {
|
|
#else
|
|
{
|
|
#endif
|
|
fwrite(&matrix_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&pad4,4,1,(FILE*)mat->fp);
|
|
start = ftell((FILE*)mat->fp);
|
|
|
|
/* Array Flags */
|
|
array_flags = matvar->class_type & CLASS_TYPE_MASK;
|
|
if ( matvar->isComplex )
|
|
array_flags |= MAT_F_COMPLEX;
|
|
if ( matvar->isGlobal )
|
|
array_flags |= MAT_F_GLOBAL;
|
|
if ( matvar->isLogical )
|
|
array_flags |= MAT_F_LOGICAL;
|
|
if ( matvar->class_type == MAT_C_SPARSE )
|
|
nzmax = ((mat_sparse_t *)matvar->data)->nzmax;
|
|
|
|
fwrite(&array_flags_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&array_flags_size,4,1,(FILE*)mat->fp);
|
|
fwrite(&array_flags,4,1,(FILE*)mat->fp);
|
|
fwrite(&nzmax,4,1,(FILE*)mat->fp);
|
|
/* Rank and Dimension */
|
|
nBytes = matvar->rank * 4;
|
|
fwrite(&dims_array_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
for ( i = 0; i < matvar->rank; i++ ) {
|
|
mat_int32_t dim;
|
|
dim = matvar->dims[i];
|
|
fwrite(&dim,4,1,(FILE*)mat->fp);
|
|
}
|
|
if ( matvar->rank % 2 != 0 )
|
|
fwrite(&pad4,4,1,(FILE*)mat->fp);
|
|
/* Name of variable */
|
|
if ( strlen(matvar->name) <= 4 ) {
|
|
mat_int32_t array_name_type = MAT_T_INT8;
|
|
mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
|
|
mat_int8_t pad1 = 0;
|
|
#if 0
|
|
fwrite(&array_name_type,2,1,(FILE*)mat->fp);
|
|
fwrite(&array_name_len,2,1,(FILE*)mat->fp);
|
|
#else
|
|
array_name_type = (array_name_len << 16) | array_name_type;
|
|
fwrite(&array_name_type,4,1,(FILE*)mat->fp);
|
|
#endif
|
|
fwrite(matvar->name,1,array_name_len,(FILE*)mat->fp);
|
|
for ( i = array_name_len; i < 4; i++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
} else {
|
|
mat_int32_t array_name_type = MAT_T_INT8;
|
|
mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
|
|
mat_int8_t pad1 = 0;
|
|
|
|
fwrite(&array_name_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&array_name_len,4,1,(FILE*)mat->fp);
|
|
fwrite(matvar->name,1,array_name_len,(FILE*)mat->fp);
|
|
if ( array_name_len % 8 )
|
|
for ( i = array_name_len % 8; i < 8; i++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
}
|
|
|
|
if ( NULL != matvar->internal ) {
|
|
matvar->internal->datapos = ftell((FILE*)mat->fp);
|
|
if ( matvar->internal->datapos == -1L ) {
|
|
Mat_Critical("Couldn't determine file position");
|
|
}
|
|
} else {
|
|
/* Must be empty */
|
|
matvar->class_type = MAT_C_EMPTY;
|
|
}
|
|
WriteType(mat,matvar);
|
|
#if defined(HAVE_ZLIB)
|
|
} else if ( compress == MAT_COMPRESSION_ZLIB ) {
|
|
mat_uint32_t comp_buf[512];
|
|
mat_uint32_t uncomp_buf[512] = {0,};
|
|
int buf_size = 512, err;
|
|
size_t byteswritten = 0;
|
|
z_streamp z;
|
|
|
|
z = (z_streamp)calloc(1,sizeof(*z));
|
|
if ( z == NULL )
|
|
return -1;
|
|
err = deflateInit(z,Z_DEFAULT_COMPRESSION);
|
|
if ( err != Z_OK ) {
|
|
free(z);
|
|
Mat_Critical("deflateInit returned %s",zError(err));
|
|
return -1;
|
|
}
|
|
|
|
matrix_type = MAT_T_COMPRESSED;
|
|
fwrite(&matrix_type,4,1,(FILE*)mat->fp);
|
|
fwrite(&pad4,4,1,(FILE*)mat->fp);
|
|
start = ftell((FILE*)mat->fp);
|
|
|
|
/* Array Flags */
|
|
array_flags = matvar->class_type & CLASS_TYPE_MASK;
|
|
if ( matvar->isComplex )
|
|
array_flags |= MAT_F_COMPLEX;
|
|
if ( matvar->isGlobal )
|
|
array_flags |= MAT_F_GLOBAL;
|
|
if ( matvar->isLogical )
|
|
array_flags |= MAT_F_LOGICAL;
|
|
if ( matvar->class_type == MAT_C_SPARSE )
|
|
nzmax = ((mat_sparse_t *)matvar->data)->nzmax;
|
|
|
|
uncomp_buf[0] = MAT_T_MATRIX;
|
|
uncomp_buf[1] = (int)GetMatrixMaxBufSize(matvar);
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = 8;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size*sizeof(*comp_buf);
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,
|
|
buf_size*sizeof(*comp_buf)-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
uncomp_buf[0] = array_flags_type;
|
|
uncomp_buf[1] = array_flags_size;
|
|
uncomp_buf[2] = array_flags;
|
|
uncomp_buf[3] = nzmax;
|
|
/* Rank and Dimension */
|
|
nBytes = matvar->rank * 4;
|
|
uncomp_buf[4] = dims_array_type;
|
|
uncomp_buf[5] = nBytes;
|
|
for ( i = 0; i < matvar->rank; i++ ) {
|
|
mat_int32_t dim;
|
|
dim = matvar->dims[i];
|
|
uncomp_buf[6+i] = dim;
|
|
}
|
|
if ( matvar->rank % 2 != 0 ) {
|
|
uncomp_buf[6+i] = pad4;
|
|
i++;
|
|
}
|
|
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = (6+i)*sizeof(*uncomp_buf);
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size*sizeof(*comp_buf);
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,
|
|
buf_size*sizeof(*comp_buf)-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
/* Name of variable */
|
|
if ( strlen(matvar->name) <= 4 ) {
|
|
mat_int16_t array_name_len = (mat_int16_t)strlen(matvar->name);
|
|
mat_int16_t array_name_type = MAT_T_INT8;
|
|
|
|
memset(uncomp_buf,0,8);
|
|
uncomp_buf[0] = (array_name_len << 16) | array_name_type;
|
|
memcpy(uncomp_buf+1,matvar->name,array_name_len);
|
|
if ( array_name_len % 4 )
|
|
array_name_len += 4-(array_name_len % 4);
|
|
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = 8;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size*sizeof(*comp_buf);
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,
|
|
buf_size*sizeof(*comp_buf)-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
} else {
|
|
mat_int32_t array_name_len = (mat_int32_t)strlen(matvar->name);
|
|
mat_int32_t array_name_type = MAT_T_INT8;
|
|
|
|
memset(uncomp_buf,0,buf_size*sizeof(*uncomp_buf));
|
|
uncomp_buf[0] = array_name_type;
|
|
uncomp_buf[1] = array_name_len;
|
|
memcpy(uncomp_buf+2,matvar->name,array_name_len);
|
|
if ( array_name_len % 8 )
|
|
array_name_len += 8-(array_name_len % 8);
|
|
z->next_in = ZLIB_BYTE_PTR(uncomp_buf);
|
|
z->avail_in = 8+array_name_len;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size*sizeof(*comp_buf);
|
|
deflate(z,Z_NO_FLUSH);
|
|
byteswritten += fwrite(comp_buf,1,
|
|
buf_size*sizeof(*comp_buf)-z->avail_out,(FILE*)mat->fp);
|
|
} while ( z->avail_out == 0 );
|
|
}
|
|
if ( NULL != matvar->internal ) {
|
|
matvar->internal->datapos = ftell((FILE*)mat->fp);
|
|
if ( matvar->internal->datapos == -1L ) {
|
|
Mat_Critical("Couldn't determine file position");
|
|
}
|
|
} else {
|
|
/* Must be empty */
|
|
matvar->class_type = MAT_C_EMPTY;
|
|
}
|
|
WriteCompressedType(mat,matvar,z);
|
|
z->next_in = NULL;
|
|
z->avail_in = 0;
|
|
do {
|
|
z->next_out = ZLIB_BYTE_PTR(comp_buf);
|
|
z->avail_out = buf_size*sizeof(*comp_buf);
|
|
err = deflate(z,Z_FINISH);
|
|
byteswritten += fwrite(comp_buf,1,
|
|
buf_size*sizeof(*comp_buf)-z->avail_out,(FILE*)mat->fp);
|
|
} while ( err != Z_STREAM_END && z->avail_out == 0 );
|
|
#if 0
|
|
if ( byteswritten % 8 )
|
|
for ( i = 0; i < 8-(byteswritten % 8); i++ )
|
|
fwrite(&pad1,1,1,(FILE*)mat->fp);
|
|
#endif
|
|
(void)deflateEnd(z);
|
|
free(z);
|
|
#endif
|
|
}
|
|
end = ftell((FILE*)mat->fp);
|
|
if ( start != -1L && end != -1L ) {
|
|
nBytes = (int)(end-start);
|
|
(void)fseek((FILE*)mat->fp,(long)-(nBytes+4),SEEK_CUR);
|
|
fwrite(&nBytes,4,1,(FILE*)mat->fp);
|
|
(void)fseek((FILE*)mat->fp,end,SEEK_SET);
|
|
} else {
|
|
Mat_Critical("Couldn't determine file position");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/** @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_VarReadNextInfo5( mat_t *mat )
|
|
{
|
|
int err;
|
|
mat_int32_t data_type, nBytes;
|
|
long fpos;
|
|
matvar_t *matvar = NULL;
|
|
mat_uint32_t array_flags;
|
|
|
|
if ( mat == NULL )
|
|
return NULL;
|
|
|
|
fpos = ftell((FILE*)mat->fp);
|
|
if ( fpos == -1L ) {
|
|
Mat_Critical("Couldn't determine file position");
|
|
return NULL;
|
|
}
|
|
err = fread(&data_type,4,1,(FILE*)mat->fp);
|
|
if ( err == 0 )
|
|
return NULL;
|
|
err = fread(&nBytes,4,1,(FILE*)mat->fp);
|
|
if ( mat->byteswap ) {
|
|
Mat_int32Swap(&data_type);
|
|
Mat_int32Swap(&nBytes);
|
|
}
|
|
switch ( data_type ) {
|
|
case MAT_T_COMPRESSED:
|
|
{
|
|
#if defined(HAVE_ZLIB)
|
|
mat_uint32_t uncomp_buf[16] = {0,};
|
|
int nbytes;
|
|
long bytesread = 0;
|
|
|
|
matvar = Mat_VarCalloc();
|
|
matvar->compression = MAT_COMPRESSION_ZLIB;
|
|
|
|
matvar->internal->z = (z_streamp)calloc(1,sizeof(z_stream));
|
|
err = inflateInit(matvar->internal->z);
|
|
if ( err != Z_OK ) {
|
|
Mat_VarFree(matvar);
|
|
matvar = NULL;
|
|
Mat_Critical("inflateInit returned %s",zError(err));
|
|
break;
|
|
}
|
|
|
|
/* Read variable tag */
|
|
bytesread += InflateVarTag(mat,matvar,uncomp_buf);
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(uncomp_buf);
|
|
(void)Mat_uint32Swap(uncomp_buf+1);
|
|
}
|
|
nbytes = uncomp_buf[1];
|
|
if ( uncomp_buf[0] != MAT_T_MATRIX ) {
|
|
(void)fseek((FILE*)mat->fp,nBytes-bytesread,SEEK_CUR);
|
|
Mat_VarFree(matvar);
|
|
matvar = NULL;
|
|
Mat_Critical("Uncompressed type not MAT_T_MATRIX");
|
|
break;
|
|
}
|
|
/* Inflate array flags */
|
|
bytesread += InflateArrayFlags(mat,matvar,uncomp_buf);
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(uncomp_buf);
|
|
(void)Mat_uint32Swap(uncomp_buf+2);
|
|
(void)Mat_uint32Swap(uncomp_buf+3);
|
|
}
|
|
/* Array flags */
|
|
if ( uncomp_buf[0] == MAT_T_UINT32 ) {
|
|
array_flags = uncomp_buf[2];
|
|
matvar->class_type = CLASS_FROM_ARRAY_FLAGS(array_flags);
|
|
matvar->isComplex = (array_flags & MAT_F_COMPLEX);
|
|
matvar->isGlobal = (array_flags & MAT_F_GLOBAL);
|
|
matvar->isLogical = (array_flags & MAT_F_LOGICAL);
|
|
if ( matvar->class_type == MAT_C_SPARSE ) {
|
|
/* Need to find a more appropriate place to store nzmax */
|
|
matvar->nbytes = uncomp_buf[3];
|
|
}
|
|
}
|
|
if ( matvar->class_type != MAT_C_OPAQUE ) {
|
|
mat_uint32_t* dims = NULL;
|
|
int do_clean = 0;
|
|
bytesread += InflateRankDims(mat,matvar,uncomp_buf,sizeof(uncomp_buf),&dims);
|
|
if ( NULL == dims )
|
|
dims = uncomp_buf + 2;
|
|
else
|
|
do_clean = 1;
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(uncomp_buf);
|
|
(void)Mat_uint32Swap(uncomp_buf+1);
|
|
}
|
|
/* Rank and dimension */
|
|
if ( uncomp_buf[0] == MAT_T_INT32 ) {
|
|
int j;
|
|
nbytes = uncomp_buf[1];
|
|
matvar->rank = nbytes / 4;
|
|
matvar->dims = (size_t*)malloc(matvar->rank*sizeof(*matvar->dims));
|
|
if ( mat->byteswap ) {
|
|
for ( j = 0; j < matvar->rank; j++ )
|
|
matvar->dims[j] = Mat_uint32Swap(dims + j);
|
|
} else {
|
|
for ( j = 0; j < matvar->rank; j++ )
|
|
matvar->dims[j] = dims[j];
|
|
}
|
|
}
|
|
if ( do_clean )
|
|
free(dims);
|
|
/* Inflate variable name tag */
|
|
bytesread += InflateVarNameTag(mat,matvar,uncomp_buf);
|
|
if ( mat->byteswap )
|
|
(void)Mat_uint32Swap(uncomp_buf);
|
|
/* Name of variable */
|
|
if ( uncomp_buf[0] == MAT_T_INT8 ) { /* Name not in tag */
|
|
mat_uint32_t len, len_pad;
|
|
if ( mat->byteswap )
|
|
len = Mat_uint32Swap(uncomp_buf+1);
|
|
else
|
|
len = uncomp_buf[1];
|
|
|
|
if ( len % 8 == 0 )
|
|
len_pad = len;
|
|
else
|
|
len_pad = len + 8 - (len % 8);
|
|
matvar->name = (char*)malloc(len_pad + 1);
|
|
if ( NULL != matvar->name ) {
|
|
/* Inflate variable name */
|
|
bytesread += InflateVarName(mat,matvar,matvar->name,len_pad);
|
|
matvar->name[len] = '\0';
|
|
}
|
|
} else {
|
|
mat_uint32_t len = (uncomp_buf[0] & 0xffff0000) >> 16;
|
|
if ( ((uncomp_buf[0] & 0x0000ffff) == MAT_T_INT8) && len > 0 && len <= 4 ) {
|
|
/* Name packed in tag */
|
|
matvar->name = (char*)malloc(len+1);
|
|
if ( NULL != matvar->name ) {
|
|
memcpy(matvar->name,uncomp_buf+1,len);
|
|
matvar->name[len] = '\0';
|
|
}
|
|
}
|
|
}
|
|
if ( matvar->class_type == MAT_C_STRUCT )
|
|
(void)ReadNextStructField(mat,matvar);
|
|
else if ( matvar->class_type == MAT_C_CELL )
|
|
(void)ReadNextCell(mat,matvar);
|
|
(void)fseek((FILE*)mat->fp,-(int)matvar->internal->z->avail_in,SEEK_CUR);
|
|
matvar->internal->datapos = ftell((FILE*)mat->fp);
|
|
if ( matvar->internal->datapos == -1L ) {
|
|
Mat_Critical("Couldn't determine file position");
|
|
}
|
|
}
|
|
(void)fseek((FILE*)mat->fp,nBytes+8+fpos,SEEK_SET);
|
|
break;
|
|
#else
|
|
Mat_Critical("Compressed variable found in \"%s\", but matio was "
|
|
"built without zlib support",mat->filename);
|
|
(void)fseek((FILE*)mat->fp,nBytes+8+fpos,SEEK_SET);
|
|
return NULL;
|
|
#endif
|
|
}
|
|
case MAT_T_MATRIX:
|
|
{
|
|
mat_uint32_t buf[6];
|
|
size_t bytesread = 0;
|
|
|
|
matvar = Mat_VarCalloc();
|
|
|
|
/* Read array flags and the dimensions tag */
|
|
bytesread += fread(buf,4,6,(FILE*)mat->fp);
|
|
if ( mat->byteswap ) {
|
|
(void)Mat_uint32Swap(buf);
|
|
(void)Mat_uint32Swap(buf+1);
|
|
(void)Mat_uint32Swap(buf+2);
|
|
(void)Mat_uint32Swap(buf+3);
|
|
(void)Mat_uint32Swap(buf+4);
|
|
(void)Mat_uint32Swap(buf+5);
|
|
}
|
|
/* Array flags */
|
|
if ( buf[0] == MAT_T_UINT32 ) {
|
|
array_flags = buf[2];
|
|
matvar->class_type = CLASS_FROM_ARRAY_FLAGS(array_flags);
|
|
matvar->isComplex = (array_flags & MAT_F_COMPLEX);
|
|
matvar->isGlobal = (array_flags & MAT_F_GLOBAL);
|
|
matvar->isLogical = (array_flags & MAT_F_LOGICAL);
|
|
if ( matvar->class_type == MAT_C_SPARSE ) {
|
|
/* Need to find a more appropriate place to store nzmax */
|
|
matvar->nbytes = buf[3];
|
|
}
|
|
}
|
|
ReadRankDims(mat, matvar, (enum matio_types)buf[4], buf[5]);
|
|
/* Variable name tag */
|
|
bytesread+=fread(buf,4,2,(FILE*)mat->fp);
|
|
if ( mat->byteswap )
|
|
(void)Mat_uint32Swap(buf);
|
|
/* Name of variable */
|
|
if ( buf[0] == MAT_T_INT8 ) { /* Name not in tag */
|
|
mat_uint32_t len, len_pad;
|
|
if ( mat->byteswap )
|
|
len = Mat_uint32Swap(buf+1);
|
|
else
|
|
len = buf[1];
|
|
if ( len % 8 == 0 )
|
|
len_pad = len;
|
|
else
|
|
len_pad = len + 8 - (len % 8);
|
|
matvar->name = (char*)malloc(len_pad + 1);
|
|
if ( NULL != matvar->name ) {
|
|
size_t readresult = fread(matvar->name,1,len_pad,(FILE*)mat->fp);
|
|
bytesread += readresult;
|
|
if ( readresult == len_pad) {
|
|
matvar->name[len] = '\0';
|
|
} else {
|
|
free(matvar->name);
|
|
matvar->name = NULL;
|
|
Mat_Critical("An error occurred in reading the MAT file");
|
|
}
|
|
}
|
|
} else {
|
|
mat_uint32_t len = (buf[0] & 0xffff0000) >> 16;
|
|
if ( ((buf[0] & 0x0000ffff) == MAT_T_INT8) && len > 0 && len <= 4 ) {
|
|
/* Name packed in tag */
|
|
matvar->name = (char*)malloc(len+1);
|
|
if ( NULL != matvar->name ) {
|
|
memcpy(matvar->name,buf+1,len);
|
|
matvar->name[len] = '\0';
|
|
}
|
|
}
|
|
}
|
|
if ( matvar->class_type == MAT_C_STRUCT )
|
|
(void)ReadNextStructField(mat,matvar);
|
|
else if ( matvar->class_type == MAT_C_CELL )
|
|
(void)ReadNextCell(mat,matvar);
|
|
else if ( matvar->class_type == MAT_C_FUNCTION )
|
|
(void)ReadNextFunctionHandle(mat,matvar);
|
|
matvar->internal->datapos = ftell((FILE*)mat->fp);
|
|
if ( matvar->internal->datapos == -1L ) {
|
|
Mat_Critical("Couldn't determine file position");
|
|
}
|
|
(void)fseek((FILE*)mat->fp,nBytes+8+fpos,SEEK_SET);
|
|
break;
|
|
}
|
|
default:
|
|
Mat_Critical("%d is not valid (MAT_T_MATRIX or MAT_T_COMPRESSED)",
|
|
data_type);
|
|
return NULL;
|
|
}
|
|
|
|
return matvar;
|
|
}
|