123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932 |
- /** @file mat.c
- * Matlab MAT version 5 file functions
- * @ingroup MAT
- */
- /*
- * Copyright (C) 2005-2006 Christopher C. Hulbert
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- /* FIXME: Implement Unicode support */
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <math.h>
- #include <time.h>
- #include "matio.h"
- #include "mat5.h"
- #include "mat4.h"
- #include "matio_private.h"
- static void
- ReadData(mat_t *mat, matvar_t *matvar)
- {
- if ( mat == NULL || matvar == NULL || mat->fp == NULL )
- return;
- else if ( mat->version != MAT_FT_MAT4 )
- Read5(mat,matvar);
- else if ( mat->version == MAT_FT_MAT4 )
- Read4(mat,matvar);
- return;
- }
- /*
- *====================================================================
- * Public Functions
- *====================================================================
- */
- /** @brief Creates a new Matlab MAT 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.
- */
- mat_t *
- Mat_Create(const char *matname,const char *hdr_str)
- {
- FILE *fp = NULL;
- mat_int16_t endian = 0, version;
- mat_t *mat = NULL;
- size_t err;
- time_t t;
- fp = fopen(matname,"wb");
- if ( !fp )
- return NULL;
- mat = malloc(sizeof(*mat));
- if ( !mat ) {
- 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 = 0;
- t = time(NULL);
- mat->fp = fp;
- mat->filename = strdup_printf("%s",matname);
- mat->mode = MAT_ACC_RDWR;
- mat->byteswap = 0;
- mat->header = calloc(1,128);
- mat->subsys_offset = calloc(1,16);
- 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));
- mat->header[115] = '\0'; /* Just to make sure it's NULL terminated */
- } else {
- err = mat_snprintf(mat->header,116,"%s",hdr_str);
- }
- mat->header[err] = ' ';
- mat_snprintf(mat->subsys_offset,15," ");
- mat->version = (int)0x0100;
- endian = 0x4d49;
- version = 0x0100;
- err = fwrite(mat->header,1,116,mat->fp);
- err = fwrite(mat->subsys_offset,1,8,mat->fp);
- err = fwrite(&version,2,1,mat->fp);
- err = fwrite(&endian,2,1,mat->fp);
- return mat;
- }
- /** @brief Opens an existing Matlab MAT file
- *
- * Tries to open a Matlab MAT file with the given name
- * @ingroup MAT
- * @param matname Name of MAT file to open
- * @param mode File access mode (MAT_ACC_RDONLY,MAT_ACC_RDWR,etc).
- * @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.
- */
- mat_t *
- Mat_Open(const char *matname,int mode)
- {
- FILE *fp = NULL;
- mat_int16_t tmp, tmp2;
- int err;
- mat_t *mat = NULL;
- if ( (mode & 0x000000ff) == MAT_ACC_RDONLY ) {
- fp = fopen( matname, "rb" );
- if ( !fp )
- return NULL;
- } else if ( (mode & 0x000000ff) == MAT_ACC_RDWR ) {
- fp = fopen( matname, "r+b" );
- if ( !fp ) {
- mat = Mat_Create(matname,NULL);
- return mat;
- }
- } else {
- mat = Mat_Create(matname,NULL);
- return mat;
- }
- mat = malloc(sizeof(mat_t));
- if ( !mat ) {
- Mat_Critical("Couldn't allocate memory for the MAT file");
- fclose(fp);
- return NULL;
- }
- mat->fp = fp;
- if ( mode & MAT_FT_MAT4 ) {
- mat->header = NULL;
- mat->subsys_offset = NULL;
- mat->version = MAT_FT_MAT4;
- mat->byteswap = 0;
- mat->mode = mode;
- mat->filename = strdup_printf("%s",matname);
- mat->bof = ftell(mat->fp);
- } else {
- mat->header = malloc(128);
- mat->subsys_offset = malloc(8);
- mat->filename = NULL;
- err = fread(mat->header,1,116,fp);
- mat->header[116] = '\0';
- err = fread(mat->subsys_offset,1,8,fp);
- err = fread(&tmp2,2,1,fp);
- fread (&tmp,1,2,fp);
- mat->bof = ftell(mat->fp);
- mat->byteswap = -1;
- if (tmp == 0x4d49)
- mat->byteswap = 0;
- else if (tmp == 0x494d) {
- mat->byteswap = 1;
- Mat_int16Swap(&tmp2);
- }
- mat->version = (int)tmp2;
- if ( mat->byteswap < 0 ) {
- Mat_Critical("%s does not seem to be a valid MAT file",matname);
- Mat_Close(mat);
- mat=NULL;
- } else if ( mat->version != 0x0100 ) {
- Mat_Critical("%s is not a version 5 MAT file", matname);
- Mat_Close(mat);
- mat=NULL;
- } else {
- mat->filename = strdup_printf("%s",matname);
- mat->mode = mode;
- }
- }
- return mat;
- }
- /** @brief Closes an open Matlab MAT file
- *
- * Closes the given Matlab MAT file and frees any memory with it.
- * @ingroup MAT
- * @param mat Pointer to the MAT file
- * @retval 0
- */
- int
- Mat_Close( mat_t *mat )
- {
- if ( NULL != mat ) {
- if ( mat->fp )
- fclose(mat->fp);
- if ( mat->header )
- free(mat->header);
- if ( mat->subsys_offset )
- free(mat->subsys_offset);
- if ( mat->filename )
- free(mat->filename);
- free(mat);
- }
- return 0;
- }
- /** @brief Rewinds a Matlab MAT file to the first variable
- *
- * Rewinds a Matlab MAT file to the first variable
- * @ingroup MAT
- * @param mat Pointer to the MAT file
- * @retval 0 on success
- */
- int
- Mat_Rewind( mat_t *mat )
- {
- if ( mat->version != MAT_FT_MAT4 )
- fseek(mat->fp,128L,SEEK_SET);
- else
- fseek(mat->fp,0L,SEEK_SET);
- return 0;
- }
- /** @brief Returns the size of a Matlab Class
- *
- * Returns the size (in bytes) of the matlab class class_type
- * @ingroup MAT
- * @param class_type Matlab class type (MAT_C_*)
- * @returns Size of the class
- */
- size_t
- Mat_SizeOfClass(int class_type)
- {
- switch (class_type) {
- case MAT_C_DOUBLE:
- return sizeof(double);
- case MAT_C_SINGLE:
- return sizeof(float);
- #ifdef HAVE_MAT_INT64_T
- case MAT_C_INT64:
- return sizeof(mat_int64_t);
- #endif
- #ifdef HAVE_MAT_UINT64_T
- case MAT_C_UINT64:
- return sizeof(mat_uint64_t);
- #endif
- case MAT_C_INT32:
- return sizeof(mat_int32_t);
- case MAT_C_UINT32:
- return sizeof(mat_uint32_t);
- case MAT_C_INT16:
- return sizeof(mat_int16_t);
- case MAT_C_UINT16:
- return sizeof(mat_uint16_t);
- case MAT_C_INT8:
- return sizeof(mat_int8_t);
- case MAT_C_UINT8:
- return sizeof(mat_uint8_t);
- case MAT_C_CHAR:
- return sizeof(mat_int16_t);
- default:
- return 0;
- }
- }
- /*
- *===================================================================
- * MAT Variable Functions
- *===================================================================
- */
- /** @brief Allocates memory for a new matvar_t and initializes all the fields
- *
- * @ingroup MAT
- * @return A newly allocated matvar_t
- */
- matvar_t *
- Mat_VarCalloc(void)
- {
- matvar_t *matvar;
- matvar = malloc(sizeof(*matvar));
- if ( NULL != matvar ) {
- matvar->nbytes = 0;
- matvar->rank = 0;
- matvar->data_type = 0;
- matvar->data_size = 0;
- matvar->class_type = 0;
- matvar->isComplex = 0;
- matvar->isGlobal = 0;
- matvar->isLogical = 0;
- matvar->dims = NULL;
- matvar->name = NULL;
- matvar->data = NULL;
- matvar->mem_conserve = 0;
- matvar->compression = 0;
- matvar->fpos = 0;
- matvar->datapos = 0;
- matvar->fp = NULL;
- #if defined(HAVE_ZLIB)
- matvar->z = NULL;
- #endif
- }
- return matvar;
- }
- /** @brief Creates a MAT Variable with the given name and (optionally) data
- *
- * Creates a MAT variable that can be written to a Matlab MAT file with the
- * given name, data type, dimensions and data. Rank should always be 2 or more.
- * i.e. Scalar values would have rank=2 and dims[2] = {1,1}. Data type is
- * one of the MAT_T types. MAT adds MAT_T_STRUCT and MAT_T_CELL to create
- * Structures and Cell Arrays respectively. For MAT_T_STRUCT, data should be a
- * NULL terminated array of matvar_t * variables (i.e. for a 3x2 structure with
- * 10 fields, there should be 61 matvar_t * variables where the last one is
- * NULL). For cell arrays, the NULL termination isn't necessary. So to create
- * a cell array of size 3x2, data would be the address of an array of 6
- * matvar_t * variables.
- *
- * EXAMPLE:
- * To create a struct of size 3x2 with 3 fields:
- * @code
- * int rank=2, dims[2] = {3,2}, nfields = 3;
- * matvar_t **vars;
- *
- * vars = malloc((3*2*nfields+1)*sizeof(matvar_t *));
- * vars[0] = Mat_VarCreate(...);
- * :
- * vars[3*2*nfields-1] = Mat_VarCreate(...);
- * vars[3*2*nfields] = NULL;
- * @endcode
- *
- * EXAMPLE:
- * To create a cell array of size 3x2:
- * @code
- * int rank=2, dims[2] = {3,2};
- * matvar_t **vars;
- *
- * vars = malloc(3*2*sizeof(matvar_t *));
- * vars[0] = Mat_VarCreate(...);
- * :
- * vars[5] = Mat_VarCreate(...);
- * @endcode
- *
- * @ingroup MAT
- * @param name Name of the variable to create
- * @param class_type class type of the variable in Matlab(one of the mx Classes)
- * @param data_type data type of the variable (one of the MAT_T_ Types)
- * @param rank Rank of the variable
- * @param dims array of dimensions of the variable of size rank
- * @param data pointer to the data
- * @param opt 0, or bitwise or of the following options:
- * - MEM_CONSERVE to just use the pointer to the data and not copy the data
- * itself. Note that the pointer should not be freed until you are done
- * with the mat variable. The Mat_VarFree function will NOT free
- * data that was created with MEM_CONSERVE, so free it yourself.
- * - MAT_F_COMPLEX to specify that the data is complex. The data variable should
- * be a contigouse piece of memory with the real part written first and
- * the imaginary second
- * - MAT_F_GLOBAL to assign the variable as a global variable
- * - MAT_F_LOGICAL to specify that it is a logical variable
- * @return A MAT variable that can be written to a file or otherwise used
- */
- matvar_t *
- Mat_VarCreate(const char *name,int class_type,int data_type,int rank,int *dims,
- void *data,int opt)
- {
- int i, nmemb = 1, nfields = 0;
- matvar_t *matvar = NULL;
- if (dims == NULL) return NULL;
- matvar = Mat_VarCalloc();
- if ( NULL == matvar )
- return NULL;
- matvar->compression = COMPRESSION_NONE;
- matvar->isComplex = opt & MAT_F_COMPLEX;
- matvar->isGlobal = opt & MAT_F_GLOBAL;
- matvar->isLogical = opt & MAT_F_LOGICAL;
- if ( name )
- matvar->name = strdup_printf("%s",name);
- matvar->rank = rank;
- matvar->dims = malloc(matvar->rank*sizeof(int));
- for ( i = 0; i < matvar->rank; i++ ) {
- matvar->dims[i] = dims[i];
- nmemb *= dims[i];
- }
- matvar->class_type = class_type;
- matvar->data_type = data_type;
- switch ( data_type ) {
- case MAT_T_INT8:
- matvar->data_size = 1;
- break;
- case MAT_T_UINT8:
- matvar->data_size = 1;
- break;
- case MAT_T_INT16:
- matvar->data_size = 2;
- break;
- case MAT_T_UINT16:
- matvar->data_size = 2;
- break;
- case MAT_T_INT64:
- matvar->data_size = 8;
- break;
- case MAT_T_UINT64:
- matvar->data_size = 8;
- break;
- case MAT_T_INT32:
- matvar->data_size = 4;
- break;
- case MAT_T_UINT32:
- matvar->data_size = 4;
- break;
- case MAT_T_SINGLE:
- matvar->data_size = sizeof(float);
- break;
- case MAT_T_DOUBLE:
- matvar->data_size = sizeof(double);
- break;
- case MAT_T_UTF8:
- matvar->data_size = 1;
- break;
- case MAT_T_UTF16:
- matvar->data_size = 2;
- break;
- case MAT_T_UTF32:
- matvar->data_size = 4;
- break;
- case MAT_T_CELL:
- matvar->data_size = sizeof(matvar_t **);
- break;
- case MAT_T_STRUCT:
- {
- matvar_t **fields;
- if ( data == NULL )
- break;
- fields = data;
- nfields = 0;
- while ( fields[nfields] != NULL )
- nfields++;
- matvar->data_size = sizeof(matvar_t **);
- nmemb = nfields; /* nfields is really nmemb*nfields */
- break;
- }
- default:
- Mat_Error("Unrecognized data_type");
- Mat_VarFree(matvar);
- return NULL;
- }
- if ( matvar->class_type == MAT_C_CHAR ) {
- #if 0
- matvar->data_size = 1;
- nmemb++;
- #endif
- matvar->nbytes = nmemb*matvar->data_size;
- } else if ( matvar->class_type == MAT_C_SPARSE ) {
- matvar->data_size = sizeof(sparse_t);
- matvar->nbytes = nmemb*matvar->data_size;
- } else {
- matvar->nbytes = nmemb*matvar->data_size;
- }
- if ( data == NULL ) {
- matvar->data = NULL;
- } else if ( opt & MEM_CONSERVE ) {
- if ( matvar->isComplex ) {
- matvar->data = malloc(sizeof(struct ComplexSplit));
- if ( NULL != data ) {
- struct ComplexSplit *complex_data = matvar->data;
- struct ComplexSplit *complex_data_in = data;
- *complex_data = *complex_data_in;
- }
- } else {
- matvar->data = (void*)data;
- }
- matvar->mem_conserve = 1;
- } else {
- if ( matvar->isComplex ) {
- matvar->data = malloc(sizeof(struct ComplexSplit));
- if ( NULL != matvar->data ) {
- struct ComplexSplit *complex_data = matvar->data;
- struct ComplexSplit *complex_data_in = data;
- complex_data->Re = malloc(matvar->nbytes);
- complex_data->Im = malloc(matvar->nbytes);
- if ( NULL != complex_data->Re )
- memcpy(complex_data->Re,complex_data_in->Re,matvar->nbytes);
- if ( NULL != complex_data->Im )
- memcpy(complex_data->Im,complex_data_in->Im,matvar->nbytes);
- }
- } else {
- matvar->data = malloc(matvar->nbytes);
- if ( NULL != matvar->data )
- memcpy(matvar->data,data,matvar->nbytes);
- }
- matvar->mem_conserve = 0;
- }
- return matvar;
- }
- /** @brief Deletes a variable from a file
- *
- * @ingroup MAT
- * @param mat Pointer to the mat_t file structure
- * @param name Name of the variable to delete
- * @returns 0 on success
- */
- int
- Mat_VarDelete(mat_t *mat, char *name)
- {
- int err = 1;
- char *tmp_name, *new_name, *temp;
- mat_t *tmp;
- matvar_t *matvar;
- temp = strdup_printf("XXXXXX");
- tmp_name = mktemp(temp);
- tmp = Mat_Create(tmp_name,mat->header);
- if ( tmp != NULL ) {
- while ( NULL != (matvar = Mat_VarReadNext(mat)) ) {
- if ( strcmp(matvar->name,name) )
- Mat_VarWrite(tmp,matvar,0);
- else
- err = 0;
- Mat_VarFree(matvar);
- }
- /* FIXME: Memory leak */
- new_name = strdup_printf("%s",mat->filename);
- fclose(mat->fp);
-
- if ( (err = remove(new_name)) == -1 ) {
- Mat_Critical("remove of %s failed",new_name);
- } else if ( !Mat_Close(tmp) && (err=rename(tmp_name,new_name))==-1) {
- Mat_Critical("rename failed oldname=%s,newname=%s",tmp_name,
- new_name);
- } else {
- tmp = Mat_Open(new_name,mat->mode);
- memcpy(mat,tmp,sizeof(mat_t));
- }
- free(tmp);
- free(new_name);
- }
- free(temp);
- return err;
- }
- /** @brief Duplicates a matvar_t structure
- *
- * Provides a clean function for duplicating a matvar_t structure.
- * @ingroup MAT
- * @param in pointer to the matvar_t structure to be duplicated
- * @param opt 0 does a shallow duplicate and only assigns the data pointer to
- * the duplicated array. 1 will do a deep duplicate and actually
- * duplicate the contents of the data. Warning: If you do a shallow
- * copy and free both structures, the data will be freed twice and
- * memory will be corrupted. This may be fixed in a later release.
- * @returns Pointer to the duplicated matvar_t structure.
- */
- matvar_t *
- Mat_VarDuplicate(const matvar_t *in, int opt)
- {
- matvar_t *out;
- int i;
- out = malloc(sizeof(matvar_t));
- if ( out == NULL )
- return NULL;
- out->nbytes = in->nbytes;
- out->rank = in->rank;
- out->data_type = in->data_type;
- out->data_size = in->data_size;
- out->class_type = in->class_type;
- out->isComplex = in->isComplex;
- out->isGlobal = in->isGlobal;
- out->isLogical = in->isLogical;
- out->mem_conserve = in->mem_conserve;
- out->compression = in->compression;
- out->fpos = in->fpos;
- out->datapos = in->datapos;
- out->name = NULL;
- out->dims = NULL;
- out->data = NULL;
- #if defined(HAVE_ZLIB)
- out->z = NULL;
- #endif
- if (in->name != NULL && (NULL != (out->name = malloc(strlen(in->name)+1))))
- memcpy(out->name,in->name,strlen(in->name)+1);
- out->dims = malloc(in->rank*sizeof(int));
- if ( out->dims != NULL )
- memcpy(out->dims,in->dims,in->rank*sizeof(int));
- #if defined(HAVE_ZLIB)
- if ( (in->z != NULL) && (NULL != (out->z = malloc(sizeof(z_stream)))) )
- inflateCopy(out->z,in->z);
- #endif
- if ( !opt ) {
- out->data = in->data;
- } else if ( (in->data != NULL) && (in->class_type == MAT_C_STRUCT) ) {
- matvar_t **infields, **outfields;
- int nfields = 0;
- out->data = malloc(in->nbytes);
- if ( out->data != NULL && in->data_size > 0 ) {
- nfields = in->nbytes / in->data_size;
- infields = (matvar_t **)in->data;
- outfields = (matvar_t **)out->data;
- for ( i = 0; i < nfields; i++ ) {
- outfields[i] = Mat_VarDuplicate(infields[i],opt);
- }
- }
- } else if ( (in->data != NULL) && (in->class_type == MAT_C_CELL) ) {
- matvar_t **incells, **outcells;
- int ncells = 0;
- out->data = malloc(in->nbytes);
- if ( out->data != NULL && in->data_size > 0 ) {
- ncells = in->nbytes / in->data_size;
- incells = (matvar_t **)in->data;
- outcells = (matvar_t **)out->data;
- for ( i = 0; i < ncells; i++ ) {
- outcells[i] = Mat_VarDuplicate(incells[i],opt);
- }
- }
- } else if ( in->data != NULL ) {
- if ( out->isComplex ) {
- out->data = malloc(sizeof(struct ComplexSplit));
- if ( out->data != NULL ) {
- struct ComplexSplit *out_data = out->data;
- struct ComplexSplit *in_data = in->data;
- out_data->Re = malloc(out->nbytes);
- if ( NULL != out_data->Re )
- memcpy(out_data->Re,in_data->Re,out->nbytes);
- out_data->Im = malloc(out->nbytes);
- if ( NULL != out_data->Im )
- memcpy(out_data->Im,in_data->Im,out->nbytes);
- }
- } else {
- out->data = malloc(in->nbytes);
- if ( out->data != NULL )
- memcpy(out->data,in->data,in->nbytes);
- }
- }
- return out;
- }
- /** @brief Frees all the allocated memory associated with the structure
- *
- * Frees memory used by a MAT variable. Frees the data associated with a
- * MAT variable if it's non-NULL and MEM_CONSERVE was not used.
- * @ingroup MAT
- * @param matvar Pointer to the matvar_t structure
- */
- void
- Mat_VarFree(matvar_t *matvar)
- {
- if ( !matvar )
- return;
- if ( matvar->dims )
- free(matvar->dims);
- if ( matvar->name )
- free(matvar->name);
- if ( (matvar->data != NULL) && (matvar->class_type == MAT_C_STRUCT ||
- matvar->class_type == MAT_C_CELL) && matvar->data_size > 0 ) {
- int i;
- matvar_t **fields = matvar->data;
- int nfields = matvar->nbytes / matvar->data_size;
- for ( i = 0; i < nfields; i++ )
- Mat_VarFree(fields[i]);
- free(matvar->data);
- } else if ( (matvar->data != NULL) && (!matvar->mem_conserve) &&
- (matvar->class_type == MAT_C_SPARSE) ) {
- sparse_t *sparse;
- sparse = matvar->data;
- if ( sparse->ir != NULL )
- free(sparse->ir);
- if ( sparse->jc != NULL )
- free(sparse->jc);
- if ( sparse->data != NULL )
- free(sparse->data);
- free(sparse);
- } else {
- if ( matvar->isComplex && NULL != matvar->data ) {
- struct ComplexSplit *complex_data = matvar->data;
- if ( !matvar->mem_conserve ) {
- free(complex_data->Re);
- free(complex_data->Im);
- }
- free(complex_data);
- } else {
- if ( matvar->data && !matvar->mem_conserve )
- free(matvar->data);
- }
- }
- #if defined(HAVE_ZLIB)
- if ( matvar->compression == COMPRESSION_ZLIB ) {
- inflateEnd(matvar->z);
- free(matvar->z);
- }
- #endif
- /* FIXME: Why does this cause a SEGV? */
- #if 0
- memset(matvar,0,sizeof(matvar_t));
- #endif
- free(matvar);
- }
- void
- Mat_VarFree2(matvar_t *matvar)
- {
- if ( !matvar )
- return;
- if ( matvar->dims )
- free(matvar->dims);
- if ( matvar->name )
- free(matvar->name);
- if ( (matvar->data != NULL) && (matvar->class_type == MAT_C_STRUCT ||
- matvar->class_type == MAT_C_CELL) && matvar->data_size > 0 ) {
- int i;
- matvar_t **fields = (matvar_t **)matvar->data;
- int nfields = matvar->nbytes / matvar->data_size;
- for ( i = 0; i < nfields; i++ )
- Mat_VarFree(fields[i]);
- free(matvar->data);
- } else if ( (matvar->data != NULL) && (!matvar->mem_conserve) &&
- (matvar->class_type == MAT_C_SPARSE) ) {
- sparse_t *sparse;
- sparse = matvar->data;
- if ( sparse->ir != NULL )
- free(sparse->ir);
- if ( sparse->jc != NULL )
- free(sparse->jc);
- if ( sparse->data != NULL )
- free(sparse->data);
- free(sparse);
- } else {
- if ( matvar->data && !matvar->mem_conserve )
- free(matvar->data);
- }
- #if defined(HAVE_ZLIB)
- if ( matvar->compression == COMPRESSION_ZLIB )
- inflateEnd(matvar->z);
- #endif
- /* FIXME: Why does this cause a SEGV? */
- #if 0
- memset(matvar,0,sizeof(matvar_t));
- #endif
- }
- /** @brief Calculate a single subscript from a set of subscript values
- *
- * Calculates a single linear subscript (0-relative) given a 1-relative
- * subscript for each dimension. The calculation uses the formula below where
- * index is the linear index, s is an array of length RANK where each element
- * is the subscript for the correspondind dimension, D is an array whose
- * elements are the dimensions of the variable.
- * \f[
- * index = \sum\limits_{k=0}^{RANK-1} [(s_k - 1) \prod\limits_{l=0}^{k} D_l ]
- * \f]
- * @ingroup MAT
- * @param rank Rank of the variable
- * @param dims dimensions of the variable
- * @param subs Dimension subscripts
- * @return Single (linear) subscript
- */
- int
- Mat_CalcSingleSubscript(int rank,int *dims,int *subs)
- {
- int index = 0, i, j, k, err = 0;
- for ( i = 0; i < rank; i++ ) {
- k = subs[i];
- if ( k > dims[i] ) {
- err = 1;
- Mat_Critical("Mat_CalcSingleSubscript: index out of bounds");
- break;
- } else if ( k < 1 ) {
- err = 1;
- break;
- }
- k--;
- for ( j = i; j--; )
- k *= dims[j];
- index += k;
- }
- if ( err )
- index = -1;
- return index;
- }
- /** @brief Calculate a set of subscript values from a single(linear) subscript
- *
- * Calculates 1-relative subscripts for each dimension given a 0-relative
- * linear index. Subscripts are calculated as follows where s is the array
- * of dimension subscripts, D is the array of dimensions, and index is the
- * linear index.
- * \f[
- * s_k = \lfloor\frac{1}{L} \prod\limits_{l = 0}^{k} D_l\rfloor + 1
- * \f]
- * \f[
- * L = index - \sum\limits_{l = k}^{RANK - 1} s_k \prod\limits_{m = 0}^{k} D_m
- * \f]
- * @ingroup MAT
- * @param rank Rank of the variable
- * @param dims dimensions of the variable
- * @param index linear index
- * @return Array of dimension subscripts
- */
- int *
- Mat_CalcSubscripts(int rank,int *dims,int index)
- {
- int i, j, k, *subs;
- double l;
- subs = malloc(rank*sizeof(int));
- l = index;
- for ( i = rank; i--; ) {
- k = 1;
- for ( j = i; j--; )
- k *= dims[j];
- subs[i] = floor(l / (double)k);
- l -= subs[i]*k;
- subs[i]++;
- }
- return subs;
- }
- /** @brief Returns a pointer to the Cell array at a specific index
- *
- * Returns a pointer to the Cell Array Field at the given 1-relative index.
- * MAT file must be a version 5 matlab file.
- * @ingroup MAT
- * @param matvar Pointer to the Cell Array MAT variable
- * @param index linear index of cell to return
- * @return Pointer to the Cell Array Field on success, NULL on error
- */
- matvar_t *
- Mat_VarGetCell(matvar_t *matvar,int index)
- {
- int nmemb = 1, i;
- matvar_t *cell = NULL;
- if ( matvar == NULL )
- return NULL;
- for ( i = 0; i < matvar->rank; i++ )
- nmemb *= matvar->dims[i];
- if ( index < nmemb )
- cell = *((matvar_t **)matvar->data + index);
- return cell;
- }
- /** @brief Indexes a cell array
- *
- * Finds cells of a cell array given a start, stride, and edge for each.
- * dimension. The cells are placed in a pointer array. The cells should not
- * be freed, but the array of pointers should be. If copies are needed,
- * use Mat_VarDuplicate on each cell.
- * MAT File version must be 5.
- * @ingroup MAT
- * @param matvar Cell Array matlab variable
- * @param start vector of length rank with 0-relative starting coordinates for
- * each diemnsion.
- * @param stride vector of length rank with strides for each diemnsion.
- * @param edge vector of length rank with the number of elements to read in
- * each diemnsion.
- * @returns an array of pointers to the cells
- */
- matvar_t **
- Mat_VarGetCells(matvar_t *matvar,int *start,
- int *stride,int *edge)
- {
- int i, j, N, I = 0;
- int inc[10] = {0,}, cnt[10] = {0,}, dimp[10] = {0,};
- matvar_t **cells;
- if ( (matvar == NULL) || (start == NULL) || (stride == NULL) ||
- (edge == NULL) ) {
- return NULL;
- } else if ( matvar->rank > 10 ) {
- return NULL;
- }
- inc[0] = stride[0]-1;
- dimp[0] = matvar->dims[0];
- N = edge[0];
- I = start[0];
- for ( i = 1; i < matvar->rank; i++ ) {
- inc[i] = stride[i]-1;
- dimp[i] = matvar->dims[i-1];
- for ( j = i ; j--; ) {
- inc[i] *= matvar->dims[j];
- dimp[i] *= matvar->dims[j+1];
- }
- N *= edge[i];
- if ( start[i] > 0 )
- I += start[i]*dimp[i-1];
- }
- cells = malloc(N*sizeof(matvar_t *));
- for ( i = 0; i < N; i+=edge[0] ) {
- for ( j = 0; j < edge[0]; j++ ) {
- cells[i+j] = *((matvar_t **)matvar->data + I);
- I += stride[0];
- }
- for ( j = 1; j < matvar->rank-1; j++ ) {
- cnt[j]++;
- if ( (cnt[j] % edge[j]) == 0 ) {
- cnt[j] = 0;
- if ( (I % dimp[j]) != 0 ) {
- I += dimp[j]-(I % dimp[j]);
- }
- } else {
- I += matvar->dims[0]-edge[0]*stride[0]-start[0];
- I += inc[j];
- break;
- }
- }
- }
- return cells;
- }
- /** @brief Indexes a cell array
- *
- * Finds cells of a cell array given a linear indexed start, stride, and edge.
- * The cells are placed in a pointer array. The cells themself should not
- * be freed as they are part of the original cell array, but the pointer array
- * should be. If copies are needed, use Mat_VarDuplicate on each of the cells.
- * MAT file version must be 5.
- * @ingroup MAT
- * @param matvar Cell Array matlab variable
- * @param start starting index
- * @param stride stride
- * @param edge Number of cells to get
- * @returns an array of pointers to the cells
- */
- matvar_t **
- Mat_VarGetCellsLinear(matvar_t *matvar,int start,int stride,int edge)
- {
- int i, I = 0;
- matvar_t **cells;
- if ( matvar == NULL || matvar->rank > 10 ) {
- cells = NULL;
- } else {
- cells = malloc(edge*sizeof(matvar_t *));
- for ( i = 0; i < edge; i++ ) {
- cells[i] = *((matvar_t **)matvar->data + I);
- I += stride;
- }
- }
- return cells;
- }
- /** @brief Calculates the size of a matlab variable in bytes
- *
- * @ingroup MAT
- * @param matvar matlab variable
- * @returns size of the variable in bytes
- */
- size_t
- Mat_VarGetSize(matvar_t *matvar)
- {
- int nmemb, i;
- size_t bytes = 0;
- if ( matvar->class_type == MAT_C_STRUCT ) {
- int nfields;
- matvar_t **fields;
- /* This is really nmemb*nfields, but we'll get a
- * more accurate count of the bytes by loopoing over all of them
- */
- nfields = matvar->nbytes / matvar->data_size;
- fields = matvar->data;
- for ( i = 0; i < nfields; i++ )
- bytes += Mat_VarGetSize(fields[i]);
- } else if ( matvar->class_type == MAT_C_CELL ) {
- int ncells;
- matvar_t **cells;
- ncells = matvar->nbytes / matvar->data_size;
- cells = matvar->data;
- for ( i = 0; i < ncells; i++ )
- bytes += Mat_VarGetSize(cells[i]);
- } else {
- nmemb = 1;
- for ( i = 0; i < matvar->rank; i++ )
- nmemb *= matvar->dims[i];
- bytes += nmemb*Mat_SizeOfClass(matvar->class_type);
- }
- return bytes;
- }
- /** @brief Adds a field to a structure
- *
- * Adds the given field to the structure. fields should be an array of matvar_t
- * pointers of the same size as the structure (i.e. 1 field per structure
- * element).
- * @ingroup MAT
- * @param matvar Pointer to the Structure MAT variable
- * @param fields Array of fields to be added
- * @retval 0 on success
- */
- int
- Mat_VarAddStructField(matvar_t *matvar,matvar_t **fields)
- {
- int i, f, nfields, nmemb, cnt = 0;
- matvar_t **new_data,**old_data;
- if ( matvar == NULL || fields == NULL )
- return -1;
- nmemb = 1;
- for ( i = 0; i < matvar->rank; i++ )
- nmemb *= matvar->dims[i];
- nfields = matvar->nbytes / (nmemb*sizeof(matvar_t *));
- new_data = malloc((nfields+1)*nmemb*sizeof(matvar_t *));
- if ( new_data == NULL )
- return -1;
- old_data = matvar->data;
- for ( i = 0; i < nmemb; i++ ) {
- for ( f = 0; f < nfields; f++ )
- new_data[cnt++] = old_data[i*nfields+f];
- new_data[cnt++] = fields[i];
- }
- free(matvar->data);
- matvar->data = new_data;
- matvar->nbytes = (nfields+1)*nmemb*sizeof(matvar_t *);
- return 0;
- }
- /** @brief Returns the number of fields in a structure variable
- *
- * Returns the number of fields in the given structure.
- * MAT file version must be 5.
- * @ingroup MAT
- * @param matvar Structure matlab variable
- * @returns Number of fields, or a negative number on error
- */
- int
- Mat_VarGetNumberOfFields(matvar_t *matvar)
- {
- int i, nfields, nmemb = 1;
- if ( matvar == NULL || matvar->class_type != MAT_C_STRUCT ||
- matvar->data_size == 0 ) {
- nfields = -1;
- } else {
- for ( i = 0; i < matvar->rank; i++ )
- nmemb *= matvar->dims[i];
- nfields = matvar->nbytes / (nmemb*matvar->data_size);
- }
- return nfields;
- }
- /** @brief Finds a field of a structure
- *
- * Returns a pointer to the structure field at the given 0-relative index. MAT
- * file version must be 5.
- * @ingroup MAT
- * @param matvar Pointer to the Structure MAT variable
- * @param name_or_index Name of the field, or the 1-relative index of the field.
- * If the index is used, it should be the address of an integer variable whose
- * value is the index number.
- * @param opt BY_NAME if the name_or_index is the name or BY_INDEX if the index
- * was passed.
- * @param index linear index of the structure to find the field of
- * @return Pointer to the Structure Field on success, NULL on error
- */
- matvar_t *
- Mat_VarGetStructField(matvar_t *matvar,void *name_or_index,int opt,int index)
- {
- int i, err = 0, nfields, nmemb;
- matvar_t *field = NULL;
- nmemb = 1;
- for ( i = 0; i < matvar->rank; i++ )
- nmemb *= matvar->dims[i];
- nfields = matvar->nbytes / (nmemb*sizeof(matvar_t *));
- if ( index >= nmemb || index < 0)
- err = 1;
- if ( !err && (opt == BY_INDEX) ) {
- int field_index;
- field_index = *(int *)name_or_index;
- if ( field_index > nfields || field_index < 1 )
- Mat_Critical("Mat_VarGetStructField: field index out of bounds");
- else
- field = *((matvar_t **)matvar->data+index*nfields+field_index - 1);
- } else if ( !err && (opt == BY_NAME) ) {
- char *field_name;
- field_name = (char *)name_or_index;
- for ( i = 0; i < nfields; i++ ) {
- field = *((matvar_t **)matvar->data+index*nfields+i);
- if ( !strcmp(field->name,field_name) )
- break;
- else
- field = NULL;
- }
- }
- return field;
- }
- /** @brief Indexes a structure
- *
- * Finds structures of a structure array given a start, stride, and edge for
- * each dimension. The structures are placed in a new structure array. If
- * copy_fields is non-zero, the indexed structures are copied and should be
- * freed, but if copy_fields is zero, the indexed structures are pointers to
- * the original, but should still be freed since the mem_conserve flag is set
- * so that the structures are not freed.
- * MAT File version must be 5.
- * @ingroup MAT
- * @param matvar Structure matlab variable
- * @param start vector of length rank with 0-relative starting coordinates for
- * each diemnsion.
- * @param stride vector of length rank with strides for each diemnsion.
- * @param edge vector of length rank with the number of elements to read in
- * each diemnsion.
- * @param copy_fields 1 to copy the fields, 0 to just set pointers to them.
- * If 0 is used, the fields should not be freed themselves.
- * @returns A new structure with fields indexed from matvar.
- */
- matvar_t *
- Mat_VarGetStructs(matvar_t *matvar,int *start,int *stride,int *edge,
- int copy_fields)
- {
- int i, j, N, I = 0;
- int inc[10] = {0,}, cnt[10] = {0,}, dimp[10] = {0,};
- int nfields, field;
- matvar_t **fields, *struct_slab;
- if ( (matvar == NULL) || (start == NULL) || (stride == NULL) ||
- (edge == NULL) ) {
- return NULL;
- } else if ( matvar->rank > 10 ) {
- return NULL;
- } else if ( matvar->class_type != MAT_C_STRUCT ) {
- return NULL;
- }
- struct_slab = Mat_VarDuplicate(matvar,0);
- if ( !copy_fields )
- struct_slab->mem_conserve = 1;
- nfields = matvar->nbytes / matvar->data_size;
- for ( i = 0; i < matvar->rank; i++ )
- nfields = nfields / matvar->dims[i];
- inc[0] = stride[0]-1;
- dimp[0] = matvar->dims[0];
- N = edge[0];
- I = start[0]*nfields;
- for ( i = 1; i < matvar->rank; i++ ) {
- inc[i] = stride[i]-1;
- dimp[i] = matvar->dims[i-1];
- for ( j = i ; j--; ) {
- inc[i] *= matvar->dims[j]*nfields;
- dimp[i] *= matvar->dims[j+1];
- }
- N *= edge[i];
- if ( start[i] > 0 )
- I += start[i]*dimp[i-1]*nfields;
- }
- struct_slab->nbytes = N*nfields*sizeof(matvar_t *);
- struct_slab->data = malloc(struct_slab->nbytes);
- if ( struct_slab->data == NULL ) {
- Mat_VarFree(struct_slab);
- return NULL;
- }
- fields = struct_slab->data;
- for ( i = 0; i < N; i+=edge[0] ) {
- for ( j = 0; j < edge[0]; j++ ) {
- for ( field = 0; field < nfields; field++ ) {
- if ( copy_fields )
- fields[(i+j)*nfields+field] =
- Mat_VarDuplicate(*((matvar_t **)matvar->data + I),1);
- else
- fields[(i+j)*nfields+field] =
- *((matvar_t **)matvar->data + I);
- I++;
- }
- I += stride[0]*nfields;
- }
- for ( j = 1; j < matvar->rank-1; j++ ) {
- cnt[j]++;
- if ( (cnt[j] % edge[j]) == 0 ) {
- cnt[j] = 0;
- if ( (I % dimp[j]) != 0 ) {
- I += dimp[j]-(I % dimp[j]);
- }
- } else {
- I += matvar->dims[0]-edge[0]*stride[0]-start[0];
- I += inc[j];
- break;
- }
- }
- }
- return struct_slab;
- }
- /** @brief Indexes a structure
- *
- * Finds structures of a structure array given a single (linear)start, stride,
- * and edge. The structures are placed in a new structure array. If
- * copy_fields is non-zero, the indexed structures are copied and should be
- * freed, but if copy_fields is zero, the indexed structures are pointers to
- * the original, but should still be freed since the mem_conserve flag is set
- * so that the structures are not freed.
- * MAT File version must be 5.
- * @ingroup MAT
- * @param matvar Structure matlab variable
- * @param start starting index
- * @param stride stride
- * @param edge Number of structures to get
- * @param copy_fields 1 to copy the fields, 0 to just set pointers to them.
- * If 0 is used, the fields should not be freed themselves.
- * @returns A new structure with fields indexed from matvar
- */
- matvar_t *
- Mat_VarGetStructsLinear(matvar_t *matvar,int start,int stride,int edge,
- int copy_fields)
- {
- int i, I = 0, field, nfields;
- matvar_t *struct_slab, **fields;
- /* FIXME: Check allocations */
- if ( matvar == NULL || matvar->rank > 10 ) {
- struct_slab = NULL;
- } else {
- struct_slab = Mat_VarDuplicate(matvar,0);
- if ( !copy_fields )
- struct_slab->mem_conserve = 1;
- nfields = matvar->nbytes / matvar->data_size;
- for ( i = 0; i < matvar->rank; i++ )
- nfields = nfields / matvar->dims[i];
- struct_slab->nbytes = edge*nfields*sizeof(matvar_t *);
- struct_slab->data = malloc(struct_slab->nbytes);
- fields = struct_slab->data;
- for ( i = 0; i < edge; i++ ) {
- if ( copy_fields ) {
- for ( field = 0; field < nfields; field++ ) {
- fields[i*nfields+field] =
- Mat_VarDuplicate(*((matvar_t **)matvar->data+I),1);
- I++;
- }
- } else {
- for ( field = 0; field < nfields; field++ ) {
- fields[i+field] = *((matvar_t **)matvar->data + I);
- I++;
- }
- }
- I += stride;
- }
- }
- return struct_slab;
- }
- /** @brief Prints the variable information
- *
- * Prints to stdout the values of the @ref matvar_t structure
- * @ingroup MAT
- * @param matvar Pointer to the matvar_t structure
- * @param printdata set to 1 if the Variables data should be printed, else 0
- */
- void
- Mat_VarPrint( matvar_t *matvar, int printdata )
- {
- if ( matvar == NULL || matvar->fp == NULL )
- return;
- else if ( matvar->fp->version != MAT_FT_MAT4 )
- Mat_VarPrint5(matvar,printdata);
- else if ( matvar->fp->version == MAT_FT_MAT4 )
- Mat_VarPrint4(matvar,printdata);
- return;
- }
- /** @brief Reads MAT variable data from a file
- *
- * Reads data from a MAT variable. 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 array of starting indeces
- * @param stride stride of data
- * @param edge array specifying the number to read in each direction
- * @retval 0 on success
- */
- int
- Mat_VarReadData(mat_t *mat,matvar_t *matvar,void *data,
- int *start,int *stride,int *edge)
- {
- int err = 0;
- if ( mat->version != MAT_FT_MAT4 )
- err = ReadData5(mat,matvar,data,start,stride,edge);
- else
- err = ReadData4(mat,matvar,data,start,stride,edge);
- return err;
- }
- /** @brief Reads all the data for a matlab variable
- *
- * Allocates memory for an reads the data for a given matlab variable.
- * @ingroup MAT
- * @param mat Matlab MAT file structure pointer
- * @param matvar Variable whose data is to be read
- * @returns non-zero on error
- */
- int
- Mat_VarReadDataAll(mat_t *mat,matvar_t *matvar)
- {
- int err = 0;
- if ( (mat == NULL) || (matvar == NULL) )
- err = 1;
- else
- ReadData(mat,matvar);
- return err;
- }
- /** @brief Reads MAT variable data from a file
- *
- * Reads data from a MAT variable using a linear indexingmode. 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_VarReadDataLinear(mat_t *mat,matvar_t *matvar,void *data,int start,
- int stride,int edge)
- {
- int err = 0, nmemb = 1, i, data_type;
- mat_int32_t tag[2];
- if ( mat->version == MAT_FT_MAT4 )
- return -1;
- fseek(mat->fp,matvar->datapos,SEEK_SET);
- if ( matvar->compression == COMPRESSION_NONE ) {
- fread(tag,4,2,mat->fp);
- if ( mat->byteswap ) {
- Mat_int32Swap(tag);
- Mat_int32Swap(tag+1);
- }
- data_type = tag[0] & 0x000000ff;
- if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
- fseek(mat->fp,-4,SEEK_CUR);
- }
- #if defined(HAVE_ZLIB)
- } else if ( matvar->compression == COMPRESSION_ZLIB ) {
- matvar->z->avail_in = 0;
- InflateDataType(mat,matvar,tag);
- if ( mat->byteswap ) {
- Mat_int32Swap(tag);
- Mat_int32Swap(tag+1);
- }
- data_type = tag[0] & 0x000000ff;
- if ( !(tag[0] & 0xffff0000) ) {/* Data is NOT packed in the tag */
- InflateSkip(mat,matvar->z,4);
- }
- #endif
- }
- for ( i = 0; i < matvar->rank; i++ )
- nmemb *= matvar->dims[i];
- if ( stride*(edge-1)+start+1 > nmemb ) {
- err = 1;
- } else {
- stride--;
- switch(matvar->class_type) {
- case MAT_C_DOUBLE:
- matvar->data_type = MAT_T_DOUBLE;
- matvar->data_size = sizeof(double);
- if ( matvar->compression == COMPRESSION_NONE ) {
- stride *= Mat_SizeOf(data_type);
- fseek(mat->fp,start,SEEK_CUR);
- for ( i = 0; i < edge; i++ ) {
- ReadDoubleData(mat,(double*)data+i,data_type,1);
- fseek(mat->fp,stride,SEEK_CUR);
- }
- #if defined(HAVE_ZLIB)
- } else {
- z_stream z_copy;
- err = inflateCopy(&z_copy,matvar->z);
- InflateSkipData(mat,&z_copy,data_type,start);
- for ( i = 0; i < edge; i++ ) {
- ReadCompressedDoubleData(mat,&z_copy,(double*)data+i,
- data_type,1);
- InflateSkipData(mat,&z_copy,data_type,stride);
- }
- inflateEnd(&z_copy);
- #endif
- }
- break;
- case MAT_C_SINGLE:
- matvar->data_type = MAT_T_SINGLE;
- matvar->data_size = sizeof(float);
- if ( matvar->compression == COMPRESSION_NONE ) {
- stride *= Mat_SizeOf(data_type);
- for ( i = 0; i < edge; i++ ) {
- ReadSingleData(mat,(float*)data+i,data_type,1);
- fseek(mat->fp,stride,SEEK_CUR);
- }
- #if defined(HAVE_ZLIB)
- } else {
- z_stream z_copy;
- err = inflateCopy(&z_copy,matvar->z);
- InflateSkipData(mat,&z_copy,data_type,start);
- for ( i = 0; i < edge; i++ ) {
- ReadCompressedSingleData(mat,&z_copy,(float*)data+i,
- data_type,1);
- InflateSkipData(mat,&z_copy,data_type,stride);
- }
- inflateEnd(&z_copy);
- #endif
- }
- break;
- #ifdef HAVE_MAT_INT64_T
- case MAT_C_INT64:
- matvar->data_type = MAT_T_INT64;
- matvar->data_size = sizeof(mat_int64_t);
- if ( matvar->compression == COMPRESSION_NONE ) {
- stride *= Mat_SizeOf(data_type);
- for ( i = 0; i < edge; i++ ) {
- ReadInt64Data(mat,(mat_int64_t*)data+i,data_type,1);
- fseek(mat->fp,stride,SEEK_CUR);
- }
- #if defined(HAVE_ZLIB)
- } else {
- z_stream z_copy;
- err = inflateCopy(&z_copy,matvar->z);
- InflateSkipData(mat,&z_copy,data_type,start);
- for ( i = 0; i < edge; i++ ) {
- ReadCompressedInt64Data(mat,&z_copy,(mat_int64_t*)data+i,
- data_type,1);
- InflateSkipData(mat,&z_copy,data_type,stride);
- }
- inflateEnd(&z_copy);
- #endif
- }
- break;
- #endif /* HAVE_MAT_INT64_T */
- #ifdef HAVE_MAT_UINT64_T
- case MAT_C_UINT64:
- matvar->data_type = MAT_T_UINT64;
- matvar->data_size = sizeof(mat_uint64_t);
- if ( matvar->compression == COMPRESSION_NONE ) {
- stride *= Mat_SizeOf(data_type);
- for ( i = 0; i < edge; i++ ) {
- ReadInt64Data(mat,(mat_int64_t*)data+i,data_type,1);
- fseek(mat->fp,stride,SEEK_CUR);
- }
- #if defined(HAVE_ZLIB)
- } else {
- z_stream z_copy;
- err = inflateCopy(&z_copy,matvar->z);
- InflateSkipData(mat,&z_copy,data_type,start);
- for ( i = 0; i < edge; i++ ) {
- ReadCompressedInt64Data(mat,&z_copy,(mat_int64_t*)data+i,
- data_type,1);
- InflateSkipData(mat,&z_copy,data_type,stride);
- }
- inflateEnd(&z_copy);
- #endif
- }
- break;
- #endif /* HAVE_MAT_UINT64_T */
- case MAT_C_INT32:
- matvar->data_type = MAT_T_INT32;
- matvar->data_size = sizeof(mat_int32_t);
- if ( matvar->compression == COMPRESSION_NONE ) {
- stride *= Mat_SizeOf(data_type);
- for ( i = 0; i < edge; i++ ) {
- ReadInt32Data(mat,(mat_int32_t*)data+i,data_type,1);
- fseek(mat->fp,stride,SEEK_CUR);
- }
- #if defined(HAVE_ZLIB)
- } else {
- z_stream z_copy;
- err = inflateCopy(&z_copy,matvar->z);
- InflateSkipData(mat,&z_copy,data_type,start);
- for ( i = 0; i < edge; i++ ) {
- ReadCompressedInt32Data(mat,&z_copy,(mat_int32_t*)data+i,
- data_type,1);
- InflateSkipData(mat,&z_copy,data_type,stride);
- }
- inflateEnd(&z_copy);
- #endif
- }
- break;
- case MAT_C_UINT32:
- matvar->data_type = MAT_T_UINT32;
- matvar->data_size = sizeof(mat_uint32_t);
- if ( matvar->compression == COMPRESSION_NONE ) {
- stride *= Mat_SizeOf(data_type);
- for ( i = 0; i < edge; i++ ) {
- ReadInt32Data(mat,(mat_int32_t*)data+i,data_type,1);
- fseek(mat->fp,stride,SEEK_CUR);
- }
- #if defined(HAVE_ZLIB)
- } else {
- z_stream z_copy;
- err = inflateCopy(&z_copy,matvar->z);
- InflateSkipData(mat,&z_copy,data_type,start);
- for ( i = 0; i < edge; i++ ) {
- ReadCompressedInt32Data(mat,&z_copy,(mat_int32_t*)data+i,
- data_type,1);
- InflateSkipData(mat,&z_copy,data_type,stride);
- }
- inflateEnd(&z_copy);
- #endif
- }
- break;
- case MAT_C_INT16:
- matvar->data_type = MAT_T_INT16;
- matvar->data_size = sizeof(mat_int16_t);
- if ( matvar->compression == COMPRESSION_NONE ) {
- stride *= Mat_SizeOf(data_type);
- for ( i = 0; i < edge; i++ ) {
- ReadInt16Data(mat,(mat_int16_t*)data+i,data_type,1);
- fseek(mat->fp,stride,SEEK_CUR);
- }
- #if defined(HAVE_ZLIB)
- } else {
- z_stream z_copy;
- err = inflateCopy(&z_copy,matvar->z);
- InflateSkipData(mat,&z_copy,data_type,start);
- for ( i = 0; i < edge; i++ ) {
- ReadCompressedInt16Data(mat,&z_copy,(mat_int16_t*)data+i,
- data_type,1);
- InflateSkipData(mat,&z_copy,data_type,stride);
- }
- inflateEnd(&z_copy);
- #endif
- }
- break;
- case MAT_C_UINT16:
- matvar->data_type = MAT_T_UINT16;
- matvar->data_size = sizeof(mat_uint16_t);
- if ( matvar->compression == COMPRESSION_NONE ) {
- stride *= Mat_SizeOf(data_type);
- for ( i = 0; i < edge; i++ ) {
- ReadInt16Data(mat,(mat_int16_t*)data+i,data_type,1);
- fseek(mat->fp,stride,SEEK_CUR);
- }
- #if defined(HAVE_ZLIB)
- } else {
- z_stream z_copy;
- err = inflateCopy(&z_copy,matvar->z);
- InflateSkipData(mat,&z_copy,data_type,start);
- for ( i = 0; i < edge; i++ ) {
- ReadCompressedInt16Data(mat,&z_copy,(mat_int16_t*)data+i,
- data_type,1);
- InflateSkipData(mat,&z_copy,data_type,stride);
- }
- inflateEnd(&z_copy);
- #endif
- }
- break;
- case MAT_C_INT8:
- matvar->data_type = MAT_T_INT8;
- matvar->data_size = sizeof(mat_int8_t);
- if ( matvar->compression == COMPRESSION_NONE ) {
- stride *= Mat_SizeOf(data_type);
- for ( i = 0; i < edge; i++ ) {
- ReadInt8Data(mat,(mat_int8_t*)data+i,data_type,1);
- fseek(mat->fp,stride,SEEK_CUR);
- }
- #if defined(HAVE_ZLIB)
- } else {
- z_stream z_copy;
- err = inflateCopy(&z_copy,matvar->z);
- InflateSkipData(mat,&z_copy,data_type,start);
- for ( i = 0; i < edge; i++ ) {
- ReadCompressedInt8Data(mat,&z_copy,(mat_int8_t*)data+i,
- data_type,1);
- InflateSkipData(mat,&z_copy,data_type,stride);
- }
- inflateEnd(&z_copy);
- #endif
- }
- break;
- case MAT_C_UINT8:
- matvar->data_type = MAT_T_UINT8;
- matvar->data_size = sizeof(mat_uint8_t);
- if ( matvar->compression == COMPRESSION_NONE ) {
- stride *= Mat_SizeOf(data_type);
- for ( i = 0; i < edge; i++ ) {
- ReadInt8Data(mat,(mat_int8_t*)data+i,data_type,1);
- fseek(mat->fp,stride,SEEK_CUR);
- }
- #if defined(HAVE_ZLIB)
- } else {
- z_stream z_copy;
- err = inflateCopy(&z_copy,matvar->z);
- InflateSkipData(mat,&z_copy,data_type,start);
- for ( i = 0; i < edge; i++ ) {
- ReadCompressedInt8Data(mat,&z_copy,(mat_int8_t*)data+i,
- data_type,1);
- InflateSkipData(mat,&z_copy,data_type,stride);
- }
- inflateEnd(&z_copy);
- #endif
- }
- break;
- }
- }
- return err;
- }
- /** @brief Reads the information of the next variable in a MAT file
- *
- * Reads the next variable's information (class,flags-complex/global/logical,
- * rank,dimensions, name, etc) from the Matlab MAT file. After reading, the MAT
- * file is positioned past the current variable.
- * @ingroup MAT
- * @param mat Pointer to the MAT file
- * @return Pointer to the @ref matvar_t structure containing the MAT
- * variable information
- */
- matvar_t *
- Mat_VarReadNextInfo( mat_t *mat )
- {
- if( mat == NULL )
- return NULL;
- else if ( mat->version == 0x0100 )
- return Mat_VarReadNextInfo5(mat);
- else
- return Mat_VarReadNextInfo4(mat);
- return NULL;
- }
- /** @brief Reads the information of a variable with the given name from a MAT file
- *
- * Reads the named variable (or the next variable if name is NULL) information
- * (class,flags-complex/global/logical,rank,dimensions,and name) from the
- * Matlab MAT file
- * @ingroup MAT
- * @param mat Pointer to the MAT file
- * @param name Name of the variable to read
- * @return Pointer to the @ref matvar_t structure containing the MAT
- * variable information
- */
- matvar_t *
- Mat_VarReadInfo( mat_t *mat, char *name )
- {
- long fpos;
- matvar_t *matvar = NULL;
- if ( (mat == NULL) || (name == NULL) )
- return NULL;
- fpos = ftell(mat->fp);
- fseek(mat->fp,mat->bof,SEEK_SET);
- do {
- #if 0
- err = fread(&data_type,4,1,mat->fp);
- if ( !err )
- return NULL;
- err = fread(&nBytes,4,1,mat->fp);
- if ( mat->byteswap ) {
- Mat_int32Swap(&data_type);
- Mat_int32Swap(&nBytes);
- }
- curpos = ftell(mat->fp);
- fseek(mat->fp,-8,SEEK_CUR);
- #endif
- matvar = Mat_VarReadNextInfo(mat);
- if ( matvar != NULL ) {
- if ( !matvar->name ) {
- Mat_VarFree(matvar);
- matvar = NULL;
- } else if ( strcmp(matvar->name,name) ) {
- Mat_VarFree(matvar);
- matvar = NULL;
- }
- } else {
- Mat_Critical("An error occurred in reading the MAT file");
- break;
- }
- #if 0
- fseek(mat->fp,curpos+nBytes,SEEK_SET);
- #endif
- } while ( !matvar && !feof(mat->fp) );
- fseek(mat->fp,fpos,SEEK_SET);
- return matvar;
- }
- /** @brief Reads the variable with the given name from a MAT file
- *
- * Reads the next variable in the Matlab MAT file
- * @ingroup MAT
- * @param mat Pointer to the MAT file
- * @param name Name of the variable to read
- * @return Pointer to the @ref matvar_t structure containing the MAT
- * variable information
- */
- matvar_t *
- Mat_VarRead( mat_t *mat, char *name )
- {
- long fpos;
- matvar_t *matvar = NULL;;
- if ( (mat == NULL) || (name == NULL) )
- return NULL;
- fpos = ftell(mat->fp);
- matvar = Mat_VarReadInfo(mat,name);
- if ( matvar )
- ReadData(mat,matvar);
- fseek(mat->fp,fpos,SEEK_SET);
- return matvar;
- }
- /** @brief Reads the next variable in a MAT file
- *
- * Reads the next variable in the Matlab MAT file
- * @ingroup MAT
- * @param mat Pointer to the MAT file
- * @return Pointer to the @ref matvar_t structure containing the MAT
- * variable information
- */
- matvar_t *
- Mat_VarReadNext( mat_t *mat )
- {
- long fpos;
- matvar_t *matvar = NULL;
- if ( feof(mat->fp) )
- return NULL;
- /* Read position so we can reset the file position if an error occurs */
- fpos = ftell(mat->fp);
- matvar = Mat_VarReadNextInfo(mat);
- if ( matvar != NULL)
- ReadData(mat,matvar);
- else
- fseek(mat->fp,fpos,SEEK_SET);
- return matvar;
- }
- /** @brief Writes the given MAT variable to a MAT file
- *
- * Writes the MAT variable information stored in matvar to the given MAT file.
- * The variable will be written to the end of the file.
- * @ingroup MAT
- * @param mat MAT file to write to
- * @param matvar MAT variable information to write
- * @retval 0 on success
- */
- int
- Mat_VarWriteInfo(mat_t *mat, matvar_t *matvar )
- {
- if ( mat == NULL || matvar == NULL || mat->fp == NULL )
- return -1;
- else if ( mat->version != MAT_FT_MAT4 )
- WriteInfo5(mat,matvar);
- #if 0
- else if ( mat->version == MAT_FT_MAT4 )
- WriteInfo4(mat,matvar);
- #endif
- return 0;
- }
- /** @brief Writes the given data to the MAT variable
- *
- * Writes data to a MAT variable. The variable must have previously been
- * written with Mat_VarWriteInfo.
- * @ingroup MAT
- * @param mat MAT file to write to
- * @param matvar MAT variable information to write
- * @param data pointer to the data to write
- * @param start array of starting indeces
- * @param stride stride of data
- * @param edge array specifying the number to read in each direction
- * @retval 0 on success
- */
- int
- Mat_VarWriteData(mat_t *mat,matvar_t *matvar,void *data,
- int *start,int *stride,int *edge)
- {
- int err = 0, k, N = 1;
- fseek(mat->fp,matvar->datapos+8,SEEK_SET);
- if ( mat == NULL || matvar == NULL || data == NULL ) {
- err = -1;
- } else if ( start == NULL && stride == NULL && edge == NULL ) {
- for ( k = 0; k < matvar->rank; k++ )
- N *= matvar->dims[k];
- if ( matvar->compression == COMPRESSION_NONE )
- WriteData(mat,data,N,matvar->data_type);
- #if 0
- else if ( matvar->compression == COMPRESSION_ZLIB ) {
- WriteCompressedData(mat,matvar->z,data,N,matvar->data_type);
- (void)deflateEnd(matvar->z);
- free(matvar->z);
- matvar->z = NULL;
- }
- #endif
- } else if ( matvar->rank == 2 ) {
- if ( stride[0]*(edge[0]-1)+start[0]+1 > matvar->dims[0] ) {
- err = 1;
- } else if ( stride[1]*(edge[1]-1)+start[1]+1 > matvar->dims[1] ) {
- err = 1;
- } else {
- switch ( matvar->class_type ) {
- case MAT_C_DOUBLE:
- case MAT_C_SINGLE:
- case MAT_C_INT64:
- case MAT_C_UINT64:
- case MAT_C_INT32:
- case MAT_C_UINT32:
- case MAT_C_INT16:
- case MAT_C_UINT16:
- case MAT_C_INT8:
- case MAT_C_UINT8:
- WriteDataSlab2(mat,data,matvar->data_type,matvar->dims,
- start,stride,edge);
- break;
- case MAT_C_CHAR:
- WriteCharDataSlab2(mat,data,matvar->data_type,matvar->dims,
- start,stride,edge);
- break;
- }
- }
- }
- return err;
- }
- /** @brief Writes the given MAT variable to a MAT file
- *
- * Writes the MAT variable information stored in matvar to the given MAT file.
- * The variable will be written to the end of the file.
- * @ingroup MAT
- * @param mat MAT file to write to
- * @param matvar MAT variable information to write
- * @param compress Whether or not to compress the data
- * (Only valid for version 5 MAT files and variables with numeric data)
- * @retval 0 on success
- */
- int
- Mat_VarWrite( mat_t *mat, matvar_t *matvar, int compress )
- {
- if ( mat == NULL || matvar == NULL )
- return -1;
- else if ( mat->version != MAT_FT_MAT4 )
- Write5(mat,matvar,compress);
- return 0;
- }
|