0

I try to implement a base64 encoder. I have this algorithm:

while (len--)
{
    char_array_3[i++] = *(data++);

    if (i == 3)
    {
        char_array_4[0] = (char_array_3[0] & 252) >> 2; //This line.
        char_array_4[1] = ((char_array_3[0] & 3) << 4) + ((char_array_3[1] & 240) >> 4);
        char_array_4[2] = ((char_array_3[1] & 15) << 2) + ((char_array_3[2] & 192) >> 6);
        char_array_4[3] = char_array_3[2] & 63;

        for (i = 0; i < 4; i++) {
            ret += base64_chars[char_array_4[i]];
        }
        i = 0;
    }
}

Why I should do char_array_3[0] & 252? I can use only >> 2. Since ...

For instance, if I put this character H:

H -> 01001000

I can do bit shift: 01001000 >> 2 = 000100100

Or use and (&)...

252 -> 11111100

01001000 & 11111100 = 01001000 I will have the same digit...

And then need to do this: 01001000 >> 2 = 000100100

May I remove the number 252, 3, 240 etc.?

lostsky25
  • 85
  • 1
  • 10
  • What do you mean by "and the other"? What other? – David Schwartz Aug 11 '20 at 16:48
  • 2
    I would try to make this code readable first. For example replace decimal constants with hex. – Slava Aug 11 '20 at 16:52
  • @David Schwartz, I mean ```252```, ```3```, ```240```, ```15```, ```192``` and ```63```. – lostsky25 Aug 11 '20 at 16:53
  • @lostsky25 If you think you can remove the `3` in `((char_array_3[0]&3)<<4)`, then you don't understand the code. – David Schwartz Aug 11 '20 at 16:54
  • @Slava, In the first implementation I had hexadecimal literals. I just changed to decimal literals. – lostsky25 Aug 11 '20 at 16:56
  • @David Schwartz, Ok, what about ```252```? – lostsky25 Aug 11 '20 at 16:57
  • You should not, it much easier to read binary in hex format. – Slava Aug 11 '20 at 16:57
  • What type is `char_array_3`? Is it an array of `char` or `unsigned char`? If it is a `signed char`, then you should keep the masks. If the code is supposed to be portable, and the type is `char`, then you should keep the masks. If it isn't `unsigned char`, it probably ought to be (or `std::uint8_t` or `std::byte`). – Eljay Aug 11 '20 at 17:57

1 Answers1

2

May I remove the number 252, 3, 240 etc.?

No, not all of them. In case of right shift and binary mask 252, 240 and 192 they are redundant and you can remove them. But 3 15 and 63 are not redundant, as you would propagate bits that you should not to.

Slava
  • 43,454
  • 1
  • 47
  • 90
  • Leaving the redundant constants there may make the code more understandable. A good optimizer would recognize that they're redundant and remove them from the compiled code. – Mark Ransom Aug 11 '20 at 17:00
  • @MarkRansom I agree, but OP's question if he can remove them, not why they are there in the first place. – Slava Aug 11 '20 at 17:01
  • Yes, I removed the redundant digits. I got the same string... And I'll change decimal constants to hexdecimal. – lostsky25 Aug 11 '20 at 17:02
  • "Why should I" was also part of the question. Realize I wasn't complaining, just presenting a different point of view. – Mark Ransom Aug 11 '20 at 17:06
  • @MarkRansom ""Why should I" was also part of the question. ". Yea missed that, good point. – Slava Aug 11 '20 at 17:08