util.c - 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
---
util.c (3219B)
---
1 #include "util.h"
2 #include <assert.h>
3 #include <ctype.h>
4 #include <errno.h>
5 #include <limits.h>
6 #include <stdarg.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 char const *arg0;
12
13 static void
14 _log(char const *fmt, va_list va)
15 {
16 if (arg0 != NULL)
17 fprintf(stderr, "%s: ", arg0);
18 vfprintf(stderr, fmt, va);
19 fprintf(stderr, "\n");
20 fflush(stderr);
21 }
22
23 void
24 err(int e, char const *fmt, ...)
25 {
26 va_list va;
27
28 va_start(va, fmt);
29 _log( fmt, va);
30 exit(e);
31 }
32
33 void
34 warn(char const *fmt, ...)
35 {
36 va_list va;
37
38 va_start(va, fmt);
39 _log(fmt, va);
40 }
41
42 void
43 debug(char const *fmt, ...)
44 {
45 static int verbose = -1;
46 va_list va;
47
48 if (verbose < 0)
49 verbose = (getenv("DEBUG") != NULL);
50 if (!verbose)
51 return;
52 va_start(va, fmt);
53 _log(fmt, va);
54 }
55
56 size_t
57 strlcpy(char *buf, const char *str, size_t sz)
58 {
59 size_t len, cpy;
60
61 cpy = ((len = strlen(str)) > sz) ? (sz) : (len);
62 memcpy(buf, str, cpy);
63 buf[sz - 1] = '\0';
64 return len;
65 }
66
67 void
68 put3utf(long rune)
69 {
70 putchar((char)(0xe0 | (0x0f & (rune >> 12)))); /* 1110xxxx */
71 putchar((char)(0x80 | (0x3f & (rune >> 6)))); /* 10xxxxxx */
72 putchar((char)(0x80 | (0x3f & (rune)))); /* 10xxxxxx */
73 }
74
75 char *
76 strsep(char **strp, const char *sep)
77 {
78 char *s, *prev;
79
80 if (*strp == NULL)
81 return NULL;
82 for (s = prev = *strp; strchr(sep, *s) == NULL; s++);
83 if (*s == '\0') {
84 *strp = NULL;
85 return prev;
86 }
87 *s = '\0';
88 *strp = s + 1;
89
90 return prev;
91 }
92
93 void
94 strchomp(char *s)
95 {
96 char *x = s + strlen(s);
97
98 while (--x >= s && (*x == '\r' || *x == '\n'))
99 *x = '\0';
100 }
101
102 /*
103 * Set 'str' to a human-readable form of 'num' with always a width of 8 (+1 for
104 * the '\0' terminator). Buffer overflow is ensured not to happen due to the
105 * max size of a double. Return the exponent.
106 */
107 int
108 humanize(char *str, double val)
109 {
110 int exp, precision;
111 char label[] = { '\0', 'M', 'G', 'T', 'E' };
112
113 for (exp = 0; ABS(val) > 1000; exp++)
114 val /= 1000;
115
116 precision = (ABS(val) < 10) ? 2 : (ABS(val) < 100) ? 1 : 0;
117 precision += (exp == 0);
118
119 snprintf(str, 9, "%+.*f %c", precision, val, label[exp]);
120 str[8] = '\0';
121 if (val >= 0)
122 str[0] = ' ';
123
124 return exp * 3;
125 }
126
127 time_t
128 scale_time_t(time_t min, time_t max, int dots)
129 {
130 time_t dt, scale[] = {
131 1, 5, 2, 10, 20, 30, 60, 60*2, 60*5, 60*10, 60*20, 60*30, 3600,
132 3600*2, 3600*6, 3600*12, 3600*24, 3600*24*2,
133 3600*24*7, 3600*24*14, 3600*24*20, 3600*24*21, 3600*24*28, 3600*24*50,
134 3600*24*100, 3600*24*365, 0
135 };
136
137 dt = max - min;
138 for (time_t *sc = scale; *sc > 0; sc++)
139 if (dt < *sc * dots)
140 return *sc;
141 return dt / dots;
142 }
143
144 /*
145 * Make the value scale aligned with round values by changing the
146 * minimal and maximal values.
147 */
148 double
149 scale_double(double min, double max, int rows)
150 {
151 double dv, step, scale[] = { 1, 2, 2.5, 5, };
152
153 dv = max - min;
154 step = 1;
155 if (dv > 1) {
156 for (double mant = 1;; mant *= 10) {
157 double *sc = scale;
158 for (; sc < scale + LEN(scale); sc++) {
159 step = mant * *sc;
160 if (dv < rows * step)
161 return step;
162 }
163 }
164 } else {
165 for (double mant = 1;; mant /= 10) {
166 double *sc = scale + LEN(scale) - 1;
167 for (; sc >= scale; sc--) {
168 double tmp = mant * *sc;
169 if (dv > rows * tmp)
170 return step;
171 step = tmp;
172 }
173 }
174 }
175 assert(!"not reached");
176 return 0;
177 }