/** @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;
}
Exemple #2
0
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;
}