1 | /* |
---|---|
2 | cencoder.c - c source to a base64 encoding algorithm implementation |
3 | |
4 | This is part of the libb64 project, and has been placed in the public domain. |
5 | For details, see http://sourceforge.net/projects/libb64 |
6 | */ |
7 | |
8 | #include "b64/cencode.h" |
9 | |
10 | void base64_init_encodestate(base64_encodestate* state_in) |
11 | { |
12 | state_in->step = step_A; |
13 | state_in->result = 0; |
14 | state_in->stepcount = 0; |
15 | } |
16 | |
17 | char base64_encode_value(char value_in) |
18 | { |
19 | static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
20 | if (value_in > 63) return '='; |
21 | return encoding[(int)value_in]; |
22 | } |
23 | |
24 | int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) |
25 | { |
26 | const char* plainchar = plaintext_in; |
27 | const char* const plaintextend = plaintext_in + length_in; |
28 | char* codechar = code_out; |
29 | char result; |
30 | char fragment; |
31 | |
32 | result = state_in->result; |
33 | |
34 | switch (state_in->step) |
35 | { |
36 | while (1) |
37 | { |
38 | case step_A: |
39 | if (plainchar == plaintextend) |
40 | { |
41 | state_in->result = result; |
42 | state_in->step = step_A; |
43 | return (int)(codechar - code_out); |
44 | } |
45 | fragment = *plainchar++; |
46 | result = (fragment & 0x0fc) >> 2; |
47 | *codechar++ = base64_encode_value(value_in: result); |
48 | result = (fragment & 0x003) << 4; |
49 | /* fall through */ |
50 | |
51 | case step_B: |
52 | if (plainchar == plaintextend) |
53 | { |
54 | state_in->result = result; |
55 | state_in->step = step_B; |
56 | return (int)(codechar - code_out); |
57 | } |
58 | fragment = *plainchar++; |
59 | result |= (fragment & 0x0f0) >> 4; |
60 | *codechar++ = base64_encode_value(value_in: result); |
61 | result = (fragment & 0x00f) << 2; |
62 | /* fall through */ |
63 | |
64 | case step_C: |
65 | if (plainchar == plaintextend) |
66 | { |
67 | state_in->result = result; |
68 | state_in->step = step_C; |
69 | return (int)(codechar - code_out); |
70 | } |
71 | fragment = *plainchar++; |
72 | result |= (fragment & 0x0c0) >> 6; |
73 | *codechar++ = base64_encode_value(value_in: result); |
74 | result = (fragment & 0x03f) >> 0; |
75 | *codechar++ = base64_encode_value(value_in: result); |
76 | |
77 | ++(state_in->stepcount); |
78 | } |
79 | } |
80 | /* control should not reach here */ |
81 | return (int)(codechar - code_out); |
82 | } |
83 | |
84 | int base64_encode_blockend(char* code_out, base64_encodestate* state_in) |
85 | { |
86 | char* codechar = code_out; |
87 | |
88 | switch (state_in->step) |
89 | { |
90 | case step_B: |
91 | *codechar++ = base64_encode_value(value_in: state_in->result); |
92 | *codechar++ = '='; |
93 | *codechar++ = '='; |
94 | break; |
95 | case step_C: |
96 | *codechar++ = base64_encode_value(value_in: state_in->result); |
97 | *codechar++ = '='; |
98 | break; |
99 | case step_A: |
100 | break; |
101 | } |
102 | *codechar++ = '\n'; |
103 | |
104 | return (int)(codechar - code_out); |
105 | } |
106 | |
107 |