X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgbase64.c;h=a6cbea459bca7368383ef476461360fe4d09ed21;hb=0a4ee12c7a9dfc82443133dfb2b18fb411d79f48;hp=59a911aae21927ee5e3c380a1d8ccf3039489980;hpb=dd7bd61c5301f92408ccb420a5bbd094faa863c3;p=platform%2Fupstream%2Fglib.git diff --git a/glib/gbase64.c b/glib/gbase64.c index 59a911a..a6cbea4 100644 --- a/glib/gbase64.c +++ b/glib/gbase64.c @@ -10,13 +10,11 @@ * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library; if not, see . * * This is based on code in camel, written by: * Michael Zucchi @@ -28,20 +26,22 @@ #include #include "gbase64.h" -#include "glib.h" +#include "gtestutils.h" #include "glibintl.h" -#include "galias.h" /** - * SECTION:base64 Base64 Encoding + * SECTION:base64 + * @title: Base64 Encoding * @short_description: encodes and decodes data in Base64 format * * Base64 is an encoding that allows a sequence of arbitrary bytes to be * encoded as a sequence of printable ASCII characters. For the definition - * of Base64, see RFC - * 1421 or RFC - * 2045. Base64 is most commonly used as a MIME transfer encoding + * of Base64, see + * [RFC 1421](http://www.ietf.org/rfc/rfc1421.txt) + * or + * [RFC 2045](http://www.ietf.org/rfc/rfc2045.txt). + * Base64 is most commonly used as a MIME transfer encoding * for email. * * GLib supports incremental encoding using g_base64_encode_step() and @@ -54,22 +54,22 @@ */ static const char base64_alphabet[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** * g_base64_encode_step: - * @in: the binary data to encode + * @in: (array length=len) (element-type guint8): the binary data to encode * @len: the length of @in * @break_lines: whether to break long lines - * @out: pointer to destination buffer - * @state: Saved state between steps, initialize to 0 - * @save: Saved state between steps, initialize to 0 + * @out: (out) (array) (element-type guint8): pointer to destination buffer + * @state: (inout): Saved state between steps, initialize to 0 + * @save: (inout): Saved state between steps, initialize to 0 * * Incrementally encode a sequence of binary data into its Base-64 stringified - * representation. By calling this function multiple times you can convert + * representation. By calling this function multiple times you can convert * data in chunks to avoid having to have the full encoded data in memory. * - * When all of the data has been converted you must call + * When all of the data has been converted you must call * g_base64_encode_close() to flush the saved state. * * The output buffer must be large enough to fit all the data that will @@ -79,24 +79,27 @@ static const char base64_alphabet[] = * ((@len / 3 + 1) * 4 + 4) / 72 + 1 bytes of extra space. * * @break_lines is typically used when putting base64-encoded data in emails. - * It breaks the lines at 72 columns instead of putting all of the text on + * It breaks the lines at 72 columns instead of putting all of the text on * the same line. This avoids problems with long lines in the email system. + * Note however that it breaks the lines with `LF` characters, not + * `CR LF` sequences, so the result cannot be passed directly to SMTP + * or certain other protocols. * - * Return value: The number of bytes of output that was written + * Returns: The number of bytes of output that was written * * Since: 2.12 */ gsize -g_base64_encode_step (const guchar *in, - gsize len, - gboolean break_lines, - gchar *out, - gint *state, - gint *save) +g_base64_encode_step (const guchar *in, + gsize len, + gboolean break_lines, + gchar *out, + gint *state, + gint *save) { char *outptr; const guchar *inptr; - + g_return_val_if_fail (in != NULL, 0); g_return_val_if_fail (out != NULL, 0); g_return_val_if_fail (state != NULL, 0); @@ -104,84 +107,84 @@ g_base64_encode_step (const guchar *in, if (len <= 0) return 0; - + inptr = in; outptr = out; - + if (len + ((char *) save) [0] > 2) { const guchar *inend = in+len-2; int c1, c2, c3; int already; - + already = *state; - + switch (((char *) save) [0]) - { - case 1: - c1 = ((unsigned char *) save) [1]; + { + case 1: + c1 = ((unsigned char *) save) [1]; goto skip1; - case 2: + case 2: c1 = ((unsigned char *) save) [1]; - c2 = ((unsigned char *) save) [2]; + c2 = ((unsigned char *) save) [2]; goto skip2; - } - - /* - * yes, we jump into the loop, no i'm not going to change it, - * it's beautiful! + } + + /* + * yes, we jump into the loop, no i'm not going to change it, + * it's beautiful! */ while (inptr < inend) - { - c1 = *inptr++; - skip1: - c2 = *inptr++; - skip2: - c3 = *inptr++; - *outptr++ = base64_alphabet [ c1 >> 2 ]; - *outptr++ = base64_alphabet [ c2 >> 4 | - ((c1&0x3) << 4) ]; - *outptr++ = base64_alphabet [ ((c2 &0x0f) << 2) | - (c3 >> 6) ]; - *outptr++ = base64_alphabet [ c3 & 0x3f ]; - /* this is a bit ugly ... */ - if (break_lines && (++already) >= 19) - { - *outptr++ = '\n'; - already = 0; - } - } - + { + c1 = *inptr++; + skip1: + c2 = *inptr++; + skip2: + c3 = *inptr++; + *outptr++ = base64_alphabet [ c1 >> 2 ]; + *outptr++ = base64_alphabet [ c2 >> 4 | + ((c1&0x3) << 4) ]; + *outptr++ = base64_alphabet [ ((c2 &0x0f) << 2) | + (c3 >> 6) ]; + *outptr++ = base64_alphabet [ c3 & 0x3f ]; + /* this is a bit ugly ... */ + if (break_lines && (++already) >= 19) + { + *outptr++ = '\n'; + already = 0; + } + } + ((char *)save)[0] = 0; len = 2 - (inptr - inend); *state = already; } - + if (len>0) { char *saveout; - + /* points to the slot for the next char to save */ saveout = & (((char *)save)[1]) + ((char *)save)[0]; - + /* len can only be 0 1 or 2 */ switch(len) - { - case 2: *saveout++ = *inptr++; - case 1: *saveout++ = *inptr++; - } + { + case 2: *saveout++ = *inptr++; + case 1: *saveout++ = *inptr++; + } ((char *)save)[0] += len; } - + return outptr - out; } /** * g_base64_encode_close: * @break_lines: whether to break long lines - * @out: pointer to destination buffer - * @state: Saved state from g_base64_encode_step() - * @save: Saved state from g_base64_encode_step() + * @out: (out) (array) (element-type guint8): pointer to destination buffer + * @state: (inout): Saved state from g_base64_encode_step() + * @save: (inout): Saved state from g_base64_encode_step() * * Flush the status from a sequence of calls to g_base64_encode_step(). * @@ -189,15 +192,15 @@ g_base64_encode_step (const guchar *in, * be written to it. It will need up to 4 bytes, or up to 5 bytes if * line-breaking is enabled. * - * Return value: The number of bytes of output that was written + * Returns: The number of bytes of output that was written * * Since: 2.12 */ gsize g_base64_encode_close (gboolean break_lines, - gchar *out, - gint *state, - gint *save) + gchar *out, + gint *state, + gint *save) { int c1, c2; char *outptr = out; @@ -208,7 +211,7 @@ g_base64_encode_close (gboolean break_lines, c1 = ((unsigned char *) save) [1]; c2 = ((unsigned char *) save) [2]; - + switch (((char *) save) [0]) { case 2: @@ -226,37 +229,36 @@ g_base64_encode_close (gboolean break_lines, } if (break_lines) *outptr++ = '\n'; - + *save = 0; *state = 0; - + return outptr - out; } /** * g_base64_encode: - * @data: the binary data to encode + * @data: (array length=len) (element-type guint8): the binary data to encode * @len: the length of @data * * Encode a sequence of binary data into its Base-64 stringified * representation. * - * Return value: a newly allocated, zero-terminated Base-64 encoded - * string representing @data. The returned string must + * Returns: (transfer full): a newly allocated, zero-terminated Base-64 + * encoded string representing @data. The returned string must * be freed with g_free(). * * Since: 2.12 */ gchar * -g_base64_encode (const guchar *data, +g_base64_encode (const guchar *data, gsize len) { gchar *out; gint state = 0, outlen; gint save = 0; - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (len > 0, NULL); + g_return_val_if_fail (data != NULL || len == 0, NULL); /* We can use a smaller limit here, since we know the saved state is 0, +1 is needed for trailing \0, also check for unlikely integer overflow */ @@ -293,32 +295,32 @@ static const unsigned char mime_base64_rank[256] = { }; /** - * g_base64_decode_step: - * @in: binary input data + * g_base64_decode_step: + * @in: (array length=len) (element-type guint8): binary input data * @len: max length of @in data to decode - * @out: output buffer - * @state: Saved state between steps, initialize to 0 - * @save: Saved state between steps, initialize to 0 + * @out: (out) (array) (element-type guint8): output buffer + * @state: (inout): Saved state between steps, initialize to 0 + * @save: (inout): Saved state between steps, initialize to 0 * * Incrementally decode a sequence of binary data from its Base-64 stringified - * representation. By calling this function multiple times you can convert + * representation. By calling this function multiple times you can convert * data in chunks to avoid having to have the full encoded data in memory. * * The output buffer must be large enough to fit all the data that will * be written to it. Since base64 encodes 3 bytes in 4 chars you need * at least: (@len / 4) * 3 + 3 bytes (+ 3 may be needed in case of non-zero * state). - * - * Return value: The number of bytes of output that was written + * + * Returns: The number of bytes of output that was written * * Since: 2.12 **/ gsize -g_base64_decode_step (const gchar *in, - gsize len, - guchar *out, - gint *state, - guint *save) +g_base64_decode_step (const gchar *in, + gsize len, + guchar *out, + gint *state, + guint *save) { const guchar *inptr; guchar *outptr; @@ -335,51 +337,64 @@ g_base64_decode_step (const gchar *in, if (len <= 0) return 0; - + inend = (const guchar *)in+len; outptr = out; - + /* convert 4 base64 bytes to 3 normal bytes */ v=*save; i=*state; - inptr = (const guchar *)in; + last[0] = last[1] = 0; + + /* we use the sign in the state to determine if we got a padding character + in the previous sequence */ + if (i < 0) + { + i = -i; + last[0] = '='; + } + + inptr = (const guchar *)in; while (inptr < inend) { c = *inptr++; rank = mime_base64_rank [c]; if (rank != 0xff) - { - last[1] = last[0]; - last[0] = c; - v = (v<<6) | rank; - i++; - if (i==4) - { - *outptr++ = v>>16; - if (last[1] != '=') - *outptr++ = v>>8; - if (last[0] != '=') - *outptr++ = v; - i=0; - } - } + { + last[1] = last[0]; + last[0] = c; + v = (v<<6) | rank; + i++; + if (i==4) + { + *outptr++ = v>>16; + if (last[1] != '=') + *outptr++ = v>>8; + if (last[0] != '=') + *outptr++ = v; + i=0; + } + } } - + *save = v; - *state = i; - + *state = last[0] == '=' ? -i : i; + return outptr - out; } /** * g_base64_decode: * @text: zero-terminated string with base64 text to decode - * @out_len: The length of the decoded data is written here + * @out_len: (out): The length of the decoded data is written here * - * Decode a sequence of Base-64 encoded text into binary data + * Decode a sequence of Base-64 encoded text into binary data. Note + * that the returned binary data is not necessarily zero-terminated, + * so it should not be used as a character string. * - * Return value: a newly allocated buffer containing the binary data + * Returns: (transfer full) (array length=out_len) (element-type guint8): + * newly allocated buffer containing the binary data * that @text represents. The returned buffer must * be freed with g_free(). * @@ -387,38 +402,37 @@ g_base64_decode_step (const gchar *in, */ guchar * g_base64_decode (const gchar *text, - gsize *out_len) + gsize *out_len) { guchar *ret; gsize input_length; gint state = 0; guint save = 0; - + g_return_val_if_fail (text != NULL, NULL); g_return_val_if_fail (out_len != NULL, NULL); input_length = strlen (text); - g_return_val_if_fail (input_length > 1, NULL); - /* We can use a smaller limit here, since we know the saved state is 0, - +1 used to avoid calling g_malloc0(0), and hence retruning NULL */ + +1 used to avoid calling g_malloc0(0), and hence returning NULL */ ret = g_malloc0 ((input_length / 4) * 3 + 1); - + *out_len = g_base64_decode_step (text, input_length, ret, &state, &save); - - return ret; + + return ret; } - + /** * g_base64_decode_inplace: - * @text: zero-terminated string with base64 text to decode - * @out_len: The length of the decoded data is written here + * @text: (inout) (array length=out_len) (element-type guint8): zero-terminated + * string with base64 text to decode + * @out_len: (inout): The length of the decoded data is written here * * Decode a sequence of Base-64 encoded text into binary data * by overwriting the input data. * - * Return value: The binary data that @text responds. This pointer + * Returns: (transfer none): The binary data that @text responds. This pointer * is the same as the input @text. * * Since: 2.20 @@ -429,7 +443,7 @@ g_base64_decode_inplace (gchar *text, { gint input_length, state = 0; guint save = 0; - + g_return_val_if_fail (text != NULL, NULL); g_return_val_if_fail (out_len != NULL, NULL); @@ -438,10 +452,6 @@ g_base64_decode_inplace (gchar *text, g_return_val_if_fail (input_length > 1, NULL); *out_len = g_base64_decode_step (text, input_length, (guchar *) text, &state, &save); - - return (guchar *) text; -} - -#define __G_BASE64_C__ -#include "galiasdef.c" + return (guchar *) text; +}