source: roaraudio/libroar/base64.c @ 6076:b81c397aee90

Last change on this file since 6076:b81c397aee90 was 6052:d48765b2475e, checked in by phi, 9 years ago

updated copyright headers

File size: 7.8 KB
Line 
1//base64.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2015
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38static char _base64_tab_fw[] =
39 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
40 "abcdefghijklmnopqrstuvwxyz"
41 "0123456789+/";
42
43static char _base64_tab_bw[] = {
44  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
45  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
46  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
47  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
48  0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
49  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
50  0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
51  0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
52  0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
53  0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
54  0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
55};
56
57
58int roar_base64_init(struct roar_base64 * state, int flags) {
59 if ( flags == -1 )
60  flags = 0;
61
62 if ( state == NULL )
63  return -1;
64
65 memset(state, 0, sizeof(struct roar_base64));
66
67 state->flags = flags;
68
69 return 0;
70}
71
72static inline void _libroar_base64_encode_block(unsigned char out[4], const unsigned char in[3]) {
73// printf("in={'%c', '%c', '%c'}\n", in[0], in[1], in[2]);
74 out[0] = _base64_tab_fw[(in[0] >> 2) & 0x3F];
75 out[1] = _base64_tab_fw[(((in[0] & 0x03) << 4) | (in[1] >> 4)) & 0x3F];
76 out[2] = _base64_tab_fw[(((in[1] & 0x0F) << 2) | ((in[2] >> 6) & 0x03)) & 0x3F];
77 out[3] = _base64_tab_fw[in[2] & 0x3F];
78}
79
80#define _setoff(x) do { if ( off != NULL ) { *off = (x); } } while (0)
81
82ssize_t roar_base64_encode(struct roar_base64 * state, void * out, size_t outlen, const void * in, size_t inlen, size_t * off, int eof) {
83 struct roar_base64 state_store;
84 size_t offset = 0;
85 size_t tlen;
86 ssize_t ret = 0;
87 unsigned char * outp;
88 const unsigned char * inp;
89
90 if ( inlen && in == NULL )
91  return -1;
92
93 if ( outlen && out == NULL )
94  return -1;
95
96 // this test should be removed as soon as those modes are supported.
97 if ( in == NULL || out == NULL )
98  return -1;
99
100 // we can not write anything anyway...
101 if ( outlen < 4 )
102  return 0;
103
104 if ( state == NULL ) {
105  state = &state_store;
106  roar_base64_init_encode(state, ROAR_BASE64_FLAG_NONE);
107  eof = 1;
108 }
109
110 if ( state->buflen ) {
111  tlen = 3 - state->buflen;
112  ROAR_DBG("roar_base64_encode(state=%p,...): Still %llu bytes in state", state, (long long unsigned int)state->buflen);
113  ROAR_DBG("roar_base64_encode(state=%p,...): Need %llu bytes", state, (long long unsigned int)tlen);
114  if ( inlen >= tlen ) {
115   memcpy(state->iobuf + state->buflen, in, tlen);
116   offset += tlen;
117   in += tlen;
118   inlen -= tlen;
119   _libroar_base64_encode_block(out, state->iobuf);
120   out += 4;
121   outlen -= 4;
122   ret += 4;
123   state->buflen = 0;
124  } else {
125   memcpy(state->iobuf + state->buflen, in, inlen);
126   state->buflen += inlen;
127   _setoff(inlen);
128   return 0;
129  }
130 }
131
132 for (; inlen >= 3 && outlen >= 4;) {
133  _libroar_base64_encode_block(out, in);
134  ret += 4;
135  out += 4;
136  in  += 3;
137  offset += 3;
138  inlen -= 3;
139  outlen -= 4;
140 }
141
142 // something left?
143 if ( inlen ) {
144  if ( eof ) {
145   if ( outlen >= 4 ) {
146    outp = out;
147    inp  = in;
148    switch (inlen) {
149     case 1:
150       outp[0] = _base64_tab_fw[inp[0] >> 2];
151       outp[1] = _base64_tab_fw[(inp[0] & 0x03) << 4];
152       outp[2] = '=';
153       outp[3] = '=';
154       ret += 4;
155       out += 4;
156       in  += 1;
157       offset += 1;
158       inlen  -= 1;
159       outlen -= 4;
160      break;
161     case 2:
162       outp[0] = _base64_tab_fw[inp[0] >> 2];
163       outp[1] = _base64_tab_fw[(((inp[0] & 0x03) << 4) | (inp[1] >> 4)) & 0x3F];
164       outp[2] = _base64_tab_fw[(((inp[1] & 0x0F) << 2))                 & 0x3F];
165       outp[3] = '=';
166       ret += 4;
167       out += 4;
168       in  += 2;
169       offset += 2;
170       inlen  -= 2;
171       outlen -= 4;
172      break;
173    }
174   }
175  } else {
176   memcpy(state->iobuf, in, inlen);
177   state->buflen = inlen;
178   offset += inlen;
179   in += inlen;
180   inlen -= inlen;
181  }
182 }
183
184 if ( outlen ) {
185  *(char*)out = 0;
186 }
187
188 _setoff(offset);
189
190 return 0;
191}
192
193ssize_t roar_base64_decode(struct roar_base64 * state, void * out, size_t outlen, const void * in, size_t inlen, size_t * off) {
194 struct roar_base64 state_store;
195 ssize_t ret = 0;
196 unsigned char c;
197 int bits;
198 const unsigned char * inp = in;
199 unsigned char * outp = out;
200 size_t offset = 0;
201
202 if ( inlen && in == NULL )
203  return -1;
204
205 if ( outlen && out == NULL )
206  return -1;
207
208 // this test should be removed as soon as those modes are supported.
209 if ( in == NULL || out == NULL )
210  return -1;
211
212 if ( state == NULL ) {
213  state = &state_store;
214  roar_base64_init_encode(state, ROAR_BASE64_FLAG_NONE);
215 }
216
217 if ( state->reglen >= 8 ) {
218  *outp  = (state->reg >> (state->reglen - 8)) & 0xFF;
219  state->reglen -= 8;
220  outp++;
221  outlen--;
222  ret++;
223 }
224
225 if ( state->flags & ROAR_BASE64_FLAG_EOF ) {
226  if ( outlen ) {
227   *outp = 0;
228  }
229  return ret;
230 }
231
232 //printf("state->reglen=%i\n", (int)state->reglen);
233
234 for (; inlen && outlen; ) {
235  c = *inp;
236  inp++;
237  inlen--;
238  offset++;
239
240  if ( c == '=' ) {
241   bits = 0;
242  } else {
243   // hi-bit set chars need to be ignored.
244   if ( (size_t)c > sizeof(_base64_tab_bw) )
245    continue;
246
247   bits = _base64_tab_bw[c];
248
249   // ignore unknown chars.
250   if ( bits == (char)0xFF )
251    continue;
252  }
253
254  state->reg   <<= 6;
255  state->reg    |= bits;
256  state->reglen += 6;
257
258  if ( state->reglen >= 8 ) {
259   *outp  = (state->reg >> (state->reglen - 8)) & 0xFF;
260   state->reglen -= 8;
261   outp++;
262   outlen--;
263   ret++;
264  }
265
266  if ( c == '=' ) {
267   state->flags |= ROAR_BASE64_FLAG_EOF;
268   if ( state->reglen <= 6 ) {
269    state->reglen = 0;
270   }
271   if ( inlen ) {
272    if ( *inp == '=' ) {
273     offset++;
274    }
275   }
276   break;
277  }
278 }
279
280 if ( off != NULL ) {
281  *off = offset;
282 }
283
284 if ( outlen ) {
285  *outp = 0;
286 }
287
288 return ret;
289}
290
291int roar_base64_is_eof(struct roar_base64 * state) {
292 if ( state == NULL )
293  return -1;
294
295 if ( state->reglen >= 8 )
296  return 0;
297
298 return !!(state->flags & ROAR_BASE64_FLAG_EOF);
299}
300
301int roar_base64_uninit(struct roar_base64 * state) {
302 if ( state == NULL )
303  return -1;
304
305 if ( state->buflen ) {
306  ROAR_WARN("roar_base64_uninit(state=%p): State has %i bytes left in IO buffer. This is a application error.", state, state->buflen);
307 }
308
309 if ( state->reglen ) {
310  ROAR_WARN("roar_base64_uninit(state=%p): State has %i bits left in decode register. This is a application error.", state, state->reglen);
311 }
312
313 return 0;
314}
315
316//ll
Note: See TracBrowser for help on using the repository browser.