117 lines
4.0 KiB
C++
117 lines
4.0 KiB
C++
|
/* sheetjs-hermesw.cpp Copyright (c) SheetJS LLC. */
|
||
|
#include <iostream>
|
||
|
#include "hermes/hermes.h"
|
||
|
|
||
|
static char *read_file(const char *filename, size_t *sz) {
|
||
|
FILE *f = fopen(filename, "rb");
|
||
|
if(!f) return NULL;
|
||
|
long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f); fseek(f, 0, SEEK_SET); }
|
||
|
char *buf = (char *)malloc(fsize * sizeof(char));
|
||
|
*sz = fread((void *) buf, 1, fsize, f);
|
||
|
fclose(f);
|
||
|
return buf;
|
||
|
}
|
||
|
|
||
|
/* Hermes-Windows requires the null terminator */
|
||
|
static char *read_file_null(const char *filename, size_t *sz) {
|
||
|
FILE *f = fopen(filename, "rb");
|
||
|
if(!f) return NULL;
|
||
|
long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f) + 1; fseek(f, 0, SEEK_SET); }
|
||
|
char *buf = (char *)malloc(fsize * sizeof(char));
|
||
|
*sz = fread((void *) buf, 1, fsize, f);
|
||
|
buf[fsize - 1] = 0;
|
||
|
fclose(f);
|
||
|
return buf;
|
||
|
}
|
||
|
|
||
|
/* Unfortunately the library provides no C-friendly Buffer classes */
|
||
|
class CBuffer : public facebook::jsi::Buffer {
|
||
|
public:
|
||
|
CBuffer(const uint8_t *data, size_t size) : buf(data), sz(size) {}
|
||
|
size_t size() const override { return sz; }
|
||
|
const uint8_t *data() const override { return buf; }
|
||
|
|
||
|
private:
|
||
|
const uint8_t *buf;
|
||
|
size_t sz;
|
||
|
};
|
||
|
/* ArrayBuffer constructor expects MutableBuffer*/
|
||
|
class CMutableBuffer : public facebook::jsi::MutableBuffer {
|
||
|
public:
|
||
|
CMutableBuffer(uint8_t *data, size_t size) : buf(data), sz(size) {}
|
||
|
size_t size() const override { return sz; }
|
||
|
uint8_t *data() override { return buf; }
|
||
|
|
||
|
private:
|
||
|
uint8_t *buf;
|
||
|
size_t sz;
|
||
|
};
|
||
|
|
||
|
int main(int argc, char **argv) {
|
||
|
std::unique_ptr<facebook::jsi::Runtime> rt(facebook::hermes::makeHermesRuntime());
|
||
|
|
||
|
/* setup */
|
||
|
try {
|
||
|
auto src = std::make_shared<facebook::jsi::StringBuffer>(
|
||
|
"var global = (function(){ return this; }).call(null);"
|
||
|
"var console = { log: function(x) { print(x); } };"
|
||
|
);
|
||
|
auto js = rt->prepareJavaScript(src, std::string("<eval>"));
|
||
|
rt->evaluatePreparedJavaScript(js);
|
||
|
} catch (const facebook::jsi::JSIException &e) {
|
||
|
std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << '\n';
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/* load SheetJS library */
|
||
|
try {
|
||
|
size_t sz; char *xlsx_full_min_js = read_file_null("xlsx.full.min.js", &sz);
|
||
|
auto src = std::make_shared<CBuffer>(CBuffer((uint8_t *)xlsx_full_min_js, sz));
|
||
|
auto js = rt->prepareJavaScript(src, std::string("xlsx.full.min.js"));
|
||
|
rt->evaluatePreparedJavaScript(js);
|
||
|
} catch (const facebook::jsi::JSIException &e) {
|
||
|
std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << '\n';
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/* print library version */
|
||
|
try {
|
||
|
auto src = std::make_shared<facebook::jsi::StringBuffer>(
|
||
|
"console.log('SheetJS Library Version: ' + XLSX.version)"
|
||
|
);
|
||
|
auto js = rt->prepareJavaScript(src, std::string("<eval>"));
|
||
|
rt->evaluatePreparedJavaScript(js);
|
||
|
} catch (const facebook::jsi::JSIException &e) {
|
||
|
std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << '\n';
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
/* load payload as ArrayBuffer */
|
||
|
size_t sz; char *data = read_file(argv[1], &sz);
|
||
|
auto payload = std::make_shared<CMutableBuffer>(CMutableBuffer((uint8_t *)data, sz));
|
||
|
auto ab = facebook::jsi::ArrayBuffer(*rt, payload);
|
||
|
|
||
|
/* define stub function to read and convert first sheet to CSV */
|
||
|
auto src = std::make_shared<facebook::jsi::StringBuffer>(
|
||
|
"(function(buf) {"
|
||
|
"var wb = XLSX.read(buf);"
|
||
|
"return XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]);"
|
||
|
"})"
|
||
|
);
|
||
|
auto js = rt->prepareJavaScript(src, std::string("<eval>"));
|
||
|
auto func = rt->evaluatePreparedJavaScript(js);
|
||
|
|
||
|
/* call stub function and capture result */
|
||
|
auto csv = func.asObject(*rt).asFunction(*rt).call(*rt, ab);
|
||
|
|
||
|
/* interpret as utf8 and print to stdout */
|
||
|
std::string str = csv.getString(*rt).utf8(*rt);
|
||
|
std::cout << str << std::endl;
|
||
|
} catch (const facebook::jsi::JSIException &e) {
|
||
|
std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << std::endl;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|