"Fossies" - the Fresh Open Source Software Archive

Member "grace-5.1.25/src/ssdata.c" (14 Feb 2015, 15620 Bytes) of package /linux/misc/grace-5.1.25.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ssdata.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.1.24_vs_5.1.25.

    1 /*
    2  * Grace - GRaphing, Advanced Computation and Exploration of data
    3  * 
    4  * Home page: http://plasma-gate.weizmann.ac.il/Grace/
    5  * 
    6  * Copyright (c) 1991-1995 Paul J Turner, Portland, OR
    7  * Copyright (c) 1996-2002 Grace Development Team
    8  * 
    9  * Maintained by Evgeny Stambulchik
   10  * 
   11  * 
   12  *                           All Rights Reserved
   13  * 
   14  *    This program is free software; you can redistribute it and/or modify
   15  *    it under the terms of the GNU General Public License as published by
   16  *    the Free Software Foundation; either version 2 of the License, or
   17  *    (at your option) any later version.
   18  * 
   19  *    This program is distributed in the hope that it will be useful,
   20  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
   21  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22  *    GNU General Public License for more details.
   23  * 
   24  *    You should have received a copy of the GNU General Public License
   25  *    along with this program; if not, write to the Free Software
   26  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   27  */
   28 
   29 /*
   30  *
   31  * spreadsheet data stuff
   32  *
   33  */
   34 
   35 #include <config.h>
   36 
   37 #include <stdio.h>
   38 #include <stdlib.h>
   39 #include <string.h>
   40 
   41 #include "defines.h"
   42 #include "globals.h"
   43 #include "utils.h"
   44 #include "graphs.h"
   45 #include "graphutils.h"
   46 #include "files.h"
   47 #include "ssdata.h"
   48 #include "parser.h"
   49 
   50 #include "protos.h"
   51 
   52 double *copy_data_column(double *src, int nrows)
   53 {
   54     double *dest;
   55     
   56     dest = xmalloc(nrows*SIZEOF_DOUBLE);
   57     if (dest != NULL) {
   58         memcpy(dest, src, nrows*SIZEOF_DOUBLE);
   59     }
   60     return dest;
   61 }
   62 
   63 char **copy_string_column(char **src, int nrows)
   64 {
   65     char **dest;
   66     int i;
   67 
   68     dest = xmalloc(nrows*sizeof(char *));
   69     if (dest != NULL) {
   70         for (i = 0; i < nrows; i++)
   71             dest[i] =copy_string(NULL, src[i]);
   72     }
   73     return dest;
   74 }
   75 
   76 /* TODO: index_shift */
   77 double *allocate_index_data(int nrows)
   78 {
   79     int i;
   80     double *retval;
   81     
   82     retval = xmalloc(nrows*SIZEOF_DOUBLE);
   83     if (retval != NULL) {
   84         for (i = 0; i < nrows; i++) {
   85             retval[i] = i;
   86         }
   87     }
   88     return retval;
   89 }
   90 
   91 double *allocate_mesh(double start, double stop, int len)
   92 {
   93     int i;
   94     double *retval;
   95     
   96     retval = xmalloc(len*SIZEOF_DOUBLE);
   97     if (retval != NULL) {
   98         double s = (start + stop)/2, d = (stop - start)/2;
   99         for (i = 0; i < len; i++) {
  100             retval[i] = s + d*((double) (2*i + 1 - len)/(len - 1));
  101         }
  102     }
  103     return retval;
  104 }
  105 
  106 static ss_data blockdata = {0, 0, NULL, NULL};
  107 
  108 void set_blockdata(ss_data *ssd)
  109 {
  110     free_ss_data(&blockdata);
  111     if (ssd) {
  112         memcpy(&blockdata, ssd, sizeof(ss_data));
  113     }
  114 }
  115 
  116 int get_blockncols(void)
  117 {
  118     return blockdata.ncols;
  119 }
  120 
  121 int get_blocknrows(void)
  122 {
  123     return blockdata.nrows;
  124 }
  125 
  126 int *get_blockformats(void)
  127 {
  128     return blockdata.formats;
  129 }
  130 
  131 int realloc_ss_data(ss_data *ssd, int nrows)
  132 {
  133     int i, j;
  134     char  **sp;
  135     
  136     for (i = 0; i < ssd->ncols; i++) {
  137         if (ssd->formats[i] == FFORMAT_STRING) {
  138             sp = (char **) ssd->data[i];
  139             for (j = nrows; j < ssd->nrows; j++) {
  140                 XCFREE(sp[j]);
  141             }
  142             ssd->data[i] = xrealloc(ssd->data[i], nrows*sizeof(char *));
  143             sp = (char **) ssd->data[i];
  144             for (j = ssd->nrows; j < nrows; j++) {
  145                 sp[j] = NULL;
  146             }
  147         } else {
  148             ssd->data[i] = xrealloc(ssd->data[i], nrows*SIZEOF_DOUBLE);
  149         }
  150     }
  151     ssd->nrows = nrows;
  152     
  153     return RETURN_SUCCESS;
  154 }
  155 
  156 void free_ss_data(ss_data *ssd)
  157 {
  158     if (ssd) {
  159         int i, j;
  160         char  **sp;
  161 
  162         for (i = 0; i < ssd->ncols; i++) {
  163             if (ssd->formats && ssd->formats[i] == FFORMAT_STRING) {
  164                 sp = (char **) ssd->data[i];
  165                 for (j = 0; j < ssd->nrows; j++) {
  166                     XCFREE(sp[j]);
  167                 }
  168             }
  169             XCFREE(ssd->data[i]);
  170         }
  171         XCFREE(ssd->data);
  172         XCFREE(ssd->formats);
  173         ssd->nrows = 0;
  174         ssd->ncols = 0;
  175     }
  176 }
  177 
  178 int init_ss_data(ss_data *ssd, int ncols, int *formats)
  179 {
  180     int i;
  181     
  182     ssd->data = xmalloc(ncols*SIZEOF_VOID_P);
  183     for (i = 0; i < ncols; i++) {
  184         ssd->data[i] = NULL;
  185     }
  186     ssd->formats = xmalloc(ncols*SIZEOF_INT);
  187     memcpy(ssd->formats, formats, ncols*SIZEOF_INT);
  188     ssd->ncols = ncols;
  189     ssd->nrows = 0;
  190 
  191     return RETURN_SUCCESS;
  192 }
  193 
  194 static char *next_token(char *s, char **token, int *quoted)
  195 {
  196     *quoted = FALSE;
  197     *token = NULL;
  198     
  199     if (s == NULL) {
  200         return NULL;
  201     }
  202     
  203     while (*s == ' ' || *s == '\t') {
  204         s++;
  205     }
  206     if (*s == '"') {
  207         s++;
  208         *token = s;
  209         while (*s != '\0' && (*s != '"' || (*s == '"' && *(s - 1) == '\\'))) {
  210             s++;
  211         }
  212         if (*s == '"') {
  213             /* successfully identified a quoted string */
  214             *quoted = TRUE;
  215         }
  216     } else {
  217         *token = s;
  218         if (**token == '\n') {
  219             /* EOL reached */
  220             return NULL;
  221         }
  222         while (*s != '\n' && *s != '\0' && *s != ' ' && *s != '\t') {
  223             s++;
  224         }
  225     }
  226     
  227     if (*s != '\0') {
  228         *s = '\0';
  229         s++;
  230         return s;
  231     } else {
  232         return NULL;
  233     }
  234 }
  235 
  236 int parse_ss_row(const char *s, int *nncols, int *nscols, int **formats)
  237 {
  238     int ncols;
  239     int quoted;
  240     char *buf, *s1, *token;
  241     double value;
  242     Dates_format df_pref, ddummy;
  243     const char *sdummy;
  244 
  245     *nscols = 0;
  246     *nncols = 0;
  247     *formats = NULL;
  248     df_pref = get_date_hint();
  249     buf = copy_string(NULL, s);
  250     s1 = buf;
  251     while ((s1 = next_token(s1, &token, &quoted)) != NULL) {
  252         if (token == NULL) {
  253             *nscols = 0;
  254             *nncols = 0;
  255             XCFREE(*formats);
  256             xfree(buf);
  257             return RETURN_FAILURE;
  258         }
  259         
  260         ncols = *nncols + *nscols;
  261         /* reallocate the formats array */
  262         if (ncols % 10 == 0) {
  263             *formats = xrealloc(*formats, (ncols + 10)*SIZEOF_INT);
  264         }
  265 
  266         if (quoted) {
  267             (*formats)[ncols] = FFORMAT_STRING;
  268             (*nscols)++;
  269         } else if (parse_date(token, df_pref, FALSE, &value, &ddummy) ==
  270             RETURN_SUCCESS) {
  271             (*formats)[ncols] = FFORMAT_DATE;
  272             (*nncols)++;
  273         } else if (parse_float(token, &value, &sdummy) == RETURN_SUCCESS) {
  274             (*formats)[ncols] = FFORMAT_NUMBER;
  275             (*nncols)++;
  276         } else {
  277             /* last resort - treat the field as string, even if not quoted */
  278             (*formats)[ncols] = FFORMAT_STRING;
  279             (*nscols)++;
  280         }
  281     }
  282     xfree(buf);
  283     
  284     return RETURN_SUCCESS;
  285 }
  286 
  287 
  288 /* NOTE: the input string will be corrupted! */
  289 int insert_data_row(ss_data *ssd, int row, char *s)
  290 {
  291     int i, j;
  292     int ncols = ssd->ncols;
  293     char *token;
  294     int quoted;
  295     char  **sp;
  296     double *np;
  297     Dates_format df_pref, ddummy;
  298     const char *sdummy;
  299     int res;
  300     
  301     df_pref = get_date_hint();
  302     for (i = 0; i < ncols; i++) {
  303         s = next_token(s, &token, &quoted);
  304         if (s == NULL || token == NULL) {
  305             /* invalid line: free the already allocated string fields */
  306             for (j = 0; j < i; j++) {
  307                 if (ssd->formats[j] == FFORMAT_STRING) {
  308                     sp = (char **) ssd->data[j];
  309                     XCFREE(sp[row]);
  310                 }
  311             }
  312             return RETURN_FAILURE;
  313         } else {
  314             if (ssd->formats[i] == FFORMAT_STRING) {
  315                 sp = (char **) ssd->data[i];
  316                 sp[row] = copy_string(NULL, token);
  317                 if (sp[row] != NULL) {
  318                     res = RETURN_SUCCESS;
  319                 } else {
  320                     res = RETURN_FAILURE;
  321                 }
  322             } else if (ssd->formats[i] == FFORMAT_DATE) {
  323                 np = (double *) ssd->data[i];
  324                 res = parse_date(token, df_pref, FALSE, &np[row], &ddummy);
  325             } else {
  326                 np = (double *) ssd->data[i];
  327                 res = parse_float(token, &np[row], &sdummy);
  328             }
  329             if (res != RETURN_SUCCESS) {
  330                 for (j = 0; j < i; j++) {
  331                     if (ssd->formats[j] == FFORMAT_STRING) {
  332                         sp = (char **) ssd->data[j];
  333                         XCFREE(sp[row]);
  334                     }
  335                 }
  336                 return RETURN_FAILURE;
  337             }
  338         }
  339     }
  340     
  341     return RETURN_SUCCESS;
  342 }
  343 
  344 
  345 int store_data(ss_data *ssd, int load_type, char *label)
  346 {
  347     int ncols, nncols, nncols_req, nscols, nrows;
  348     int i, j;
  349     double *xdata;
  350     int gno, setno;
  351     int x_from_index;
  352     
  353     if (ssd == NULL) {
  354         return RETURN_FAILURE;
  355     }
  356     ncols = ssd->ncols;
  357     nrows = ssd->nrows;
  358     if (ncols <= 0 || nrows <= 0) {
  359         return RETURN_FAILURE;
  360     }
  361 
  362     nncols = 0;
  363     for (j = 0; j < ncols; j++) {
  364         if (ssd->formats[j] != FFORMAT_STRING) {
  365             nncols++;
  366         }
  367     }
  368     nscols = ncols - nncols;
  369     
  370     gno = get_parser_gno();
  371     if (is_valid_gno(gno) != TRUE) {
  372         return RETURN_FAILURE;
  373     }
  374     
  375     switch (load_type) {
  376     case LOAD_SINGLE:
  377         if (nscols > 1) {
  378             errmsg("Can not use more than one column of strings per set");
  379             free_ss_data(ssd);
  380             return RETURN_FAILURE;
  381         }
  382 
  383         nncols_req = settype_cols(curtype);
  384         x_from_index = FALSE;
  385         if (nncols_req == nncols + 1) {
  386             x_from_index = TRUE;
  387         } else if (nncols_req != nncols) {
  388         errmsg("Column count incorrect");
  389         return RETURN_FAILURE;
  390         }
  391 
  392         setno = nextset(gno);
  393         set_dataset_type(gno, setno, curtype);
  394 
  395         nncols = 0;
  396         if (x_from_index) {
  397             xdata = allocate_index_data(nrows);
  398             if (xdata == NULL) {
  399                 free_ss_data(ssd);
  400             }
  401             setcol(gno, setno, nncols, xdata, nrows);
  402             nncols++;
  403         }
  404         for (j = 0; j < ncols; j++) {
  405             if (ssd->formats[j] == FFORMAT_STRING) {
  406                 set_set_strings(gno, setno, nrows, (char **) ssd->data[j]);
  407             } else {
  408                 setcol(gno, setno, nncols, (double *) ssd->data[j], nrows);
  409                 nncols++;
  410             }
  411         }
  412         if (!strlen(getcomment(gno, setno))) {
  413             setcomment(gno, setno, label);
  414         }
  415         
  416         XCFREE(ssd->data);
  417         XCFREE(ssd->formats);
  418         break;
  419     case LOAD_NXY:
  420         if (nscols != 0) {
  421             errmsg("Can not yet use strings when reading in data as NXY");
  422             free_ss_data(ssd);
  423             return RETURN_FAILURE;
  424         }
  425         
  426         for (i = 0; i < ncols - 1; i++) {
  427             setno = nextset(gno);
  428             if (setno == -1) {
  429                 free_ss_data(ssd);
  430                 return RETURN_FAILURE;
  431             }
  432             if (i > 0) {
  433                 xdata = copy_data_column((double *) ssd->data[0], nrows);
  434                 if (xdata == NULL) {
  435                     free_ss_data(ssd);
  436                 }
  437             } else {
  438                 xdata = (double *) ssd->data[0];
  439             }
  440             set_dataset_type(gno, setno, SET_XY);
  441             setcol(gno, setno, DATA_X, xdata, nrows);
  442             setcol(gno, setno, DATA_Y, (double *) ssd->data[i + 1], nrows);
  443             setcomment(gno, setno, label);
  444         }
  445     
  446         XCFREE(ssd->data);
  447         XCFREE(ssd->formats);
  448         break;
  449     case LOAD_BLOCK:
  450         set_blockdata(ssd);
  451         break;
  452     default:
  453         errmsg("Internal error");
  454         free_ss_data(ssd);
  455         return RETURN_FAILURE;
  456     }
  457     
  458     return RETURN_SUCCESS;
  459 }
  460 
  461 int field_string_to_cols(const char *fs, int *nc, int **cols, int *scol)
  462 {
  463     int col;
  464     char *s, *buf;
  465 
  466     buf = copy_string(NULL, fs);
  467     if (buf == NULL) {
  468         return RETURN_FAILURE;
  469     }
  470 
  471     s = buf;
  472     *nc = 0;
  473     while ((s = strtok(s, ":")) != NULL) {
  474     (*nc)++;
  475     s = NULL;
  476     }
  477     *cols = xmalloc((*nc)*SIZEOF_INT);
  478     if (*cols == NULL) {
  479         xfree(buf);
  480         return RETURN_FAILURE;
  481     }
  482 
  483     strcpy(buf, fs);
  484     s = buf;
  485     *nc = 0;
  486     *scol = -1;
  487     while ((s = strtok(s, ":")) != NULL) {
  488         int strcol;
  489         if (*s == '{') {
  490             char *s1;
  491             strcol = TRUE;
  492             s++;
  493             if ((s1 = strchr(s, '}')) != NULL) {
  494                 *s1 = '\0';
  495             }
  496         } else {
  497             strcol = FALSE;
  498         }
  499         col = atoi(s);
  500         col--;
  501         if (strcol) {
  502             *scol = col;
  503         } else {
  504             (*cols)[*nc] = col;
  505         (*nc)++;
  506         }
  507     s = NULL;
  508     }
  509     
  510     xfree(buf);
  511     
  512     return RETURN_SUCCESS;
  513 }
  514 
  515 char *cols_to_field_string(int nc, int *cols, int scol)
  516 {
  517     int i;
  518     char *s, buf[32];
  519     
  520     s = NULL;
  521     for (i = 0; i < nc; i++) {
  522         sprintf(buf, "%d", cols[i] + 1);
  523         if (i != 0) {
  524             s = concat_strings(s, ":");
  525         }
  526         s = concat_strings(s, buf);
  527     }
  528     if (scol >= 0) {
  529         sprintf(buf, ":{%d}", scol + 1);
  530         s = concat_strings(s, buf);
  531     }
  532     
  533     return s;
  534 }
  535 
  536 int create_set_fromblock(int gno, int setno,
  537     int type, int nc, int *coli, int scol, int autoscale)
  538 {
  539     int i, ncols, blockncols, blocklen, column;
  540     double *cdata;
  541     char buf[256], *s;
  542 
  543     blockncols = get_blockncols();
  544     if (blockncols <= 0) {
  545         errmsg("No block data read");
  546         return RETURN_FAILURE;
  547     }
  548 
  549     blocklen = get_blocknrows();
  550     
  551     ncols = settype_cols(type);
  552     if (nc > ncols) {
  553         errmsg("Too many columns scanned in column string");
  554         return RETURN_FAILURE;
  555     }
  556     if (nc < ncols) {
  557     errmsg("Too few columns scanned in column string");
  558     return RETURN_FAILURE;
  559     }
  560     
  561     for (i = 0; i < nc; i++) {
  562     if (coli[i] < -1 || coli[i] >= blockncols) {
  563         errmsg("Column index out of range");
  564         return RETURN_FAILURE;
  565     }
  566     }
  567     
  568     if (scol >= blockncols) {
  569     errmsg("String column index out of range");
  570     return RETURN_FAILURE;
  571     }
  572     
  573     if (setno == NEW_SET) {
  574         setno = nextset(gno);
  575         if (setno == -1) {
  576             return RETURN_FAILURE;
  577         }
  578     }
  579     
  580     /* clear data stored in the set, if any */
  581     killsetdata(gno, setno);
  582     
  583     if (activateset(gno, setno) != RETURN_SUCCESS) {
  584         return RETURN_FAILURE;
  585     }
  586     
  587     set_dataset_type(gno, setno, type);
  588 
  589     for (i = 0; i < nc; i++) {
  590         column = coli[i];
  591         if (column == -1) {
  592             cdata = allocate_index_data(blocklen);
  593         } else {
  594             if (blockdata.formats[column] != FFORMAT_STRING) {
  595                 cdata = copy_data_column((double *) blockdata.data[column], blocklen);
  596             } else {
  597                 errmsg("Tried to read doubles from strings!");
  598                 killsetdata(gno, setno);
  599                 return RETURN_FAILURE;
  600             }
  601         }
  602         if (cdata == NULL) {
  603             killsetdata(gno, setno);
  604             return RETURN_FAILURE;
  605         }
  606         setcol(gno, setno, i, cdata, blocklen);
  607     }
  608 
  609     /* strings, if any */
  610     if (scol >= 0) {
  611         if (blockdata.formats[scol] != FFORMAT_STRING) {
  612             errmsg("Tried to read strings from doubles!");
  613             killsetdata(gno, setno);
  614             return RETURN_FAILURE;
  615         } else {
  616             set_set_strings(gno, setno, blocklen,
  617                 copy_string_column((char **) blockdata.data[scol], blocklen));
  618         }
  619     }
  620 
  621     s = cols_to_field_string(nc, coli, scol);
  622     sprintf(buf, "Cols %s", s);
  623     xfree(s);
  624     setcomment(gno, setno, buf);
  625 
  626     autoscale_graph(gno, autoscale);
  627 
  628     return RETURN_SUCCESS;
  629 }