Skip to content

Commit b5e5fd1

Browse files
committed
Add a public domain base64 encode/decode implementation.
1 parent 4524488 commit b5e5fd1

File tree

3 files changed

+121
-2
lines changed

3 files changed

+121
-2
lines changed

src/6model/base64.c

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
3+
This code is public domain software.
4+
5+
*/
6+
7+
#include <stdlib.h>
8+
9+
// base64 encoding
10+
//
11+
// buf: binary input data
12+
// size: size of input (bytes)
13+
// return: base64-encoded string (null-terminated)
14+
// memory for output will be allocated here, free it later
15+
//
16+
char* base64_encode(const void* buf, size_t size)
17+
{
18+
static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
19+
20+
char* str = (char*) malloc((size+3)*4/3 + 1);
21+
22+
char* p = str;
23+
unsigned char* q = (unsigned char*) buf;
24+
size_t i = 0;
25+
26+
while (i < size) {
27+
int c = q[i++];
28+
c *= 256;
29+
if (i < size)
30+
c += q[i];
31+
i++;
32+
33+
c *= 256;
34+
if (i < size)
35+
c += q[i];
36+
i++;
37+
38+
*p++ = base64[(c & 0x00fc0000) >> 18];
39+
*p++ = base64[(c & 0x0003f000) >> 12];
40+
41+
if (i > size + 1)
42+
*p++ = '=';
43+
else
44+
*p++ = base64[(c & 0x00000fc0) >> 6];
45+
46+
if (i > size)
47+
*p++ = '=';
48+
else
49+
*p++ = base64[c & 0x0000003f];
50+
}
51+
52+
*p = 0;
53+
54+
return str;
55+
}
56+
57+
58+
// single base64 character conversion
59+
//
60+
static int POS(char c)
61+
{
62+
if (c>='A' && c<='Z') return c - 'A';
63+
if (c>='a' && c<='z') return c - 'a' + 26;
64+
if (c>='0' && c<='9') return c - '0' + 52;
65+
if (c == '+') return 62;
66+
if (c == '/') return 63;
67+
if (c == '=') return -1;
68+
return -2;
69+
}
70+
71+
// base64 decoding
72+
//
73+
// s: base64 string, must be null-terminated
74+
// data: output buffer for decoded data
75+
// data_len size of decoded data
76+
// return: allocated data buffer
77+
//
78+
void* base64_decode(char* s, size_t *data_len)
79+
{
80+
char *p;
81+
unsigned char *q, *data;
82+
int n[4];
83+
84+
size_t len = strlen(s);
85+
if (len % 4)
86+
return NULL;
87+
data = (unsigned char*) malloc(len/4*3);
88+
q = (unsigned char*) data;
89+
90+
for (p = s; *p; ) {
91+
n[0] = POS(*p++);
92+
n[1] = POS(*p++);
93+
n[2] = POS(*p++);
94+
n[3] = POS(*p++);
95+
96+
if (n[0] == -2 || n[1] == -2 || n[2] == -2 || n[3] == -2)
97+
return NULL;
98+
99+
if (n[0] == -1 || n[1] == -1)
100+
return NULL;
101+
102+
if (n[2] == -1 && n[3] != -1)
103+
return NULL;
104+
105+
q[0] = (n[0] << 2) + (n[1] >> 4);
106+
if (n[2] != -1)
107+
q[1] = ((n[1] & 15) << 4) + (n[2] >> 2);
108+
if (n[3] != -1)
109+
q[2] = ((n[2] & 3) << 6) + n[3];
110+
q += 3;
111+
}
112+
113+
*data_len = q-data - (n[2]==-1) - (n[3]==-1);
114+
115+
return data;
116+
}

src/6model/base64.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
char* base64_encode(const void* buf, size_t size);
2+
void* base64_decode(const char* s, size_t *data_len);

tools/build/Makefile.in

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,15 +189,15 @@ METAMODEL_SOURCE = src/6model/sixmodelobject.h src/6model/sixmodelobject.c \
189189
src/6model/storage_spec.h src/6model/serialization_context.c \
190190
src/6model/serialization_context.h src/6model/serialization.c \
191191
src/6model/serialization.h src/guts/multi_dispatch.h \
192-
src/guts/multi_dispatch.c \
192+
src/guts/multi_dispatch.c src/6model/base64.c src/6model/base64.h \
193193

194194
METAMODEL_OBJS = ../6model/sixmodelobject$(O) ../6model/repr_registry$(O) \
195195
../6model/knowhow_bootstrapper$(O) ../6model/reprs/KnowHOWREPR$(O) \
196196
../6model/reprs/P6opaque$(O) ../6model/reprs/P6int$(O) \
197197
../6model/reprs/P6str$(O) ../6model/reprs/P6num$(O) \
198198
../6model/reprs/HashAttrStore$(O) ../6model/reprs/Uninstantiable$(O) \
199199
../6model/serialization_context$(O) ../6model/serialization$(O) \
200-
../guts/multi_dispatch$(O)
200+
../guts/multi_dispatch$(O) ../6model/base64$(O)
201201

202202
LIBTOMMATH_BIN = $(TOM)core$(O) \
203203
$(TOM)_error$(O) \
@@ -697,6 +697,7 @@ $(OPS_DIR)/$(OPS)$(LOAD_EXT): $(OPS_DIR)/$(OPS_SOURCE) $(DYNPMC)
697697
cd src/6model/reprs && $(CC) -c @cc_o_out@Uninstantiable$(O) -I../../../$(PMC_DIR) $(CINCLUDES) $(CFLAGS) Uninstantiable.c
698698
cd src/6model && $(CC) -c @cc_o_out@serialization_context$(O) -I../../$(PMC_DIR) $(CINCLUDES) $(CFLAGS) serialization_context.c
699699
cd src/6model && $(CC) -c @cc_o_out@serialization$(O) -I../../$(PMC_DIR) $(CINCLUDES) $(CFLAGS) serialization.c
700+
cd src/6model && $(CC) -c @cc_o_out@base64$(O) -I../../$(PMC_DIR) $(CINCLUDES) $(CFLAGS) base64.c
700701
cd src/guts && $(CC) -c @cc_o_out@multi_dispatch$(O) -I../../$(PMC_DIR) $(CINCLUDES) $(CFLAGS) multi_dispatch.c
701702
cd 3rdparty/sha1 && $(CC) -c @cc_o_out@sha1$(O) $(CINCLUDES) $(CFLAGS) sha1.c
702703
cd $(OPS_DIR) && $(LD) @ld_out@$(OPS)$(LOAD_EXT) $(OPS)$(O) $(METAMODEL_OBJS) ../../3rdparty/sha1/sha1$(O) $(LINKARGS)

0 commit comments

Comments
 (0)