
[英]Base64 decoding - bit shift results in unexpected end of char array in C
[英]C - Bit Shifting while decoding base64
我正在尝试解码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 ++ = buf >> 16; ,它告诉我,out的值将等于buff,它应该是1000000向右移16位? 值中甚至没有16位,所以它不会归零吗? 我真的很想了解这些代码的其余部分,非常感谢任何帮助。 提前致谢!
你可以一步一步地解决这个问题。 让我们跳过空格,等号和无效字符以及最后填充的代码,并关注循环和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'
现在看看缓冲区是否已满。 (这是在读取每个字节后完成的,但为了清楚起见,我已将其删除了。)这是通过按位并使用0x1000000
buf
完成的:
.... ...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
这些值写入字节,即无符号字符,将其截断为最低的8位:
---- ---- ---- ---- ---- ---- aaaa aabb // (uchar) (buf >> 16)
---- ---- ---- ---- ---- ---- bbbb cccc // (uchar) (buf >> 8)
---- ---- ---- ---- ---- ---- ccdd dddd // (uchar) buf
现在,将buf
重置为1
并读取下一个字节。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.