tcsv.c - ploot - simple plotting tools
(HTM) git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ploot
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Tags
(DIR) README
---
tcsv.c (2343B)
---
1 #include "csv.h"
2
3 #include <errno.h>
4 #include <assert.h>
5 #include <string.h>
6 #include <time.h>
7 #include <stdlib.h>
8 #include <limits.h>
9 #include <time.h>
10
11 #include "log.h"
12 #include "util.h"
13
14 /*
15 * Read CSV data onto a set of (struct csv).
16 */
17
18 static void
19 csv_addtime(struct csv *vl, time_t epoch)
20 {
21 assert(vl->t = realloc(vl->t, (vl->n + 1) * sizeof(*vl->t)));
22 vl->t[vl->n] = epoch;
23 }
24
25 static void
26 csv_addval(struct csv *vl, double field)
27 {
28 assert(vl->v = realloc(vl->v, (vl->n + 1) * sizeof(*vl->v)));
29 vl->v[vl->n] = field;
30 }
31
32 /*
33 * Add to each column the value on the current row. The time_t
34 * buffer is shared among all fields.
35 */
36 void
37 csv_addrow(struct csv *vl, size_t ncol, char *line)
38 {
39 char *field;
40 time_t *tbuf;
41 long l;
42 double d;
43
44 field = strsep(&line, ",");
45 if (!field)
46 die(1, "missing epoch at row %zu", vl->n);
47
48 l = strtol(field, NULL, 10);
49 if (errno)
50 die(100, "parsing number '%s'", field);
51 csv_addtime(vl, l);
52 tbuf = vl[0].t;
53 for (; (field = strsep(&line, ",")); ncol--, vl->n++, vl++) {
54 if (ncol == 0)
55 die(1, "too many fields at line %zu", vl->n);
56 d = strtod(field, NULL);
57 if (errno)
58 die(100, "parsing double '%s'", field);
59 csv_addval(vl, d);
60 vl->t = tbuf;
61 }
62 if (ncol > 0)
63 die(1, "too few fields at line %zu", vl->n);
64 }
65
66 /*
67 * < *ncol >
68 * epoch,label1,label2,label3
69 */
70 void
71 csv_labels(FILE *fp, struct csv **vl, size_t *ncol)
72 {
73 char *field, *line, *cp;
74 struct csv *col;
75 size_t sz;
76 ssize_t r;
77
78 sz = 0, line = NULL;
79 r = getline(&line, &sz, fp);
80 if (ferror(fp))
81 die(111, "error while reading from file");
82 if (r == -1)
83 die(100, "missing label line");
84 strchomp(line);
85
86 cp = line;
87 if (strcmp(strsep(&cp, ","), "epoch") != 0)
88 die(1, "first label must be 'epoch'");
89
90 *vl = NULL;
91 *ncol = 0;
92 while ((field = strsep(&cp, ","))) {
93 assert(*vl = realloc(*vl, sz += sizeof(**vl)));
94 col = (*vl) + (*ncol)++;
95 strlcpy(col->label, field, sizeof(col->label));
96 }
97
98 free(line);
99 }
100
101 /*
102 * < ncol >
103 * epoch,a1,b1,c1 ^
104 * epoch,a2,b2,c2 vl->n
105 * epoch,a3,b3,c3 v
106 */
107 void
108 csv_values(FILE *fp, struct csv *vl, size_t ncol)
109 {
110 char *line;
111 size_t sz;
112
113 sz = 0, line = NULL;
114 while (getline(&line, &sz, fp) > -1)
115 csv_addrow(vl, ncol, line);
116 if (vl->n == 0)
117 die(1, "no value could be read");
118 if (vl->n == 1)
119 die(1, "only one value could be read");
120
121 free(line);
122 }