stk/Extensions/base64.c

134 lines
3.0 KiB
C

/*
*
* b a s e 6 4 . c -- Base64 support for STk
*
* Copyright © 1998-1999 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
*
*
* Permission to use, copy, modify, distribute,and license this
* software and its documentation for any purpose is hereby granted,
* provided that existing copyright notices are retained in all
* copies and that this notice is included verbatim in any
* distributions. No written agreement, license, or royalty fee is
* required for any of the authorized uses.
* This software is provided ``AS IS'' without express or implied
* warranty.
*
* Author: Erick Gallesio [eg@unice.fr]
* Creation date: 20-Jul-1998 12:19
* Last file update: 3-Sep-1999 20:18 (eg)
*/
#include <stk.h>
#include <ctype.h>
static char table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static char rev_table[128];
#define OutChar(c, f) {Putc((c), (f)); if (++count>=72) {Putc('\n', (f)); count=0;}}
static void initialize_rev_table(void)
{
char *p;
int count = 0;
for (p = table; *p; p++) rev_table[(int) *p] = count++;
}
static void encode(SCM f, SCM g)
{
int c, state, count, old;
state = old = count = 0;
while ((c = Getc(f)) != EOF) {
switch (++state) {
case 1: OutChar(table[(c>>2) & 0x3f], g);
break;
case 2: OutChar(table[((old<<4) & 0x30) | ((c>>4) & 0x0f)], g);
break;
case 3: OutChar(table[((old<<2) & 0x3c) | ((c>>6) & 0x03)], g);
OutChar(table[c & 0x3f], g);
state = 0;
break;
}
old = c;
}
switch (state) {
case 0: /* nothing */;
case 1: OutChar(table[(old<<4) & 0x30], g);
OutChar('=', g);
OutChar('=', g);
break;
case 2: OutChar(table[(old<<2) & 0x3c], g);
OutChar('=', g);
break;
}
}
static void decode(SCM f, SCM g)
{
static int initialized = 0;
int c, bits, group, j;
if (!initialized) {
initialize_rev_table();
initialized = 1;
}
group = 0; j = 18;
while ((c = Getc(f)) != EOF) {
if (c != '\n') {
if (c != '=') {
bits = rev_table[c];
group |= bits << j;
}
j -= 6;
if (j < 0) {
c = (group&0xff0000) >> 16; if (c) Putc(c, g);
c = (group&0x00ff00) >> 8; if (c) Putc(c, g);
c = (group&0x0000ff); if (c) Putc(c, g);
group = 0;
j = 18;
}
}
}
}
static PRIMITIVE base64_encode(SCM f, SCM g)
{
ENTER_PRIMITIVE("base64-encode");
if (!INP(f)) Serror("bad input port", f);
if (g == UNBOUND)
g = STk_curr_oport;
else
if (!OUTP(g)) Serror("bad output port", g);
encode(f, g);
return UNDEFINED;
}
static PRIMITIVE base64_decode(SCM f, SCM g)
{
ENTER_PRIMITIVE("base64-decode");
if (!INP(f)) Serror("bad input port", f);
if (g == UNBOUND)
g = STk_curr_oport;
else
if (!OUTP(g)) Serror("bad output port", g);
decode(f, g);
return UNDEFINED;
}
PRIMITIVE STk_init_base64(void)
{
STk_add_new_primitive("base64-decode", tc_subr_1_or_2, base64_decode);
STk_add_new_primitive("base64-encode", tc_subr_1_or_2, base64_encode);
return UNDEFINED;
}