]> mj.ucw.cz Git - libucw.git/commitdiff
Fastbuf: Added fw-hex wrapper
authorMartin Mares <mj@ucw.cz>
Wed, 8 Jul 2015 17:02:48 +0000 (19:02 +0200)
committerMartin Mares <mj@ucw.cz>
Wed, 8 Jul 2015 17:02:48 +0000 (19:02 +0200)
ucw/Makefile
ucw/doc/fastbuf.txt
ucw/fw-hex.c [new file with mode: 0644]
ucw/fw-hex.h [new file with mode: 0644]

index c886cb697bdc50a64cc39f49995f5c36003e143c..dfdc9fbe49ef920175ab605660e2b56ceca15e7e 100644 (file)
@@ -1,4 +1,4 @@
-# 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
@@ -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 \
index 13590a5dd431101a97ae3baec0b3947f6f8915c2..0d0456f9a2f29c060fb469db1ecd4cb9c874ed8c 100644 (file)
@@ -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:
 - <<ffbasic,Basic functions>>
 
+.Wrappers:
+- <<fwhex,Hexadecimal wrapper>>
+
 .Other reading:
 - <<internal,Internal structure>>
 - <<bconfig,Configuring streams>>
@@ -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 (file)
index 0000000..18e70ce
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ *     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;
+}
diff --git a/ucw/fw-hex.h b/ucw/fw-hex.h
new file mode 100644 (file)
index 0000000..666f9b2
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *     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