Introduction
Introduction Statistics Contact Development Disclaimer Help
util.c - farbfeld - suckless image format with conversion tools
git clone git://git.suckless.org/farbfeld
Log
Files
Refs
README
LICENSE
---
util.c (4197B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <arpa/inet.h>
3
4 #include <errno.h>
5 #include <limits.h>
6 #include <stdarg.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/types.h>
12
13 #include "util.h"
14
15 char *argv0;
16
17 static void
18 verr(const char *fmt, va_list ap)
19 {
20 if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) {
21 fprintf(stderr, "%s: ", argv0);
22 }
23
24 vfprintf(stderr, fmt, ap);
25
26 if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
27 fputc(' ', stderr);
28 perror(NULL);
29 } else {
30 fputc('\n', stderr);
31 }
32 }
33
34 void
35 warn(const char *fmt, ...)
36 {
37 va_list ap;
38
39 va_start(ap, fmt);
40 verr(fmt, ap);
41 va_end(ap);
42 }
43
44 void
45 die(const char *fmt, ...)
46 {
47 va_list ap;
48
49 va_start(ap, fmt);
50 verr(fmt, ap);
51 va_end(ap);
52
53 exit(1);
54 }
55
56 void
57 ff_read_header(uint32_t *width, uint32_t *height)
58 {
59 uint32_t hdr[4];
60
61 efread(hdr, sizeof(*hdr), LEN(hdr), stdin);
62
63 if (memcmp("farbfeld", hdr, sizeof("farbfeld") - 1)) {
64 die("Invalid magic value");
65 }
66
67 *width = ntohl(hdr[2]);
68 *height = ntohl(hdr[3]);
69 }
70
71 void
72 ff_write_header(uint32_t width, uint32_t height)
73 {
74 uint32_t tmp;
75
76 fputs("farbfeld", stdout);
77
78 tmp = htonl(width);
79 efwrite(&tmp, sizeof(tmp), 1, stdout);
80
81 tmp = htonl(height);
82 efwrite(&tmp, sizeof(tmp), 1, stdout);
83 }
84
85 int
86 parse_mask(const char *s, uint16_t mask[3])
87 {
88 size_t slen, i;
89 unsigned int col[3], colfac;
90 char fmt[] = "%#x%#x%#x";
91
92 slen = strlen(s);
93 if (slen != 3 && slen != 6 && slen != 12) {
94 return 1;
95 }
96
97 fmt[1] = fmt[4] = fmt[7] = ((slen / 3) + '0');
98 if (sscanf(s, fmt, col, col + 1, col + 2) != 3) {
99 return 1;
100 }
101
102 colfac = (slen == 3) ? UINT16_MAX / 0xf :
103 (slen == 6) ? UINT16_MAX / 0xff :
104 UINT16_MAX / 0xffff;
105
106 for (i = 0; i < 3; i++) {
107 mask[i] = col[i] * colfac;
108 }
109
110 return 0;
111 }
112
113 int
114 fshut(FILE *fp, const char *fname)
115 {
116 int ret = 0;
117
118 /* fflush() is undefined for input streams by ISO C,
119 * but not POSIX 2008 if you ignore ISO C overrides.
120 * Leave it unchecked and rely on the following
121 * functions to detect errors.
122 */
123 fflush(fp);
124
125 if (ferror(fp) && !ret) {
126 warn("ferror '%s':", fname);
127 ret = 1;
128 }
129
130 if (fclose(fp) && !ret) {
131 warn("fclose '%s':", fname);
132 ret = 1;
133 }
134
135 return ret;
136 }
137
138 void
139 efread(void *p, size_t s, size_t n, FILE *f)
140 {
141 if (fread(p, s, n, f) != n) {
142 if (ferror(f)) {
143 die("fread:");
144 } else {
145 die("fread: Unexpected end of file");
146 }
147 }
148 }
149
150 void
151 efwrite(const void *p, size_t s, size_t n, FILE *f)
152 {
153 if (fwrite(p, s, n, f) != n) {
154 die("fwrite:");
155 }
156 }
157
158 void *
159 ereallocarray(void *optr, size_t nmemb, size_t size)
160 {
161 void *p;
162
163 if (!(p = reallocarray(optr, nmemb, size))) {
164 die("reallocarray: Out of memory");
165 }
166
167 return p;
168 }
169
170 long long
171 estrtonum(const char *numstr, long long minval, long long maxval)
172 {
173 const char *errstr;
174 long long ll;
175
176 ll = strtonum(numstr, minval, maxval, &errstr);
177 if (errstr) {
178 die("strtonum '%s': %s", numstr, errstr);
179 }
180
181 return ll;
182 }
183
184 /*
185 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
186 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
187 */
188 #define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
189
190 void *
191 reallocarray(void *optr, size_t nmemb, size_t size)
192 {
193 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
194 nmemb > 0 && SIZE_MAX / nmemb < size) {
195 errno = ENOMEM;
196 return NULL;
197 }
198 return realloc(optr, size * nmemb);
199 }
200
201 #define INVALID 1
202 #define TOOSMALL 2
203 #define TOOLARGE 3
204
205 long long
206 strtonum(const char *numstr, long long minval, long long maxval,
207 const char **errstrp)
208 {
209 long long ll = 0;
210 int error = 0;
211 char *ep;
212 struct errval {
213 const char *errstr;
214 int err;
215 } ev[4] = {
216 { NULL, 0 },
217 { "invalid", EINVAL },
218 { "too small", ERANGE },
219 { "too large", ERANGE },
220 };
221
222 ev[0].err = errno;
223 errno = 0;
224 if (minval > maxval) {
225 error = INVALID;
226 } else {
227 ll = strtoll(numstr, &ep, 10);
228 if (numstr == ep || *ep != '\0')
229 error = INVALID;
230 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < mi…
231 error = TOOSMALL;
232 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > ma…
233 error = TOOLARGE;
234 }
235 if (errstrp != NULL)
236 *errstrp = ev[error].errstr;
237 errno = ev[error].err;
238 if (error)
239 ll = 0;
240
241 return (ll);
242 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.