Created
August 12, 2023 08:24
-
-
Save z0ero/e9c777f87b82d8478a64ac3e9799128d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <fstream> | |
#include <array> | |
#include <vector> | |
using namespace std; | |
constexpr size_t calcEncodedSize(size_t size) | |
{ | |
return (size * 8 + 5) / 6; | |
} | |
static constexpr char btoa[] = "+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | |
void encode(char *dst, const uint8_t *ptr, size_t in_len) | |
{ | |
auto end = ptr + in_len; | |
// 3byteずつ4文字に詰め込む | |
for (; ptr + 3 <= end; ptr += 3) | |
{ | |
uint32_t c = (ptr[0] << 16) | (ptr[1] << 8) | ptr[2]; | |
*dst++ = btoa[c >> 18]; | |
*dst++ = btoa[(c >> 12) & 63]; | |
*dst++ = btoa[(c >> 6) & 63]; | |
*dst++ = btoa[c & 63]; | |
} | |
// 残り1byteの場合2文字目は末尾2bitを先頭に持って行ってXX0000の形にする | |
if (ptr + 1 == end) | |
{ | |
*dst++ = btoa[ptr[0] >> 2]; | |
*dst++ = btoa[(ptr[0] << 4) & 63]; | |
} | |
// 残り2byteの場合3文字目はXXXX00の形 | |
else if (ptr + 2 == end) | |
{ | |
uint32_t c = (ptr[0] << 8) | ptr[1]; | |
*dst++ = btoa[c >> 10]; | |
*dst++ = btoa[(c >> 4) & 63]; | |
*dst++ = btoa[(c << 2) & 63]; | |
} | |
} | |
// wasmをbase64化しArrayBufferに復元するjsコードもセットで埋め込む | |
int main(int argc, const char **argv) | |
{ | |
ifstream ifs(argv[1], ios::binary); | |
ifs.seekg(0, ios::end); | |
size_t size = ifs.tellg(); | |
ifs.seekg(0, ios::beg); | |
vector<char> buf(size); | |
ifs.read(buf.data(), size); | |
vector<char> result(calcEncodedSize(size)); | |
encode(result.data(), reinterpret_cast<const uint8_t*>(buf.data()), size); | |
ofstream ofs(argv[2], ios::binary); | |
ofs << R"( | |
const decoder = new Uint8Array(123); | |
decoder.set([)"; | |
char8_t pre = 0; | |
int count = 0; | |
for (auto c : btoa) | |
{ | |
if (c == 0)break; | |
while (pre != c) | |
{ | |
ofs << "0,"; | |
pre++; | |
} | |
ofs << count++ << ','; | |
pre++; | |
} | |
ofs << R"(]); | |
const encoded = ')"; | |
// 長すぎる文字列リテラルはminifierで失敗するので8kbごとに区切る | |
for (size_t blocks = result.size() >> 13, i = 0; i <= blocks; ++i) | |
{ | |
ofs.write(result.data() + (i << 13), std::min<size_t>(8192, result.size() - (i << 13))); | |
ofs << "'+'"; | |
} | |
ofs << R"('; | |
const decode_bin = new Uint8Array()" << size << R"(); | |
let dst = 0; | |
let ptr = 0; | |
const end = encoded.length; | |
const read = i => decoder[encoded.charCodeAt(i)]; | |
for (; ptr + 4 <= end; ptr += 4) { | |
const c = (read(ptr) << 18) | (read(ptr + 1) << 12) | (read(ptr + 2) << 6) | read(ptr + 3); | |
decode_bin[dst++] = c >> 16; | |
decode_bin[dst++] = (c >> 8) & 255; | |
decode_bin[dst++] = c & 255; | |
} | |
switch (end - ptr) { | |
case 2: | |
decode_bin[dst] = (read(ptr) << 2) | (read(ptr + 1) >> 4); | |
break; | |
case 3: | |
{ | |
const c = (read(ptr) << 10) | (read(ptr + 1) << 4) | (read(ptr + 2) >> 2); | |
decode_bin[dst++] = c >> 8; | |
decode_bin[dst] = c & 255; | |
}break; | |
} | |
var Module = { wasmBinary: decode_bin }; | |
module.exports = Module; | |
const process = undefined; | |
const Buffer = undefined; | |
const setImmediate = undefined; | |
)"; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment