// Base64EnDe.cpp : アプリケーションのエントリ ポイントを定義します。
//
#include <iostream>
#include <string>
#include <vector>
#include <cstdint>
#include <tuple>
typedef std::vector<std::uint8_t> DType;
const std::string Token = "ABCDEFGHIJKLNMOPQRSTUVWXYZabcdefghijklnmopqrstuvwxyz0123456789+/";
const std::string Pad = "=";
DType Char3Enc4(const char& A, const char& B, const char& C) {
std::uint64_t V1 = 0;
std::uint64_t V2 = 0;
std::uint64_t P = 0;
DType D;
D.reserve(4);
V1 = A;
P = (V1 >> 2) & 0x3f;
D.push_back(P);
V1 &= 3;
V2 = (B<0) ? 0:B;
P = ((V1 << 4) & 0x3f) | ((V2 >> 4) & 0x3f);
D.push_back(P);
V1 = V2 - ((V2 >> 4) << 4);
V2 = (C<0) ? 0:C;
if (B < 0) return D;
P = ((V1 << 2) & 0x3f) | ((V2 >> 6) & 0x3f);
D.push_back(P);
V1 = V2 - ((V2 >> 6) << 6);
if (C < 0) return D;
P = V1 & 0x3f;
D.push_back(P);
return D;
}
std::string Base64Enc(const std::string& s) {
DType D;
DType T;
std::string R;
char A = 0;
char B = 0;
char C = 0;
for (std::size_t i = 0; i < s.size(); i+=3) {
A = i < s.size() ? s[i]:-1;
B = i+1 < s.size() ? s[i+1]:-1;
C = i+2 < s.size() ? s[i+2]:-1;
T = Char3Enc4(A, B, C);
D.insert(D.begin()+D.size(), T.begin(), T.end());
}
for (auto& o : D) {
R += Token[o];
}
for (std::size_t i = 0; i < (R.size() % 4); i++) {
R += Pad;
}
return R;
}
DType Enc4Char3(const char& A, const char& B, const char& C, const char& D) {
std::int16_t E = (A != '=') ? Token.find(A, 0) : -1;
std::int16_t F = (B != '=') ? Token.find(B, 0) : -1;
std::int16_t G = (C != '=') ? Token.find(C, 0) : -1;
std::int16_t H = (D != '=') ? Token.find(D, 0) : -1;
std::uint8_t V=0;
DType DT;
if (E >= 0) {
if (F >= 0) {
V = (E & 0x3f) << 2 | (F & 0x3f) >> 4;
DT.push_back(V);
}
else {
V = (E & 0x3f) << 2;
DT.push_back(V);
return DT;
}
}
if (F >= 0) {
if (G >= 0) {
V = (F & 0x3f) << 4 | (G & 0x3f) >> 2;
DT.push_back(V);
}
else {
V = (F & 0x3f) << 4;
DT.push_back(V);
return DT;
}
}
if (G >= 0) {
if (H >= 0) {
V = (G & 0x3f) << 6 | (H & 0x3f);
DT.push_back(V);
}
else {
V =(G & 0x3f) << 6 ;
DT.push_back(V);
return DT;
}
}
return DT;
}
std::string Base64Dec(const std::string& S) {
DType D;
std::string R;
for (std::size_t i = 0; i < S.size(); i += 4) {
D = Enc4Char3(S[i], S[i + 1], S[i + 2], S[i + 3]);//エンコード文字列が4字組みになってることを信じている。サクッと死ぬ。
R.insert(R.begin() + R.size(), D.begin(), D.end());
}
return R;
}
int main()
{
std::string S;
std::string R;
S = "ABCDEFG";
R = Base64Enc(S);
std::cout << R << std::endl;
R = Base64Dec(R);
std::cout << R << std::endl;
return 0;
}
Ly8gQmFzZTY0RW5EZS5jcHAgOiDjgqLjg5fjg6rjgrHjg7zjgrfjg6fjg7Pjga7jgqjjg7Pjg4jjg6og44Od44Kk44Oz44OI44KS5a6a576p44GX44G+44GZ44CCCi8vCiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPGNzdGRpbnQ+CiNpbmNsdWRlIDx0dXBsZT4KCgp0eXBlZGVmIHN0ZDo6dmVjdG9yPHN0ZDo6dWludDhfdD4gRFR5cGU7CmNvbnN0IHN0ZDo6c3RyaW5nIFRva2VuID0gIkFCQ0RFRkdISUpLTE5NT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbm1vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8iOwpjb25zdCBzdGQ6OnN0cmluZyBQYWQgPSAiPSI7CgpEVHlwZSBDaGFyM0VuYzQoY29uc3QgY2hhciYgQSwgY29uc3QgY2hhciYgQiwgY29uc3QgY2hhciYgQykgewoJc3RkOjp1aW50NjRfdCBWMSA9IDA7CglzdGQ6OnVpbnQ2NF90IFYyID0gMDsKCXN0ZDo6dWludDY0X3QgUCA9IDA7CglEVHlwZSBEOwoJRC5yZXNlcnZlKDQpOwoJVjEgPSBBOwoJUCA9IChWMSA+PiAyKSAmIDB4M2Y7CglELnB1c2hfYmFjayhQKTsKCVYxICY9IDM7CglWMiA9IChCPDApID8gMDpCOwoKCVAgPSAoKFYxIDw8IDQpICYgMHgzZikgfCAoKFYyID4+IDQpICYgMHgzZik7CglELnB1c2hfYmFjayhQKTsKCVYxID0gVjIgLSAoKFYyID4+IDQpIDw8IDQpOwoJVjIgPSAoQzwwKSA/IDA6QzsKCglpZiAoQiA8IDApIHJldHVybiBEOwoKCVAgPSAoKFYxIDw8IDIpICYgMHgzZikgfCAoKFYyID4+IDYpICYgMHgzZik7CglELnB1c2hfYmFjayhQKTsKCVYxID0gVjIgLSAoKFYyID4+IDYpIDw8IDYpOwoKCWlmIChDIDwgMCkgcmV0dXJuIEQ7CgoJUCA9IFYxICYgMHgzZjsKCUQucHVzaF9iYWNrKFApOwoKCXJldHVybiBEOwp9CgoKc3RkOjpzdHJpbmcgQmFzZTY0RW5jKGNvbnN0IHN0ZDo6c3RyaW5nJiBzKSB7CgoJRFR5cGUgRDsKCURUeXBlIFQ7CglzdGQ6OnN0cmluZyBSOwoJY2hhciBBID0gMDsKCWNoYXIgQiA9IDA7CgljaGFyIEMgPSAwOwoKCglmb3IgKHN0ZDo6c2l6ZV90IGkgPSAwOyBpIDwgcy5zaXplKCk7IGkrPTMpIHsKCQlBID0gaSA8IHMuc2l6ZSgpID8gc1tpXTotMTsKCQlCID0gaSsxIDwgcy5zaXplKCkgPyBzW2krMV06LTE7CgkJQyA9IGkrMiA8IHMuc2l6ZSgpID8gc1tpKzJdOi0xOwoJCgkJVCA9IENoYXIzRW5jNChBLCBCLCBDKTsKCQlELmluc2VydChELmJlZ2luKCkrRC5zaXplKCksIFQuYmVnaW4oKSwgVC5lbmQoKSk7Cgl9CgoJZm9yIChhdXRvJiBvIDogRCkgewoJCVIgKz0gVG9rZW5bb107Cgl9Cglmb3IgKHN0ZDo6c2l6ZV90IGkgPSAwOyBpIDwgKFIuc2l6ZSgpICUgNCk7IGkrKykgewoJCVIgKz0gUGFkOwoJfQoKCXJldHVybiBSOwp9CgpEVHlwZSBFbmM0Q2hhcjMoY29uc3QgY2hhciYgQSwgY29uc3QgY2hhciYgQiwgY29uc3QgY2hhciYgQywgY29uc3QgY2hhciYgRCkgewoJc3RkOjppbnQxNl90IEUgPSAoQSAhPSAnPScpID8gVG9rZW4uZmluZChBLCAwKSA6IC0xOwoJc3RkOjppbnQxNl90IEYgPSAoQiAhPSAnPScpID8gVG9rZW4uZmluZChCLCAwKSA6IC0xOwoJc3RkOjppbnQxNl90IEcgPSAoQyAhPSAnPScpID8gVG9rZW4uZmluZChDLCAwKSA6IC0xOwoJc3RkOjppbnQxNl90IEggPSAoRCAhPSAnPScpID8gVG9rZW4uZmluZChELCAwKSA6IC0xOwoKCXN0ZDo6dWludDhfdCBWPTA7CglEVHlwZSBEVDsKCglpZiAoRSA+PSAwKSB7CgkJaWYgKEYgPj0gMCkgewoJCQlWID0gKEUgJiAweDNmKSA8PCAyIHwgKEYgJiAweDNmKSA+PiA0OwoJCQlEVC5wdXNoX2JhY2soVik7CgkJfQoJCWVsc2UgewoJCQlWID0gKEUgJiAweDNmKSA8PCAyOwoJCQlEVC5wdXNoX2JhY2soVik7CgkJCXJldHVybiBEVDsKCQl9Cgl9CglpZiAoRiA+PSAwKSB7CgkJaWYgKEcgPj0gMCkgewoJCQlWID0gKEYgJiAweDNmKSA8PCA0IHwgKEcgJiAweDNmKSA+PiAyOwoJCQlEVC5wdXNoX2JhY2soVik7CgkJfQoJCWVsc2UgewoJCQlWID0gKEYgJiAweDNmKSA8PCA0OwoJCQlEVC5wdXNoX2JhY2soVik7CgkJCXJldHVybiBEVDsKCQl9Cgl9CglpZiAoRyA+PSAwKSB7CgkJaWYgKEggPj0gMCkgewoJCQlWID0gKEcgJiAweDNmKSA8PCA2IHwgKEggJiAweDNmKTsKCQkJRFQucHVzaF9iYWNrKFYpOwoJCX0KCQllbHNlIHsKCQkJViA9KEcgJiAweDNmKSA8PCA2IDsKCQkJRFQucHVzaF9iYWNrKFYpOwoJCQlyZXR1cm4gRFQ7CgkJfQoJfQoKCXJldHVybiBEVDsKCn0KCnN0ZDo6c3RyaW5nIEJhc2U2NERlYyhjb25zdCBzdGQ6OnN0cmluZyYgUykgewoKCURUeXBlIEQ7CglzdGQ6OnN0cmluZyBSOwoJZm9yIChzdGQ6OnNpemVfdCBpID0gMDsgaSA8IFMuc2l6ZSgpOyBpICs9IDQpIHsKCQlEID0gRW5jNENoYXIzKFNbaV0sIFNbaSArIDFdLCBTW2kgKyAyXSwgU1tpICsgM10pOy8v44Ko44Oz44Kz44O844OJ5paH5a2X5YiX44GM77yU5a2X57WE44G/44Gr44Gq44Gj44Gm44KL44GT44Go44KS5L+h44GY44Gm44GE44KL44CC44K144Kv44OD44Go5q2744Gs44CCCgkJUi5pbnNlcnQoUi5iZWdpbigpICsgUi5zaXplKCksIEQuYmVnaW4oKSwgRC5lbmQoKSk7Cgl9CgoJcmV0dXJuIFI7Cgp9CgppbnQgbWFpbigpCnsKCXN0ZDo6c3RyaW5nIFM7CglzdGQ6OnN0cmluZyBSOwoKCVMgPSAiQUJDREVGRyI7CglSID0gQmFzZTY0RW5jKFMpOwoJc3RkOjpjb3V0IDw8IFIgPDwgc3RkOjplbmRsOwoJUiA9IEJhc2U2NERlYyhSKTsKCXN0ZDo6Y291dCA8PCBSIDw8IHN0ZDo6ZW5kbDsKICAgIHJldHVybiAwOwp9Cgo=