URI: 
       tsv.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
   DIR 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 on these data.
           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 }