/********************************************************* LOADMAT.C This function is used to load matrices and Matlab strings recorded in Matfile format into memory for use by a C program. Matlab strings are converted to C nul-terminated strings. Memory is allocated on the heap for all matrices and strings loaded, so the calling program does not have to know beforehand how large the arrays are. In order to permit this function to be used with arrays of different types (double, float, etc.), the function arguments use (char **) for passing the data arrays. When the function is called, casts to this type should be used in the argument list. For example, to load floating point arrays, the call would be: FILE *fp; char type; char name[30]; int rows, columns; int imag_flag; float *a_real, *a_imag; err = loadmat(fp, &type, name, &rows, &columns, &imag_flag, (char **) &a_real, (char **) &a_imag); err = 0 if the load is completed successfully, EOF if end of file is encountered when trying to read the Fmatrix, 1 if any other error is encountered. Note that space for the matrix name must be allocated by the calling routine, while space for the data arrays is allocated by loadmat, and must be freed by the calling routine when it is no longer needed. This version of loadmat does not take into account the machine on which the MATfile was written. It will work only when loading MATfiles on the same type of machine with which they were written. This is a major modification of a function written by J. N. Little, 86-11-03, for MATLAB. Eric Firing 88-02-12 Mon 03-13-1989 Added support for machines other than the PC, via alternative initialization of bytes_per_word. ***********************************************************/ #include "common.h" #include "matfile.h" #define invalid_type(x) (x<0 || x>4) #if (MACHINE_TYPE == PC) static int bytes_per_word[] = { 8, 4, 4, 2, 2}; #else static int bytes_per_word[] = { 8, 4, 4, 4, 4}; #endif static char type_letter[] = {'d', 'f', 'l', 'i', 'u'}; /**** Convert a Matlab string to a nul-terminated string. The c-string is returned in the same space as the Matlab string was stored. ****/ char *convert_mat_string(double *s, int n) { int i; char *cstring; cstring = (char *) calloc(n+1, sizeof(char)); if (cstring==NULL) return ((char *) NULL); /* error condition */ for (i=0; idouble, 1->float, 2->long, 3->short, 4->ushort */ text_flag, /* 1 if text */ c_storage; /* 1 if stored by C program: by rows */ /* * Get Fmatrix structure from file */ if (fread((char *)&x, sizeof(Fmatrix), 1, fp) != 1) { if (feof(fp)) return(EOF); printf("\nLOADMAT error, can't read Fmatrix.\n"); return(1); } c_storage = (x.type%1000)/100; num_type = (x.type%100)/10; text_flag = (x.type%10); if (invalid_type(num_type)) { printf("\nLOADMAT error, invalid type: %ld\n", (long) x.type); return(1); } nbytes = bytes_per_word[num_type]; if (text_flag) *type = 't'; else *type = type_letter[num_type]; if (c_storage || text_flag) { /* stored C-fashion, by rows */ *mrows = x.mrows; *ncols = x.ncols; } else { /* stored Fortran-fashion, by columns */ *mrows = x.ncols; /* so the MATfile column is a C row */ *ncols = x.mrows; /* and vise-versa */ } *imagf = x.imagf; namlen = x.namlen; mn = x.mrows * x.ncols * nbytes; /* * Get matrix name from file */ if (fread(pname, sizeof(char), namlen, fp) != namlen) { printf("\nLOADMAT error, can't read matrix name.\n"); return(1); } /* * Get Real part of matrix from file */ if ((*preal = (char *)malloc(mn) ) == NULL) { printf("\nLOADMAT error, not enough memory for real part\n"); return(1); } if (fread(*preal, 1, mn, fp) != mn) { free(*preal); return(1); } if(text_flag) { char *string; /* temporary pointer, used only here */ string = convert_mat_string((double *) *preal, (*ncols)*(*mrows)); if (string == NULL) { printf("LOADMAT error, not enough memory for C string.\n"); free(*preal); return(1); } else { *preal = string; return (0); /* If it is a string, ignore imaginary part.*/ } } /* * Get Imag part of matrix from file, if it exists */ if (x.imagf) { if ((*pimag = (char *)malloc(mn) ) == NULL) { printf("\nLOADMAT error, not enough memory for imaginary part\n"); free(*preal); return(1); } if (fread(*pimag, 1, mn, fp) != mn) { free(*pimag); free(*preal); return(1); } } return(0); } /* loadmat() */