~ubuntu-branches/ubuntu/karmic/grace/karmic

« back to all changes in this revision

Viewing changes to src/ssdata.c

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2002-03-19 14:19:58 UTC
  • Revision ID: james.westby@ubuntu.com-20020319141958-5gxna6vo1ek3zjml
Tags: upstream-5.1.7
ImportĀ upstreamĀ versionĀ 5.1.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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-2000 Grace Development Team
 
8
 * 
 
9
 * Maintained by Evgeny Stambulchik <fnevgeny@plasma-gate.weizmann.ac.il>
 
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
    memcpy(&blockdata, ssd, sizeof(ss_data));
 
112
}
 
113
 
 
114
int get_blockncols(void)
 
115
{
 
116
    return blockdata.ncols;
 
117
}
 
118
 
 
119
int get_blocknrows(void)
 
120
{
 
121
    return blockdata.nrows;
 
122
}
 
123
 
 
124
int *get_blockformats(void)
 
125
{
 
126
    return blockdata.formats;
 
127
}
 
128
 
 
129
int realloc_ss_data(ss_data *ssd, int nrows)
 
130
{
 
131
    int i, j;
 
132
    char  **sp;
 
133
    
 
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++) {
 
138
                XCFREE(sp[j]);
 
139
            }
 
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++) {
 
143
                sp[j] = NULL;
 
144
            }
 
145
        } else {
 
146
            ssd->data[i] = xrealloc(ssd->data[i], nrows*SIZEOF_DOUBLE);
 
147
        }
 
148
    }
 
149
    ssd->nrows = nrows;
 
150
    
 
151
    return RETURN_SUCCESS;
 
152
}
 
153
 
 
154
void free_ss_data(ss_data *ssd)
 
155
{
 
156
    int i, j;
 
157
    char  **sp;
 
158
    
 
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++) {
 
163
                XCFREE(sp[j]);
 
164
            }
 
165
        }
 
166
        XCFREE(ssd->data[i]);
 
167
    }
 
168
    XCFREE(ssd->data);
 
169
    XCFREE(ssd->formats);
 
170
    ssd->nrows = 0;
 
171
    ssd->ncols = 0;
 
172
}
 
173
 
 
174
int init_ss_data(ss_data *ssd, int ncols, int *formats)
 
175
{
 
176
    int i;
 
177
    
 
178
    ssd->data = xmalloc(ncols*SIZEOF_VOID_P);
 
179
    for (i = 0; i < ncols; i++) {
 
180
        ssd->data[i] = NULL;
 
181
    }
 
182
    ssd->formats = formats;
 
183
    ssd->ncols = ncols;
 
184
    ssd->nrows = 0;
 
185
 
 
186
    return RETURN_SUCCESS;
 
187
}
 
188
 
 
189
static char *next_token(char *s, char **token, int *quoted)
 
190
{
 
191
    *quoted = FALSE;
 
192
    *token = NULL;
 
193
    
 
194
    if (s == NULL) {
 
195
        return NULL;
 
196
    }
 
197
    
 
198
    while (*s == ' ' || *s == '\t') {
 
199
        s++;
 
200
    }
 
201
    if (*s == '"') {
 
202
        s++;
 
203
        *token = s;
 
204
        while (*s != '\0' && (*s != '"' || (*s == '"' && *(s - 1) == '\\'))) {
 
205
            s++;
 
206
        }
 
207
        if (*s == '"') {
 
208
            /* successfully identified a quoted string */
 
209
            *quoted = TRUE;
 
210
        }
 
211
    } else {
 
212
        *token = s;
 
213
        if (**token == '\n') {
 
214
            /* EOL reached */
 
215
            return NULL;
 
216
        }
 
217
        while (*s != '\n' && *s != '\0' && *s != ' ' && *s != '\t') {
 
218
            s++;
 
219
        }
 
220
    }
 
221
    
 
222
    if (*s != '\0') {
 
223
        *s = '\0';
 
224
        s++;
 
225
        return s;
 
226
    } else {
 
227
        return NULL;
 
228
    }
 
229
}
 
230
 
 
231
int parse_ss_row(const char *s, int *nncols, int *nscols, int **formats)
 
