varnish-cache/lib/libvarnish/vte.c
0
/*-
1
 * Copyright (c) 2019 Varnish Software AS
2
 * All rights reserved.
3
 *
4
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
5
 * Author: Dridi Boukelmoune <dridi.boukelmoune@gmail.com>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 */
31
32
#include "config.h"
33
34
#include <errno.h>
35
#include <limits.h>
36
#include <stdarg.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <sys/types.h> /* for MUSL (ssize_t) */
40
41
#include "vdef.h"
42
#include "miniobj.h"
43
44
#include "vas.h"
45
#include "vsb.h"
46
#include "vte.h"
47
48
#define MINSEP 1
49
#define MAXSEP 3
50
51
struct vte {
52
        unsigned        magic;
53
#define VTE_MAGIC       0xedf42b97
54
        struct vsb      *vsb;
55
        int             c_off;          /* input char offset */
56
        int             l_sz;           /* input line size */
57
        int             l_maxsz;        /* maximum input line size */
58
        int             o_sz;           /* output sz */
59
        int             o_sep;          /* output field separators */
60
        int             f_off;          /* input field offset */
61
        int             f_sz;           /* input field size */
62
        int             f_cnt;          /* actual number of fields */
63
        int             f_maxcnt;       /* maximum number of fields */
64
        int             f_maxsz[];      /* maximum size per field */
65
};
66
67
struct vte *
68 24250
VTE_new(int maxfields, int width)
69
{
70
        struct vte *vte;
71
72 24250
        assert(maxfields > 0);
73 24250
        assert(width > 0);
74
75 24250
        ALLOC_FLEX_OBJ(vte, f_maxsz, maxfields, VTE_MAGIC);
76 24250
        if (vte != NULL) {
77 24250
                vte->o_sz = width;
78 24250
                vte->f_maxcnt = maxfields;
79 24250
                vte->vsb = VSB_new_auto();
80 24250
                AN(vte->vsb);
81 24250
        }
82 24250
        return (vte);
83
}
84
85
void
86 24250
VTE_destroy(struct vte **vtep)
87
{
88
        struct vte *vte;
89
90 24250
        TAKE_OBJ_NOTNULL(vte, vtep, VTE_MAGIC);
91 24250
        AN(vte->vsb);
92 24250
        VSB_destroy(&vte->vsb);
93 24250
        FREE_OBJ(vte);
94 24250
}
95
96
static int
97 156509
vte_update(struct vte *vte)
98
{
99
        const char *p, *q;
100
        int len, fno;
101
102 156509
        AZ(vte->o_sep);
103
104 156509
        len = VSB_len(vte->vsb);
105 156509
        assert(len >= vte->c_off);
106
107 156509
        p = vte->vsb->s_buf + vte->c_off;
108 156509
        q = vte->vsb->s_buf + len;
109 3063912
        for (; p < q; p++) {
110 2907403
                if (vte->f_off < 0) {
111 118100
                        while (p < q && *p != '\n')
112 116300
                                p++;
113 1800
                }
114 2907403
                if (vte->l_sz == 0 && *p == ' ') {
115 1800
                        vte->f_off = -1;
116 1800
                        continue;
117
                }
118 2905603
                if (vte->f_off >= 0 && vte->f_sz == 0 && *p == '\v')
119 4242
                        p++;
120 2905603
                if (*p == '\t' || *p == '\n') {
121 295085
                        fno = vte->f_off;
122 295085
                        if (fno >= 0 && vte->f_sz > vte->f_maxsz[fno])
123 184317
                                vte->f_maxsz[fno] = vte->f_sz;
124 295085
                        fno++;
125 295085
                        assert(fno <= vte->f_maxcnt);
126 295085
                        if (*p == '\t' && fno == vte->f_maxcnt) {
127 0
                                errno = EOVERFLOW;
128 0
                                vte->o_sep = -1;
129 0
                                return (-1);
130
                        }
131 295085
                        vte->f_off = fno;
132 295085
                        vte->f_sz = 0;
133 295085
                }
134 2905603
                if (*p == '\n') {
135 60867
                        vte->f_cnt = vmax(vte->f_cnt, vte->f_off);
136 60867
                        vte->l_maxsz = vmax(vte->l_maxsz, vte->l_sz);
137 60867
                        vte->f_off = 0;
138 60867
                        vte->f_sz = 0;
139 60867
                        vte->l_sz = 0;
140 2905603
                } else if (*p != '\t') {
141 2610518
                        vte->f_sz++;
142 2610518
                        vte->l_sz++;
143 2610518
                }
144 2905603
        }
145
146 156509
        vte->c_off = len;
147 156509
        return (0);
148 156509
}
149
150
int
151 0
VTE_putc(struct vte *vte, char c)
152
{
153
154 0
        CHECK_OBJ_NOTNULL(vte, VTE_MAGIC);
155 0
        AN(c);
156
157 0
        if (vte->o_sep != 0)
158 0
                return (-1);
159
160 0
        if (VSB_putc(vte->vsb, c) < 0) {
161 0
                vte->o_sep = -1;
162 0
                return (-1);
163
        }
164
165 0
        return (vte_update(vte));
166 0
}
167
168
int
169 65917
VTE_cat(struct vte *vte, const char *s)
170
{
171
172 65917
        CHECK_OBJ_NOTNULL(vte, VTE_MAGIC);
173 65917
        AN(s);
174
175 65917
        if (vte->o_sep != 0)
176 0
                return (-1);
177
178 65917
        if (VSB_cat(vte->vsb, s) < 0) {
179 0
                vte->o_sep = -1;
180 0
                return (-1);
181
        }
182
183 65917
        return (vte_update(vte));
184 65917
}
185
186
int
187 90592
VTE_printf(struct vte *vte, const char *fmt, ...)
188
{
189
        va_list ap;
190
        int res;
191
192 90592
        CHECK_OBJ_NOTNULL(vte, VTE_MAGIC);
193 90592
        AN(fmt);
194
195 90592
        if (vte->o_sep != 0)
196 0
                return (-1);
197
198 90592
        va_start(ap, fmt);
199 90592
        res = VSB_vprintf(vte->vsb, fmt, ap);
200 90592
        va_end(ap);
201
202 90592
        if (res < 0) {
203 0
                vte->o_sep = -1;
204 0
                return (-1);
205
        }
206
207 90592
        return (vte_update(vte));
208 90592
}
209
210
int
211 24250
VTE_finish(struct vte *vte)
212
{
213
        int sep;
214
215 24250
        CHECK_OBJ_NOTNULL(vte, VTE_MAGIC);
216
217 24250
        if (vte->o_sep != 0)
218 0
                return (-1);
219
220 24250
        if (VSB_finish(vte->vsb) < 0) {
221 0
                vte->o_sep = -1;
222 0
                return (-1);
223
        }
224
225 24250
        if (vte->f_cnt == 0) {
226 50
                vte->o_sep = INT_MAX;
227 50
                return (0);
228
        }
229
230 24200
        sep = (vte->o_sz - vte->l_maxsz) / vte->f_cnt;
231 24200
        vte->o_sep = vlimit_t(int, sep, MINSEP, MAXSEP);
232 24200
        return (0);
233 24250
}
234
235
#define VTE_FORMAT(func, priv, ...)                     \
236
        do {                                            \
237
                if (func(priv, __VA_ARGS__) < 0)        \
238
                        return (-1);                    \
239
        } while (0)
