From 45e367725dbbf70bf2d326393ff6e459d609695d Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Wed, 8 Jul 2015 19:02:48 +0200 Subject: [PATCH] Fastbuf: Added fw-hex wrapper --- ucw/Makefile | 5 ++- ucw/doc/fastbuf.txt | 13 +++++- ucw/fw-hex.c | 103 ++++++++++++++++++++++++++++++++++++++++++++ ucw/fw-hex.h | 45 +++++++++++++++++++ 4 files changed, 163 insertions(+), 3 deletions(-) create mode 100644 ucw/fw-hex.c create mode 100644 ucw/fw-hex.h diff --git a/ucw/Makefile b/ucw/Makefile index c886cb69..dfdc9fbe 100644 --- a/ucw/Makefile +++ b/ucw/Makefile @@ -1,4 +1,4 @@ -# Makefile for the UCW Library (c) 1997--2014 Martin Mares +# Makefile for the UCW Library (c) 1997--2015 Martin Mares DIRS+=ucw LIBUCW=$(o)/ucw/libucw.pc @@ -18,6 +18,7 @@ LIBUCW_MODS= \ ipaccess \ fastbuf ff-binary ff-string ff-printf ff-unicode ff-varint ff-stkstring \ fb-file fb-mem fb-temp tempfile fb-mmap fb-limfd fb-buffer fb-grow fb-pool fb-atomic fb-param fb-socket fb-multi fb-null \ + fw-hex \ char-cat char-upper char-lower unicode varint stkstring \ wildmatch regex \ prime primetable random \ @@ -54,7 +55,7 @@ LIBUCW_MAIN_INCLUDES= \ prime.h \ bitops.h \ conf.h getopt.h ipaccess.h \ - fastbuf.h io.h ff-unicode.h ff-varint.h ff-binary.h fb-socket.h \ + fastbuf.h io.h ff-unicode.h ff-varint.h ff-binary.h fb-socket.h fw-hex.h \ url.h \ mainloop.h \ process.h \ diff --git a/ucw/doc/fastbuf.txt b/ucw/doc/fastbuf.txt index 13590a5d..0d0456f9 100644 --- a/ucw/doc/fastbuf.txt +++ b/ucw/doc/fastbuf.txt @@ -8,10 +8,13 @@ Fastbufs can represent many different kinds of objects: regular files, network sockets, file descriptors in general, or various memory buffers. These objects are handled by different fastbuf *back-ends.* -Once you have a fastbuf, you can access it by fuctions similar to those of +Once you have a fastbuf, you can access it by functions similar to those of `stdio.h`, or you can use a variety of fastbuf *front-ends* providing various formatted operations. +There are also fastbuf *wrappers*, which serve as both back-ends and front-ends, +taking one stream and converting it to another on the fly. + Please keep in mind that fastbufs do not allow arbitrary mixing of reads and writes on the same stream. If you need to mix them, you have to call @bflush() inbetween and remember that the file position reported by @btell() points after @@ -37,6 +40,9 @@ When the pool gets cleaned up, the fastbuf is automatically closed. If you call .Front-ends: - <> +.Wrappers: +- <> + .Other reading: - <> - <> @@ -68,6 +74,11 @@ ucw/ff-binary.h !!ucw/ff-binary.h +ucw/fw-hex.h [[fwhex]] +---------------------- + +!!ucw/fw-hex.h + Exceptions [[fbexc]] -------------------- diff --git a/ucw/fw-hex.c b/ucw/fw-hex.c new file mode 100644 index 00000000..18e70ced --- /dev/null +++ b/ucw/fw-hex.c @@ -0,0 +1,103 @@ +/* + * UCW Library -- I/O Wrapper for Hexadecimal Escaped Debugging Output + * + * (c) 2015 Martin Mares + * + * This software may be freely distributed and used according to the terms + * of the GNU Lesser General Public License. + */ + +#include +#include +#include +#include + +#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 <= 0x7f && 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 = ""; + 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 = ""; + 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; +} diff --git a/ucw/fw-hex.h b/ucw/fw-hex.h new file mode 100644 index 00000000..666f9b2c --- /dev/null +++ b/ucw/fw-hex.h @@ -0,0 +1,45 @@ +/* + * UCW Library -- I/O Wrapper for Hexadecimal Escaped Debugging Output + * + * (c) 2015 Martin Mares + * + * This software may be freely distributed and used according to the terms + * of the GNU Lesser General Public License. + */ + +#ifndef _UCW_FW_HEX_H +#define _UCW_FW_HEX_H + +#include + +#ifdef CONFIG_UCW_CLEAN_ABI +// FIXME +#endif + +/*** + * When debugging a program, you might wonder what strange characters + * are there in the output, or you might want to spice up the input + * with Unicode snowmen to make the program freeze. + * + * In such situations, you can wrap your input or output stream in + * the hex wrapper, which converts between strange characters and their + * hexadecimal representation. + ***/ + +/** + * Creates an output hex wrapper for the given fastbuf. Printable ASCII + * characters written to the wrapper are copied verbatim to @f. + * Control characters, whitespace and everything outside ASCII + * are transcribed hexadecimally as ``. A newline is appended + * at the end of the output. + **/ +struct fastbuf *fb_wrap_hex_out(struct fastbuf *f); + +/** + * Creates an input hex wrapper for the given fastbuf. It reads characters + * from @f and translates hexadecimal sequences ``. All other characters + * are copied verbatim. + **/ +struct fastbuf *fb_wrap_hex_in(struct fastbuf *f); + +#endif -- 2.39.2