util.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 --- 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 }