#include <mLib/alloc.h>
#include <mLib/base64.h>
+#include <mLib/base32.h>
#include <mLib/dstr.h>
#include <mLib/hex.h>
#include <mLib/mdwopt.h>
#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)
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 }
\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);
}