tcsv.c - ploot - simple plotting tools HTML 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 }