我正在尝试解码C中的base64数据。我找到了我想要使用的实现,但我不确定它是如何工作的,我希望对使用的一般语法有一些帮助/解释在这里:Base64Decode
我想要了解的代码是:
int base64decode (char *in, size_t inLen, unsigned char *out, size_t *outLen) {
char *end = in + inLen;
size_t buf = 1, len = 0;
while (in < end) {
unsigned char c = d[*in++];
switch (c) {
case WHITESPACE: continue; /* skip whitespace */
case INVALID: return 1; /* invalid input, return error */
case EQUALS: /* pad character, end of data */
in = end;
continue;
default:
buf = buf << 6 | c;
/* If the buffer is full, split it into bytes */
if (buf & 0x1000000) {
if ((len += 3) > *outLen) return 1; /* buffer overflow */
*out++ = buf >> 16;
*out++ = buf >> 8;
*out++ = buf;
buf = 1;
}
}
}
if (buf & 0x40000) {
if ((len += 2) > *outLen) return 1; /* buffer overflow */
*out++ = buf >> 10;
*out++ = buf >> 2;
}
else if (buf & 0x1000) {
if (++len > *outLen) return 1; /* buffer overflow */
*out++ = buf >> 4;
}
*outLen = len; /* modify to reflect the actual output size */
return 0;
}
我坚持* out ++ out = buf&gt;&gt; 16; ,它告诉我,out的值将等于buff,它应该是1000000向右移16位?值中甚至没有16位,所以它不会归零吗?我真的很想了解这些代码的其余部分,非常感谢任何帮助。提前谢谢!
答案 0 :(得分:2)
您可以一步一步地解决这个问题。让我们跳过空格,等号和无效字符以及最后填充的代码,并关注循环和defualt子句:
size_t buf = 1;
while (in < end) {
unsigned char c
/* read next byte */
c = d[*in++];
/* append byte to number */
buf = buf << 6 | c;
/* If the buffer is full, split it into bytes */
if (buf & 0x1000000) {
*out++ = buf >> 16;
*out++ = buf >> 8;
*out++ = buf;
buf = 1;
}
}
代码逐字节读取,然后附加到buf
。输入为6-ybit-chunks,输出应为8-bit-chunk,又称字节。 (非法输入字符是设置了前两位中的任何一个的字符。)
这个想法是使用buf
作为辅助缓冲区,存储四个六位值,直到它满。然后,将该缓冲区的内容写为三个八位值。
我们从buf == 1
开始:
.... .... .... .... .... .... .... ...1
空位在这里表示为点,它比零更容易阅读。 1
是哨兵值。好的,读取下一个字节,用a
表示。将缓冲区移动六个位置
.... .... .... .... .... .... .1.. .... // buf = buf << 6
并做一个逻辑或数据:
.... .... .... .... .... .... .1aa aaaa // buf = buf | 'a'
好的,下一个字节,'b':
.... .... .... .... ...1 aaaa aa.. .... // buf = buf << 6
.... .... .... .... ...1 aaaa aabb bbbb // buf = buf | 'b'
下一个字节'c':
.... .... .... .1aa aaaa bbbb bb.. .... // buf = buf << 6
.... .... .... .1aa aaaa bbbb bbcc cccc // buf = buf | 'c'
和'd':
.... ...1 aaaa aabb bbbb cccc cc.. .... // buf = buf << 6
.... ...1 aaaa aabb bbbb cccc ccdd dddd // buf = buf | 'd'
现在查看缓冲区是否已满。 (这是在读取每个字节后完成的,但为了清楚起见,我将其删除了。)这是通过buf
与0x1000000
进行逐位和.... ...1 aaaa aabb bbbb cccc ccdd dddd // buf
.... ...1 .... .... .... .... .... .... // 0x1000000
.... ...1 .... .... .... .... .... .... // buf & 0x1000000
完成的:
.... .... .... .... .... ...1 aaaa aabb // buf >> 16
.... .... .... ...1 aaaa aabb bbbb cccc // buf >> 8
.... ...1 aaaa aabb bbbb cccc ccdd dddd // buf
这个值第一次现在是真的,这意味着我们已经读取了四个六位块,我们现在需要将数据写为三个八位块。
---- ---- ---- ---- ---- ---- aaaa aabb // (uchar) (buf >> 16)
---- ---- ---- ---- ---- ---- bbbb cccc // (uchar) (buf >> 8)
---- ---- ---- ---- ---- ---- ccdd dddd // (uchar) buf
这些值写入字节,即无符号字符,将其截断为最低的8位:
buf
现在,将1
重置为{{1}}并阅读下一个字节。