]> git.lizzy.rs Git - plan9front.git/commitdiff
libc: add encode(2) variants for custom alphabets
authorOri Bernstein <ori@eigenstate.org>
Sat, 3 Jul 2021 20:03:17 +0000 (20:03 +0000)
committerOri Bernstein <ori@eigenstate.org>
Sat, 3 Jul 2021 20:03:17 +0000 (20:03 +0000)
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.

sys/include/libc.h
sys/man/2/encode
sys/src/libc/port/u32.c
sys/src/libc/port/u64.c

index 4eecd028f91ed49caea81b6c95b4cc5beac63037..ecc23c3432a290aaff0b6689362d5ca8149ac64f 100644 (file)
@@ -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*);
index db79449453dc742718351abff2f1b8389259ed99..3827e7a6e979d83f781dd671024955a8c35f3748 100644 (file)
@@ -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
index 9ad9eb781ccdea952e9bce678579a92ccc0b7dbd..a7abdc012a70ecb8e9bab1a1e18a9ec1d63d955f 100644 (file)
@@ -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<nsrc; i++){
-                       j = dec32chr(src[i]);
+                       j = chr(src[i]);
                        if(j < 0)
                                j = 0;
                        u[i] = j;
@@ -73,7 +73,7 @@ out:
 }
 
 int
-enc32(char *dest, int ndest, uchar *src, int nsrc)
+enc32x(char *dest, int ndest, uchar *src, int nsrc, int (*chr)(int))
 {
        char *start;
        int j;
@@ -83,50 +83,62 @@ enc32(char *dest, int ndest, uchar *src, int nsrc)
        start = dest;
        while(nsrc>=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);
+}
index 44f716fbeb0f4ed1b90c1cb3b992a5d68a05e1e9..5be0142b844239d2e75134e68920d74ad01c48de 100644 (file)
@@ -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);
+}