summaryrefslogtreecommitdiffstats
path: root/src/puny.c
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2023-03-13 21:41:56 +0100
committerLouis Burda <quent.burda@gmail.com>2023-03-13 21:42:03 +0100
commit15ade3d4f156b70da74f599cd2f16dd818e63c41 (patch)
treebe1bb8ff2909cd9cfc694c9f11ef2471144e605f /src/puny.c
parent42636a96271693fc5545da691d624b51b6192b5f (diff)
downloadlibbootstr-c-15ade3d4f156b70da74f599cd2f16dd818e63c41.tar.gz
libbootstr-c-15ade3d4f156b70da74f599cd2f16dd818e63c41.zip
Reorganize and fix install target
Diffstat (limited to 'src/puny.c')
-rw-r--r--src/puny.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/puny.c b/src/puny.c
new file mode 100644
index 0000000..0ea9c29
--- /dev/null
+++ b/src/puny.c
@@ -0,0 +1,120 @@
+#include "bootstr.h"
+
+#include <unistr.h>
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#define CHUNKSIZE 4096
+
+bool is_ascii(uint32_t c);
+
+const struct bootstr_cfg puny_cfg = {
+ .base = U"abcdefghijklmnopqrstuvwxyz0123456789",
+ .baselen = 36,
+ .delim = U"-",
+ .is_basic = is_ascii,
+ .tmin = 1,
+ .tmax = 26,
+ .skew = 38,
+ .damp = 700,
+ .initial_bias = 72,
+ .initial_n = 128
+};
+
+bool
+is_ascii(uint32_t c)
+{
+ return c < 128;
+}
+
+uint8_t *
+readall(FILE *file, size_t *len)
+{
+ ssize_t nread;
+ size_t cap;
+ uint8_t *data;
+
+ *len = 0;
+ cap = CHUNKSIZE + 1;
+ data = malloc(cap);
+ if (!data) err(1, "malloc");
+
+ while (1) {
+ if (*len + CHUNKSIZE + 1 > cap) {
+ cap *= 2;
+ data = realloc(data, cap);
+ if (!data) err(1, "realloc");
+ }
+
+ nread = fread(data + *len, 1, CHUNKSIZE, file);
+ if (nread <= 0) break;
+
+ *len += nread;
+ }
+
+ *(data + *len) = '\0';
+
+ return data;
+}
+
+int
+main(int argc, const char **argv)
+{
+ const char **arg;
+ uint8_t *in, *out;
+ uint32_t *u_in, *u_out;
+ size_t inlen, outlen;
+ size_t u_inlen, u_outlen;
+ const char *filepath;
+ bool encode;
+ char *tok;
+ FILE *file;
+ int ret;
+
+ encode = true;
+ filepath = NULL;
+ for (arg = argv + 1; *arg; arg++) {
+ if (!strcmp(*arg, "-e")) {
+ encode = true;
+ } else if (!strcmp(*arg, "-d")) {
+ encode = false;
+ } else if (!filepath) {
+ filepath = *arg;
+ } else {
+ errx(1, "unknown arg %s", *arg);
+ }
+ }
+
+ out = NULL;
+ if (filepath) {
+ file = fopen(filepath, "r");
+ if (!file) err(1, "fopen %s", filepath);
+ in = readall(file, &inlen);
+ fclose(file);
+ } else {
+ in = readall(stdin, &inlen);
+ }
+ tok = strchr((char *)in, '\n');
+ if (tok) *tok = '\0';
+
+ u_in = u8_to_u32(in, inlen + 1, NULL, &u_inlen);
+ u_out = NULL;
+
+ if (encode) {
+ ret = bootstr_encode(&puny_cfg, u_in, &u_out);
+ if (ret) errx(1, "encode: %s", strerror(ret));
+ } else {
+ ret = bootstr_decode(&puny_cfg, u_in, &u_out);
+ if (ret) errx(1, "decode: %s", strerror(ret));
+ }
+
+ out = u32_to_u8(u_out, u32_strlen(u_out) + 1, NULL, &outlen);
+ printf("%s\n", (char *)out);
+
+ free(u_out);
+ free(u_in);
+ free(out);
+ free(in);
+}