/*
* 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_ENCODE_H
#define API_BASE_UTIL_BASE64_ENCODE_H
#include
#include
#include
#include
BASE_BEGIN_NAMESPACE()
namespace Detail {
static constexpr const char TO_BASE64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
inline void ToBase64(const uint8_t* threeBytes, char* output)
{
output[0U] = TO_BASE64[threeBytes[0u] >> 2u];
output[1U] = TO_BASE64[((threeBytes[0u] << 4u) | (threeBytes[1u] >> 4u)) & 0x3f];
output[2U] = TO_BASE64[((threeBytes[1u] << 2u) | (threeBytes[2u] >> 6u)) & 0x3f];
output[3U] = TO_BASE64[threeBytes[2u] & 0x3f];
}
inline void ToBase64(const uint8_t* threeBytes, char* output, signed left)
{
output[0U] = TO_BASE64[threeBytes[0u] >> 2u];
output[1U] = TO_BASE64[((threeBytes[0u] << 4u) | (threeBytes[1u] >> 4u)) & 0x3f];
output[2U] = left > 1 ? (TO_BASE64[((threeBytes[1u] << 2u) | (threeBytes[2u] >> 6u)) & 0x3f]) : '=';
output[3U] = left > 2 ? TO_BASE64[threeBytes[2u] & 0x3f] : '=';
}
inline signed EncodeTriplets(char*& dst, const uint8_t*& src, signed left)
{
for (; left >= 3; left -= 3) {
Detail::ToBase64(src, dst);
src += 3U;
dst += 4U;
}
return left;
}
inline void FillTriplet(uint8_t* dst, const uint8_t*& src, signed left)
{
switch (left) {
case 2:
*dst++ = *src++;
case 1:
*dst++ = *src++;
}
}
inline void EncodeTail(char* dst, const uint8_t* src, signed left)
{
if (left) {
uint8_t rest[3] { 0, 0, 0 };
FillTriplet(rest, src, left);
Detail::ToBase64(rest, dst, left);
}
}
} // namespace Detail
/** Base 64 encode data.
* @param binaryData Data to encode.
* @return Data as a base64 string.
*/
inline string Base64Encode(array_view binaryData)
{
// The length of the encoded binary data will be about 4/3 of the encoded string.
string encodedString((binaryData.size() + 2U) / 3U * 4U, '=');
auto dst = encodedString.data();
auto src = binaryData.data();
signed left = static_cast(binaryData.size());
// First write the full groups of three bytes
left = Detail::EncodeTriplets(dst, src, left);
// Add the rest of the bytes that was not divisible by three
Detail::EncodeTail(dst, src, left);
return encodedString;
}
BASE_END_NAMESPACE()
#endif // API_BASE_UTIL_BASE64_ENCODE_H