chiark / gitweb /
Various fixes.
[misc] / gorp.c
diff --git a/gorp.c b/gorp.c
index 398e852b3b2dbc260e827da26c93575e2792227e..81b4608d8c425c56f9ffddb60fc9a5a3459f6415 100644 (file)
--- a/gorp.c
+++ b/gorp.c
@@ -7,6 +7,7 @@
 
 #include <mLib/alloc.h>
 #include <mLib/base64.h>
+#include <mLib/base32.h>
 #include <mLib/dstr.h>
 #include <mLib/hex.h>
 #include <mLib/mdwopt.h>
@@ -23,102 +24,91 @@ struct format {
 
 #define CHUNK 1024
 
-static void format_base64(size_t n, unsigned line)
+static void do_format(size_t n, unsigned line, void *ctx,
+                     void (*encode)(void *, char *, size_t, dstr *),
+                     void (*fix)(char *, size_t))
 {
-  unsigned char buf[CHUNK];
+  char buf[CHUNK];
   dstr d = DSTR_INIT;
-  base64_ctx b;
-
-  base64_init(&b);
-  if (line) {
-    b.indent = "\n";
-    b.maxline = line;
-  } else {
-    b.indent = "";
-    b.maxline = 0;
-  }
 
   while (n) {
     size_t nn = CHUNK;
     if (nn > n) nn = n;
     rand_get(RAND_GLOBAL, buf, nn);
-    base64_encode(&b, buf, nn, &d);
+    encode(ctx, buf, nn, &d);
+    if (fix) fix(d.buf, d.len);
     DWRITE(&d, stdout);
     DRESET(&d);
     n -= nn;
   }
-  base64_encode(&b, 0, 0, &d);
+  encode(ctx, 0, 0, &d);
   if (!line) {
     while (d.len && d.buf[d.len - 1] == '=')
       d.len--;
   }
+  if (fix) fix(d.buf, d.len);
   DPUTC(&d, '\n');
-  DWRITE(&d, stdout);
+  DWRITE(&d, stdout);  
 }
 
-static void file_fix(char *p, size_t n)
+static void do_base64(void *ctx, char *p, size_t sz, dstr *d)
+  { base64_encode(ctx, p, sz, d); }
+static void do_format_base64(size_t n, unsigned line,
+                            void (*fix)(char *, size_t))
+{
+  base64_ctx b;
+
+  base64_init(&b);
+  if (line) { b.indent = "\n"; b.maxline = line; }
+  else { b.indent = ""; b.maxline = 0; }
+  do_format(n, line, &b, do_base64, fix);
+}
+static void format_base64(size_t n, unsigned line)
+  { do_format_base64(n, line, 0); }
+  
+static void do_base32(void *ctx, char *p, size_t sz, dstr *d)
+  { base32_encode(ctx, p, sz, d); }
+static void format_base32(size_t n, unsigned line)
+{
+  base32_ctx b;
+
+  base32_init(&b);
+  if (line) { b.indent = "\n"; b.maxline = line; }
+  else { b.indent = ""; b.maxline = 0; }
+  do_format(n, line, &b, do_base32, 0);
+}
+
+static void fix_file64(char *p, size_t n)
 {
   while (n) {
     if (*p == '/') *p = '%';
     p++; n--;
   }
 }
-
 static void format_file64(size_t n, unsigned line)
-{
-  unsigned char buf[CHUNK];
-  dstr d = DSTR_INIT;
-  base64_ctx b;
-
-  base64_init(&b);
-  b.indent = "";
-  b.maxline = 0;
+  { do_format_base64(n, line, fix_file64); }
 
+static void fix_safe64(char *p, size_t n)
+{
   while (n) {
-    size_t nn = CHUNK;
-    if (nn > n) nn = n;
-    rand_get(RAND_GLOBAL, buf, nn);
-    base64_encode(&b, buf, nn, &d);
-    file_fix(d.buf, d.len);
-    DWRITE(&d, stdout);
-    DRESET(&d);
-    n -= nn;
+    if (*p == '+') *p = '-';
+    else if (*p == '/') *p = '_';
+    p++; n--;
   }
-  base64_encode(&b, 0, 0, &d);
-  file_fix(d.buf, d.len);
-  while (d.len && d.buf[d.len - 1] == '=')
-    d.len--;
-  DPUTC(&d, '\n');
-  DWRITE(&d, stdout);
 }
+static void format_safe64(size_t n, unsigned line)
+  { do_format_base64(n, line, fix_safe64); }
 
+static void do_hex(void *ctx, char *p, size_t sz, dstr *d)
+  { hex_encode(ctx, p, sz, d); }
 static void format_hex(size_t n, unsigned line)
 {
-  unsigned char buf[CHUNK];
-  dstr d = DSTR_INIT;
-  hex_ctx h;
+  hex_ctx b;
 
-  hex_init(&h);
-  if (line) {
-    h.indent = "\n";
-    h.maxline = line;
-  } else {
-    h.indent = "";
-    h.maxline = 0;
-  }
-
-  while (n) {
-    size_t nn = CHUNK;
-    if (nn > n) nn = n;
-    rand_get(RAND_GLOBAL, buf, nn);
-    hex_encode(&h, buf, nn, &d);
-    DWRITE(&d, stdout);
-    DRESET(&d);
-    n -= nn;
-  }
-  hex_encode(&h, 0, 0, &d);
-  DPUTC(&d, '\n');
-  DWRITE(&d, stdout);
+  hex_init(&b);
+  if (line) { b.indent = "\n"; b.maxline = line; }
+  else { b.indent = ""; b.maxline = 0; }
+  do_format(n, line, &b, do_hex, 0);
 }
 
 static void format_raw(size_t n, unsigned line)
@@ -137,6 +127,8 @@ static void format_raw(size_t n, unsigned line)
 static const struct format fmt[] = {
   { "base64",  format_base64 },
   { "file64",  format_file64 },
+  { "safe64",  format_safe64 },
+  { "base32",  format_base32 },
   { "hex",     format_hex },
   { "raw",     format_raw },
   { 0,         0 }
@@ -178,7 +170,8 @@ Options:\n\
 \n\
 -y, --bytes            Output length is bytes, not bits.\n\
 -l, --line=LENGTH      For textual output, limit line length to LENGTH.\n\
--f, --format=FORMAT    Select output format: base64, file64, hex, raw.\n\
+-f, --format=FORMAT    Select output format:\n\
+                         base64, file64, safe64, base32, hex, raw.\n\
 ", stdout);
 }