Blue Swirl wrote: > On Sat, May 22, 2010 at 8:18 AM, Jan Kiszka <jan.kis...@web.de> wrote: >> From: Jan Kiszka <jan.kis...@siemens.com> >> >> Will be used by QBuffer. >> >> Signed-off-by: Jan Kiszka <jan.kis...@siemens.com> >> --- >> Makefile.objs | 2 +- >> base64.c | 202 >> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >> base64.h | 18 +++++ >> 3 files changed, 221 insertions(+), 1 deletions(-) >> create mode 100644 base64.c >> create mode 100644 base64.h >> >> diff --git a/Makefile.objs b/Makefile.objs >> index acbaf22..2c603b2 100644 >> --- a/Makefile.objs >> +++ b/Makefile.objs >> @@ -2,7 +2,7 @@ >> # QObject >> qobject-obj-y = qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o >> qobject-obj-y += qjson.o json-lexer.o json-streamer.o json-parser.o >> -qobject-obj-y += qerror.o >> +qobject-obj-y += qerror.o base64.o >> >> ####################################################################### >> # block-obj-y is code used by both qemu system emulation and qemu-img >> diff --git a/base64.c b/base64.c >> new file mode 100644 >> index 0000000..543e8c6 >> --- /dev/null >> +++ b/base64.c >> @@ -0,0 +1,202 @@ >> +/* >> + * Base64 encoder/decoder conforming to RFC 4648 >> + * (based on Mozilla's nsprpub/lib/libc/src/base64.c) >> + * >> + * Copyright (C) 2010 Siemens AG >> + * >> + * Authors: >> + * Jan Kiszka <jan.kis...@siemens.com> >> + * >> + * This work is licensed under the terms of the GNU LGPL, version 2.1 or >> later. >> + * See the COPYING.LIB file in the top-level directory. >> + * >> + */ >> + >> +#include "inttypes.h" > > Why not <inttypes.h>?
Oops, no intention. > >> +#include "base64.h" >> + >> +static const char base[] = >> + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; >> + >> +static void encode3to4(const char *src, char *dest) >> +{ >> + uint32_t b32 = 0; >> + int i, j = 18; >> + >> + for (i = 0; i < 3; i++) { >> + b32 <<= 8; >> + b32 |= src[i]; >> + } >> + for (i = 0; i < 4; i++) { >> + dest[i] = base[(b32 >> j) & 0x3F]; >> + j -= 6; >> + } >> +} >> + >> +static void encode2to4(const char *src, char *dest) >> +{ >> + dest[0] = base[(src[0] >> 2) & 0x3F]; >> + dest[1] = base[((src[0] & 0x03) << 4) | ((src[1] >> 4) & 0x0F)]; >> + dest[2] = base[(src[1] & 0x0F) << 2]; >> + dest[3] = '='; >> +} >> + >> +static void encode1to4(const char *src, char *dest) >> +{ >> + dest[0] = base[(src[0] >> 2) & 0x3F]; >> + dest[1] = base[(src[0] & 0x03) << 4]; >> + dest[2] = '='; >> + dest[3] = '='; >> +} >> + >> +/* >> + * Encode data in 'src' of length 'srclen' to a base64 string, saving the >> + * null-terminated result in 'dest'. The size of the destition buffer must >> be >> + * at least ((srclen + 2) / 3) * 4 + 1. >> + */ >> +void base64_encode(const void *src, size_t srclen, char *dest) >> +{ >> + while (srclen >= 3) { >> + encode3to4(src, dest); >> + src += 3; >> + dest += 4; >> + srclen -= 3; >> + } >> + switch (srclen) { >> + case 2: >> + encode2to4(src, dest); >> + dest += 4; >> + break; >> + case 1: >> + encode1to4(src, dest); >> + dest += 4; >> + break; >> + case 0: >> + break; >> + } >> + dest[0] = 0; >> +} >> + >> +static int32_t codetovalue(char c) >> +{ >> + if (c >= 'A' && c <= 'Z') { >> + return c - 'A'; >> + } else if (c >= 'a' && c <= 'z') { >> + return c - 'a' + 26; >> + } else if (c >= '0' && c <= '9') { >> + return c - '0' + 52; >> + } else if (c == '+') { >> + return 62; >> + } else if ( c == '/') { >> + return 63; >> + } else { >> + return -1; >> + } >> +} >> + >> +static int decode4to3 (const char *src, char *dest) >> +{ >> + uint32_t b32 = 0; >> + int32_t bits; >> + int i; >> + >> + for (i = 0; i < 4; i++) { >> + bits = codetovalue(src[i]); >> + if (bits < 0) { >> + return bits; >> + } >> + b32 <<= 6; >> + b32 |= bits; >> + } >> + dest[0] = (b32 >> 16) & 0xFF; >> + dest[1] = (b32 >> 8) & 0xFF; >> + dest[2] = b32 & 0xFF; >> + >> + return 0; >> +} >> + >> +static int decode3to2(const char *src, char *dest) >> +{ >> + uint32_t b32 = 0; >> + int32_t bits; >> + >> + bits = codetovalue(src[0]); >> + if (bits < 0) { >> + return bits; >> + } >> + b32 = (uint32_t)bits; >> + b32 <<= 6; >> + >> + bits = codetovalue(src[1]); >> + if (bits < 0) { >> + return bits; >> + } >> + b32 |= (uint32_t)bits; >> + b32 <<= 4; >> + >> + bits = codetovalue(src[2]); >> + if (bits < 0) { >> + return bits; >> + } >> + b32 |= ((uint32_t)bits) >> 2; >> + >> + dest[0] = (b32 >> 8) & 0xFF; >> + dest[1] = b32 & 0xFF; >> + >> + return 0; >> +} >> + >> +static int decode2to1(const char *src, char *dest) >> +{ >> + uint32_t b32; >> + int32_t bits; >> + >> + bits = codetovalue(src[0]); >> + if (bits < 0) { >> + return bits; >> + } >> + b32 = (uint32_t)bits << 2; >> + >> + bits = codetovalue(src[1]); >> + if (bits < 0) { >> + return bits; >> + } >> + b32 |= ((uint32_t)bits) >> 4; >> + >> + dest[0] = b32; >> + >> + return 0; >> +} >> + >> +/* >> + * Convert string 'src' of length 'srclen' from base64 to binary form, >> + * saving the result in 'dest'. The size of the destination buffer must be >> at >> + * least srclen * 3 / 4. >> + * >> + * Returns 0 on success, -1 on conversion error. >> + */ >> +int base64_decode(const char *src, size_t srclen, void *dest) > > I think dest should be char *, like all the functions where dest is passed to. The output may but need not be a string, it's binary data. And to avoid needless warnings about signedness mismatches if unsigned char or uint8_t buffers are passed, I chose void *. > >> +{ >> + int ret; >> + >> + while (srclen >= 4) { >> + ret = decode4to3(src, dest); >> + if (ret < 0) { >> + return ret; >> + } >> + src += 4; >> + dest += 3; >> + srclen -= 4; >> + } >> + >> + switch (srclen) { >> + case 3: >> + return decode3to2(src, dest); >> + case 2: >> + return decode2to1(src, dest); >> + case 1: >> + return -1; >> + default: /* 0 */ >> + return 0; >> + } >> +} >> diff --git a/base64.h b/base64.h >> new file mode 100644 >> index 0000000..9a0e03a >> --- /dev/null >> +++ b/base64.h >> @@ -0,0 +1,18 @@ >> +/* >> + * Base64 encoder/decoder conforming to RFC 4648 >> + * (based on Mozilla's nsprpub/lib/libc/src/base64.c) >> + * >> + * Copyright (C) 2010 Siemens AG >> + * >> + * Authors: >> + * Jan Kiszka <jan.kis...@siemens.com> >> + * >> + * This work is licensed under the terms of the GNU LGPL, version 2.1 or >> later. >> + * See the COPYING.LIB file in the top-level directory. >> + * >> + */ >> + >> +#include <unistd.h> > > Maybe <stddef.h> instead, it's only for size_t? Makes sense. > >> + >> +void base64_encode(const void *src, size_t srclen, char *dest); >> +int base64_decode(const char *src, size_t srclen, void *dest); >> -- >> 1.6.0.2 >> >> >> Thanks, Jan
signature.asc
Description: OpenPGP digital signature