move from CSV to TSV - 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
(DIR) LICENSE
---
(DIR) commit 98d0cb5aa9d2adb27b2a992e90debce8b3843c5b
(DIR) parent 8836c19534760f2ce037c39bde9dc5591011ed07
(HTM) Author: Josuah Demangeon <me@josuah.net>
Date: Sun, 27 Jun 2021 04:57:00 +0200
move from CSV to TSV
Diffstat:
M Makefile | 6 +++---
M README.md | 6 +++---
D csv.c | 154 -------------------------------
D csv.h | 22 ----------------------
D example.csv | 114 -------------------------------
M example.png | 0
A example.tsv | 114 +++++++++++++++++++++++++++++++
M ploot-braille.c | 14 +++++++-------
D ploot-csv.5 | 77 -------------------------------
M ploot-farbfeld.1 | 10 +++++-----
M ploot-farbfeld.c | 18 +++++++++---------
M ploot-feed.1 | 6 +++---
M ploot-feed.c | 10 +++++-----
A ploot-tsv.5 | 77 +++++++++++++++++++++++++++++++
A tsv.c | 154 +++++++++++++++++++++++++++++++
A tsv.h | 22 ++++++++++++++++++++++
16 files changed, 402 insertions(+), 402 deletions(-)
---
(DIR) diff --git a/Makefile b/Makefile
@@ -7,9 +7,9 @@ LFLAGS = -static -lm
PREFIX = /usr/local
MANOREFIX = $(PREFIX)/share/man
-SRC = csv.c drawille.c font.c font13.c font8.c util.c
-INC = csv.h drawille.h font.h util.h
-BIN = ploot-feed ploot-braille ploot-text ploot-farbfeld
+SRC = tsv.c drawille.c font.c font13.c font8.c util.c
+INC = tsv.h drawille.h font.h util.h
+BIN = ploot-farbfeld ploot-feed ploot-braille ploot-text
OBJ = ${SRC:.c=.o}
all: ${BIN}
(DIR) diff --git a/README.md b/README.md
@@ -3,7 +3,7 @@ ploot
ploot-ffplot
--------------
-*ploot-ffplot* reads collectd-style comma separated values (CSV) and produces a plot
+*ploot-ffplot* reads collectd-style comma separated values (TSV) and produces a plot
in the ffplot [1] image format (pipe it to ff2png). It is an alternative to
RRDtool [2].
@@ -16,12 +16,12 @@ name of the curves.
ploot-feed
----------
-*ploot-feed* also reads collectd-style comma separated values (CSV) but produces
+*ploot-feed* also reads collectd-style comma separated values (TSV) but produces
a plain text continuous waterfall chart for live monitoring in the terminal. it
is an alternative to grafana [1].
```
-% plootxt 1 1 1 <load-average.csv
+% plootxt 1 1 1 <load-average.tsv
│shortterm │midterm │longterm │
17:34:00 _│⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣯⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
18/05/01 │⣟⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
(DIR) diff --git a/csv.c b/csv.c
@@ -1,154 +0,0 @@
-#include "csv.h"
-#include <errno.h>
-#include <assert.h>
-#include <string.h>
-#include <time.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <time.h>
-#include "util.h"
-
-/*
- * Read CSV data onto a set of (struct csv) and some utilities to work on these data.
- */
-
-int
-csv_min_max(struct csv *vl, int ncol,
- time_t *tmin, time_t *tmax,
- double *vmin, double *vmax)
-{
- double *v;
- time_t *t;
- size_t n;
-
- *vmin = *vmax = 0; /* always show 0 on the scale */
- *tmin = *tmax = *vl->t;
-
- for (; ncol > 0; ncol--, vl++) {
- for (t = vl->t, v = vl->v, n = vl->n; n > 0; t++, v++, n--) {
- if (*v < *vmin) *vmin = *v;
- if (*v > *vmax) *vmax = *v;
- if (*t < *tmin) *tmin = *t;
- if (*t > *tmax) *tmax = *t;
- }
- }
- if (*tmin == *tmax)
- return -1;
- return 0;
-}
-
-static void
-csv_add_time(struct csv *vl, time_t epoch)
-{
- void *mem;
-
- if ((mem = realloc(vl->t, (vl->n + 1) * sizeof *vl->t)) == NULL)
- err(1, "realloc: %s", strerror(errno));
- vl->t = mem;
- vl->t[vl->n] = epoch;
-}
-
-static void
-csv_add_val(struct csv *vl, double field)
-{
- void *mem;
-
- if ((mem = realloc(vl->v, (vl->n + 1) * sizeof *vl->v)) == NULL)
- err(1, "", strerror(errno));
- vl->v = mem;
- vl->v[vl->n] = field;
-}
-
-/*
- * Add to each column the value on the current row. The time_t
- * buffer is shared among all fields.
- */
-static void
-csv_add_row(struct csv *vl, size_t ncol, char *line)
-{
- char *field;
- time_t *tbuf;
- long l;
- double d;
-
- if ((field = strsep(&line, ",")) == NULL)
- err(1, "missing epoch at row %zu", vl->n);
-
- l = strtol(field, NULL, 10);
- if (errno)
- err(100, "parsing number '%s'", field);
-
- csv_add_time(vl, l);
- tbuf = vl[0].t;
- for (; (field = strsep(&line, ",")); ncol--, vl->n++, vl++) {
- if (ncol == 0)
- err(1, "too many fields at line %zu", vl->n);
- d = strtod(field, NULL);
- if (errno)
- err(100, "parsing double '%s'", field);
- csv_add_val(vl, d);
- vl->t = tbuf;
- }
- if (ncol > 0)
- err(1, "too few fields at line %zu", vl->n);
-}
-
-/*
- * < (ncol) >
- * label1,label2,label3
- */
-void
-csv_labels(FILE *fp, struct csv **vlp, size_t *ncol)
-{
- char *field, *line, *cp;
- struct csv *vl, *col;
- size_t sz;
- ssize_t r;
-
- sz = 0, line = NULL;
- r = getline(&line, &sz, fp);
- if (ferror(fp))
- err(111, "error while reading from file");
- if (feof(fp))
- err(100, "missing label line");
- strchomp(line);
-
- cp = line;
- if (strcmp(strsep(&cp, ","), "epoch") != 0)
- err(1, "first label must be 'epoch'");
-
- sz = 0, vl = NULL, *ncol = 0;
- while ((field = strsep(&cp, ","))) {
- if ((vl = realloc(vl, sz += sizeof *vl)) == NULL)
- err(1, "realloc: %s", strerror(errno));
- col = vl + (*ncol)++;
- memset(col, 0, sizeof *vl);
- strlcpy(col->label, field, sizeof col->label);
- }
- free(line);
- *vlp = vl;
-}
-
-/*
- * < (ncol) >
- * val1a,val1b,val1c ^
- * val2a,val2b,val2c |
- * val3a,val3b,val3c (vl->n)
- * val4a,val4b,val4c |
- * val5a,val5b,val5c v
- */
-void
-csv_values(FILE *fp, struct csv *vl, size_t ncol)
-{
- char *line;
- size_t sz;
-
- sz = 0, line = NULL;
- while (getline(&line, &sz, fp) > -1)
- csv_add_row(vl, ncol, line);
- if (vl->n == 0)
- err(1, "no value could be read");
- if (vl->n == 1)
- err(1, "only one value could be read");
- free(line);
-}
(DIR) diff --git a/csv.h b/csv.h
@@ -1,22 +0,0 @@
-#ifndef CSV_H
-#define CSV_H
-
-#include <stdio.h>
-#include <time.h>
-
-/*
- * List of values and timestamps. Both have their dedicated buffer
- * so that the timestamp buffer can be shared across csv objects.
- */
-struct csv {
- time_t *t; /* array of timestamps */
- double *v; /* array of values */
- size_t n; /* number of values */
- char label[64]; /* for the legend */
-};
-
-void csv_labels(FILE *, struct csv **, size_t *);
-void csv_values(FILE *, struct csv *, size_t);
-int csv_min_max(struct csv *, int, time_t *, time_t *, double *, double *);
-
-#endif
(DIR) diff --git a/example.csv b/example.csv
@@ -1,114 +0,0 @@
-epoch,shortterm,midterm,longterm
-1525186140,0.023804,0.056885,0.049561
-1525187040,0.035767,0.047485,0.043701
-1525187940,0.057861,0.050293,0.042480
-1525188840,0.098267,0.099609,0.072266
-1525189740,0.083618,0.091187,0.079468
-1525190640,0.055298,0.063843,0.063354
-1525191540,0.046875,0.056152,0.058960
-1525192440,0.091187,0.062622,0.058716
-1525193340,0.067871,0.060303,0.059937
-1525194240,0.085571,0.056763,0.052612
-1525195140,0.020874,0.054810,0.055176
-1525196040,0.125122,0.062500,0.048096
-1525196940,0.040649,0.041870,0.040649
-1525197840,0.032471,0.049194,0.042114
-1525198740,0.073853,0.088501,0.071045
-1525199640,0.119995,0.072998,0.064697
-1525200540,0.030518,0.043335,0.046265
-1525201440,0.037842,0.042969,0.040894
-1525202340,0.054810,0.049927,0.042358
-1525203240,0.120728,0.077271,0.053589
-1525204140,0.068970,0.086670,0.074585
-1525205040,0.071289,0.083496,0.079834
-1525205940,0.046265,0.059326,0.068848
-1525206840,0.064209,0.083374,0.069214
-1525207740,0.055054,0.046753,0.051758
-1525208640,0.170410,0.088867,0.064575
-1525209540,0.067627,0.092407,0.092163
-1525210440,0.078003,0.087646,0.083130
-1525211340,0.032959,0.043457,0.059204
-1525212240,0.036377,0.054810,0.057861
-1525213140,0.054565,0.078369,0.071655
-1525214040,0.026611,0.041138,0.051514
-1525214940,0.065186,0.067505,0.061768
-1525215840,0.071411,0.055298,0.055176
-1525229081,0.041260,0.045044,0.045654
-1525229081,0.041260,0.045044,0.045654
-1525229981,0.059692,0.102051,0.105835
-1525230881,0.077148,0.067017,0.073730
-1525231781,0.080200,0.074341,0.064575
-1525232681,0.122437,0.099487,0.075806
-1525233581,0.085815,0.076050,0.073486
-1525234481,0.074585,0.064087,0.062012
-1525235381,0.024902,0.047241,0.053345
-1525236281,0.107910,0.081543,0.065918
-1525237181,0.038696,0.075684,0.080688
-1525238081,0.204834,0.181152,0.130737
-1525238981,0.231445,0.158325,0.137695
-1525239881,0.067505,0.089355,0.109497
-1525240781,0.047852,0.088745,0.107910
-1525241681,0.094360,0.085693,0.083618
-1525242581,0.047363,0.043335,0.052856
-1525243481,0.047363,0.031982,0.036621
-1525244381,0.055054,0.042236,0.040039
-1525245281,0.034668,0.041626,0.040039
-1525246181,0.088867,0.065918,0.048706
-1525247081,0.049072,0.051880,0.042236
-1525247981,0.045166,0.048828,0.041382
-1525248881,0.067261,0.061768,0.047852
-1525249781,0.039917,0.056519,0.045654
-1525250681,0.017822,0.030273,0.033081
-1525251581,0.034668,0.033691,0.034546
-1525252481,0.053223,0.051880,0.045166
-1525253381,0.028687,0.050049,0.050659
-1525254281,0.021118,0.042358,0.040649
-1525255181,0.059204,0.047974,0.041870
-1525256081,0.206421,0.141968,0.086670
-1525256981,0.105713,0.087158,0.073486
-1525257881,0.048950,0.060913,0.068359
-1525258781,0.024414,0.036621,0.046753
-1525259681,0.245239,0.109619,0.071045
-1525260581,0.042236,0.063965,0.069092
-1525261481,0.016724,0.054077,0.059692
-1525262381,0.018433,0.078003,0.076660
-1525263281,0.042480,0.057617,0.061890
-1525264181,0.040161,0.041138,0.044189
-1525265081,0.059082,0.090698,0.064575
-1525265981,0.129272,0.080811,0.073486
-1525266881,0.228516,0.164551,0.112915
-1525267781,0.083130,0.058594,0.067627
-1525268681,0.062378,0.063965,0.061523
-1525269581,0.066895,0.069702,0.062500
-1525270481,0.061768,0.080322,0.065674
-1525271381,0.123657,0.089478,0.072021
-1525272281,0.056885,0.045532,0.051514
-1525273181,0.108887,0.056519,0.046387
-1525274081,0.072266,0.119629,0.080078
-1525274981,0.033447,0.058350,0.070190
-1525275881,0.028198,0.050781,0.058105
-1525276781,0.067261,0.059937,0.057495
-1525277681,0.024780,0.028809,0.038452
-1525278581,0.053955,0.049561,0.041748
-1525279481,0.086304,0.065308,0.048096
-1525281698,0.019165,0.047485,0.041870
-1525281698,0.019165,0.047485,0.041870
-1525282598,0.039551,0.034302,0.038086
-1525283498,0.017700,0.022827,0.026367
-1525284398,0.023560,0.034790,0.024292
-1525285298,0.093506,0.078857,0.053101
-1525286198,0.051025,0.066162,0.069458
-1525287098,0.054077,0.057861,0.059082
-1525287998,0.080200,0.071655,0.062744
-1525288898,0.478638,0.375122,0.247192
-1525289798,0.393066,0.390991,0.347046
-1525290698,0.368164,0.383545,0.365723
-1525291598,0.459229,0.463867,0.432129
-1525292498,0.286865,0.354980,0.381958
-1525293398,0.180786,0.178833,0.232910
-1525294298,0.278198,0.260864,0.242920
-1525295198,0.192505,0.183716,0.200806
-1525296098,0.109375,0.185669,0.207153
-1525296098,0.109375,0.185669,0.207153
-1525296998,0.137085,0.126221,0.138184
-1525297898,0.077881,0.092529,0.109619
(DIR) diff --git a/example.png b/example.png
Binary files differ.
(DIR) diff --git a/example.tsv b/example.tsv
@@ -0,0 +1,114 @@
+epoch shortterm midterm longterm
+1525186140 0.023804 0.056885 0.049561
+1525187040 0.035767 0.047485 0.043701
+1525187940 0.057861 0.050293 0.042480
+1525188840 0.098267 0.099609 0.072266
+1525189740 0.083618 0.091187 0.079468
+1525190640 0.055298 0.063843 0.063354
+1525191540 0.046875 0.056152 0.058960
+1525192440 0.091187 0.062622 0.058716
+1525193340 0.067871 0.060303 0.059937
+1525194240 0.085571 0.056763 0.052612
+1525195140 0.020874 0.054810 0.055176
+1525196040 0.125122 0.062500 0.048096
+1525196940 0.040649 0.041870 0.040649
+1525197840 0.032471 0.049194 0.042114
+1525198740 0.073853 0.088501 0.071045
+1525199640 0.119995 0.072998 0.064697
+1525200540 0.030518 0.043335 0.046265
+1525201440 0.037842 0.042969 0.040894
+1525202340 0.054810 0.049927 0.042358
+1525203240 0.120728 0.077271 0.053589
+1525204140 0.068970 0.086670 0.074585
+1525205040 0.071289 0.083496 0.079834
+1525205940 0.046265 0.059326 0.068848
+1525206840 0.064209 0.083374 0.069214
+1525207740 0.055054 0.046753 0.051758
+1525208640 0.170410 0.088867 0.064575
+1525209540 0.067627 0.092407 0.092163
+1525210440 0.078003 0.087646 0.083130
+1525211340 0.032959 0.043457 0.059204
+1525212240 0.036377 0.054810 0.057861
+1525213140 0.054565 0.078369 0.071655
+1525214040 0.026611 0.041138 0.051514
+1525214940 0.065186 0.067505 0.061768
+1525215840 0.071411 0.055298 0.055176
+1525229081 0.041260 0.045044 0.045654
+1525229081 0.041260 0.045044 0.045654
+1525229981 0.059692 0.102051 0.105835
+1525230881 0.077148 0.067017 0.073730
+1525231781 0.080200 0.074341 0.064575
+1525232681 0.122437 0.099487 0.075806
+1525233581 0.085815 0.076050 0.073486
+1525234481 0.074585 0.064087 0.062012
+1525235381 0.024902 0.047241 0.053345
+1525236281 0.107910 0.081543 0.065918
+1525237181 0.038696 0.075684 0.080688
+1525238081 0.204834 0.181152 0.130737
+1525238981 0.231445 0.158325 0.137695
+1525239881 0.067505 0.089355 0.109497
+1525240781 0.047852 0.088745 0.107910
+1525241681 0.094360 0.085693 0.083618
+1525242581 0.047363 0.043335 0.052856
+1525243481 0.047363 0.031982 0.036621
+1525244381 0.055054 0.042236 0.040039
+1525245281 0.034668 0.041626 0.040039
+1525246181 0.088867 0.065918 0.048706
+1525247081 0.049072 0.051880 0.042236
+1525247981 0.045166 0.048828 0.041382
+1525248881 0.067261 0.061768 0.047852
+1525249781 0.039917 0.056519 0.045654
+1525250681 0.017822 0.030273 0.033081
+1525251581 0.034668 0.033691 0.034546
+1525252481 0.053223 0.051880 0.045166
+1525253381 0.028687 0.050049 0.050659
+1525254281 0.021118 0.042358 0.040649
+1525255181 0.059204 0.047974 0.041870
+1525256081 0.206421 0.141968 0.086670
+1525256981 0.105713 0.087158 0.073486
+1525257881 0.048950 0.060913 0.068359
+1525258781 0.024414 0.036621 0.046753
+1525259681 0.245239 0.109619 0.071045
+1525260581 0.042236 0.063965 0.069092
+1525261481 0.016724 0.054077 0.059692
+1525262381 0.018433 0.078003 0.076660
+1525263281 0.042480 0.057617 0.061890
+1525264181 0.040161 0.041138 0.044189
+1525265081 0.059082 0.090698 0.064575
+1525265981 0.129272 0.080811 0.073486
+1525266881 0.228516 0.164551 0.112915
+1525267781 0.083130 0.058594 0.067627
+1525268681 0.062378 0.063965 0.061523
+1525269581 0.066895 0.069702 0.062500
+1525270481 0.061768 0.080322 0.065674
+1525271381 0.123657 0.089478 0.072021
+1525272281 0.056885 0.045532 0.051514
+1525273181 0.108887 0.056519 0.046387
+1525274081 0.072266 0.119629 0.080078
+1525274981 0.033447 0.058350 0.070190
+1525275881 0.028198 0.050781 0.058105
+1525276781 0.067261 0.059937 0.057495
+1525277681 0.024780 0.028809 0.038452
+1525278581 0.053955 0.049561 0.041748
+1525279481 0.086304 0.065308 0.048096
+1525281698 0.019165 0.047485 0.041870
+1525281698 0.019165 0.047485 0.041870
+1525282598 0.039551 0.034302 0.038086
+1525283498 0.017700 0.022827 0.026367
+1525284398 0.023560 0.034790 0.024292
+1525285298 0.093506 0.078857 0.053101
+1525286198 0.051025 0.066162 0.069458
+1525287098 0.054077 0.057861 0.059082
+1525287998 0.080200 0.071655 0.062744
+1525288898 0.478638 0.375122 0.247192
+1525289798 0.393066 0.390991 0.347046
+1525290698 0.368164 0.383545 0.365723
+1525291598 0.459229 0.463867 0.432129
+1525292498 0.286865 0.354980 0.381958
+1525293398 0.180786 0.178833 0.232910
+1525294298 0.278198 0.260864 0.242920
+1525295198 0.192505 0.183716 0.200806
+1525296098 0.109375 0.185669 0.207153
+1525296098 0.109375 0.185669 0.207153
+1525296998 0.137085 0.126221 0.138184
+1525297898 0.077881 0.092529 0.109619
(DIR) diff --git a/ploot-braille.c b/ploot-braille.c
@@ -9,7 +9,7 @@
#include <unistd.h>
#include "drawille.h"
#include "util.h"
-#include "csv.h"
+#include "tsv.h"
#ifndef __OpenBSD__
#define pledge(...) 0
@@ -20,7 +20,7 @@
* a vertical and horizontal axis.
*/
static int
-braille_histogram(struct csv *vl, struct drawille *drw,
+braille_histogram(struct tsv *vl, struct drawille *drw,
time_t tmin, time_t tmax, double vmin, double vmax)
{
int x, xprev, y, yprev, zero;
@@ -104,7 +104,7 @@ braille_render(struct drawille *drw, FILE *fp, double min, double max)
}
static void
-plot(struct csv *vl, size_t ncol, int rows, int cols, FILE *fp)
+plot(struct tsv *vl, size_t ncol, int rows, int cols, FILE *fp)
{
double vmin, vmax, vstep;
time_t tmin, tmax, tstep;
@@ -112,7 +112,7 @@ plot(struct csv *vl, size_t ncol, int rows, int cols, FILE *fp)
rows = MAX(rows, 2); /* readable */
- if (csv_min_max(vl, ncol, &tmin, &tmax, &vmin, &vmax) < 0)
+ if (tsv_min_max(vl, ncol, &tmin, &tmax, &vmin, &vmax) < 0)
err(1, "invalid scale: tmin=%lld tmax=%lld vmin=%fd vmax=%fd",
(long long)tmin, (long long)tmax, vmin, vmax);
@@ -145,7 +145,7 @@ usage(void)
int
main(int argc, char **argv)
{
- struct csv *vl;
+ struct tsv *vl;
size_t ncol;
int c, rows, cols;
@@ -181,8 +181,8 @@ main(int argc, char **argv)
if (argc > 0)
usage();
- csv_labels(stdin, &vl, &ncol);
- csv_values(stdin, vl, ncol);
+ tsv_labels(stdin, &vl, &ncol);
+ tsv_values(stdin, vl, ncol);
plot(vl, ncol, rows, cols, stdout);
(DIR) diff --git a/ploot-csv.5 b/ploot-csv.5
@@ -1,77 +0,0 @@
-.Dd $Mdocdate: February 01 2020$
-.Dt PLOOT-CSV 5
-.Os
-.
-.
-.Sh NAME
-.
-.Nm ploot-csv
-.Nd input format used by the ploot set of programs
-.
-.
-.Sh SYNOPSIS
-.
-.Bd -literal
-epoch,column-name-1,column-name-2
-timestamp,value1,value2
-timestamp,value1,value2
-\&...
-.Ed
-.
-.
-.Sh DESCRIPTION
-.
-This is the simple coma-separated format used by the ploot-* programs.
-.
-.
-.Sh INPUT FORMAT
-.
-.Nm
-has a first header line, then zero or more data lines, both
-coma-separated list of values.
-.
-.
-.Ss Header line
-.
-The input must contain a first header line with the label of each column in order.
-The first column is always
-.Dq epoch .
-Then there are the actual column names.
-.
-.Bd -literal -offset indent
-epoch,free_memory,process_count
-.Ed
-.
-.
-.Ss Data lines
-.
-The following lines are the data.
-The first column is always an unix timestamp as in
-.Vt time_t .
-The remaining columns are values parsed as floating point numbers by
-.Xr strtod 3 :
-.
-.Bd -literal -offset indent
-1533752053,16.3,45
-1533752054,18.7,42
-1533752055,40.1,39
-1533752056,40.1,39
-.Ed
-.
-.
-.Sh SEE ALSO
-.
-.Xr ploot-feed 1 ,
-.Xr ploot-farbfeld 1
-.
-.Sh HISTORY
-.
-.Nm
-was defined at
-.Lk gopher://bitreich.org/1/scm/ploot/ "Bitreich"
-.
-.
-.Sh AUTHORS
-.
-.An Josuah Demangeon
-.Aq Mt me@josuah.net
(DIR) diff --git a/ploot-farbfeld.1 b/ploot-farbfeld.1
@@ -6,7 +6,7 @@
.Sh NAME
.
.Nm ploot-ffplot
-.Nd produce a ffplot image of csv input
+.Nd produce a ffplot image of tsv input
.
.
.Sh SYNOPSIS
@@ -20,7 +20,7 @@
.
The
.Nm
-utility plots an image in the ffplot format out of csv values coming from stdin.
+utility plots an image in the ffplot format out of tsv values coming from stdin.
.
.Bl -tag -width 6n
.
@@ -29,7 +29,7 @@ Set the title of the plot printed at the top left corner.
.
.It Ar colors
List of argument that specify the color for each column.
-If the input csv have 5 columns in addition of the timestamp, there must
+If the input tsv have 5 columns in addition of the timestamp, there must
be 5 maxval arguments.
color_ts available are red, orange, yellow, green, cyan and blue.
.
@@ -37,7 +37,7 @@ color_ts available are red, orange, yellow, green, cyan and blue.
.
.Pp
The input format is documented in the
-.Xr ploot-csv 7
+.Xr ploot-tsv 7
manual page.
.
.
@@ -62,7 +62,7 @@ $ ploot-ffplot -t demo -u MB red yellow <sample.txt
.Sh SEE ALSO
.
.Xr ploot-ffplot 1 ,
-.Xr ploot-csv 7
+.Xr ploot-tsv 7
.
.Pp
The
(DIR) diff --git a/ploot-farbfeld.c b/ploot-farbfeld.c
@@ -11,7 +11,7 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
-#include "csv.h"
+#include "tsv.h"
#include "font.h"
#include "util.h"
@@ -287,7 +287,7 @@ ffplot_title(struct ffplot *plot, struct ffcolor *ct, char *title)
}
static void
-ffplot_plot(struct ffplot *plot, struct csv *vl, struct ffcolor *color,
+ffplot_plot(struct ffplot *plot, struct tsv *vl, struct ffcolor *color,
double vmin, double vmax,
time_t tmin, time_t tmax)
{
@@ -310,7 +310,7 @@ ffplot_plot(struct ffplot *plot, struct csv *vl, struct ffcolor *color,
}
static void
-ffplot_values(struct ffplot *plot, struct csv *vl, struct ffcolor **cl, size_t ncol,
+ffplot_values(struct ffplot *plot, struct tsv *vl, struct ffcolor **cl, size_t ncol,
time_t tmin, time_t tmax,
double vmin, double vmax)
{
@@ -319,7 +319,7 @@ ffplot_values(struct ffplot *plot, struct csv *vl, struct ffcolor **cl, size_t n
}
static void
-ffplot_legend(struct ffplot *plot, struct ffcolor *fg, struct csv *vl, struct ffcolor **cl, size_t ncol)
+ffplot_legend(struct ffplot *plot, struct ffcolor *fg, struct tsv *vl, struct ffcolor **cl, size_t ncol)
{
size_t x, y;
@@ -342,7 +342,7 @@ ffplot_legend(struct ffplot *plot, struct ffcolor *fg, struct csv *vl, struct ff
* x label here
*/
static void
-plot(struct csv *vl, struct ffcolor **cl, size_t ncol, char *name)
+plot(struct tsv *vl, struct ffcolor **cl, size_t ncol, char *name)
{
struct ffplot plot = { IMAGE_W, IMAGE_H, 0, 0, NULL };
struct ffcolor plot_bg = { 0x2222, 0x2222, 0x2222, 0xffff };
@@ -353,7 +353,7 @@ plot(struct csv *vl, struct ffcolor **cl, size_t ncol, char *name)
double vmin, vmax, vstep;
time_t tmin, tmax, tstep;
- csv_min_max(vl, ncol, &tmin, &tmax, &vmin, &vmax);
+ tsv_min_max(vl, ncol, &tmin, &tmax, &vmin, &vmax);
tstep = scale_time_t(tmin, tmax, 7);
vstep = scale_double(vmin, vmax, 7);
@@ -424,7 +424,7 @@ usage(void)
int
main(int argc, char **argv)
{
- struct csv *vl;
+ struct tsv *vl;
struct ffcolor **cl;
size_t ncol;
int c;
@@ -451,12 +451,12 @@ main(int argc, char **argv)
if ((cl = calloc(argc, sizeof *cl)) == NULL)
err(1, "calloc: %s", strerror(errno));
- csv_labels(stdin, &vl, &ncol);
+ tsv_labels(stdin, &vl, &ncol);
if (ncol > (size_t)argc)
err(1, "too many columns or not enough arguments");
else if (ncol < (size_t)argc)
err(1, "too many arguments or not enough columns");
- csv_values(stdin, vl, ncol);
+ tsv_values(stdin, vl, ncol);
argv_to_color(cl, argv);
plot(vl, cl, argc, flag_title);
(DIR) diff --git a/ploot-feed.1 b/ploot-feed.1
@@ -20,7 +20,7 @@
.
The
.Nm
-utility plots a text chart of csv values coming from stdin in real time.
+utility plots a text chart of tsv values coming from stdin in real time.
.
.Bl -tag -width 6n
.
@@ -29,14 +29,14 @@ is the width of the plot in characters.
.
.It Ar maxval
is a list of argument that specify the maximum value for each column.
-If the input csv have 5 columns in addition of the timestamp, there must
+If the input tsv have 5 columns in addition of the timestamp, there must
be 5 maxval arguments.
.
.El
.
.Pp
The input format is documented in the
-.Xr ploot-csv 7
+.Xr ploot-tsv 7
manual page.
.
.
(DIR) diff --git a/ploot-feed.c b/ploot-feed.c
@@ -59,14 +59,14 @@ plot_row(long *out, char *line, double *max, int nrow, int ncol)
int n;
char *tok;
- tok = strsep(&line, ",");
+ tok = strsep(&line, "\t");
if (!tok)
err(100, "*** missing epoch value");
epoch = strtol(tok, NULL, 10);
if (errno)
warn("*** parsing epoch '%s'", tok);
- for (n = 0; (tok = strsep(&line, ",")) != NULL; n++) {
+ for (n = 0; (tok = strsep(&line, "\t")) != NULL; n++) {
if (n >= ncol)
err(100, "too many values");
val = atof(tok);
@@ -186,10 +186,10 @@ read_labels(char **labv)
strchomp(line);
cp = line;
- if (strcmp(strsep(&cp, ","), "epoch") != 0)
+ if (strcmp(strsep(&cp, "\t"), "epoch") != 0)
err(100, "first label must be 'epoch'");
- for (ncol = 0; (tok = strsep(&cp, ",")) != NULL; ncol++, labv++)
+ for (ncol = 0; (tok = strsep(&cp, "\t")) != NULL; ncol++, labv++)
*labv = tok;
*labv = NULL;
@@ -212,7 +212,7 @@ fmt_labels(char out[4069], int ncol, char *labels[4069 / 2])
static void
usage(void)
{
- fprintf(stderr, "usage: %s [-w width] maxval... <csv\n", arg0);
+ fprintf(stderr, "usage: %s [-w width] maxval... <tsv\n", arg0);
exit(1);
}
(DIR) diff --git a/ploot-tsv.5 b/ploot-tsv.5
@@ -0,0 +1,77 @@
+.Dd $Mdocdate: February 01 2020$
+.Dt PLOOT-TSV 5
+.Os
+.
+.
+.Sh NAME
+.
+.Nm ploot-tsv
+.Nd input format used by the ploot set of programs
+.
+.
+.Sh SYNOPSIS
+.
+.Bd -literal
+epoch,column-name-1,column-name-2
+timestamp,value1,value2
+timestamp,value1,value2
+\&...
+.Ed
+.
+.
+.Sh DESCRIPTION
+.
+This is the simple coma-separated format used by the ploot-* programs.
+.
+.
+.Sh INPUT FORMAT
+.
+.Nm
+has a first header line, then zero or more data lines, both
+coma-separated list of values.
+.
+.
+.Ss Header line
+.
+The input must contain a first header line with the label of each column in order.
+The first column is always
+.Dq epoch .
+Then there are the actual column names.
+.
+.Bd -literal -offset indent
+epoch,free_memory,process_count
+.Ed
+.
+.
+.Ss Data lines
+.
+The following lines are the data.
+The first column is always an unix timestamp as in
+.Vt time_t .
+The remaining columns are values parsed as floating point numbers by
+.Xr strtod 3 :
+.
+.Bd -literal -offset indent
+1533752053,16.3,45
+1533752054,18.7,42
+1533752055,40.1,39
+1533752056,40.1,39
+.Ed
+.
+.
+.Sh SEE ALSO
+.
+.Xr ploot-feed 1 ,
+.Xr ploot-farbfeld 1
+.
+.Sh HISTORY
+.
+.Nm
+was defined at
+.Lk gopher://bitreich.org/1/scm/ploot/ "Bitreich"
+.
+.
+.Sh AUTHORS
+.
+.An Josuah Demangeon
+.Aq Mt me@josuah.net
(DIR) diff --git a/tsv.c b/tsv.c
@@ -0,0 +1,154 @@
+#include "tsv.h"
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <time.h>
+#include "util.h"
+
+/*
+ * Read TSV data onto a set of (struct tsv) and some utilities to work on these data.
+ */
+
+int
+tsv_min_max(struct tsv *vl, int ncol,
+ time_t *tmin, time_t *tmax,
+ double *vmin, double *vmax)
+{
+ double *v;
+ time_t *t;
+ size_t n;
+
+ *vmin = *vmax = 0; /* always show 0 on the scale */
+ *tmin = *tmax = *vl->t;
+
+ for (; ncol > 0; ncol--, vl++) {
+ for (t = vl->t, v = vl->v, n = vl->n; n > 0; t++, v++, n--) {
+ if (*v < *vmin) *vmin = *v;
+ if (*v > *vmax) *vmax = *v;
+ if (*t < *tmin) *tmin = *t;
+ if (*t > *tmax) *tmax = *t;
+ }
+ }
+ if (*tmin == *tmax)
+ return -1;
+ return 0;
+}
+
+static void
+tsv_add_time(struct tsv *vl, time_t epoch)
+{
+ void *mem;
+
+ if ((mem = realloc(vl->t, (vl->n + 1) * sizeof *vl->t)) == NULL)
+ err(1, "realloc: %s", strerror(errno));
+ vl->t = mem;
+ vl->t[vl->n] = epoch;
+}
+
+static void
+tsv_add_val(struct tsv *vl, double field)
+{
+ void *mem;
+
+ if ((mem = realloc(vl->v, (vl->n + 1) * sizeof *vl->v)) == NULL)
+ err(1, "", strerror(errno));
+ vl->v = mem;
+ vl->v[vl->n] = field;
+}
+
+/*
+ * Add to each column the value on the current row. The time_t
+ * buffer is shared among all fields.
+ */
+static void
+tsv_add_row(struct tsv *vl, size_t ncol, char *line)
+{
+ char *field;
+ time_t *tbuf;
+ long l;
+ double d;
+
+ if ((field = strsep(&line, "\t")) == NULL)
+ err(1, "missing epoch at row %zu", vl->n);
+
+ l = strtol(field, NULL, 10);
+ if (errno)
+ err(100, "parsing number '%s'", field);
+
+ tsv_add_time(vl, l);
+ tbuf = vl[0].t;
+ for (; (field = strsep(&line, "\t")); ncol--, vl->n++, vl++) {
+ if (ncol == 0)
+ err(1, "too many fields at line %zu", vl->n);
+ d = strtod(field, NULL);
+ if (errno)
+ err(100, "parsing double '%s'", field);
+ tsv_add_val(vl, d);
+ vl->t = tbuf;
+ }
+ if (ncol > 0)
+ err(1, "too few fields at line %zu", vl->n);
+}
+
+/*
+ * < (ncol) >
+ * label1,label2,label3
+ */
+void
+tsv_labels(FILE *fp, struct tsv **vlp, size_t *ncol)
+{
+ char *field, *line, *cp;
+ struct tsv *vl, *col;
+ size_t sz;
+ ssize_t r;
+
+ sz = 0, line = NULL;
+ r = getline(&line, &sz, fp);
+ if (ferror(fp))
+ err(111, "error while reading from file");
+ if (feof(fp))
+ err(100, "missing label line");
+ strchomp(line);
+
+ cp = line;
+ if (strcmp(strsep(&cp, "\t"), "epoch") != 0)
+ err(1, "first label must be 'epoch'");
+
+ sz = 0, vl = NULL, *ncol = 0;
+ while ((field = strsep(&cp, "\t"))) {
+ if ((vl = realloc(vl, sz += sizeof *vl)) == NULL)
+ err(1, "realloc: %s", strerror(errno));
+ col = vl + (*ncol)++;
+ memset(col, 0, sizeof *vl);
+ strlcpy(col->label, field, sizeof col->label);
+ }
+ free(line);
+ *vlp = vl;
+}
+
+/*
+ * < (ncol) >
+ * val1a,val1b,val1c ^
+ * val2a,val2b,val2c |
+ * val3a,val3b,val3c (vl->n)
+ * val4a,val4b,val4c |
+ * val5a,val5b,val5c v
+ */
+void
+tsv_values(FILE *fp, struct tsv *vl, size_t ncol)
+{
+ char *line;
+ size_t sz;
+
+ sz = 0, line = NULL;
+ while (getline(&line, &sz, fp) > -1)
+ tsv_add_row(vl, ncol, line);
+ if (vl->n == 0)
+ err(1, "no value could be read");
+ if (vl->n == 1)
+ err(1, "only one value could be read");
+ free(line);
+}
(DIR) diff --git a/tsv.h b/tsv.h
@@ -0,0 +1,22 @@
+#ifndef TSV_H
+#define TSV_H
+
+#include <stdio.h>
+#include <time.h>
+
+/*
+ * List of values and timestamps. Both have their dedicated buffer
+ * so that the timestamp buffer can be shared across tsv objects.
+ */
+struct tsv {
+ time_t *t; /* array of timestamps */
+ double *v; /* array of values */
+ size_t n; /* number of values */
+ char label[64]; /* for the legend */
+};
+
+void tsv_labels(FILE *, struct tsv **, size_t *);
+void tsv_values(FILE *, struct tsv *, size_t);
+int tsv_min_max(struct tsv *, int, time_t *, time_t *, double *, double *);
+
+#endif