240
241
int
242 24250
VTE_format(const struct vte *vte, VTE_format_f *func, void *priv)
243
{
244
        int fno, fsz, nsp, just_left;
245
        const char *p, *q, *sep;
246
247 24250
        CHECK_OBJ_NOTNULL(vte, VTE_MAGIC);
248 24250
        AN(func);
249
250 24250
        if (vte->o_sep <= 0)
251 0
                return (-1);
252
253 24250
        nsp = vte->o_sep;
254 24250
        p = VSB_data(vte->vsb);
255 24250
        AN(p);
256 24250
        q = p;
257
258 24250
        fno = 0;
259 24250
        sep = "";
260 24250
        just_left = 0;
261 319360
        while (*p != 0) {
262 295110
                if (*p == '\v') {
263 4242
                        if (p > q) {
264 0
                                VTE_FORMAT(func, priv, "%.*s%s",
265
                                    (int)(p - q), q, sep);
266 0
                        }
267 4242
                        q = ++p;
268 4242
                        just_left = 1;
269 4242
                }
270 295110
                if (!just_left && fno == 0 && *p == ' ')
271 1800
                        fsz = strcspn(p, "\n");
272
                else
273 293310
                        fsz = strcspn(p, "\t\n");
274 295110
                p += fsz;
275 295110
                if (*p == '\t') {
276 234218
                        assert(vte->f_maxsz[fno] + nsp > fsz);
277 234218
                        if (just_left) {
278 4242
                                VTE_FORMAT(func, priv, "%*s%.*s%*s",
279
                                    vte->f_maxsz[fno] - fsz, "",
280
                                    (int)(p - q), q,
281
                                    nsp, "");
282 4242
                                just_left = 0;
283 4242
                        } else {
284 229976
                                VTE_FORMAT(func, priv, "%.*s%*s",
285
                                    (int)(p - q), q,
286
                                    vte->f_maxsz[fno] + nsp - fsz, "");
287
                        }
288 234218
                        fno++;
289 234218
                        q = ++p;
290 234218
                        sep = "";
291 295110
                } else if (*p == '\n') {
292 60867
                        fno = 0;
293 60867
                        p++;
294 60867
                        sep = "\n";
295 60867
                }
296
        }
297
298 24250
        if (q < p)
299 24200
                VTE_FORMAT(func, priv, "%s", q);
300 24250
        return (0);
301 24250
}
302
303
#ifdef TEST_DRIVER
304
305
#include <stdio.h>
306
307
static const char *test_vte =
308
    "name\tref\tcomment\n"
