blob: 2103d6d5a687688759f40f6e7cad0fce190eada8 (
plain) (
blame)
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/core/utils/base64/Base64.h>
#include <cstring>
using namespace Aws::Utils::Base64;
static const uint8_t SENTINEL_VALUE = 255;
static const char BASE64_ENCODING_TABLE_MIME[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
namespace Aws
{
namespace Utils
{
namespace Base64
{
Base64::Base64(const char *encodingTable)
{
if(encodingTable == nullptr)
{
encodingTable = BASE64_ENCODING_TABLE_MIME;
}
size_t encodingTableLength = strlen(encodingTable);
if(encodingTableLength != 64)
{
encodingTable = BASE64_ENCODING_TABLE_MIME;
encodingTableLength = 64;
}
memcpy(m_mimeBase64EncodingTable, encodingTable, encodingTableLength);
memset((void *)m_mimeBase64DecodingTable, 0, 256);
for(uint32_t i = 0; i < encodingTableLength; ++i)
{
uint32_t index = static_cast<uint32_t>(m_mimeBase64EncodingTable[i]);
m_mimeBase64DecodingTable[index] = static_cast<uint8_t>(i);
}
m_mimeBase64DecodingTable[(uint32_t)'='] = SENTINEL_VALUE;
}
Aws::String Base64::Encode(const Aws::Utils::ByteBuffer& buffer) const
{
size_t bufferLength = buffer.GetLength();
size_t blockCount = (bufferLength + 2) / 3;
size_t remainderCount = (bufferLength % 3);
Aws::String outputString;
outputString.reserve(CalculateBase64EncodedLength(buffer));
for(size_t i = 0; i < bufferLength; i += 3 )
{
uint32_t block = buffer[ i ];
block <<= 8;
if (i + 1 < bufferLength)
{
block = block | buffer[ i + 1 ];
}
block <<= 8;
if (i + 2 < bufferLength)
{
block = block | buffer[ i + 2 ];
}
outputString.push_back(m_mimeBase64EncodingTable[(block >> 18) & 0x3F]);
outputString.push_back(m_mimeBase64EncodingTable[(block >> 12) & 0x3F]);
outputString.push_back(m_mimeBase64EncodingTable[(block >> 6) & 0x3F]);
outputString.push_back(m_mimeBase64EncodingTable[block & 0x3F]);
}
if(remainderCount > 0)
{
outputString[blockCount * 4 - 1] = '=';
if(remainderCount == 1)
{
outputString[blockCount * 4 - 2] = '=';
}
}
return outputString;
}
Aws::Utils::ByteBuffer Base64::Decode(const Aws::String& str) const
{
size_t decodedLength = CalculateBase64DecodedLength(str);
Aws::Utils::ByteBuffer buffer(decodedLength);
const char* rawString = str.c_str();
size_t blockCount = str.length() / 4;
for(size_t i = 0; i < blockCount; ++i)
{
size_t stringIndex = i * 4;
uint32_t value1 = m_mimeBase64DecodingTable[uint32_t(rawString[stringIndex])];
uint32_t value2 = m_mimeBase64DecodingTable[uint32_t(rawString[++stringIndex])];
uint32_t value3 = m_mimeBase64DecodingTable[uint32_t(rawString[++stringIndex])];
uint32_t value4 = m_mimeBase64DecodingTable[uint32_t(rawString[++stringIndex])];
size_t bufferIndex = i * 3;
buffer[bufferIndex] = static_cast<uint8_t>((value1 << 2) | ((value2 >> 4) & 0x03));
if(value3 != SENTINEL_VALUE)
{
buffer[++bufferIndex] = static_cast<uint8_t>(((value2 << 4) & 0xF0) | ((value3 >> 2) & 0x0F));
if(value4 != SENTINEL_VALUE)
{
buffer[++bufferIndex] = static_cast<uint8_t>((value3 & 0x03) << 6 | value4);
}
}
}
return buffer;
}
size_t Base64::CalculateBase64DecodedLength(const Aws::String& b64input)
{
const size_t len = b64input.length();
if(len < 2)
{
return 0;
}
size_t padding = 0;
if (b64input[len - 1] == '=' && b64input[len - 2] == '=') //last two chars are =
padding = 2;
else if (b64input[len - 1] == '=') //last char is =
padding = 1;
return (len * 3 / 4 - padding);
}
size_t Base64::CalculateBase64EncodedLength(const Aws::Utils::ByteBuffer& buffer)
{
return 4 * ((buffer.GetLength() + 2) / 3);
}
} // namespace Base64
} // namespace Utils
} // namespace Aws
|