From: Ori Bernstein Date: Sat, 3 Jul 2021 20:03:17 +0000 (+0000) Subject: libc: add encode(2) variants for custom alphabets X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=e934530ee4512f033952e4efa80a80058607b741;p=plan9front.git libc: add encode(2) variants for custom alphabets There are a number of alphabets in common use for base32 and base64 encoding, such as url-safe encodings. This adds support for passing a function to encode into arbitary alphabets. --- diff --git a/sys/include/libc.h b/sys/include/libc.h index 4eecd028f..ecc23c343 100644 --- a/sys/include/libc.h +++ b/sys/include/libc.h @@ -385,10 +385,15 @@ extern double charstod(int(*)(void*), void*); extern char* cleanname(char*); extern int decrypt(void*, void*, int); extern int encrypt(void*, void*, int); + extern int dec64(uchar*, int, char*, int); extern int enc64(char*, int, uchar*, int); +extern int dec64x(uchar*, int, char*, int, int (*)(int)); +extern int enc64x(char*, int, uchar*, int, int (*)(int)); extern int dec32(uchar*, int, char*, int); extern int enc32(char*, int, uchar*, int); +extern int dec32x(uchar*, int, char*, int, int (*)(int)); +extern int enc32x(char*, int, uchar*, int, int (*)(int)); extern int dec16(uchar*, int, char*, int); extern int enc16(char*, int, uchar*, int); extern int dec64chr(int); @@ -397,6 +402,7 @@ extern int dec32chr(int); extern int enc32chr(int); extern int dec16chr(int); extern int enc16chr(int); + extern int encodefmt(Fmt*); extern void exits(char*); extern double frexp(double, int*); diff --git a/sys/man/2/encode b/sys/man/2/encode index db7944945..3827e7a6e 100644 --- a/sys/man/2/encode +++ b/sys/man/2/encode @@ -1,6 +1,7 @@ .TH ENCODE 2 .SH NAME dec64, enc64, dec32, enc32, dec16, enc16, \ +dec64x, enc64x, dec32x, enc32x, \ dec64chr, enc64chr, dec32chr, enc32chr, dec16chr, enc16chr, \ encodefmt \- encoding byte arrays as strings .SH SYNOPSIS @@ -12,15 +13,27 @@ encodefmt \- encoding byte arrays as strings int dec64(uchar *out, int lim, char *in, int n) .PP .B +int dec64x(uchar *out, int lim, char *in, int n, int (*map)(int)) +.PP +.B int enc64(char *out, int lim, uchar *in, int n) .PP .B +int enc64x(char *out, int lim, uchar *in, int n, int (*map)(int)) +.PP +.B int dec32(uchar *out, int lim, char *in, int n) .PP .B +int dec32x(uchar *out, int lim, char *in, int n, int (*map)(int)) +.PP +.B int enc32(char *out, int lim, uchar *in, int n) .PP .B +int enc32x(char *out, int lim, uchar *in, int n, int (*map)(int)) +.PP +.B int dec16(uchar *out, int lim, char *in, int n) .PP .B @@ -82,6 +95,31 @@ and .I enc64chr encode a symbol of the alphabet given a value. if the value is out of range then zero is returned. +.PP +The +.I enc64x +and +.I enc32x +variants are identical to the above, except that they take a +function mapping from an arbitrary index in the alphabet to +the encoded character. +For example, in the following 32-character alphabet, +.EX +.I ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 +.EE +the chr function would map the value +.I 3 +to the character +.IR D . + +The +.I dec64x +and +.I dec32x +variants are similar to the above, however the function passed +maps from a character within the alphabet to the index within +the alphabet. + .PP .I Encodefmt can be used with diff --git a/sys/src/libc/port/u32.c b/sys/src/libc/port/u32.c index 9ad9eb781..a7abdc012 100644 --- a/sys/src/libc/port/u32.c +++ b/sys/src/libc/port/u32.c @@ -25,7 +25,7 @@ dec32chr(int c) } int -dec32(uchar *dest, int ndest, char *src, int nsrc) +dec32x(uchar *dest, int ndest, char *src, int nsrc, int (*chr)(int)) { uchar *start; int i, j, u[8]; @@ -35,7 +35,7 @@ dec32(uchar *dest, int ndest, char *src, int nsrc) start = dest; while(nsrc>=8){ for(i=0; i<8; i++){ - j = dec32chr(src[i]); + j = chr(src[i]); if(j < 0) j = 0; u[i] = j; @@ -52,7 +52,7 @@ dec32(uchar *dest, int ndest, char *src, int nsrc) if(nsrc == 1 || nsrc == 3 || nsrc == 6) return -1; for(i=0; i=5){ j = (0x1f & (src[0]>>3)); - *dest++ = enc32chr(j); + *dest++ = chr(j); j = (0x1c & (src[0]<<2)) | (0x03 & (src[1]>>6)); - *dest++ = enc32chr(j); + *dest++ = chr(j); j = (0x1f & (src[1]>>1)); - *dest++ = enc32chr(j); + *dest++ = chr(j); j = (0x10 & (src[1]<<4)) | (0x0f & (src[2]>>4)); - *dest++ = enc32chr(j); + *dest++ = chr(j); j = (0x1e & (src[2]<<1)) | (0x01 & (src[3]>>7)); - *dest++ = enc32chr(j); + *dest++ = chr(j); j = (0x1f & (src[3]>>2)); - *dest++ = enc32chr(j); + *dest++ = chr(j); j = (0x18 & (src[3]<<3)) | (0x07 & (src[4]>>5)); - *dest++ = enc32chr(j); + *dest++ = chr(j); j = (0x1f & (src[4])); - *dest++ = enc32chr(j); + *dest++ = chr(j); src += 5; nsrc -= 5; } if(nsrc){ j = (0x1f & (src[0]>>3)); - *dest++ = enc32chr(j); + *dest++ = chr(j); j = (0x1c & (src[0]<<2)); if(nsrc == 1) goto out; j |= (0x03 & (src[1]>>6)); - *dest++ = enc32chr(j); + *dest++ = chr(j); j = (0x1f & (src[1]>>1)); - *dest++ = enc32chr(j); + *dest++ = chr(j); j = (0x10 & (src[1]<<4)); if(nsrc == 2) goto out; j |= (0x0f & (src[2]>>4)); - *dest++ = enc32chr(j); + *dest++ = chr(j); j = (0x1e & (src[2]<<1)); if(nsrc == 3) goto out; j |= (0x01 & (src[3]>>7)); - *dest++ = enc32chr(j); + *dest++ = chr(j); j = (0x1f & (src[3]>>2)); - *dest++ = enc32chr(j); + *dest++ = chr(j); j = (0x18 & (src[3]<<3)); out: - *dest++ = enc32chr(j); + *dest++ = chr(j); } *dest = 0; return dest-start; } + +int +enc32(char *dest, int ndest, uchar *src, int nsrc) +{ + return enc32x(dest, ndest, src, nsrc, enc32chr); +} + +int +dec32(uchar *dest, int ndest, char *src, int nsrc) +{ + return dec32x(dest, ndest, src, nsrc, dec32chr); +} diff --git a/sys/src/libc/port/u64.c b/sys/src/libc/port/u64.c index 44f716fbe..5be0142b8 100644 --- a/sys/src/libc/port/u64.c +++ b/sys/src/libc/port/u64.c @@ -30,7 +30,7 @@ dec64chr(int c) } int -dec64(uchar *out, int lim, char *in, int n) +dec64x(uchar *out, int lim, char *in, int n, int (*chr)(int)) { ulong b24; uchar *start = out; @@ -40,7 +40,7 @@ dec64(uchar *out, int lim, char *in, int n) b24 = 0; i = 0; while(n-- > 0){ - c = dec64chr(*in++); + c = chr(*in++); if(c < 0) continue; switch(i){ @@ -84,7 +84,7 @@ exhausted: } int -enc64(char *out, int lim, uchar *in, int n) +enc64x(char *out, int lim, uchar *in, int n, int (*chr)(int)) { int i; ulong b24; @@ -97,10 +97,10 @@ enc64(char *out, int lim, uchar *in, int n) b24 |= *in++; if(out + 4 >= e) goto exhausted; - *out++ = enc64chr(b24>>18); - *out++ = enc64chr((b24>>12)&0x3f); - *out++ = enc64chr((b24>>6)&0x3f); - *out++ = enc64chr(b24&0x3f); + *out++ = chr(b24>>18); + *out++ = chr((b24>>12)&0x3f); + *out++ = chr((b24>>6)&0x3f); + *out++ = chr(b24&0x3f); } switch(n%3){ @@ -109,17 +109,17 @@ enc64(char *out, int lim, uchar *in, int n) b24 |= *in<<8; if(out + 4 >= e) goto exhausted; - *out++ = enc64chr(b24>>18); - *out++ = enc64chr((b24>>12)&0x3f); - *out++ = enc64chr((b24>>6)&0x3f); + *out++ = chr(b24>>18); + *out++ = chr((b24>>12)&0x3f); + *out++ = chr((b24>>6)&0x3f); *out++ = '='; break; case 1: b24 = *in<<16; if(out + 4 >= e) goto exhausted; - *out++ = enc64chr(b24>>18); - *out++ = enc64chr((b24>>12)&0x3f); + *out++ = chr(b24>>18); + *out++ = chr((b24>>12)&0x3f); *out++ = '='; *out++ = '='; break; @@ -128,3 +128,15 @@ exhausted: *out = 0; return out - start; } + +int +enc64(char *out, int lim, uchar *in, int n) +{ + return enc64x(out, lim, in, n, enc64chr); +} + +int +dec64(uchar *out, int lim, char *in, int n) +{ + return dec64x(out, lim, in, n, dec64chr); +}