Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / ace / Codecs.cpp
blob7b22f273542168f0a06fe8e3e45cfeaf5748c022
1 #include "ace/Codecs.h"
2 #include "ace/Log_Category.h"
3 #include "ace/OS_Memory.h"
4 #include "ace/OS_NS_ctype.h"
6 #if defined (ACE_HAS_ALLOC_HOOKS)
7 # include "ace/Malloc_Base.h"
8 #endif /* ACE_HAS_ALLOC_HOOKS */
10 namespace
12 // Just in case ...
13 #undef alphabet
14 #undef pad
15 #undef max_columns
17 // Symbols which form the Base64 alphabet (Defined as per RFC 2045)
18 ACE_Byte const alphabet[] =
19 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
21 // The padding character used in the encoding
22 ACE_Byte const pad = '=';
24 // Number of columns per line of encoded output (Can have a maximum
25 // value of 76).
26 int const max_columns = 72;
29 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
31 bool ACE_Base64::init_ = false;
33 ACE_Byte ACE_Base64::decoder_[256];
35 ACE_Byte ACE_Base64::member_[256];
37 ACE_Byte*
38 ACE_Base64::encode (const ACE_Byte* input,
39 const size_t input_len,
40 size_t* output_len,
41 bool is_chunked)
43 if (!ACE_Base64::init_)
44 ACE_Base64::init();
46 if (!input)
47 return 0;
49 ACE_Byte* result = 0;
51 size_t length = ((input_len + 2) / 3) * 4;
52 size_t num_lines = length / max_columns + 1;
53 length += num_lines + 1;
54 #if defined (ACE_HAS_ALLOC_HOOKS)
55 ACE_ALLOCATOR_RETURN (result, static_cast<ACE_Byte*> (ACE_Allocator::instance()->malloc(sizeof (ACE_Byte) * length)), 0);
56 #else
57 ACE_NEW_RETURN (result, ACE_Byte[length], 0);
58 #endif /* ACE_HAS_ALLOC_HOOKS */
60 int char_count = 0;
61 int bits = 0;
62 size_t pos = 0;
63 int cols = 0;
65 for (size_t i = 0; i < input_len; ++i)
67 bits += input[i];
68 ++char_count;
70 if (char_count == 3)
72 result[pos++] = alphabet[bits >> 18];
73 result[pos++] = alphabet[(bits >> 12) & 0x3f];
74 result[pos++] = alphabet[(bits >> 6) & 0x3f];
75 result[pos++] = alphabet[bits & 0x3f];
76 cols += 4;
77 if (cols == max_columns) {
78 if (is_chunked)
79 result[pos++] = '\n';
80 cols = 0;
82 bits = 0;
83 char_count = 0;
85 else
87 bits <<= 8;
91 if (char_count != 0)
93 bits <<= (16 - (8 * char_count));
94 result[pos++] = alphabet[bits >> 18];
95 result[pos++] = alphabet[(bits >> 12) & 0x3f];
96 cols += 2;
97 if (char_count == 1)
99 result[pos++] = pad;
100 result[pos++] = pad;
101 cols += 2;
103 else
105 result[pos++] = alphabet[(bits >> 6) & 0x3f];
106 result[pos++] = pad;
107 cols += 2;
111 if (cols > 0 && is_chunked)
112 result[pos++] = '\n';
114 result[pos] = 0;
115 *output_len = pos;
116 return result;
119 size_t
120 ACE_Base64::length (const ACE_Byte* input)
122 if (!ACE_Base64::init_)
123 ACE_Base64::init();
125 ACE_Byte* ptr = const_cast<ACE_Byte*> (input);
126 while (*ptr != 0 &&
127 (member_[*(ptr)] == 1 || *ptr == pad
128 || ACE_OS::ace_isspace (*ptr)))
129 ++ptr;
130 size_t len = ptr - input;
131 len = ((len + 3) / 4) * 3 + 1 ;
132 return len;
135 ACE_Byte*
136 ACE_Base64::decode (const ACE_Byte* input, size_t* output_len)
138 if (!ACE_Base64::init_)
139 ACE_Base64::init();
141 if (!input)
142 return 0;
144 size_t result_len = ACE_Base64::length (input);
145 ACE_Byte* result = 0;
147 #if defined (ACE_HAS_ALLOC_HOOKS)
148 ACE_ALLOCATOR_RETURN (result, static_cast<ACE_Byte*> (ACE_Allocator::instance()->malloc(sizeof (ACE_Byte) * result_len)), 0);
149 #else
150 ACE_NEW_RETURN (result, ACE_Byte[result_len], 0);
151 #endif /* ACE_HAS_ALLOC_HOOKS */
153 ACE_Byte* ptr = const_cast<ACE_Byte*> (input);
154 while (*ptr != 0 &&
155 (member_[*(ptr)] == 1 || *ptr == pad
156 || ACE_OS::ace_isspace (*ptr)))
157 ++ptr;
158 size_t input_len = ptr - input;
160 int char_count = 0;
161 int bits = 0;
162 size_t pos = 0;
164 size_t i = 0;
165 for (; i < input_len; ++i)
167 if (input[i] == pad)
168 break;
169 if (!ACE_Base64::member_[input[i]])
170 continue;
171 bits += decoder_[input[i]];
172 ++char_count;
174 if (char_count == 4)
176 result[pos++] = static_cast<ACE_Byte> (bits >> 16);
177 result[pos++] = static_cast<ACE_Byte> ((bits >> 8) & 0xff);
178 result[pos++] = static_cast<ACE_Byte> (bits & 0xff);
179 bits = 0;
180 char_count = 0;
182 else
184 bits <<= 6;
188 int errors = 0;
189 if ( i == input_len)
191 if (char_count)
193 ACELIB_ERROR ((LM_ERROR,
194 ACE_TEXT ("Decoding incomplete: atleast %d bits truncated\n"),
195 (4 - char_count) * 6));
196 ++errors;
199 else
201 switch (char_count)
203 case 1:
204 ACELIB_ERROR ((LM_ERROR,
205 ACE_TEXT ("Decoding incomplete: atleast 2 bits missing\n")));
206 ++errors;
207 break;
208 case 2:
209 result[pos++] = static_cast<ACE_Byte> (bits >> 10);
210 break;
211 case 3:
212 result[pos++] = static_cast<ACE_Byte> (bits >> 16);
213 result[pos++] = static_cast<ACE_Byte> ((bits >> 8) & 0xff);
214 break;
218 if (errors)
220 #if defined (ACE_HAS_ALLOC_HOOKS)
221 ACE_Allocator::instance()->free(result);
222 #else
223 delete[] result;
224 #endif /* ACE_HAS_ALLOC_HOOKS */
225 return 0;
227 result[pos] = 0;
228 *output_len = pos;
229 return result;
232 void
233 ACE_Base64::init ()
235 if (!ACE_Base64::init_)
237 for (ACE_Byte i = 0; i < sizeof (alphabet); ++i)
239 ACE_Base64::decoder_[alphabet[i]] = i;
240 ACE_Base64::member_ [alphabet[i]] = 1;
242 ACE_Base64::init_ = true;
244 return;
247 ACE_END_VERSIONED_NAMESPACE_DECL