/** @file mat5.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 "matio_private.h"
static const char *class_type_desc[16] = {"Undefined","Cell Array","Structure",
"Object","Character Array","Sparse Array","Double Precision Array",
"Single Precision Array", "8-bit, signed Integer Array",
"8-bit, Unsigned Integer Array","16-bit, signed Integer Array",
"16-bit, unsigned Integer Array","32-bit, signed Integer Array",
"32-bit, unsigned Integer Array","Matlab Array","Compressed Data"};
static const char *data_type_desc[23] = {"Unknown","8-bit, signed integer",
"8-bit, unsigned integer","16-bit, signed integer",
"16-bit, unsigned integer","32-bit, signed integer",
"32-bit, unsigned integer","IEEE 754 single-precision","RESERVED",
"IEEE 754 double-precision","RESERVED","RESERVED",
"64-bit, signed integer","64-bit, unsigned integer", "Matlab Array",
"Compressed Data","Unicode UTF-8 Encoded Character Data",
"Unicode UTF-16 Encoded Character Data",
"Unicode UTF-32 Encoded Character Data","","String","Cell Array",
"Structure"};
/*
* -------------------------------------------------------------
* Private Functions
* -------------------------------------------------------------
*/
static size_t GetMatrixMaxBufSize(matvar_t *matvar);
static size_t GetStructFieldBufSize(matvar_t *matvar);
static size_t GetCellArrayFieldBufSize(matvar_t *matvar);
/** @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,len;
size_t tag_size = 8, array_flags_size = 8;
int nmemb = 1, i;
if ( matvar == NULL )
return nBytes;
/* Have to account for the matrix tag in a struct field */
nBytes += tag_size;
/* 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;
/* Add rank and dimensions, padded to an 8 byte block */
for ( i = 0, len = 0; i < matvar->rank; i++ )
nmemb *= matvar->dims[i];
if ( matvar->rank % 2 )
nBytes += tag_size + matvar->rank*4 + 4;
else
nBytes += tag_size + matvar->rank*4;
if ( matvar->class_type == MAT_C_STRUCT ) {
matvar_t **fields = matvar->data;
int i, nfields;
size_t maxlen = 0;
nfields = matvar->nbytes / (nmemb*matvar->data_size);
for ( i = 0; i < nfields; i++ ) {
if ( NULL != fields[i]->name && strlen(fields[i]->name) > maxlen )
maxlen = strlen(fields[i]->name);
}
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 ) {
for ( i = 0; i < nfields*nmemb; i++ )
nBytes += GetStructFieldBufSize(fields[i]);
}
} else if ( matvar->class_type == MAT_C_CELL ) {
matvar_t **cells = matvar->data;
int i, ncells = matvar->nbytes / matvar->data_size;
if ( NULL != cells && ncells > 0 ) {
for ( i = 0; i < ncells; i++ )
nBytes += GetCellArrayFieldBufSize(cells[i]);
}
} else if ( matvar->class_type == MAT_C_SPARSE ) {
sparse_t *sparse = matvar->data;
nBytes += tag_size + sparse->njc*sizeof(mat_int32_t) +
tag_size + sparse->nir*sizeof(mat_int32_t) +
tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
if ( matvar->isComplex )
nBytes += tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
} else {
nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
if (nmemb*Mat_SizeOf(matvar->data_type) % 8) {
nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
}
if ( matvar->isComplex ) {
nBytes += tag_size + nmemb*Mat_SizeOf(matvar->data_type);
if (nmemb*Mat_SizeOf(matvar->data_type) % 8) {
nBytes += (8 - (nmemb*Mat_SizeOf(matvar->data_type) % 8));
}
}
}
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,len;
size_t tag_size = 8, array_flags_size = 8;
int nmemb = 1, i;
if ( matvar == NULL )
return nBytes;
/* Have to account for the matrix tag in a struct field */
nBytes += tag_size;
/* 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;
}
/* Add rank and dimensions, padded to an 8 byte block */
for ( i = 0, len = 0; i < matvar->rank; i++ )
nmemb *= matvar->dims[i];
if ( matvar->rank % 2 )
nBytes += tag_size + matvar->rank*4 + 4;
else
nBytes += tag_size + matvar->rank*4;
if ( matvar->class_type == MAT_C_STRUCT ) {
matvar_t **fields = matvar->data;
int i, nfields;
size_t maxlen = 0;
nfields = matvar->nbytes / (nmemb*matvar->data_size);
for ( i = 0; i < nfields; i++ ) {
if ( NULL != fields[i]->name && strlen(fields[i]->name) > maxlen )
maxlen = strlen(fields[i]->name);
}
maxlen++;
while ( nfields*maxlen % 8 != 0 )
maxlen++;
nBytes += tag_size + tag_size + maxlen*nfields;
if ( NULL != fields && nfields > 0 ) {
for ( i = 0; i < nfields*nmemb; i++ )
nBytes += GetStructFieldBufSize(fields[i]);
}
} else if ( matvar->class_type == MAT_C_CELL ) {
matvar_t **cells = matvar->data;
int i, ncells = matvar->nbytes / matvar->data_size;
if ( NULL != cells && ncells > 0 ) {
for ( i = 0; i < ncells; i++ )
nBytes += GetCellArrayFieldBufSize(cells[i]);
}
} else if ( matvar->class_type == MAT_C_SPARSE ) {
sparse_t *sparse = matvar->data;
nBytes += tag_size + sparse->njc*sizeof(mat_int32_t) +
tag_size + sparse->nir*sizeof(mat_int32_t) +
tag_size + sparse->ndata*Mat_SizeOf(matvar->data_type);
if ( matvar->isComplex )
评论2