/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef API_BASE_UTIL_BASE64_DECODE_H
#define API_BASE_UTIL_BASE64_DECODE_H
#include
#include
#include
#include
BASE_BEGIN_NAMESPACE()
namespace Detail {
static constexpr const uint8_t FROM_BASE64[] = {
62U, // '+' (ascii 43)
0, 0, 0, // invalid
63U, // '/' (ascii 47)
52U, 53U, 54U, 55U, 56U, 57U, 58U, 59U, 60U, 61U, //'0' '9' (ascii 48-57)
0, 0, 0, // invalid
0, // '=' padding (ascii 61)
0, 0, 0, // invalid
0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 16U, 17U, 18U, 19U, 20U, 21U, 22U, 23U, 24U,
25U, //'A' 'Z' (ascii 65-90)
0, 0, 0, 0, 0, 0, // invalid
26U, 27U, 28U, 29U, 30U, 31U, 32U, 33U, 34U, 35U, 36U, 37U, 38U, 39U, 40U, 41U, 42U, 43U, 44U, 45U, 46U, 47U, 48U,
49U, 50U, 51U //'a' 'z' (ascii 97-122)
};
inline uint8_t FromBase64(uint8_t c)
{
// Map characters to values from the table if they are in the 43..122 range. Invalid characters will return zeros.
if (c >= 43 && c <= 122) {
return FROM_BASE64[c - 43];
} else {
return 0;
}
}
inline uint32_t FromBase64(const char*& src)
{
uint32_t bits = static_cast(Detail::FromBase64((uint8_t)(*src++))) << (3u * 6u);
bits |= Detail::FromBase64((uint8_t)(*src++)) << (2u * 6u);
bits |= Detail::FromBase64((uint8_t)(*src++)) << (1u * 6u);
bits |= Detail::FromBase64((uint8_t)(*src++)) << (0u * 6u);
return bits;
}
inline void DecodeQuartets(uint8_t* dst, const char* src, signed left)
{
for (; left >= 4; left -= 4) {
auto bits = FromBase64(src);
*dst++ = uint8_t((bits >> 16u) & 0xff);
*dst++ = uint8_t((bits >> 8u) & 0xff);
*dst++ = uint8_t((bits >> 0u) & 0xff);
}
}
inline size_t CountPadding(string_view encodedString)
{
auto end = encodedString.end();
auto first = --end;
while (*first == '=') {
--first;
}
return static_cast(end - first);
}
} // namespace Detail
/** Decode base64 encoded data.
* A base64 encoded string should be padded to the next four bytes with '=' characters.
* @param encodedString String containing the base64 encoded data.
* @return Decoded data.
*/
inline vector Base64Decode(string_view encodedString)
{
// the length of the decoded binary data will be 3/4 of the encoded string.
vector decodedBinary(encodedString.size() * 3u / 4u);
Detail::DecodeQuartets(decodedBinary.data(), encodedString.data(), static_cast(encodedString.size()));
decodedBinary.erase(
decodedBinary.cend() - static_cast(Detail::CountPadding(encodedString)), decodedBinary.cend());
return decodedBinary;
}
BASE_END_NAMESPACE()
#endif // API_BASE_UTIL_BASE64_DECODE_H