309
    "foo\t\v1\tthe foo\n"
310
    "bar\t\v10\tthe bars\n"
311
    "baz\t\v0\t\n"
312
    "qux\t\v-1\tno eol";
313
314
static const char *test_fmt =
315
    "name  ref  comment\n"
316
    "foo     1  the foo\n"
317
    "bar    10  the bars\n"
318
    "baz     0  \n"
319
    "qux    -1  no eol";
320
321
static int
322 275
test_vsb_format(void *priv, const char *fmt, ...)
323
{
324
        struct vsb *vsb;
325
        va_list ap;
326
        int res;
327
328 275
        CAST_OBJ_NOTNULL(vsb, priv, VSB_MAGIC);
329 275
        AN(fmt);
330
331 275
        va_start(ap, fmt);
332 275
        res = VSB_vprintf(vsb, fmt, ap);
333 275
        va_end(ap);
334
335 275
        return (res);
336
}
337
338
int
339 25
main(int argc, char **argv)
340
{
341
        struct vte *vte;
342
        struct vsb *vsb;
343 25
        int err = 0;
344
345 25
        (void)argc;
346 25
        (void)argv;
347
348 25
        vte = VTE_new(3, 20);
349 25
        AN(vte);
350 25
        AZ(VTE_cat(vte, test_vte));
351 25
        AZ(VTE_finish(vte));
352
353 25
        vsb = VSB_new_auto();
354 25
        AN(vsb);
355 25
        AZ(VTE_format(vte, test_vsb_format, vsb));
356 25
        AZ(VSB_finish(vsb));
357
358 25
        assert(vte->o_sep == 2);
359 25
        assert(vte->f_maxsz[0] == 4);
360 25
        assert(vte->f_maxsz[1] == 3);
361 25
        assert(vte->f_maxsz[2] == 8);
362
363 25
        if (strcmp(VSB_data(vsb), test_fmt)) {
364 0
                fprintf(stderr,
365
                    "Error: VTE output mismatch\n"
366
                    "<<<<<<<\n"
367
                    "%s\n"
368
                    "=======\n"
369
                    "%s\n"
370
                    ">>>>>>>\n"
371
                    "FAIL\n",
372 0
                    VSB_data(vsb), test_fmt);
373 0
                err = 1;
374 0
        }
375
376 25
        VSB_destroy(&vsb);
377 25
        VTE_destroy(&vte);
378 25
        if (!err)
379 25
                printf("PASS\n");
380 25
        return (err);
381
}
382
383
#endif