]> mj.ucw.cz Git - libucw.git/blob - ucw/fw-hex.c
io-careful: Do not fail if a system call is interrupted by a signal
[libucw.git] / ucw / fw-hex.c
1 /*
2  *      UCW Library -- I/O Wrapper for Hexadecimal Escaped Debugging Output
3  *
4  *      (c) 2015 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include <ucw/lib.h>
11 #include <ucw/chartype.h>
12 #include <ucw/fastbuf.h>
13 #include <ucw/fw-hex.h>
14
15 #define HEX_BUFSIZE 1024
16
17 struct fb_hex {
18   struct fastbuf fb;
19   struct fastbuf *orig;
20   byte buf[HEX_BUFSIZE];
21 };
22 #define FB_HEX(f) ((struct fb_hex *)(f))
23
24 static void
25 fb_hex_spout(struct fastbuf *f)
26 {
27   struct fastbuf *orig = FB_HEX(f)->orig;
28
29   for (byte *p = f->buffer; p < f->bptr; p++)
30     {
31       uint c = *p;
32       if (c >= 0x21 && c <= 0x7e && c != '<' && c != '>')
33         bputc(orig, c);
34       else
35         bprintf(orig, "<%02x>", c);
36     }
37   f->bptr = f->buffer;
38 }
39
40 static int
41 fb_hex_refill(struct fastbuf *f)
42 {
43   struct fastbuf *orig = FB_HEX(f)->orig;
44
45   f->bptr = f->bstop = f->buffer;
46   while (f->bstop < f->bufend)
47     {
48       int c = bgetc(orig);
49       if (c < 0)
50         break;
51       if (c == '<')
52         {
53           uint x = 0;
54           for (int i=0; i<2; i++)
55             {
56               int d = bgetc(orig);
57               if (!Cxdigit(d))
58                 bthrow(f, "fbhex", "fb_hex: Malformed hexadecimal representation");
59               x = (x << 4) | Cxvalue(d);
60             }
61           c = bgetc(orig);
62           if (c != '>')
63             bthrow(f, "fbhex", "fb_hex: Expecting '>'");
64           *f->bstop++ = x;
65         }
66       else
67         *f->bstop++ = c;
68     }
69   return (f->bstop > f->bptr);
70 }
71
72 static void
73 fb_hex_close(struct fastbuf *f)
74 {
75   if (f->spout)
76     bputc(FB_HEX(f)->orig, '\n');
77   bflush(FB_HEX(f)->orig);
78   xfree(f);
79 }
80
81 struct fastbuf *fb_wrap_hex_out(struct fastbuf *f)
82 {
83   struct fastbuf *g = xmalloc_zero(sizeof(struct fb_hex));
84   FB_HEX(g)->orig = f;
85   g->name = "<hex-out>";
86   g->spout = fb_hex_spout;
87   g->close = fb_hex_close;
88   g->buffer = g->bstop = g->bptr = FB_HEX(g)->buf;
89   g->bufend = g->buffer + HEX_BUFSIZE;
90   return g;
91 }
92
93 struct fastbuf *fb_wrap_hex_in(struct fastbuf *f)
94 {
95   struct fastbuf *g = xmalloc_zero(sizeof(struct fb_hex));
96   FB_HEX(g)->orig = f;
97   g->name = "<hex-in>";
98   g->refill = fb_hex_refill;
99   g->close = fb_hex_close;
100   g->buffer = g->bstop = g->bptr = FB_HEX(g)->buf;
101   g->bufend = g->buffer + HEX_BUFSIZE;
102   return g;
103 }