bard / purplebridge

This URL has Read+Write access

bard (author)
Sun Aug 10 07:05:06 -0700 2008
purplebridge / lbase64.c
100644 120 lines (108 sloc) 2.386 kb
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
* lbase64.c
* base64 encoding and decoding for Lua 5.1
* Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br>
* 27 Jun 2007 19:04:40
* This code is hereby placed in the public domain.
*/
 
#include <string.h>
 
#include "lua.h"
#include "lauxlib.h"
 
#define MYNAME "base64"
#define MYVERSION MYNAME " library for " LUA_VERSION " / Jun 2007"
 
#define uint unsigned int
 
static const char code[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
static void encode(luaL_Buffer *b, uint c1, uint c2, uint c3, int n)
{
 unsigned long tuple=c3+256UL*(c2+256UL*c1);
 int i;
 char s[4];
 for (i=0; i<4; i++) {
  s[3-i] = code[tuple % 64];
  tuple /= 64;
 }
 for (i=n+1; i<4; i++) s[i]='=';
 luaL_addlstring(b,s,4);
}
 
static int Lencode(lua_State *L) /** encode(s) */
{
 size_t l;
 const unsigned char *s=(const unsigned char*)luaL_checklstring(L,1,&l);
 luaL_Buffer b;
 int n;
 luaL_buffinit(L,&b);
 for (n=l/3; n--; s+=3) encode(&b,s[0],s[1],s[2],3);
 switch (l%3)
 {
  case 1: encode(&b,s[0],0,0,1); break;
  case 2: encode(&b,s[0],s[1],0,2); break;
 }
 luaL_pushresult(&b);
 return 1;
}
 
static void decode(luaL_Buffer *b, int c1, int c2, int c3, int c4, int n)
{
 unsigned long tuple=c4+64L*(c3+64L*(c2+64L*c1));
 char s[3];
 switch (--n)
 {
  case 3: s[2]=tuple;
  case 2: s[1]=tuple >> 8;
  case 1: s[0]=tuple >> 16;
 }
 luaL_addlstring(b,s,n);
}
 
static int Ldecode(lua_State *L) /** decode(s) */
{
 size_t l;
 const char *s=luaL_checklstring(L,1,&l);
 luaL_Buffer b;
 int n=0;
 char t[4];
 luaL_buffinit(L,&b);
 for (;;)
 {
  int c=*s++;
  switch (c)
  {
   const char *p;
   default:
    p=strchr(code,c); if (p==NULL) return 0;
    t[n++]= p-code;
    if (n==4)
    {
     decode(&b,t[0],t[1],t[2],t[3],4);
     n=0;
    }
    break;
   case '=':
    switch (n)
    {
     case 1: decode(&b,t[0],0,0,0,1); break;
     case 2: decode(&b,t[0],t[1],0,0,2); break;
     case 3: decode(&b,t[0],t[1],t[2],0,3); break;
    }
   case 0:
    luaL_pushresult(&b);
    return 1;
   case '\n': case '\r': case '\t': case ' ': case '\f': case '\b':
    break;
  }
 }
 return 0;
}
 
static const luaL_reg R[] =
{
{ "encode", Lencode },
{ "decode", Ldecode },
{ NULL, NULL }
};
 
LUALIB_API int luaopen_base64(lua_State *L)
{
 luaL_openlib(L,MYNAME,R,0);
 lua_pushliteral(L,"version"); /** version */
 lua_pushliteral(L,MYVERSION);
 lua_settable(L,-3);
 return 1;
}