converting to base 64

I am trying to write a program to convert a character array in to base64.
I think I'm on the right track but I'm getting stuck. Here is what I have so far.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <sstream>
#include <math.h>
using namespace std;

int main()
{
    char input[] = "d2Viam9ic0BpaGVhcnRyYWRpby5jb20"; 
    stringstream ss;
    for(int i = 0; input[i] !='\0'; i++)
    {
        for( int j = 7; j >= 0; j-- )
        {
            int bit = input[i] & ( 0x01 << j );
            if ( bit > 0 ) ss << 1;
            else ss << 0;
        }
    }
    return 0;
} 


So basiclly, I think have a string stream containing the binary stream of the original character array. I'm not sure if this is the most elegant way to do this but it's the best I could come up with.
I don't understand stringstream all that well. I think what I need to do is extract 6 bits at a time and convert it in to an intege. Finally, convert it in to a character. I'm just not pull out 6 bits at a time and but it into an integer.

Any advice?

Incedently. I'm trying to write this with as few libraries as possible and no asm insertions.

Only suggestion that I can think of is that you need 8 bits to make a character.

I don't understand your base 64 thing. could you explain that part of your program a bit more?
First thought that comes to my mind is to deal with the 6-bit groupings in threes (after all, since LCM(6, 8) = 24, each group of three 8-bit characters will give you four 6-bit base-64 values).

So I would read the input in groups of 3:
1
2
3
4
5
6
7
char a, b, c;
// Store 3 characters in a, b, and c
int val1, val2, val3, val4; // Could be done with arrays, but I'm just being lazy right now
val1 = (a & 0xFC) >> 2; // First 6 bits of a
val2 = ((a & 3) << 4) | ((b & 0xF0) >> 4); // Last 2 bits of a and first 4 bits of b
val3 = ((b & 0xF) << 2) | ((c & 0xC0) >> 6); // Last 4 bits of b and first 2 bits of c
val4 = c & 0x3F; // Last 6 bits of c 

If you're wondering where the "magic" hexadecimal numbers come from:
0xFC = 11111100 in binary
   3 = 00000011 in binary
0xF0 = 11110000 in binary
 0xF = 00001111 in binary
0xC0 = 11000000 in binary
0x3F = 00111111 in binary
.
You'll also have to deal with the case where the size of the input isn't a multiple of 3.
Last edited on
Thanks, I knew it was something simple. I'm still getting used to bit shifting
below are the two functions two encode to base64

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
char valuetochar(int v)
{
    char c;
    switch (v)
    {
        case 0: c='A';break;case 1: c='B';break;case 2: c='C';break;case 3: c='D';break;
        case 4: c='E';break;case 5: c='F';break;case 6: c='G';break;case 7: c='H';break;
        case 8: c='I';break;case 9: c='J';break;case 10: c='K';break;case 11: c='L';break;
        case 12: c='M';break;case 13: c='N';break;case 14: c='O';break;case 15: c='P';break;
        case 16: c='Q';break;case 17: c='R';break;case 18: c='S';break;case 19: c='T';break;
        case 20: c='U';break;case 21: c='V';break;case 22: c='W';break;case 23: c='X';break;
        case 24: c='Y';break;case 25: c='Z';break;case 26: c='a';break;case 27: c='b';break;
        case 28: c='c';break;case 29: c='d';break;case 30: c='e';break;case 31: c='f';break;
        case 32: c='g';break;case 33: c='h';break;case 34: c='i';break;case 35: c='j';break;
        case 36: c='k';break;case 37: c='l';break;case 38: c='m';break;case 39: c='n';break;
        case 40: c='o';break;case 41: c='p';break;case 42: c='q';break;case 43: c='r';break;
        case 44: c='s';break;case 45: c='t';break;case 46: c='u';break;case 47: c='v';break;
        case 48: c='w';break;case 49: c='x';break;case 50: c='y';break;case 51: c='z';break;
        case 52: c='0';break;case 53: c='1';break;case 54: c='2';break;case 55: c='3';break;
        case 56: c='4';break;case 57: c='5';break;case 58: c='6';break;case 59: c='7';break;
        case 60: c='8';break;case 61: c='9';break;case 62: c='+';break;case 63: c='/';break;
    }
    return c;
}

void encode64(char input[])
{
    unsigned int padding = 0;
    std::vector<int> v;			
    for( unsigned int i=0; input[i] != '\0'; i+=3 )
    {
        v.push_back ((input[i] & 0xFC) >> 2);
        if(input[i+1] == '\0')
        {
        padding = 2;
        break;
        }
        v.push_back (((input[i] & 0x03) << 4) | ((input[i+1] & 0xF0) >> 4));
        if(input[i+2] == '\0')
        {
        padding = 1;
        break;
        }
        v.push_back (((input[i+1] & 0x0F) << 2) | ((input[i+2] & 0xC0) >> 6));
        if(input[i+2] == '\0')
        {
        padding = 1;
        break;
        }
        v.push_back (input[i+2] & 0x3F);
    }
    for( unsigned int i = 0; i < v.size(); i++) std::cout << valuetochar(v[i]);
    for( ;padding > 0; padding--) std::cout << "=" ;
    std::cout << std::endl;
}


It seems to work pretty well. Now to write the decoder. :)
Topic archived. No new replies allowed.