You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
2.2 KiB
104 lines
2.2 KiB
3 months ago
|
/*
|
||
|
* UCW Library -- I/O Wrapper for Hexadecimal Escaped Debugging Output
|
||
|
*
|
||
|
* (c) 2015 Martin Mares <mj@ucw.cz>
|
||
|
*
|
||
|
* This software may be freely distributed and used according to the terms
|
||
|
* of the GNU Lesser General Public License.
|
||
|
*/
|
||
|
|
||
|
#include <ucw/lib.h>
|
||
|
#include <ucw/chartype.h>
|
||
|
#include <ucw/fastbuf.h>
|
||
|
#include <ucw/fw-hex.h>
|
||
|
|
||
|
#define HEX_BUFSIZE 1024
|
||
|
|
||
|
struct fb_hex {
|
||
|
struct fastbuf fb;
|
||
|
struct fastbuf *orig;
|
||
|
byte buf[HEX_BUFSIZE];
|
||
|
};
|
||
|
#define FB_HEX(f) ((struct fb_hex *)(f))
|
||
|
|
||
|
static void
|
||
|
fb_hex_spout(struct fastbuf *f)
|
||
|
{
|
||
|
struct fastbuf *orig = FB_HEX(f)->orig;
|
||
|
|
||
|
for (byte *p = f->buffer; p < f->bptr; p++)
|
||
|
{
|
||
|
uint c = *p;
|
||
|
if (c >= 0x21 && c <= 0x7e && c != '<' && c != '>')
|
||
|
bputc(orig, c);
|
||
|
else
|
||
|
bprintf(orig, "<%02x>", c);
|
||
|
}
|
||
|
f->bptr = f->buffer;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
fb_hex_refill(struct fastbuf *f)
|
||
|
{
|
||
|
struct fastbuf *orig = FB_HEX(f)->orig;
|
||
|
|
||
|
f->bptr = f->bstop = f->buffer;
|
||
|
while (f->bstop < f->bufend)
|
||
|
{
|
||
|
int c = bgetc(orig);
|
||
|
if (c < 0)
|
||
|
break;
|
||
|
if (c == '<')
|
||
|
{
|
||
|
uint x = 0;
|
||
|
for (int i=0; i<2; i++)
|
||
|
{
|
||
|
int d = bgetc(orig);
|
||
|
if (!Cxdigit(d))
|
||
|
bthrow(f, "fbhex", "fb_hex: Malformed hexadecimal representation");
|
||
|
x = (x << 4) | Cxvalue(d);
|
||
|
}
|
||
|
c = bgetc(orig);
|
||
|
if (c != '>')
|
||
|
bthrow(f, "fbhex", "fb_hex: Expecting '>'");
|
||
|
*f->bstop++ = x;
|
||
|
}
|
||
|
else
|
||
|
*f->bstop++ = c;
|
||
|
}
|
||
|
return (f->bstop > f->bptr);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
fb_hex_close(struct fastbuf *f)
|
||
|
{
|
||
|
if (f->spout)
|
||
|
bputc(FB_HEX(f)->orig, '\n');
|
||
|
bflush(FB_HEX(f)->orig);
|
||
|
xfree(f);
|
||
|
}
|
||
|
|
||
|
struct fastbuf *fb_wrap_hex_out(struct fastbuf *f)
|
||
|
{
|
||
|
struct fastbuf *g = xmalloc_zero(sizeof(struct fb_hex));
|
||
|
FB_HEX(g)->orig = f;
|
||
|
g->name = "<hex-out>";
|
||
|
g->spout = fb_hex_spout;
|
||
|
g->close = fb_hex_close;
|
||
|
g->buffer = g->bstop = g->bptr = FB_HEX(g)->buf;
|
||
|
g->bufend = g->buffer + HEX_BUFSIZE;
|
||
|
return g;
|
||
|
}
|
||
|
|
||
|
struct fastbuf *fb_wrap_hex_in(struct fastbuf *f)
|
||
|
{
|
||
|
struct fastbuf *g = xmalloc_zero(sizeof(struct fb_hex));
|
||
|
FB_HEX(g)->orig = f;
|
||
|
g->name = "<hex-in>";
|
||
|
g->refill = fb_hex_refill;
|
||
|
g->close = fb_hex_close;
|
||
|
g->buffer = g->bstop = g->bptr = FB_HEX(g)->buf;
|
||
|
g->bufend = g->buffer + HEX_BUFSIZE;
|
||
|
return g;
|
||
|
}
|