fix some docs
[glib.git] / glib / gbase64.c
blob437c4c983898b28cd56d4e83dd1767f79bb5e238
1 /* gbase64.c - Base64 encoding/decoding
3 * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
4 * Copyright (C) 2000-2003 Ximian Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
21 * This is based on code in camel, written by:
22 * Michael Zucchi <notzed@ximian.com>
23 * Jeffrey Stedfast <fejj@ximian.com>
26 #include "config.h"
28 #include <string.h>
30 #include "gbase64.h"
31 #include "glib.h"
32 #include "glibintl.h"
34 #include "galias.h"
36 static const char base64_alphabet[] =
37 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
39 /**
40 * g_base64_encode_step:
41 * @in: the binary data to encode
42 * @len: the length of @in
43 * @break_lines: whether to break long lines
44 * @out: pointer to destination buffer
45 * @state: Saved state between steps, initialize to 0
46 * @save: Saved state between steps, initialize to 0
48 * Incrementally encode a sequence of binary data into it's Base-64 stringified
49 * representation. By calling this function multiple times you can convert
50 * data in chunks to avoid having to have the full encoded data in memory.
52 * When all of the data has been converted you must call
53 * g_base64_encode_close() to flush the saved state.
55 * The output buffer must be large enough to fit all the data that will
56 * be written to it. Due to the way base64 encodes you will need
57 * at least: @len * 4 / 3 + 6 bytes. If you enable line-breaking you will
58 * need at least: @len * 4 / 3 + @len * 4 / (3 * 72) + 7 bytes.
60 * @break_lines is typically used when putting base64-encoded data in emails.
61 * It breaks the lines at 72 columns instead of putting all of the text on
62 * the same line. This avoids problems with long lines in the email system.
64 * Return value: The number of bytes of output that was written
66 * Since: 2.12
68 gsize
69 g_base64_encode_step (const guchar *in,
70 gsize len,
71 gboolean break_lines,
72 gchar *out,
73 gint *state,
74 gint *save)
76 char *outptr;
77 const guchar *inptr;
79 g_return_val_if_fail (in != NULL, 0);
80 g_return_val_if_fail (out != NULL, 0);
81 g_return_val_if_fail (state != NULL, 0);
82 g_return_val_if_fail (save != NULL, 0);
84 if (len <= 0)
85 return 0;
87 inptr = in;
88 outptr = out;
90 if (len + ((char *) save) [0] > 2)
92 const guchar *inend = in+len-2;
93 int c1, c2, c3;
94 int already;
96 already = *state;
98 switch (((char *) save) [0])
100 case 1:
101 c1 = ((unsigned char *) save) [1];
102 goto skip1;
103 case 2:
104 c1 = ((unsigned char *) save) [1];
105 c2 = ((unsigned char *) save) [2];
106 goto skip2;
110 * yes, we jump into the loop, no i'm not going to change it,
111 * it's beautiful!
113 while (inptr < inend)
115 c1 = *inptr++;
116 skip1:
117 c2 = *inptr++;
118 skip2:
119 c3 = *inptr++;
120 *outptr++ = base64_alphabet [ c1 >> 2 ];
121 *outptr++ = base64_alphabet [ c2 >> 4 |
122 ((c1&0x3) << 4) ];
123 *outptr++ = base64_alphabet [ ((c2 &0x0f) << 2) |
124 (c3 >> 6) ];
125 *outptr++ = base64_alphabet [ c3 & 0x3f ];
126 /* this is a bit ugly ... */
127 if (break_lines && (++already) >= 19)
129 *outptr++ = '\n';
130 already = 0;
134 ((char *)save)[0] = 0;
135 len = 2 - (inptr - inend);
136 *state = already;
139 if (len>0)
141 char *saveout;
143 /* points to the slot for the next char to save */
144 saveout = & (((char *)save)[1]) + ((char *)save)[0];
146 /* len can only be 0 1 or 2 */
147 switch(len)
149 case 2: *saveout++ = *inptr++;
150 case 1: *saveout++ = *inptr++;
152 ((char *)save)[0] += len;
155 return outptr - out;
159 * g_base64_encode_close:
160 * @break_lines: whether to break long lines
161 * @out: pointer to destination buffer
162 * @state: Saved state from g_base64_encode_step()
163 * @save: Saved state from g_base64_encode_step()
165 * Flush the status from a sequence of calls to g_base64_encode_step().
167 * Return value: The number of bytes of output that was written
169 * Since: 2.12
171 gsize
172 g_base64_encode_close (gboolean break_lines,
173 gchar *out,
174 gint *state,
175 gint *save)
177 int c1, c2;
178 char *outptr = out;
180 g_return_val_if_fail (out != NULL, 0);
181 g_return_val_if_fail (state != NULL, 0);
182 g_return_val_if_fail (save != NULL, 0);
184 c1 = ((unsigned char *) save) [1];
185 c2 = ((unsigned char *) save) [2];
187 switch (((char *) save) [0])
189 case 2:
190 outptr [2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
191 g_assert (outptr [2] != 0);
192 goto skip;
193 case 1:
194 outptr[2] = '=';
195 skip:
196 outptr [0] = base64_alphabet [ c1 >> 2 ];
197 outptr [1] = base64_alphabet [ c2 >> 4 | ( (c1&0x3) << 4 )];
198 outptr [3] = '=';
199 outptr += 4;
200 break;
202 if (break_lines)
203 *outptr++ = '\n';
205 *save = 0;
206 *state = 0;
208 return outptr - out;
212 * g_base64_encode:
213 * @data: the binary data to encode
214 * @len: the length of @data
216 * Encode a sequence of binary data into its Base-64 stringified
217 * representation.
219 * Return value: a newly allocated, zero-terminated Base-64 encoded
220 * string representing @data. The returned string must
221 * be freed with g_free().
223 * Since: 2.12
225 gchar *
226 g_base64_encode (const guchar *data,
227 gsize len)
229 gchar *out;
230 gint state = 0, outlen;
231 gint save = 0;
233 g_return_val_if_fail (data != NULL, NULL);
234 g_return_val_if_fail (len > 0, NULL);
236 /* We can use a smaller limit here, since we know the saved state is 0 */
237 out = g_malloc (len * 4 / 3 + 4);
238 outlen = g_base64_encode_step (data, len, FALSE, out, &state, &save);
239 outlen += g_base64_encode_close (FALSE, out + outlen, &state, &save);
240 out[outlen] = '\0';
242 return (gchar *) out;
245 static const unsigned char mime_base64_rank[256] = {
246 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
247 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
248 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
249 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
250 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
251 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
252 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
253 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
254 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
256 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
257 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
258 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
259 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
260 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
261 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
265 * g_base64_decode_step:
266 * @in: binary input data
267 * @len: max length of @in data to decode
268 * @out: output buffer
269 * @state: Saved state between steps, initialize to 0
270 * @save: Saved state between steps, initialize to 0
272 * Incrementally decode a sequence of binary data from its Base-64 stringified
273 * representation. By calling this function multiple times you can convert
274 * data in chunks to avoid having to have the full encoded data in memory.
276 * The output buffer must be large enough to fit all the data that will
277 * be written to it. Since base64 encodes 3 bytes in 4 chars you need
278 * at least: @len * 3 / 4 bytes.
280 * Return value: The number of bytes of output that was written
282 * Since: 2.12
284 gsize
285 g_base64_decode_step (const gchar *in,
286 gsize len,
287 guchar *out,
288 gint *state,
289 guint *save)
291 const guchar *inptr;
292 guchar *outptr;
293 const guchar *inend;
294 guchar c, rank;
295 guchar last[2];
296 unsigned int v;
297 int i;
299 g_return_val_if_fail (in != NULL, 0);
300 g_return_val_if_fail (out != NULL, 0);
301 g_return_val_if_fail (state != NULL, 0);
302 g_return_val_if_fail (save != NULL, 0);
304 if (len <= 0)
305 return 0;
307 inend = (const guchar *)in+len;
308 outptr = out;
310 /* convert 4 base64 bytes to 3 normal bytes */
311 v=*save;
312 i=*state;
313 inptr = (const guchar *)in;
314 last[0] = last[1] = 0;
315 while (inptr < inend)
317 c = *inptr++;
318 rank = mime_base64_rank [c];
319 if (rank != 0xff)
321 last[1] = last[0];
322 last[0] = c;
323 v = (v<<6) | rank;
324 i++;
325 if (i==4)
327 *outptr++ = v>>16;
328 if (last[1] != '=')
329 *outptr++ = v>>8;
330 if (last[0] != '=')
331 *outptr++ = v;
332 i=0;
337 *save = v;
338 *state = i;
340 return outptr - out;
344 * g_base64_decode:
345 * @text: zero-terminated string with base64 text to decode
346 * @out_len: The length of the decoded data is written here
348 * Decode a sequence of Base-64 encoded text into binary data
350 * Return value: a newly allocated buffer containing the binary data
351 * that @text represents. The returned buffer must
352 * be freed with g_free().
354 * Since: 2.12
356 guchar *
357 g_base64_decode (const gchar *text,
358 gsize *out_len)
360 guchar *ret;
361 gint input_length, state = 0;
362 guint save = 0;
364 g_return_val_if_fail (text != NULL, NULL);
365 g_return_val_if_fail (out_len != NULL, NULL);
367 input_length = strlen (text);
369 g_return_val_if_fail (input_length > 1, NULL);
371 ret = g_malloc0 (input_length * 3 / 4);
373 *out_len = g_base64_decode_step (text, input_length, ret, &state, &save);
375 return ret;
378 #define __G_BASE64_C__
379 #include "galiasdef.c"