繁体   English   中英

C - 解码base64时的位移位

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM