/** @file mat4.c * Matlab MAT version 4 file functions * @ingroup MAT */ /* * Copyright (c) 2005-2019, Christopher C. Hulbert * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #if defined(__GLIBC__) #include #endif #include "matio_private.h" #include "mat4.h" /** @if mat_devman * @brief Creates a new Matlab MAT version 4 file * * Tries to create a new Matlab MAT file with the given name. * @ingroup MAT * @param matname Name of MAT file to create * @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_Create4(const char* matname) { FILE *fp; mat_t *mat = NULL; fp = fopen(matname,"w+b"); if ( !fp ) return NULL; mat = (mat_t*)malloc(sizeof(*mat)); if ( NULL == mat ) { fclose(fp); Mat_Critical("Couldn't allocate memory for the MAT file"); return NULL; } mat->fp = fp; mat->header = NULL; mat->subsys_offset = NULL; mat->filename = strdup_printf("%s",matname); mat->version = MAT_FT_MAT4; mat->byteswap = 0; mat->mode = 0; mat->bof = 0; mat->next_index = 0; mat->num_datasets = 0; #if defined(MAT73) && MAT73 mat->refs_id = -1; #endif mat->dir = NULL; Mat_Rewind(mat); return mat; } /** @if mat_devman * @brief Writes a matlab variable to a version 4 matlab file * * @ingroup mat_internal * @param mat MAT file pointer * @param matvar pointer to the mat variable * @retval 0 on success * @endif */ int Mat_VarWrite4(mat_t *mat,matvar_t *matvar) { typedef struct { mat_int32_t type; mat_int32_t mrows; mat_int32_t ncols; mat_int32_t imagf; mat_int32_t namelen; } Fmatrix; mat_int32_t nelems = 1, i; Fmatrix x; if ( NULL == mat || NULL == matvar || NULL == matvar->name || matvar->rank != 2 ) return -1; switch ( matvar->data_type ) { case MAT_T_DOUBLE: x.type = 0; break; case MAT_T_SINGLE: x.type = 10; break; case MAT_T_INT32: x.type = 20; break; case MAT_T_INT16: x.type = 30; break; case MAT_T_UINT16: x.type = 40; break; case MAT_T_UINT8: x.type = 50; break; default: return 2; } #if defined(__GLIBC__) #if (__BYTE_ORDER == __LITTLE_ENDIAN) #elif (__BYTE_ORDER == __BIG_ENDIAN) x.type += 1000; #else return -1; #endif #elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) x.type += 1000; #elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) #elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || \ defined(__ppc__) || defined(__hpux) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) x.type += 1000; #elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || \ defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || \ defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || \ defined(_M_X64) || defined(__bfin__) #else return -1; #endif x.namelen = (mat_int32_t)strlen(matvar->name) + 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 */ switch ( matvar->class_type ) { case MAT_C_CHAR: x.type++; /* Fall through */ case MAT_C_DOUBLE: case MAT_C_SINGLE: case MAT_C_INT32: case MAT_C_INT16: case MAT_C_UINT16: case MAT_C_UINT8: for ( i = 0; i < matvar->rank; i++ ) { mat_int32_t dim; dim = (mat_int32_t)matvar->dims[i]; nelems *= dim; } x.mrows = (mat_int32_t)matvar->dims[0]; x.ncols = (mat_int32_t)matvar->dims[1]; x.imagf = matvar->isComplex ? 1 : 0; fwrite(&x, sizeof(Fmatrix), 1, (FILE*)mat->fp); fwrite(matvar->name, sizeof(char), x.namelen, (FILE*)mat->fp); if ( matvar->isComplex ) { mat_complex_split_t *complex_data; complex_data = (mat_complex_split_t*)matvar->data; fwrite(complex_data->Re, matvar->data_size, nelems, (FILE*)mat->fp); fwrite(complex_data->Im, matvar->data_size, nelems, (FILE*)mat->fp); } else { fwrite(matvar->data, matvar->data_size, nelems, (FILE*)mat->fp); } break; case MAT_C_SPARSE: { mat_sparse_t* sparse; double tmp; int j; size_t stride = Mat_SizeOf(matvar->data_type); #if !defined(EXTENDED_SPARSE) if ( MAT_T_DOUBLE != matvar->data_type ) break; #endif sparse = (mat_sparse_t*)matvar->data; x.type += 2; x.mrows = sparse->njc > 0 ? sparse->jc[sparse->njc - 1] + 1 : 1; x.ncols = matvar->isComplex ? 4 : 3; x.imagf = 0; fwrite(&x, sizeof(Fmatrix), 1, (FILE*)mat->fp); fwrite(matvar->name, sizeof(char), x.namelen, (FILE*)mat->fp); for ( i = 0; i < sparse->njc - 1; i++ ) { for ( j = sparse->jc[i]; j < sparse->jc[i + 1] && j < sparse->ndata; j++ ) { tmp = sparse->ir[j] + 1; fwrite(&tmp, sizeof(double), 1, (FILE*)mat->fp); } } tmp = matvar->dims[0]; fwrite(&tmp, sizeof(double), 1, (FILE*)mat->fp); for ( i = 0; i < sparse->njc - 1; i++ ) { for ( j = sparse->jc[i]; j < sparse->jc[i + 1] && j < sparse->ndata; j++ ) { tmp = i + 1; fwrite(&tmp, sizeof(double), 1, (FILE*)mat->fp); } } tmp = matvar->dims[1]; fwrite(&tmp, sizeof(double), 1, (FILE*)mat->fp); tmp = 0.; if ( matvar->isComplex ) { mat_complex_split_t *complex_data; char* re, *im; complex_data = (mat_complex_split_t*)sparse->data; re = (char*)complex_data->Re; im = (char*)complex_data->Im; for ( i = 0; i < sparse->njc - 1; i++ ) { for ( j = sparse->jc[i]; j < sparse->jc[i + 1] && j < sparse->ndata; j++ ) { fwrite(re + j*stride, stride, 1, (FILE*)mat->fp); } } fwrite(&tmp, stride, 1, (FILE*)mat->fp); for ( i = 0; i < sparse->njc - 1; i++ ) { for ( j = sparse->jc[i]; j < sparse->jc[i + 1] && j < sparse->ndata; j++ ) { fwrite(im + j*stride, stride, 1, (FILE*)mat->fp); } } } else { char *data = (char*)sparse->data; for ( i = 0; i < sparse->njc - 1; i++ ) { for ( j = sparse->jc[i]; j < sparse->jc[i + 1] && j < sparse->ndata; j++ ) { fwrite(data + j*stride, stride, 1, (FILE*)mat->fp); } } } fwrite(&tmp, stride, 1, (FILE*)mat->fp); break; } default: break; } return 0; } /** @if mat_devman * @brief Reads the data of a version 4 MAT file variable * * @ingroup mat_internal * @param mat MAT file pointer * @param matvar MAT variable pointer to read the data * @endif */ void Mat_VarRead4(mat_t *mat,matvar_t *matvar) { size_t nelems = 1; SafeMulDims(matvar, &nelems); (void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET); switch ( matvar->class_type ) { case MAT_C_DOUBLE: matvar->data_size = sizeof(double); SafeMul(&matvar->nbytes, nelems, matvar->data_size); if ( matvar->isComplex ) { mat_complex_split_t *complex_data = ComplexMalloc(matvar->nbytes); if ( NULL != complex_data ) { matvar->data = complex_data; ReadDoubleData(mat, (double*)complex_data->Re, matvar->data_type, nelems); ReadDoubleData(mat, (double*)complex_data->Im, matvar->data_type, nelems); } else { Mat_Critical("Couldn't allocate memory for the complex data"); } } else { matvar->data = malloc(matvar->nbytes); if ( NULL != matvar->data ) { ReadDoubleData(mat, (double*)matvar->data, matvar->data_type, nelems); } else { Mat_Critical("Couldn't allocate memory for the data"); } } /* Update data type to match format of matvar->data */ matvar->data_type = MAT_T_DOUBLE; break; case MAT_C_CHAR: matvar->data_size = 1; matvar->nbytes = nelems; matvar->data = malloc(matvar->nbytes); if ( NULL != matvar->data ) { ReadUInt8Data(mat, (mat_uint8_t*)matvar->data, matvar->data_type, nelems); } else { Mat_Critical("Couldn't allocate memory for the data"); } matvar->data_type = MAT_T_UINT8; break; case MAT_C_SPARSE: matvar->data_size = sizeof(mat_sparse_t); matvar->data = malloc(matvar->data_size); if ( NULL != matvar->data ) { double tmp; int i; mat_sparse_t* sparse; long fpos; enum matio_types data_type = MAT_T_DOUBLE; /* matvar->dims[1] either is 3 for real or 4 for complex sparse */ matvar->isComplex = matvar->dims[1] == 4 ? 1 : 0; sparse = (mat_sparse_t*)matvar->data; sparse->nir = matvar->dims[0] - 1; sparse->nzmax = sparse->nir; sparse->ir = (mat_int32_t*)malloc(sparse->nir*sizeof(mat_int32_t)); if ( sparse->ir != NULL ) { ReadInt32Data(mat, sparse->ir, data_type, sparse->nir); for ( i = 0; i < sparse->nir; i++ ) sparse->ir[i] = sparse->ir[i] - 1; } else { free(matvar->data); matvar->data = NULL; Mat_Critical("Couldn't allocate memory for the sparse row array"); return; } ReadDoubleData(mat, &tmp, data_type, 1); matvar->dims[0] = (size_t)tmp; fpos = ftell((FILE*)mat->fp); if ( fpos == -1L ) { free(sparse->ir); free(matvar->data); matvar->data = NULL; Mat_Critical("Couldn't determine file position"); return; } (void)fseek((FILE*)mat->fp,sparse->nir*Mat_SizeOf(data_type), SEEK_CUR); ReadDoubleData(mat, &tmp, data_type, 1); if ( tmp > INT_MAX-1 || tmp < 0 ) { free(sparse->ir); free(matvar->data); matvar->data = NULL; Mat_Critical("Invalid column dimension for sparse matrix"); return; } matvar->dims[1] = (size_t)tmp; (void)fseek((FILE*)mat->fp,fpos,SEEK_SET); if ( matvar->dims[1] > INT_MAX-1 ) { free(sparse->ir); free(matvar->data); matvar->data = NULL; Mat_Critical("Invalid column dimension for sparse matrix"); return; } sparse->njc = (int)matvar->dims[1] + 1; sparse->jc = (mat_int32_t*)malloc(sparse->njc*sizeof(mat_int32_t)); if ( sparse->jc != NULL ) { mat_int32_t *jc; jc = (mat_int32_t*)malloc(sparse->nir*sizeof(mat_int32_t)); if ( jc != NULL ) { int j = 0; sparse->jc[0] = 0; ReadInt32Data(mat, jc, data_type, sparse->nir); for ( i = 1; i < sparse->njc-1; i++ ) { while ( j < sparse->nir && jc[j] <= i ) j++; sparse->jc[i] = j; } free(jc); /* terminating nnz */ sparse->jc[sparse->njc-1] = sparse->nir; } else { free(sparse->jc); free(sparse->ir); free(matvar->data); matvar->data = NULL; Mat_Critical("Couldn't allocate memory for the sparse index array"); return; } } else { free(sparse->ir); free(matvar->data); matvar->data = NULL; Mat_Critical("Couldn't allocate memory for the sparse index array"); return; } ReadDoubleData(mat, &tmp, data_type, 1); sparse->ndata = sparse->nir; data_type = matvar->data_type; if ( matvar->isComplex ) { mat_complex_split_t *complex_data = ComplexMalloc(sparse->ndata*Mat_SizeOf(data_type)); if ( NULL != complex_data ) { sparse->data = complex_data; #if defined(EXTENDED_SPARSE) switch ( data_type ) { case MAT_T_DOUBLE: ReadDoubleData(mat, (double*)complex_data->Re, data_type, sparse->ndata); ReadDoubleData(mat, &tmp, data_type, 1); ReadDoubleData(mat, (double*)complex_data->Im, data_type, sparse->ndata); ReadDoubleData(mat, &tmp, data_type, 1); break; case MAT_T_SINGLE: { float tmp2; ReadSingleData(mat, (float*)complex_data->Re, data_type, sparse->ndata); ReadSingleData(mat, &tmp2, data_type, 1); ReadSingleData(mat, (float*)complex_data->Im, data_type, sparse->ndata); ReadSingleData(mat, &tmp2, data_type, 1); break; } case MAT_T_INT32: { mat_int32_t tmp2; ReadInt32Data(mat, (mat_int32_t*)complex_data->Re, data_type, sparse->ndata); ReadInt32Data(mat, &tmp2, data_type, 1); ReadInt32Data(mat, (mat_int32_t*)complex_data->Im, data_type, sparse->ndata); ReadInt32Data(mat, &tmp2, data_type, 1); break; } case MAT_T_INT16: { mat_int16_t tmp2; ReadInt16Data(mat, (mat_int16_t*)complex_data->Re, data_type, sparse->ndata); ReadInt16Data(mat, &tmp2, data_type, 1); ReadInt16Data(mat, (mat_int16_t*)complex_data->Im, data_type, sparse->ndata); ReadInt16Data(mat, &tmp2, data_type, 1); break; } case MAT_T_UINT16: { mat_uint16_t tmp2; ReadUInt16Data(mat, (mat_uint16_t*)complex_data->Re, data_type, sparse->ndata); ReadUInt16Data(mat, &tmp2, data_type, 1); ReadUInt16Data(mat, (mat_uint16_t*)complex_data->Im, data_type, sparse->ndata); ReadUInt16Data(mat, &tmp2, data_type, 1); break; } case MAT_T_UINT8: { mat_uint8_t tmp2; ReadUInt8Data(mat, (mat_uint8_t*)complex_data->Re, data_type, sparse->ndata); ReadUInt8Data(mat, &tmp2, data_type, 1); ReadUInt8Data(mat, (mat_uint8_t*)complex_data->Im, data_type, sparse->ndata); ReadUInt8Data(mat, &tmp2, data_type, 1); break; } default: free(complex_data->Re); free(complex_data->Im); free(complex_data); free(sparse->jc); free(sparse->ir); free(matvar->data); matvar->data = NULL; Mat_Critical("Mat_VarRead4: %d is not a supported data type for " "extended sparse", data_type); return; } #else ReadDoubleData(mat, (double*)complex_data->Re, data_type, sparse->ndata); ReadDoubleData(mat, &tmp, data_type, 1); ReadDoubleData(mat, (double*)complex_data->Im, data_type, sparse->ndata); ReadDoubleData(mat, &tmp, data_type, 1); #endif } else { free(sparse->jc); free(sparse->ir); free(matvar->data); matvar->data = NULL; Mat_Critical("Couldn't allocate memory for the complex sparse data"); return; } } else { sparse->data = malloc(sparse->ndata*Mat_SizeOf(data_type)); if ( sparse->data != NULL ) { #if defined(EXTENDED_SPARSE) switch ( data_type ) { case MAT_T_DOUBLE: ReadDoubleData(mat, (double*)sparse->data, data_type, sparse->ndata); ReadDoubleData(mat, &tmp, data_type, 1); break; case MAT_T_SINGLE: { float tmp2; ReadSingleData(mat, (float*)sparse->data, data_type, sparse->ndata); ReadSingleData(mat, &tmp2, data_type, 1); break; } case MAT_T_INT32: { mat_int32_t tmp2; ReadInt32Data(mat, (mat_int32_t*)sparse->data, data_type, sparse->ndata); ReadInt32Data(mat, &tmp2, data_type, 1); break; } case MAT_T_INT16: { mat_int16_t tmp2; ReadInt16Data(mat, (mat_int16_t*)sparse->data, data_type, sparse->ndata); ReadInt16Data(mat, &tmp2, data_type, 1); break; } case MAT_T_UINT16: { mat_uint16_t tmp2; ReadUInt16Data(mat, (mat_uint16_t*)sparse->data, data_type, sparse->ndata); ReadUInt16Data(mat, &tmp2, data_type, 1); break; } case MAT_T_UINT8: { mat_uint8_t tmp2; ReadUInt8Data(mat, (mat_uint8_t*)sparse->data, data_type, sparse->ndata); ReadUInt8Data(mat, &tmp2, data_type, 1); break; } default: free(sparse->data); free(sparse->jc); free(sparse->ir); free(matvar->data); matvar->data = NULL; Mat_Critical("Mat_VarRead4: %d is not a supported data type for " "extended sparse", data_type); return; } #else ReadDoubleData(mat, (double*)sparse->data, data_type, sparse->ndata); ReadDoubleData(mat, &tmp, data_type, 1); #endif } else { free(sparse->jc); free(sparse->ir); free(matvar->data); matvar->data = NULL; Mat_Critical("Couldn't allocate memory for the sparse data"); return; } } break; } else { Mat_Critical("Couldn't allocate memory for the data"); return; } default: Mat_Critical("MAT V4 data type error"); return; } return; } /** @if mat_devman * @brief Reads a slab of data from a version 4 MAT file for the @c matvar variable * * @ingroup mat_internal * @param mat Version 4 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_VarReadData4(mat_t *mat,matvar_t *matvar,void *data, int *start,int *stride,int *edge) { int err = 0; (void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET); switch( matvar->data_type ) { case MAT_T_DOUBLE: case MAT_T_SINGLE: case MAT_T_INT32: case MAT_T_INT16: case MAT_T_UINT16: case MAT_T_UINT8: break; default: return 1; } 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; if ( matvar->isComplex ) { mat_complex_split_t *cdata = (mat_complex_split_t*)data; size_t nbytes = Mat_SizeOf(matvar->data_type); SafeMulDims(matvar, &nbytes); ReadDataSlab2(mat,cdata->Re,matvar->class_type,matvar->data_type, matvar->dims,start,stride,edge); (void)fseek((FILE*)mat->fp,matvar->internal->datapos+nbytes,SEEK_SET); ReadDataSlab2(mat,cdata->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); } } else if ( matvar->isComplex ) { mat_complex_split_t *cdata = (mat_complex_split_t*)data; size_t nbytes = Mat_SizeOf(matvar->data_type); SafeMulDims(matvar, &nbytes); ReadDataSlabN(mat,cdata->Re,matvar->class_type,matvar->data_type, matvar->rank,matvar->dims,start,stride,edge); (void)fseek((FILE*)mat->fp,matvar->internal->datapos+nbytes,SEEK_SET); ReadDataSlabN(mat,cdata->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); } 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_VarReadDataLinear4(mat_t *mat,matvar_t *matvar,void *data,int start, int stride,int edge) { int err = 0; size_t nelems = 1; err = SafeMulDims(matvar, &nelems); (void)fseek((FILE*)mat->fp,matvar->internal->datapos,SEEK_SET); matvar->data_size = Mat_SizeOf(matvar->data_type); if ( (size_t)stride*(edge-1)+start+1 > nelems ) { return 1; } if ( matvar->isComplex ) { mat_complex_split_t *complex_data = (mat_complex_split_t*)data; long nbytes = nelems*matvar->data_size; ReadDataSlab1(mat,complex_data->Re,matvar->class_type, matvar->data_type,start,stride,edge); (void)fseek((FILE*)mat->fp,matvar->internal->datapos+nbytes,SEEK_SET); 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); } return err; } /** @if mat_devman * @brief Reads the header information for the next MAT variable in a version 4 MAT file * * @ingroup mat_internal * @param mat MAT file pointer * @return pointer to the MAT variable or NULL * @endif */ matvar_t * Mat_VarReadNextInfo4(mat_t *mat) { int M,O,data_type,class_type; mat_int32_t tmp; long nBytes; size_t err; matvar_t *matvar = NULL; union { mat_uint32_t u; mat_uint8_t c[4]; } endian; if ( mat == NULL || mat->fp == NULL ) return NULL; else if ( NULL == (matvar = Mat_VarCalloc()) ) return NULL; err = fread(&tmp,sizeof(int),1,(FILE*)mat->fp); if ( !err ) { Mat_VarFree(matvar); return NULL; } endian.u = 0x01020304; /* See if MOPT may need byteswapping */ if ( tmp < 0 || tmp > 4052 ) { if ( Mat_int32Swap(&tmp) > 4052 ) { Mat_VarFree(matvar); return NULL; } } M = (int)floor(tmp / 1000.0); tmp -= M*1000; O = (int)floor(tmp / 100.0); tmp -= O*100; data_type = (int)floor(tmp / 10.0); tmp -= data_type*10; class_type = (int)floor(tmp / 1.0); switch ( M ) { case 0: /* IEEE little endian */ mat->byteswap = (endian.c[0] != 4); break; case 1: /* IEEE big endian */ mat->byteswap = (endian.c[0] != 1); break; default: /* VAX, Cray, or bogus */ Mat_VarFree(matvar); return NULL; } /* O must be zero */ if ( 0 != O ) { Mat_VarFree(matvar); return NULL; } /* Convert the V4 data type */ switch ( data_type ) { case 0: matvar->data_type = MAT_T_DOUBLE; break; case 1: matvar->data_type = MAT_T_SINGLE; break; case 2: matvar->data_type = MAT_T_INT32; break; case 3: matvar->data_type = MAT_T_INT16; break; case 4: matvar->data_type = MAT_T_UINT16; break; case 5: matvar->data_type = MAT_T_UINT8; break; default: Mat_VarFree(matvar); return NULL; } switch ( class_type ) { case 0: matvar->class_type = MAT_C_DOUBLE; break; case 1: matvar->class_type = MAT_C_CHAR; break; case 2: matvar->class_type = MAT_C_SPARSE; break; default: Mat_VarFree(matvar); return NULL; } matvar->rank = 2; matvar->dims = (size_t*)malloc(2*sizeof(*matvar->dims)); if ( NULL == matvar->dims ) { Mat_VarFree(matvar); return NULL; } err = fread(&tmp,sizeof(int),1,(FILE*)mat->fp); if ( mat->byteswap ) Mat_int32Swap(&tmp); matvar->dims[0] = tmp; if ( !err ) { Mat_VarFree(matvar); return NULL; } err = fread(&tmp,sizeof(int),1,(FILE*)mat->fp); if ( mat->byteswap ) Mat_int32Swap(&tmp); matvar->dims[1] = tmp; if ( !err ) { Mat_VarFree(matvar); return NULL; } err = fread(&(matvar->isComplex),sizeof(int),1,(FILE*)mat->fp); if ( !err ) { Mat_VarFree(matvar); return NULL; } if ( matvar->isComplex && MAT_C_CHAR == matvar->class_type ) { Mat_VarFree(matvar); return NULL; } err = fread(&tmp,sizeof(int),1,(FILE*)mat->fp); if ( !err ) { Mat_VarFree(matvar); return NULL; } if ( mat->byteswap ) Mat_int32Swap(&tmp); /* Check that the length of the variable name is at least 1 */ if ( tmp < 1 ) { Mat_VarFree(matvar); return NULL; } matvar->name = (char*)malloc(tmp); if ( NULL == matvar->name ) { Mat_VarFree(matvar); return NULL; } err = fread(matvar->name,1,tmp,(FILE*)mat->fp); if ( !err ) { Mat_VarFree(matvar); return NULL; } matvar->internal->datapos = ftell((FILE*)mat->fp); if ( matvar->internal->datapos == -1L ) { Mat_VarFree(matvar); Mat_Critical("Couldn't determine file position"); return NULL; } { size_t tmp2 = Mat_SizeOf(matvar->data_type); if ( matvar->isComplex ) tmp2 *= 2; SafeMulDims(matvar, &tmp2); nBytes = (long)tmp2; } (void)fseek((FILE*)mat->fp,nBytes,SEEK_CUR); return matvar; }