232
{
 
233
    int ncols;
 
234
    int quoted;
 
235
    char *buf, *s1, *token;
 
236
    double value;
 
237
    Dates_format df_pref, ddummy;
 
238
    const char *sdummy;
 
239
 
 
240
    *nscols = 0;
 
241
    *nncols = 0;
 
242
    *formats = NULL;
 
243
    df_pref = get_date_hint();
 
244
    buf = copy_string(NULL, s);
 
245
    s1 = buf;
 
246
    while ((s1 = next_token(s1, &token, &quoted)) != NULL) {
 
247
        if (token == NULL) {
 
248
            *nscols = 0;
 
249
            *nncols = 0;
 
250
            XCFREE(*formats);
 
251
            xfree(buf);
 
252
            return RETURN_FAILURE;
 
253
        }
 
254
        
 
255
        ncols = *nncols + *nscols;
 
256
        /* reallocate the formats array */
 
257
        if (ncols % 10 == 0) {
 
258
            *formats = xrealloc(*formats, (ncols + 10)*SIZEOF_INT);
 
259
        }
 
260
 
 
261
        if (quoted) {
 
262
            (*formats)[ncols] = FFORMAT_STRING;
 
263
            (*nscols)++;
 
264
        } else if (parse_date(token, df_pref, FALSE, &value, &ddummy) ==
 
265
            RETURN_SUCCESS) {
 
266
            (*formats)[ncols] = FFORMAT_DATE;
 
267
            (*nncols)++;
 
268
        } else if (parse_float(token, &value, &sdummy) == RETURN_SUCCESS) {
 
269
            (*formats)[ncols] = FFORMAT_NUMBER;
 
270
            (*nncols)++;
 
271
        } else {
 
272
            /* last resort - treat the field as string, even if not quoted */
 
273
            (*formats)[ncols] = FFORMAT_STRING;
 
274
            (*nscols)++;
 
275
        }
 
276
    }
 
277
    xfree(buf);
 
278
    
 
279
    return RETURN_SUCCESS;
 
280
}
 
281
 
 
282
 
 
283
/* NOTE: the input string will be corrupted! */
 
284
int insert_data_row(ss_data *ssd, int row, char *s)
 
285
{
 
286
    int i, j;
 
287
    int ncols = ssd->ncols;
 
288
    char *token;
 
289
    int quoted;
 
290
    char  **sp;
 
291
    double *np;
 
292
    Dates_format df_pref, ddummy;
 
293
    const char *sdummy;
 
294
    int res;
 
295
    
 
296
    df_pref = get_date_hint();
 
297
    for (i = 0; i < ncols; i++) {
 
298
        s = next_token(s, &token, &quoted);
 
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];
 
304
                    XCFREE(sp[row]);
 
305
                }
 
306
            }
 
307
            return RETURN_FAILURE;
 
308
        } else {
 
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;
 
314
                } else {
 
315
                    res = RETURN_FAILURE;
 
316
                }
 
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);
 
320
            } else {
 
321
                np = (double *) ssd->data[i];
 
322
                res = parse_float(token, &np[row], &sdummy);
 
323
            }
 
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];
 
328
                        XCFREE(sp[row]);
 
329
                    }
 
330
                }
 
331
                return RETURN_FAILURE;
 
332
            }
 
333
        }
 
334
    }
 
335
    
 
336
    return RETURN_SUCCESS;
 
337
}
 
338
 
 
339
 
 
340
int store_data(ss_data *ssd, int load_type, char *label)
 
