tcsv.c - ploot - simple plotting tools | |
git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65… | |
Log | |
Files | |
Refs | |
Tags | |
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 } |