Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>

enum {
        INVAL=  255
};

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
dec64(uchar *out, int lim, char *in, int n)
{
        ulong b24;
        uchar *start = out;
        uchar *e = out + lim;
        int i, c;

        b24 = 0;
        i = 0;
        while(n-- > 0){
 
                c = t64d[*(uchar*)in++];
                if(c == INVAL)
                        continue;
                switch(i){
                case 0:
                        b24 = c<<18;
                        break;
                case 1:
                        b24 |= c<<12;
                        break;
                case 2:
                        b24 |= c<<6;
                        break;
                case 3:
                        if(out + 3 > e)
                                goto exhausted;

                        b24 |= c;
                        *out++ = b24>>16;
                        *out++ = b24>>8;
                        *out++ = b24;
                        i = -1;
                        break;
                }
                i++;
        }
        switch(i){
        case 2:
                if(out + 1 > e)
                        goto exhausted;
                *out++ = b24>>16;
                break;
        case 3:
                if(out + 2 > e)
                        goto exhausted;
                *out++ = b24>>16;
                *out++ = b24>>8;
                break;
        }
exhausted:
        return out - start;
}

int
enc64(char *out, int lim, uchar *in, int n)
{
        int i;
        ulong b24;
        char *start = out;
        char *e = out + lim;

        for(i = n/3; i > 0; i--){
                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];
        }

        switch(n%3){
        case 2:
                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++ = '=';
                break;
        case 1:
                b24 = (*in)<<16;
                if(out + 4 >= e)
                        goto exhausted;
                *out++ = t64e[(b24>>18)];
                *out++ = t64e[(b24>>12)&0x3f];
                *out++ = '=';
                *out++ = '=';
                break;
        }
exhausted:
        *out = 0;
        return out - start;
}