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}