/** @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 (0-relative) * @param stride stride (1 reads consecutive elements) * @param edge Number of elements to read * @param copy_fields 1 to copy the fields, 0 to just set pointers to them. * @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->internal->num_fields; struct_slab->nbytes = edge*nfields*sizeof(matvar_t *); struct_slab->data = malloc(struct_slab->nbytes); struct_slab->dims[0] = edge; struct_slab->dims[1] = 1; fields = struct_slab->data; I = start*nfields; 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*nfields+field] = *((matvar_t **)matvar->data + I); I++; } } I += (stride-1)*nfields; } } return struct_slab; }
static void read_selected_data(mat_t *mat,matvar_t *matvar,char *index_str) { char *next_tok_pos, next_tok = 0; char *open = NULL, *close = NULL; int err, i = 0, j, done = 0; next_tok_pos = get_next_token(index_str); next_tok = *next_tok_pos; while ( !done ) { /* Check If the user is selecting a subset of the dataset */ if ( next_tok == '(' ) { int rank, *start, *stride, *edge,nmemb; open = next_tok_pos; close = strchr(open+1,')'); /* Get the next token after this selection */ next_tok_pos = get_next_token(close+1); if ( next_tok_pos != (close+1) ) { *next_tok_pos = '\0'; next_tok = *next_tok_pos; } else { done = 1; } /* Make sure that the partial I/O is the last token */ if ( !done ) { fprintf(stderr,"Partial I/O must be the last operation in " "the expression"); break; } /* Get the rank of the dataset */ rank = slab_get_rank(open,close); start = malloc(rank*sizeof(int)); stride = malloc(rank*sizeof(int)); edge = malloc(rank*sizeof(int)); for ( j = 0; j < rank; j++ ) { start[j] = 0; stride[j] = 1; edge[j] = 1; } /* Get the start,stride,edge using matlab syntax */ slab_get_select(open,close,rank,start,stride,edge); /* Check if the users selection is valid and if so read the data */ if ((nmemb = slab_select_valid(rank,start,stride,edge,matvar))) { matvar->data_size = Mat_SizeOfClass(matvar->class_type); matvar->nbytes = nmemb*matvar->data_size; if ( matvar->isComplex ) { mat_complex_split_t *z; matvar->data = malloc(sizeof(*z)); z = matvar->data; z->Re = malloc(matvar->nbytes); z->Im = malloc(matvar->nbytes); } else { matvar->data = malloc(matvar->nbytes); } if ( matvar->data == NULL ) { fprintf(stderr,"Couldn't allocate memory for the data"); err = 1; } else if ( rank == 1 ) { Mat_VarReadDataLinear(mat,matvar,matvar->data,*start, *stride,*edge); if (matvar->rank == 2 && matvar->dims[0] == 1) { matvar->dims[1] = *edge; } else if (matvar->rank == 2 && matvar->dims[1] == 1) { matvar->dims[0] = *edge; } else { matvar->rank = 2; matvar->dims[0] = *edge; matvar->dims[1] = 1; } } else { Mat_VarReadData(mat,matvar,matvar->data,start,stride,edge); for ( i = 0; i < rank; i++ ) matvar->dims[i] = (size_t)edge[i]; } } free(start); free(stride); free(edge); } else if ( next_tok == '.' ) { matvar_t *field; char *varname; if ( matvar->class_type == MAT_C_STRUCT ) { varname = next_tok_pos+1; next_tok_pos = get_next_token(next_tok_pos+1); if ( next_tok_pos != varname ) { next_tok = *next_tok_pos; *next_tok_pos = '\0'; } else { done = 1; } /* FIXME: Handle structures > 1x1 */ field = Mat_VarGetStructFieldByName(matvar, varname, 0); if ( field == NULL ) { fprintf(stderr,"field %s was not found in structure %s", varname,matvar->name); break; } field = Mat_VarDuplicate(field,1); Mat_VarFree(matvar); matvar = field; } else if ( matvar->class_type == MAT_C_CELL ) { int ncells; matvar_t *cell, **cells; ncells = matvar->nbytes / matvar->data_size; cells = matvar->data; varname = next_tok_pos+1; next_tok_pos = get_next_token(next_tok_pos+1); if ( next_tok_pos != varname ) { next_tok = *next_tok_pos; *next_tok_pos = '\0'; } else { done = 1; } for ( j = 0 ; j < ncells; j++ ) { cell = Mat_VarGetCell(matvar,j); if ( cell == NULL || cell->class_type != MAT_C_STRUCT ) { fprintf(stderr,"cell index %d is not a structure",j); break; } else { /* FIXME: Handle structures > 1x1 */ field = Mat_VarGetStructFieldByName(cell,varname,0); if ( field == NULL ) { fprintf(stderr,"field %s was not found in " "structure %s",varname,matvar->name); break; } field = Mat_VarDuplicate(field,1); Mat_VarFree(cell); cells[j] = field; } } if ( j != ncells ) break; } else { fprintf(stderr,"%s is not a structure", varname); break; } } else if ( next_tok == '{' ) { int rank, *start, *stride, *edge,nmemb, err = 0; if ( matvar->class_type != MAT_C_CELL ) { fprintf(stderr,"Only Cell Arrays can index with {}"); break; } open = next_tok_pos; close = strchr(open+1,'}'); /* Get the next token after this selection */ next_tok_pos = get_next_token(close+1); if ( *next_tok_pos != '\0' ) { next_tok = *next_tok_pos; *next_tok_pos = '\0'; } else { done = 1; } /* Get the rank of the dataset */ rank = slab_get_rank(open,close); start = malloc(rank*sizeof(int)); stride = malloc(rank*sizeof(int)); edge = malloc(rank*sizeof(int)); for ( j = 0; j < rank; j++ ) { start[j] = 0; stride[j] = 1; edge[j] = 1; } /* Get the start,stride,edge using matlab syntax */ slab_get_select(open,close,rank,start,stride,edge); /* Check if the users selection is valid and if so read the data */ if ((nmemb = slab_select_valid(rank,start,stride,edge,matvar))) { matvar_t **cells, *tmp; if ( rank == 1 ) { cells = Mat_VarGetCellsLinear(matvar,*start, *stride,*edge); if (matvar->rank == 2 && matvar->dims[0] == 1) { matvar->dims[1] = *edge; } else if (matvar->rank == 2 && matvar->dims[1] == 1) { matvar->dims[0] = *edge; } else { matvar->rank = 1; matvar->dims[0] = *edge; } } else { cells = Mat_VarGetCells(matvar,start,stride,edge); memcpy(matvar->dims,edge,matvar->rank*sizeof(int)); } if ( cells == NULL ) { fprintf(stderr,"Error getting the indexed cells"); err = 1; } else { for ( j = 0; j < nmemb; j++ ) cells[j] = Mat_VarDuplicate(cells[j],1); tmp = Mat_VarCreate(matvar->name,MAT_C_CELL, MAT_T_CELL,matvar->rank,matvar->dims,cells, MAT_F_DONT_COPY_DATA); Mat_VarFree(matvar); matvar = tmp; } } else { fprintf(stderr,"Cell selection not valid"); err = 1; } free(start); free(stride); free(edge); if ( err ) break; } } }
/** @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. The structures have a flag set * so that the structure fields are not freed. * * Note that this function is limited to structure arrays with a rank less than * 10. * * @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. * @returns A new structure array with fields indexed from @c matvar. */ matvar_t * Mat_VarGetStructs(matvar_t *matvar,int *start,int *stride,int *edge, int copy_fields) { size_t i,j,N,I,nfields,field,idx[10] = {0,},cnt[10] = {0,},dimp[10] = {0,}; matvar_t **fields, *struct_slab; if ( (matvar == NULL) || (start == NULL) || (stride == NULL) || (edge == NULL) ) { return NULL; } else if ( matvar->rank > 9 ) { 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->internal->num_fields; dimp[0] = matvar->dims[0]; N = edge[0]; I = start[0]; struct_slab->dims[0] = edge[0]; idx[0] = start[0]; for ( i = 1; i < matvar->rank; i++ ) { idx[i] = start[i]; dimp[i] = dimp[i-1]*matvar->dims[i]; N *= edge[i]; I += start[i]*dimp[i-1]; struct_slab->dims[i] = edge[i]; } I *= 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++; } if ( stride != 0 ) I += (stride[0]-1)*nfields; } idx[0] = start[0]; I = idx[0]; cnt[1]++; idx[1] += stride[1]; for ( j = 1; j < matvar->rank; j++ ) { if ( cnt[j] == edge[j] ) { cnt[j] = 0; idx[j] = start[j]; cnt[j+1]++; idx[j+1] += stride[j+1]; } I += idx[j]*dimp[j-1]; } I *= nfields; } return struct_slab; }