libbootstr-c

C bootstring encoding library
git clone https://git.sinitax.com/sinitax/libbootstr-c
Log | Files | Refs | LICENSE | sfeed.txt

puny.c (2128B)


      1#include "bootstr.h"
      2
      3#include <unistr.h>
      4#include <err.h>
      5#include <stdio.h>
      6#include <string.h>
      7#include <stdint.h>
      8
      9#define CHUNKSIZE 4096
     10
     11bool is_ascii(uint32_t c);
     12
     13const struct bootstr_cfg puny_cfg = {
     14	.base = U"abcdefghijklmnopqrstuvwxyz0123456789",
     15	.baselen = 36,
     16	.delim = U"-",
     17	.is_basic = is_ascii,
     18	.tmin = 1,
     19	.tmax = 26,
     20	.skew = 38,
     21	.damp = 700,
     22	.initial_bias = 72,
     23	.initial_n = 128
     24};
     25
     26bool
     27is_ascii(uint32_t c)
     28{
     29	return c < 128;
     30}
     31
     32uint8_t *
     33readall(FILE *file, size_t *len)
     34{
     35	ssize_t nread;
     36	size_t cap;
     37	uint8_t *data;
     38
     39	*len = 0;
     40	cap = CHUNKSIZE + 1;
     41	data = malloc(cap);
     42	if (!data) err(1, "malloc");
     43
     44	while (1) {
     45		if (*len + CHUNKSIZE + 1 > cap) {
     46			cap *= 2;
     47			data = realloc(data, cap);
     48			if (!data) err(1, "realloc");
     49		}
     50
     51		nread = fread(data + *len, 1, CHUNKSIZE, file);
     52		if (nread <= 0) break;
     53
     54		*len += nread;
     55	}
     56
     57	*(data + *len) = '\0';
     58
     59	return data;
     60}
     61
     62int
     63main(int argc, const char **argv)
     64{
     65	const char **arg;
     66	uint8_t *in, *out;
     67	uint32_t *u_in, *u_out;
     68	size_t inlen, outlen;
     69	size_t u_inlen, u_outlen;
     70	const char *filepath;
     71	bool encode;
     72	char *tok;
     73	FILE *file;
     74	int ret;
     75
     76	encode = true;
     77	filepath = NULL;
     78	for (arg = argv + 1; *arg; arg++) {
     79		if (!strcmp(*arg, "-e")) {
     80			encode = true;
     81		} else if (!strcmp(*arg, "-d")) {
     82			encode = false;
     83		} else if (!filepath) {
     84			filepath = *arg;
     85		} else {
     86			errx(1, "unknown arg %s", *arg);
     87		}
     88	}
     89
     90	out = NULL;
     91	if (filepath) {
     92		file = fopen(filepath, "r");
     93		if (!file) err(1, "fopen %s", filepath);
     94		in = readall(file, &inlen);
     95		fclose(file);
     96	} else {
     97		in = readall(stdin, &inlen);
     98	}
     99	tok = strchr((char *)in, '\n');
    100	if (tok) *tok = '\0';
    101
    102	u_in = u8_to_u32(in, inlen + 1, NULL, &u_inlen);
    103	if (!u_in) errx(1, "invalid utf8");
    104	u_out = NULL;
    105
    106	if (encode) {
    107		ret = bootstr_encode(&puny_cfg, u_in, &u_out);
    108		if (ret) errx(1, "encode: %s", strerror(ret));
    109	} else {
    110		ret = bootstr_decode(&puny_cfg, u_in, &u_out);
    111		if (ret) errx(1, "decode: %s", strerror(ret));
    112	}
    113
    114	out = u32_to_u8(u_out, u32_strlen(u_out) + 1, NULL, &outlen);
    115	printf("%s\n", (char *)out);
    116
    117	free(u_out);
    118	free(u_in);
    119	free(out);
    120	free(in);
    121}