2
* Grace - GRaphing, Advanced Computation and Exploration of data
4
* Home page: http://plasma-gate.weizmann.ac.il/Grace/
6
* Copyright (c) 1991-1995 Paul J Turner, Portland, OR
7
* Copyright (c) 1996-2000 Grace Development Team
9
* Maintained by Evgeny Stambulchik <fnevgeny@plasma-gate.weizmann.ac.il>
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.
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.
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.
31
* spreadsheet data stuff
45
#include "graphutils.h"
52
double *copy_data_column(double *src, int nrows)
56
dest = xmalloc(nrows*SIZEOF_DOUBLE);
58
memcpy(dest, src, nrows*SIZEOF_DOUBLE);
63
char **copy_string_column(char **src, int nrows)
68
dest = xmalloc(nrows*sizeof(char *));
70
for (i = 0; i < nrows; i++)
71
dest[i] =copy_string(NULL, src[i]);
76
/* TODO: index_shift */
77
double *allocate_index_data(int nrows)
82
retval = xmalloc(nrows*SIZEOF_DOUBLE);
84
for (i = 0; i < nrows; i++) {
91
double *allocate_mesh(double start, double stop, int len)
96
retval = xmalloc(len*SIZEOF_DOUBLE);
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));
106
static ss_data blockdata = {0, 0, NULL, NULL};
108
void set_blockdata(ss_data *ssd)
110
free_ss_data(&blockdata);
111
memcpy(&blockdata, ssd, sizeof(ss_data));
114
int get_blockncols(void)
116
return blockdata.ncols;
119
int get_blocknrows(void)
121
return blockdata.nrows;
124
int *get_blockformats(void)
126
return blockdata.formats;
129
int realloc_ss_data(ss_data *ssd, int nrows)
134
for (i = 0; i < ssd->ncols; i++) {
135
if (ssd->formats[i] == FFORMAT_STRING) {
136
sp = (char **) ssd->data[i];
137
for (j = nrows; j < ssd->nrows; j++) {
140
ssd->data[i] = xrealloc(ssd->data[i], nrows*sizeof(char *));
141
sp = (char **) ssd->data[i];
142
for (j = ssd->nrows; j < nrows; j++) {
146
ssd->data[i] = xrealloc(ssd->data[i], nrows*SIZEOF_DOUBLE);
151
return RETURN_SUCCESS;
154
void free_ss_data(ss_data *ssd)
159
for (i = 0; i < ssd->ncols; i++) {
160
if (ssd->formats[i] == FFORMAT_STRING) {
161
sp = (char **) ssd->data[i];
162
for (j = 0; j < ssd->nrows; j++) {
166
XCFREE(ssd->data[i]);
169
XCFREE(ssd->formats);
174
int init_ss_data(ss_data *ssd, int ncols, int *formats)
178
ssd->data = xmalloc(ncols*SIZEOF_VOID_P);
179
for (i = 0; i < ncols; i++) {
182
ssd->formats = formats;
186
return RETURN_SUCCESS;
189
static char *next_token(char *s, char **token, int *quoted)
198
while (*s == ' ' || *s == '\t') {
204
while (*s != '\0' && (*s != '"' || (*s == '"' && *(s - 1) == '\\'))) {
208
/* successfully identified a quoted string */
213
if (**token == '\n') {
217
while (*s != '\n' && *s != '\0' && *s != ' ' && *s != '\t') {
231
int parse_ss_row(const char *s, int *nncols, int *nscols, int **formats)
235
char *buf, *s1, *token;
237
Dates_format df_pref, ddummy;
243
df_pref = get_date_hint();
244
buf = copy_string(NULL, s);
246
while ((s1 = next_token(s1, &token, "ed)) != NULL) {
252
return RETURN_FAILURE;
255
ncols = *nncols + *nscols;
256
/* reallocate the formats array */
257
if (ncols % 10 == 0) {
258
*formats = xrealloc(*formats, (ncols + 10)*SIZEOF_INT);
262
(*formats)[ncols] = FFORMAT_STRING;
264
} else if (parse_date(token, df_pref, FALSE, &value, &ddummy) ==
266
(*formats)[ncols] = FFORMAT_DATE;
268
} else if (parse_float(token, &value, &sdummy) == RETURN_SUCCESS) {
269
(*formats)[ncols] = FFORMAT_NUMBER;
272
/* last resort - treat the field as string, even if not quoted */
273
(*formats)[ncols] = FFORMAT_STRING;
279
return RETURN_SUCCESS;
283
/* NOTE: the input string will be corrupted! */
284
int insert_data_row(ss_data *ssd, int row, char *s)
287
int ncols = ssd->ncols;
292
Dates_format df_pref, ddummy;
296
df_pref = get_date_hint();
297
for (i = 0; i < ncols; i++) {
298
s = next_token(s, &token, "ed);
299
if (s == NULL || token == NULL) {
300
/* invalid line: free the already allocated string fields */
301
for (j = 0; j < i; j++) {
302
if (ssd->formats[j] == FFORMAT_STRING) {
303
sp = (char **) ssd->data[j];
307
return RETURN_FAILURE;
309
if (ssd->formats[i] == FFORMAT_STRING) {
310
sp = (char **) ssd->data[i];
311
sp[row] = copy_string(NULL, token);
312
if (sp[row] != NULL) {
313
res = RETURN_SUCCESS;
315
res = RETURN_FAILURE;
317
} else if (ssd->formats[i] == FFORMAT_DATE) {
318
np = (double *) ssd->data[i];
319
res = parse_date(token, df_pref, FALSE, &np[row], &ddummy);
321
np = (double *) ssd->data[i];
322
res = parse_float(token, &np[row], &sdummy);
324
if (res != RETURN_SUCCESS) {
325
for (j = 0; j < i; j++) {
326
if (ssd->formats[j] == FFORMAT_STRING) {
327
sp = (char **) ssd->data[j];
331
return RETURN_FAILURE;
336
return RETURN_SUCCESS;
340
int store_data(ss_data *ssd, int load_type, char *label)
342
int ncols, nncols, nncols_req, nscols, nrows;
349
return RETURN_FAILURE;
353
if (ncols <= 0 || nrows <= 0) {
354
return RETURN_FAILURE;
358
for (j = 0; j < ncols; j++) {
359
if (ssd->formats[j] != FFORMAT_STRING) {
363
nscols = ncols - nncols;
365
gno = get_parser_gno();
366
if (is_valid_gno(gno) != TRUE) {
367
return RETURN_FAILURE;
372
if (nncols > MAX_SET_COLS || nscols > 1) {
373
errmsg("Internal error");
375
return RETURN_FAILURE;
378
nncols_req = settype_cols(curtype);
379
x_from_index = FALSE;
380
if (nncols_req == nncols + 1) {
382
} else if (nncols_req != nncols) {
383
errmsg("Column count incorrect");
384
return RETURN_FAILURE;
387
setno = nextset(gno);
388
set_dataset_type(gno, setno, curtype);
392
xdata = allocate_index_data(nrows);
396
setcol(gno, setno, nncols, xdata, nrows);
399
for (j = 0; j < ncols; j++) {
400
if (ssd->formats[j] == FFORMAT_STRING) {
401
set_set_strings(gno, setno, nrows, (char **) ssd->data[j]);
403
setcol(gno, setno, nncols, (double *) ssd->data[j], nrows);
407
if (!strlen(getcomment(gno, setno))) {
408
setcomment(gno, setno, label);
415
errmsg("Can not yet use strings when reading in data as NXY");
417
return RETURN_FAILURE;
420
for (i = 0; i < ncols - 1; i++) {
421
setno = nextset(gno);
424
return RETURN_FAILURE;
427
xdata = copy_data_column((double *) ssd->data[0], nrows);
432
xdata = (double *) ssd->data[0];
434
set_dataset_type(gno, setno, SET_XY);
435
setcol(gno, setno, DATA_X, xdata, nrows);
436
setcol(gno, setno, DATA_Y, (double *) ssd->data[i + 1], nrows);
437
setcomment(gno, setno, label);
446
errmsg("Internal error");
448
return RETURN_FAILURE;
451
return RETURN_SUCCESS;
454
int field_string_to_cols(const char *fs, int *nc, int **cols, int *scol)
459
buf = copy_string(NULL, fs);
461
return RETURN_FAILURE;
466
while ((s = strtok(s, ":")) != NULL) {
470
*cols = xmalloc((*nc)*SIZEOF_INT);
473
return RETURN_FAILURE;
480
while ((s = strtok(s, ":")) != NULL) {
486
if ((s1 = index(s, '}')) != NULL) {
505
return RETURN_SUCCESS;
508
char *cols_to_field_string(int nc, int *cols, int scol)
514
for (i = 0; i < nc; i++) {
515
sprintf(buf, "%d", cols[i] + 1);
517
s = concat_strings(s, ":");
519
s = concat_strings(s, buf);
522
sprintf(buf, ":{%d}", scol + 1);
523
s = concat_strings(s, buf);
529
int create_set_fromblock(int gno, int setno,
530
int type, int nc, int *coli, int scol, int autoscale)
532
int i, ncols, blockncols, blocklen, column;
536
blockncols = get_blockncols();
537
if (blockncols <= 0) {
538
errmsg("No block data read");
539
return RETURN_FAILURE;
542
blocklen = get_blocknrows();
544
ncols = settype_cols(type);
546
errmsg("Too many columns scanned in column string");
547
return RETURN_FAILURE;
550
errmsg("Too few columns scanned in column string");
551
return RETURN_FAILURE;
554
for (i = 0; i < nc; i++) {
555
if (coli[i] < -1 || coli[i] >= blockncols) {
556
errmsg("Column index out of range");
557
return RETURN_FAILURE;
561
if (scol >= blockncols) {
562
errmsg("String column index out of range");
563
return RETURN_FAILURE;
566
if (setno == NEW_SET) {
567
setno = nextset(gno);
569
return RETURN_FAILURE;
573
/* clear data stored in the set, if any */
574
killsetdata(gno, setno);
576
if (activateset(gno, setno) != RETURN_SUCCESS) {
577
return RETURN_FAILURE;
580
set_dataset_type(gno, setno, type);
582
for (i = 0; i < nc; i++) {
585
cdata = allocate_index_data(blocklen);
587
if (blockdata.formats[column] != FFORMAT_STRING) {
588
cdata = copy_data_column((double *) blockdata.data[column], blocklen);
590
errmsg("Tried to read doubles from strings!");
591
killsetdata(gno, setno);
592
return RETURN_FAILURE;
596
killsetdata(gno, setno);
597
return RETURN_FAILURE;
599
setcol(gno, setno, i, cdata, blocklen);
602
/* strings, if any */
604
if (blockdata.formats[scol] != FFORMAT_STRING) {
605
errmsg("Tried to read strings from doubles!");
606
killsetdata(gno, setno);
607
return RETURN_FAILURE;
609
set_set_strings(gno, setno, blocklen,
610
copy_string_column((char **) blockdata.data[scol], blocklen));
614
sprintf(buf, "Cols %s", cols_to_field_string(nc, coli, scol));
615
setcomment(gno, setno, buf);
617
autoscale_graph(gno, autoscale);
619
return RETURN_SUCCESS;