341
{
 
342
    int ncols, nncols, nncols_req, nscols, nrows;
 
343
    int i, j;
 
344
    double *xdata;
 
345
    int gno, setno;
 
346
    int x_from_index;
 
347
    
 
348
    if (ssd == NULL) {
 
349
        return RETURN_FAILURE;
 
350
    }
 
351
    ncols = ssd->ncols;
 
352
    nrows = ssd->nrows;
 
353
    if (ncols <= 0 || nrows <= 0) {
 
354
        return RETURN_FAILURE;
 
355
    }
 
356
 
 
357
    nncols = 0;
 
358
    for (j = 0; j < ncols; j++) {
 
359
        if (ssd->formats[j] != FFORMAT_STRING) {
 
360
            nncols++;
 
361
        }
 
362
    }
 
363
    nscols = ncols - nncols;
 
364
    
 
365
    gno = get_parser_gno();
 
366
    if (is_valid_gno(gno) != TRUE) {
 
367
        return RETURN_FAILURE;
 
368
    }
 
369
    
 
370
    switch (load_type) {
 
371
    case LOAD_SINGLE:
 
372
        if (nncols > MAX_SET_COLS || nscols > 1) {
 
373
            errmsg("Internal error");
 
374
            free_ss_data(ssd);
 
375
            return RETURN_FAILURE;
 
376
        }
 
377
 
 
378
        nncols_req = settype_cols(curtype);
 
379
        x_from_index = FALSE;
 
380
        if (nncols_req == nncols + 1) {
 
381
            x_from_index = TRUE;
 
382
        } else if (nncols_req != nncols) {
 
383
            errmsg("Column count incorrect");
 
384
            return RETURN_FAILURE;
 
385
        }
 
386
 
 
387
        setno = nextset(gno);
 
388
        set_dataset_type(gno, setno, curtype);
 
389
 
 
390
        nncols = 0;
 
391
        if (x_from_index) {
 
392
            xdata = allocate_index_data(nrows);
 
393
            if (xdata == NULL) {
 
394
                free_ss_data(ssd);
 
395
            }
 
396
            setcol(gno, setno, nncols, xdata, nrows);
 
397
            nncols++;
 
398
        }
 
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]);
 
402
            } else {
 
403
                setcol(gno, setno, nncols, (double *) ssd->data[j], nrows);
 
404
                nncols++;
 
405
            }
 
406
        }
 
407
        if (!strlen(getcomment(gno, setno))) {
 
408
            setcomment(gno, setno, label);
 
409
        }
 
410
        
 
411
        XCFREE(ssd->data);
 
412
        break;
 
413
    case LOAD_NXY:
 
414
        if (nscols != 0) {
 
415
            errmsg("Can not yet use strings when reading in data as NXY");
 
416
            free_ss_data(ssd);
 
417
            return RETURN_FAILURE;
 
418
        }
 
419
        
 
420
        for (i = 0; i < ncols - 1; i++) {
 
421
            setno = nextset(gno);
 
422
            if (setno == -1) {
 
423
                free_ss_data(ssd);
 
424
                return RETURN_FAILURE;
 
425
            }
 
426
            if (i > 0) {
 
427
                xdata = copy_data_column((double *) ssd->data[0], nrows);
 
428
                if (xdata == NULL) {
 
429
                    free_ss_data(ssd);
 
430
                }
 
431
            } else {
 
432
                xdata = (double *) ssd->data[0];
 
433
            }
 
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);
 
438
        }
 
439
    
 
440
        XCFREE(ssd->data);
 
441
        break;
 
442
    case LOAD_BLOCK:
 
443
        set_blockdata(ssd);
 
444
        break;
 
445
    default:
 
446
        errmsg("Internal error");
 
447
        free_ss_data(ssd);
 
448
        return RETURN_FAILURE;
 
449
    }
 
450
    
 
451
    return RETURN_SUCCESS;
 
452
}
 
453
 
 
454
int field_string_to_cols(const char *fs, int *nc, int **cols, int *scol)
 
455
{
 
456
    int col;
 
457
    char *s, *buf;
 
458
 
 
459
    buf = copy_string(NULL, fs);
 
460
    if (buf == NULL) {
 
461
        return RETURN_FAILURE;
 
462
    }
 
463
 
 
464
    s = buf;
 
465
    *nc = 0;
 
466
    while ((s = strtok(s, ":")) != NULL) {
 
467
        (*nc)++;
 
468
        s = NULL;
 
469
    }
 
470
    *cols = xmalloc((*nc)*SIZEOF_INT);
 
471
    if (*cols == NULL) {
 
472
        xfree(buf);
 
473
        return RETURN_FAILURE;
 
474
    }
 
475
 
 
476
    strcpy(buf, fs);
 
477
    s = buf;
 
478
    *nc = 0;
 
479
    *scol = -1;
 
480
    while ((s = strtok(s, ":")) != NULL) {
 
481
        int strcol;
 
482
        if (*s == '{') {
 
483
            char *s1;
 
484
            strcol = TRUE;
 
485
            s++;
 
486
            if ((s1 = index(s, '}')) != NULL) {
 
487
                *s1 = '\0';
 
488
            }
 
489
        } else {
 
490
            strcol = FALSE;
 
491
        }
 
492
        col = atoi(s);
 
493
        col--;
 
494
        if (strcol) {
 
495
            *scol = col;
 
496
        } else {
 
497
            (*cols)[*nc] = col;
 
498
            (*nc)++;
 
499
        }
 
500
        s = NULL;
 
501
    }
 
502
    
 
503
    xfree(buf);
 
504
    
 
505
    return RETURN_SUCCESS;
 
506
}
 
