tsv.c - ploot - simple plotting tools | |
git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
LICENSE | |
--- | |
tsv.c (3148B) | |
--- | |
1 #include "tsv.h" | |
2 #include <errno.h> | |
3 #include <assert.h> | |
4 #include <string.h> | |
5 #include <time.h> | |
6 #include <stdlib.h> | |
7 #include <limits.h> | |
8 #include <time.h> | |
9 #include "util.h" | |
10 | |
11 /* | |
12 * Read TSV data onto a set of (struct tsv) and some utilities to work o… | |
13 */ | |
14 | |
15 int | |
16 tsv_min_max(struct tsv *vl, int ncol, | |
17 time_t *tmin, time_t *tmax, | |
18 double *vmin, double *vmax) | |
19 { | |
20 double *v; | |
21 time_t *t; | |
22 size_t n; | |
23 | |
24 *vmin = *vmax = 0; /* always show 0 on the scale */ | |
25 *tmin = *tmax = *vl->t; | |
26 | |
27 for (; ncol > 0; ncol--, vl++) { | |
28 for (t = vl->t, v = vl->v, n = vl->n; n > 0; t++, v++, n… | |
29 if (*v < *vmin) *vmin = *v; | |
30 if (*v > *vmax) *vmax = *v; | |
31 if (*t < *tmin) *tmin = *t; | |
32 if (*t > *tmax) *tmax = *t; | |
33 } | |
34 } | |
35 if (*tmin == *tmax) | |
36 return -1; | |
37 return 0; | |
38 } | |
39 | |
40 static void | |
41 tsv_add_time(struct tsv *vl, time_t epoch) | |
42 { | |
43 void *mem; | |
44 | |
45 if ((mem = realloc(vl->t, (vl->n + 1) * sizeof *vl->t)) == NULL) | |
46 err(1, "realloc: %s", strerror(errno)); | |
47 vl->t = mem; | |
48 vl->t[vl->n] = epoch; | |
49 } | |
50 | |
51 static void | |
52 tsv_add_val(struct tsv *vl, double field) | |
53 { | |
54 void *mem; | |
55 | |
56 if ((mem = realloc(vl->v, (vl->n + 1) * sizeof *vl->v)) == NULL) | |
57 err(1, "", strerror(errno)); | |
58 vl->v = mem; | |
59 vl->v[vl->n] = field; | |
60 } | |
61 | |
62 /* | |
63 * Add to each column the value on the current row. The time_t | |
64 * buffer is shared among all fields. | |
65 */ | |
66 static void | |
67 tsv_add_row(struct tsv *vl, size_t ncol, char *line) | |
68 { | |
69 char *field; | |
70 time_t *tbuf; | |
71 long l; | |
72 double d; | |
73 | |
74 if ((field = strsep(&line, "\t")) == NULL) | |
75 err(1, "missing epoch at row %zu", vl->n); | |
76 | |
77 l = strtol(field, NULL, 10); | |
78 if (errno) | |
79 err(100, "parsing number '%s'", field); | |
80 | |
81 tsv_add_time(vl, l); | |
82 tbuf = vl[0].t; | |
83 for (; (field = strsep(&line, "\t")); ncol--, vl->n++, vl++) { | |
84 if (ncol == 0) | |
85 err(1, "too many fields at line %zu", vl->n); | |
86 d = strtod(field, NULL); | |
87 if (errno) | |
88 err(100, "parsing double '%s'", field); | |
89 tsv_add_val(vl, d); | |
90 vl->t = tbuf; | |
91 } | |
92 if (ncol > 0) | |
93 err(1, "too few fields at line %zu", vl->n); | |
94 } | |
95 | |
96 /* | |
97 * < (ncol) > | |
98 * label1,label2,label3 | |
99 */ | |
100 void | |
101 tsv_labels(FILE *fp, struct tsv **vlp, size_t *ncol) | |
102 { | |
103 char *field, *line, *cp; | |
104 struct tsv *vl, *col; | |
105 size_t sz; | |
106 | |
107 sz = 0, line = NULL; | |
108 getline(&line, &sz, fp); | |
109 if (ferror(fp)) | |
110 err(111, "error while reading from file"); | |
111 if (feof(fp)) | |
112 err(100, "missing label line"); | |
113 strchomp(line); | |
114 | |
115 cp = line; | |
116 if (strcmp(strsep(&cp, "\t"), "epoch") != 0) | |
117 err(1, "first label must be 'epoch'"); | |
118 | |
119 sz = 0, vl = NULL, *ncol = 0; | |
120 while ((field = strsep(&cp, "\t"))) { | |
121 if ((vl = realloc(vl, sz += sizeof *vl)) == NULL) | |
122 err(1, "realloc: %s", strerror(errno)); | |
123 col = vl + (*ncol)++; | |
124 memset(col, 0, sizeof *vl); | |
125 strlcpy(col->label, field, sizeof col->label); | |
126 } | |
127 free(line); | |
128 *vlp = vl; | |
129 } | |
130 | |
131 /* | |
132 * < (ncol) > | |
133 * val1a,val1b,val1c ^ | |
134 * val2a,val2b,val2c | | |
135 * val3a,val3b,val3c (vl->n) | |
136 * val4a,val4b,val4c | | |
137 * val5a,val5b,val5c v | |
138 */ | |
139 void | |
140 tsv_values(FILE *fp, struct tsv *vl, size_t ncol) | |
141 { | |
142 char *line; | |
143 size_t sz; | |
144 | |
145 sz = 0, line = NULL; | |
146 while (getline(&line, &sz, fp) > -1) | |
147 tsv_add_row(vl, ncol, line); | |
148 if (vl->n == 0) | |
149 err(1, "no value could be read"); | |
150 if (vl->n == 1) | |
151 err(1, "only one value could be read"); | |
152 free(line); | |
153 } |