Skip to content

Instantly share code, notes, and snippets.

@z0ero
Created August 12, 2023 08:24
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 z0ero/e9c777f87b82d8478a64ac3e9799128d to your computer and use it in GitHub Desktop.
Save z0ero/e9c777f87b82d8478a64ac3e9799128d to your computer and use it in GitHub Desktop.
#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