507
 
 
508
char *cols_to_field_string(int nc, int *cols, int scol)
 
509
{
 
510
    int i;
 
511
    char *s, buf[32];
 
512
    
 
513
    s = NULL;
 
514
    for (i = 0; i < nc; i++) {
 
515
        sprintf(buf, "%d", cols[i] + 1);
 
516
        if (i != 0) {
 
517
            s = concat_strings(s, ":");
 
518
        }
 
519
        s = concat_strings(s, buf);
 
520
    }
 
521
    if (scol >= 0) {
 
522
        sprintf(buf, ":{%d}", scol + 1);
 
523
        s = concat_strings(s, buf);
 
524
    }
 
525
    
 
526
    return s;
 
527
}
 
528
 
 
529
int create_set_fromblock(int gno, int setno,
 
530
    int type, int nc, int *coli, int scol, int autoscale)
 
531
{
 
532
    int i, ncols, blockncols, blocklen, column;
 
533
    double *cdata;
 
534
    char buf[256];
 
535
 
 
536
    blockncols = get_blockncols();
 
537
    if (blockncols <= 0) {
 
538
        errmsg("No block data read");
 
539
        return RETURN_FAILURE;
 
540
    }
 
541
 
 
542
    blocklen = get_blocknrows();
 
543
    
 
544
    ncols = settype_cols(type);
 
545
    if (nc > ncols) {
 
546
        errmsg("Too many columns scanned in column string");
 
547
        return RETURN_FAILURE;
 
548
    }
 
549
    if (nc < ncols) {
 
550
        errmsg("Too few columns scanned in column string");
 
551
        return RETURN_FAILURE;
 
552
    }
 
553
    
 
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;
 
558
        }
 
559
    }
 
560
    
 
561
    if (scol >= blockncols) {
 
562
        errmsg("String column index out of range");
 
563
        return RETURN_FAILURE;
 
564
    }
 
565
    
 
566
    if (setno == NEW_SET) {
 
567
        setno = nextset(gno);
 
568
        if (setno == -1) {
 
569
            return RETURN_FAILURE;
 
570
        }
 
571
    }
 
572
    
 
573
    /* clear data stored in the set, if any */
 
574
    killsetdata(gno, setno);
 
575
    
 
576
    if (activateset(gno, setno) != RETURN_SUCCESS) {
 
577
        return RETURN_FAILURE;
 
578
    }
 
579
    
 
580
    set_dataset_type(gno, setno, type);
 
581
 
 
582
    for (i = 0; i < nc; i++) {
 
583
        column = coli[i];
 
584
        if (column == -1) {
 
585
            cdata = allocate_index_data(blocklen);
 
586
        } else {
 
587
            if (blockdata.formats[column] != FFORMAT_STRING) {
 
588
                cdata = copy_data_column((double *) blockdata.data[column], blocklen);
 
589
            } else {
 
590
                errmsg("Tried to read doubles from strings!");
 
591
                killsetdata(gno, setno);
 
592
                return RETURN_FAILURE;
 
593
            }
 
594
        }
 
595
        if (cdata == NULL) {
 
596
            killsetdata(gno, setno);
 
597
            return RETURN_FAILURE;
 
598
        }
 
599
        setcol(gno, setno, i, cdata, blocklen);
 
600
    }
 
601
 
 
602
    /* strings, if any */
 
603
    if (scol >= 0) {
 
604
        if (blockdata.formats[scol] != FFORMAT_STRING) {
 
605
            errmsg("Tried to read strings from doubles!");
 
606
            killsetdata(gno, setno);
 
607
            return RETURN_FAILURE;
 
608
        } else {
 
609
            set_set_strings(gno, setno, blocklen,
 
610
                copy_string_column((char **) blockdata.data[scol], blocklen));
 
611
        }
 
612
    }
 
613
 
 
614
    sprintf(buf, "Cols %s", cols_to_field_string(nc, coli, scol));
 
615
    setcomment(gno, setno, buf);
 
616
 
 
617
    autoscale_graph(gno, autoscale);
 
618
 
 
619
    return RETURN_SUCCESS;
 
620
}