-# Makefile for the UCW Library (c) 1997--2014 Martin Mares <mj@ucw.cz>
+# Makefile for the UCW Library (c) 1997--2015 Martin Mares <mj@ucw.cz>
DIRS+=ucw
LIBUCW=$(o)/ucw/libucw.pc
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 \
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 \
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
.Front-ends:
- <<ffbasic,Basic functions>>
+.Wrappers:
+- <<fwhex,Hexadecimal wrapper>>
+
.Other reading:
- <<internal,Internal structure>>
- <<bconfig,Configuring streams>>
!!ucw/ff-binary.h
+ucw/fw-hex.h [[fwhex]]
+----------------------
+
+!!ucw/fw-hex.h
+
Exceptions [[fbexc]]
--------------------
--- /dev/null
+/*
+ * 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 <= 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 = "<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;
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef _UCW_FW_HEX_H
+#define _UCW_FW_HEX_H
+
+#include <ucw/fastbuf.h>
+
+#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 `<XY>`. 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 `<XY>`. All other characters
+ * are copied verbatim.
+ **/
+struct fastbuf *fb_wrap_hex_in(struct fastbuf *f);
+
+#endif