Skip to content

Instantly share code, notes, and snippets.

@EmingK
Created February 18, 2023 02:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EmingK/dc134a2c525c4c29114f5ba850836076 to your computer and use it in GitHub Desktop.
Save EmingK/dc134a2c525c4c29114f5ba850836076 to your computer and use it in GitHub Desktop.
A Base64 Encoding Implementation using C++ Template Metaprogramming
#include <iostream>
#include <type_traits>
template <char ...chars>
using TString = std::integer_sequence<char, chars...>;
template <typename T, T ...chars>
constexpr TString<chars...> operator""_tstr() { return { }; }
template <typename>
char const FromTString[] = { 0 };
template <char ..._Bytes>
char const FromTString<TString<_Bytes...>>[] = { _Bytes..., 0 };
template <char _First, typename>
struct TStringPrepend {} ;
template <char _First, char ..._Bytes>
struct TStringPrepend<_First, TString<_Bytes...>> {
using type = TString<_First, _Bytes...>;
};
constexpr char Base64Lookup(int idx) {
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[idx];
}
template <int _Bits, int _Data, char _First, char ..._Rest>
struct Base64Inner;
template <int _Bits, int _Data>
struct Base64Last;
template <int _Bits, int _Encoded, int _NextBits, int _Next, char _First, char ..._Rest>
struct Base64EncodeNextType {
using type = typename TStringPrepend<_Encoded, typename Base64Inner<_NextBits, _Next, _Rest...>::StringType>::type;
};
template <int _Encoded, int _Next, int _NextBits, char _First, char ..._Rest>
struct Base64EncodeNextType<6, _Encoded, _NextBits, _Next, _First, _Rest...> {
using type = typename TStringPrepend<_Encoded, typename Base64Inner<0, 0, _First, _Rest...>::StringType>::type;
};
template <int _Bits, int _Data, char _First, char ..._Rest>
struct Base64Inner {
static constexpr int EncodeBits = 6 - _Bits;
static constexpr int ShiftBits = 8 - EncodeBits;
static constexpr int EncodedByte = Base64Lookup((_Data << EncodeBits) | (((unsigned char)_First) >> ShiftBits));
static constexpr int StagedByte = _First & ((1 << ShiftBits) - 1);
using StringType = typename Base64EncodeNextType<_Bits, EncodedByte, ShiftBits, StagedByte, _First, _Rest...>::type;
};
template <int _Data, char _Only>
struct Base64Inner<6, _Data, _Only> {
using StringType = typename TStringPrepend<Base64Lookup(_Data), typename Base64Inner<0, 0, _Only>::StringType>::type;
};
template <int _Bits, int _Data, char _Only>
struct Base64Inner<_Bits, _Data, _Only> {
static constexpr int EncodeBits = 6 - _Bits;
static constexpr int ShiftBits = 8 - EncodeBits;
static constexpr int EncodedByte = Base64Lookup((_Data << EncodeBits) | (((unsigned char)_Only) >> ShiftBits));
static constexpr int StagedByte = _Only & ((1 << ShiftBits) - 1);
using StringType = typename TStringPrepend<EncodedByte, typename Base64Last<ShiftBits, StagedByte>::StringType>::type;
};
template <int _Bits, int _Data>
struct Base64Last {};
template <int _Data>
struct Base64Last<2, _Data> {
using StringType = TString<Base64Lookup(_Data), '=', '='>;
};
template <int _Data>
struct Base64Last<4, _Data> {
using StringType = TString<Base64Lookup(_Data), '='>;
};
template <int _Data>
struct Base64Last<6, _Data> {
using StringType = TString<Base64Lookup(_Data)>;
};
template <char ..._Bytes>
using Base64Impl = typename Base64Inner<0, 0, _Bytes...>::StringType;
template <typename>
struct Base64 {};
template <char ..._Bytes>
struct Base64<TString<_Bytes...>> {
using StringType = Base64Impl<_Bytes...>;
};
int main() {
const char *encoded = FromTString<Base64<decltype("偶像好帅"_tstr)>::StringType>;
std::cout << encoded << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment