aboutsummaryrefslogtreecommitdiff
path: root/web/storage.cpp
blob: 780926ec14ce50d17c490f707f59febacd98ac33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "storage.h"

#include "emscripten.h"
#include <filesystem>
#include <fstream>

EM_JS(int, inbrowser, (), { return typeof window !== 'undefined'; });
EM_JS(int, inworker, (), { return typeof WorkerGlobalScope !== 'undefined' &&
    self instanceof WorkerGlobalScope; });

std::string getprefix() {
	return inbrowser() || inworker() ? "/tables/" : "./tables/";
}

EM_ASYNC_JS(int, loadfs, (), {
	const inBrowser = typeof window !== 'undefined';
	const inWorker = typeof WorkerGlobalScope !== 'undefined' &&
	    self instanceof WorkerGlobalScope;
	console.assert(inBrowser || inWorker, "Non-browsers not supported");

	const dir = '/tables';

	if (!FS.analyzePath(dir).exists)
		FS.mkdir(dir);

	if (FS.analyzePath(dir).object.mount.mountpoint != dir) {
		FS.mount(IDBFS, { autoPersist: true }, dir);

		await new Promise((resolve, reject) => {
			FS.syncfs(true, function (err) {
				if (err)
					reject(err);
				else
					resolve(true);
			});
		});
	}
});

EM_ASYNC_JS(int, download_and_store, (const char *key, const char *url), {
	const inBrowser = typeof window !== 'undefined';
	const inWorker = typeof WorkerGlobalScope !== 'undefined' &&
	    self instanceof WorkerGlobalScope;
	console.assert(inBrowser || inWorker, "Non-browsers not supported");

	// This is a workaround related to usign WASM64
	// JavaScript's UTF8ToString expects a pointer argument, which for JS is
	// of type "number", but WASM64 is passing a BigInt. See also:
	// https://github.com/emscripten-core/emscripten/issues/21541
	// (but I could not make the suggested solution work in this case).
	// TODO: check if there is a better workaround.
	const non64_url = Number(url);
	const non64_key = Number(key);
	url = UTF8ToString(non64_url);
	key = UTF8ToString(non64_key);
	let response = await fetch(url);
	if (!response.ok) {
		console.log("Error downloading data for " + key);
		console.log("" + response.status + ": " + response.statusText);
		return 0;
	}

	let data = await response.bytes();
	var stream = FS.open("/tables/" + key, "w+");
	FS.write(stream, data, 0, data.length, 0);
	FS.close(stream);
	console.log("Data for " + key + " stored (" + data.length + " bytes)");
	return 1;
});

bool storage::read(std::string key, size_t data_size, char *data)
{
	loadfs();

	std::filesystem::path path(getprefix() + key);
	if (!std::filesystem::exists(path))
		return false;

	std::ifstream ifs(path, std::ios::binary);
	ifs.read(data, data_size);
	ifs.close();

	return !ifs.fail();
}

bool storage::write(std::string key, size_t data_size, const char *data)
{
	loadfs();

	std::filesystem::path path(getprefix() + key);

	std::ofstream ofs(path, std::ios::binary);
	ofs.write(data, data_size);
	ofs.close();

	return !ofs.fail();
}

int storage::download(std::string key, std::string url)
{
	loadfs();
	return download_and_store(key.c_str(), url.c_str());
}

Generated with cgit - Back to sebastiano.tronto.net