diff options
| -rw-r--r-- | sys/include/libc.h | 6 | ||||
| -rw-r--r-- | sys/man/2/encode | 52 | ||||
| -rw-r--r-- | sys/src/libc/port/encodefmt.c | 13 | ||||
| -rw-r--r-- | sys/src/libc/port/u16.c | 38 | ||||
| -rw-r--r-- | sys/src/libc/port/u32.c | 80 | ||||
| -rw-r--r-- | sys/src/libc/port/u64.c | 85 |
6 files changed, 185 insertions, 89 deletions
diff --git a/sys/include/libc.h b/sys/include/libc.h index 33d0dbaef..98226dc05 100644 --- a/sys/include/libc.h +++ b/sys/include/libc.h @@ -369,6 +369,12 @@ extern int dec32(uchar*, int, char*, int); extern int enc32(char*, int, uchar*, int); extern int dec16(uchar*, int, char*, int); extern int enc16(char*, int, uchar*, int); +extern int dec64chr(int); +extern int enc64chr(int); +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 3a8ca61e4..db7944945 100644 --- a/sys/man/2/encode +++ b/sys/man/2/encode @@ -1,6 +1,8 @@ .TH ENCODE 2 .SH NAME -dec64, enc64, dec32, enc32, dec16, enc16, encodefmt \- encoding byte arrays as strings +dec64, enc64, dec32, enc32, dec16, enc16, \ +dec64chr, enc64chr, dec32chr, enc32chr, dec16chr, enc16chr, \ +encodefmt \- encoding byte arrays as strings .SH SYNOPSIS .B #include <u.h> .br @@ -25,8 +27,28 @@ int dec16(uchar *out, int lim, char *in, int n) int enc16(char *out, int lim, uchar *in, int n) .PP .B +int dec64chr(int c) +.PP +.B +int enc64chr(int o) +.PP +.B +int dec32chr(int c) +.PP +.B +int enc32chr(int o) +.PP +.B +int dec16chr(int c) +.PP +.B +int enc16chr(int o) +.PP +.B int encodefmt(Fmt*) .SH DESCRIPTION +The functions described here handle encoding and decoding of +bytes to printable ASCII strings as specified by RFC4648. .PP .IR Enc16 , .I enc32 @@ -47,6 +69,20 @@ The decoding fails if the output buffer is not large enough or, for base 32, if the input buffer length is not a multiple of 8. .PP +.IR Dec16chr , +.I dec32chr +and +.I dec64chr +return the value for a symbol of the alphabet or -1 when the +symbol is not in the alphabet. +.PP +.IR Enc16chr , +.I enc32chr +and +.I enc64chr +encode a symbol of the alphabet given a value. +if the value is out of range then zero is returned. +.PP .I Encodefmt can be used with .IR fmtinstall (2) @@ -62,7 +98,8 @@ in upper case. The flag forces lower case. .TP .B < -base 32 +base 32. The default is upper case, same as +.BR H . .TP .B [ base 64 (same as MIME) @@ -80,8 +117,19 @@ For example, to display a 15 byte array as hex: .EE .SH SOURCE +.B /sys/src/libc/port/u16.c +.br .B /sys/src/libc/port/u32.c .br .B /sys/src/libc/port/u64.c .br .B /sys/src/libc/port/encodefmt.c +.SH HISTORY +In Jan 2018, base 32 encoding was changed from non-standard +to standard RFC4648 alphabet. +.TP +old: +.B "23456789abcdefghijkmnpqrstuvwxyz" +.TP +new: +.B "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" diff --git a/sys/src/libc/port/encodefmt.c b/sys/src/libc/port/encodefmt.c index 721a58c9f..92cc4154a 100644 --- a/sys/src/libc/port/encodefmt.c +++ b/sys/src/libc/port/encodefmt.c @@ -48,17 +48,14 @@ encodefmt(Fmt *f) // convert out = buf; switch(f->r){ - case '<': - rv = enc32(out, len, b, ilen); - break; case '[': rv = enc64(out, len, b, ilen); break; + case '<': + rv = enc32(out, len, b, ilen); + break; case 'H': rv = enc16(out, len, b, ilen); - if(rv >= 0 && (f->flags & FmtLong)) - for(p = buf; *p; p++) - *p = tolower(*p); break; default: rv = -1; @@ -67,6 +64,10 @@ encodefmt(Fmt *f) if(rv < 0) goto error; + if((f->flags & FmtLong) != 0 && f->r != '[') + for(p = buf; *p; p++) + *p = tolower(*p); + fmtstrcpy(f, buf); if(buf != obuf) free(buf); diff --git a/sys/src/libc/port/u16.c b/sys/src/libc/port/u16.c index 4e1637120..60ffa72c8 100644 --- a/sys/src/libc/port/u16.c +++ b/sys/src/libc/port/u16.c @@ -1,6 +1,28 @@ #include <u.h> #include <libc.h> -static char t16e[] = "0123456789ABCDEF"; + +#define between(x,min,max) (((min-1-x) & (x-max-1))>>8) + +int +enc16chr(int o) +{ + int c; + + c = between(o, 0, 9) & ('0'+o); + c |= between(o, 10, 15) & ('A'+(o-10)); + return c; +} + +int +dec16chr(int c) +{ + int o; + + o = between(c, '0', '9') & (1+(c-'0')); + o |= between(c, 'A', 'F') & (1+10+(c-'A')); + o |= between(c, 'a', 'f') & (1+10+(c-'a')); + return o-1; +} int dec16(uchar *out, int lim, char *in, int n) @@ -10,14 +32,8 @@ dec16(uchar *out, int lim, char *in, int n) uchar *eout = out + lim; while(n-- > 0){ - c = *in++; - if('0' <= c && c <= '9') - c = c - '0'; - else if('a' <= c && c <= 'z') - c = c - 'a' + 10; - else if('A' <= c && c <= 'Z') - c = c - 'A' + 10; - else + c = dec16chr(*in++); + if(c < 0) continue; w = (w<<4) + c; i++; @@ -44,8 +60,8 @@ enc16(char *out, int lim, uchar *in, int n) c = *in++; if(out + 2 >= eout) goto exhausted; - *out++ = t16e[c>>4]; - *out++ = t16e[c&0xf]; + *out++ = enc16chr(c>>4); + *out++ = enc16chr(c&15); } exhausted: *out = 0; diff --git a/sys/src/libc/port/u32.c b/sys/src/libc/port/u32.c index 7423984a2..9ad9eb781 100644 --- a/sys/src/libc/port/u32.c +++ b/sys/src/libc/port/u32.c @@ -1,21 +1,44 @@ #include <u.h> #include <libc.h> +#define between(x,min,max) (((min-1-x) & (x-max-1))>>8) + +int +enc32chr(int o) +{ + int c; + + c = between(o, 0, 25) & ('A'+o); + c |= between(o, 26, 31) & ('2'+(o-26)); + return c; +} + +int +dec32chr(int c) +{ + int o; + + o = between(c, 'A', 'Z') & (1+(c-'A')); + o |= between(c, 'a', 'z') & (1+(c-'a')); + o |= between(c, '2', '7') & (1+26+(c-'2')); + return o-1; +} + int dec32(uchar *dest, int ndest, char *src, int nsrc) { - char *s, *tab; uchar *start; - int i, u[8]; + int i, j, u[8]; if(ndest+1 < (5*nsrc+7)/8) return -1; start = dest; - tab = "23456789abcdefghijkmnpqrstuvwxyz"; while(nsrc>=8){ for(i=0; i<8; i++){ - s = strchr(tab,(int)src[i]); - u[i] = s ? s-tab : 0; + j = dec32chr(src[i]); + if(j < 0) + j = 0; + u[i] = j; } *dest++ = (u[0]<<3) | (0x7 & (u[1]>>2)); *dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4)); @@ -29,8 +52,10 @@ dec32(uchar *dest, int ndest, char *src, int nsrc) if(nsrc == 1 || nsrc == 3 || nsrc == 6) return -1; for(i=0; i<nsrc; i++){ - s = strchr(tab,(int)src[i]); - u[i] = s ? s-tab : 0; + j = dec32chr(src[i]); + if(j < 0) + j = 0; + u[i] = j; } *dest++ = (u[0]<<3) | (0x7 & (u[1]>>2)); if(nsrc == 2) @@ -50,60 +75,57 @@ out: int enc32(char *dest, int ndest, uchar *src, int nsrc) { - char *tab, *start; + char *start; int j; - if(ndest <= (8*nsrc+4)/5 ) + if(ndest <= (8*nsrc+4)/5) return -1; start = dest; - tab = "23456789abcdefghijkmnpqrstuvwxyz"; while(nsrc>=5){ j = (0x1f & (src[0]>>3)); - *dest++ = tab[j]; + *dest++ = enc32chr(j); j = (0x1c & (src[0]<<2)) | (0x03 & (src[1]>>6)); - *dest++ = tab[j]; + *dest++ = enc32chr(j); j = (0x1f & (src[1]>>1)); - *dest++ = tab[j]; + *dest++ = enc32chr(j); j = (0x10 & (src[1]<<4)) | (0x0f & (src[2]>>4)); - *dest++ = tab[j]; + *dest++ = enc32chr(j); j = (0x1e & (src[2]<<1)) | (0x01 & (src[3]>>7)); - *dest++ = tab[j]; + *dest++ = enc32chr(j); j = (0x1f & (src[3]>>2)); - *dest++ = tab[j]; + *dest++ = enc32chr(j); j = (0x18 & (src[3]<<3)) | (0x07 & (src[4]>>5)); - *dest++ = tab[j]; + *dest++ = enc32chr(j); j = (0x1f & (src[4])); - *dest++ = tab[j]; + *dest++ = enc32chr(j); src += 5; nsrc -= 5; } if(nsrc){ j = (0x1f & (src[0]>>3)); - *dest++ = tab[j]; + *dest++ = enc32chr(j); j = (0x1c & (src[0]<<2)); if(nsrc == 1) goto out; j |= (0x03 & (src[1]>>6)); - *dest++ = tab[j]; + *dest++ = enc32chr(j); j = (0x1f & (src[1]>>1)); - if(nsrc == 2) - goto out; - *dest++ = tab[j]; + *dest++ = enc32chr(j); j = (0x10 & (src[1]<<4)); - if(nsrc == 3) + if(nsrc == 2) goto out; j |= (0x0f & (src[2]>>4)); - *dest++ = tab[j]; + *dest++ = enc32chr(j); j = (0x1e & (src[2]<<1)); - if(nsrc == 4) + if(nsrc == 3) goto out; j |= (0x01 & (src[3]>>7)); - *dest++ = tab[j]; + *dest++ = enc32chr(j); j = (0x1f & (src[3]>>2)); - *dest++ = tab[j]; + *dest++ = enc32chr(j); j = (0x18 & (src[3]<<3)); out: - *dest++ = tab[j]; + *dest++ = enc32chr(j); } *dest = 0; return dest-start; diff --git a/sys/src/libc/port/u64.c b/sys/src/libc/port/u64.c index 432cec899..44f716fbe 100644 --- a/sys/src/libc/port/u64.c +++ b/sys/src/libc/port/u64.c @@ -1,29 +1,33 @@ #include <u.h> #include <libc.h> -enum { - INVAL= 255 -}; +#define between(x,min,max) (((min-1-x) & (x-max-1))>>8) -static uchar t64d[256] = { - INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, - INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, - INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, 62,INVAL,INVAL,INVAL, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, - INVAL, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,INVAL,INVAL,INVAL,INVAL,INVAL, - INVAL, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,INVAL,INVAL,INVAL,INVAL,INVAL, - INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, - INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, - INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, - INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, - INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, - INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, - INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, - INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL -}; -static char t64e[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +int +enc64chr(int o) +{ + int c; + + c = between(o, 0, 25) & ('A'+o); + c |= between(o, 26, 51) & ('a'+(o-26)); + c |= between(o, 52, 61) & ('0'+(o-52)); + c |= between(o, 62, 62) & ('+'); + c |= between(o, 63, 63) & ('/'); + return c; +} + +int +dec64chr(int c) +{ + int o; + + o = between(c, 'A', 'Z') & (1+(c-'A')); + o |= between(c, 'a', 'z') & (1+26+(c-'a')); + o |= between(c, '0', '9') & (1+52+(c-'0')); + o |= between(c, '+', '+') & (1+62); + o |= between(c, '/', '/') & (1+63); + return o-1; +} int dec64(uchar *out, int lim, char *in, int n) @@ -36,9 +40,8 @@ dec64(uchar *out, int lim, char *in, int n) b24 = 0; i = 0; while(n-- > 0){ - - c = t64d[*(uchar*)in++]; - if(c == INVAL) + c = dec64chr(*in++); + if(c < 0) continue; switch(i){ case 0: @@ -58,8 +61,8 @@ dec64(uchar *out, int lim, char *in, int n) *out++ = b24>>16; *out++ = b24>>8; *out++ = b24; - i = -1; - break; + i = 0; + continue; } i++; } @@ -89,34 +92,34 @@ enc64(char *out, int lim, uchar *in, int n) char *e = out + lim; for(i = n/3; i > 0; i--){ - b24 = (*in++)<<16; - b24 |= (*in++)<<8; + b24 = *in++<<16; + b24 |= *in++<<8; b24 |= *in++; if(out + 4 >= e) goto exhausted; - *out++ = t64e[(b24>>18)]; - *out++ = t64e[(b24>>12)&0x3f]; - *out++ = t64e[(b24>>6)&0x3f]; - *out++ = t64e[(b24)&0x3f]; + *out++ = enc64chr(b24>>18); + *out++ = enc64chr((b24>>12)&0x3f); + *out++ = enc64chr((b24>>6)&0x3f); + *out++ = enc64chr(b24&0x3f); } switch(n%3){ case 2: - b24 = (*in++)<<16; - b24 |= (*in)<<8; + b24 = *in++<<16; + b24 |= *in<<8; if(out + 4 >= e) goto exhausted; - *out++ = t64e[(b24>>18)]; - *out++ = t64e[(b24>>12)&0x3f]; - *out++ = t64e[(b24>>6)&0x3f]; + *out++ = enc64chr(b24>>18); + *out++ = enc64chr((b24>>12)&0x3f); + *out++ = enc64chr((b24>>6)&0x3f); *out++ = '='; break; case 1: - b24 = (*in)<<16; + b24 = *in<<16; if(out + 4 >= e) goto exhausted; - *out++ = t64e[(b24>>18)]; - *out++ = t64e[(b24>>12)&0x3f]; + *out++ = enc64chr(b24>>18); + *out++ = enc64chr((b24>>12)&0x3f); *out++ = '='; *out++ = '='; break; |
