docs.sheetjs.com/docz/static/jsc/sheetjs-jsc.c
2024-04-25 04:39:55 -04:00

112 lines
2.8 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <JavaScriptCore/JavaScript.h>
/* simple wrapper to read the entire script file */
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(buf, 1, fsize, f);
fclose(f);
return buf;
}
#define JS_STR_TO_C \
JSStringRef str = JSValueToStringCopy(ctx, result, NULL); \
size_t sz = JSStringGetMaximumUTF8CStringSize(str); \
char *buf = (char *)malloc(sz); \
JSStringGetUTF8CString(str, buf, sz); \
#define DOIT(cmd) \
JSStringRef script = JSStringCreateWithUTF8CString(cmd); \
JSValueRef result = JSEvaluateScript(ctx, script, NULL, NULL, 0, NULL); \
JSStringRelease(script);
int main(int argc, char **argv) {
int res = 0;
size_t sz = 0;
char *file = NULL;
/* initialize */
JSGlobalContextRef ctx = JSGlobalContextCreate(NULL);
/* JSC does not expose a standard "global" by default */
{ DOIT("var global = (function(){ return this; }).call(null);") }
/* load library */
{
file = read_file("xlsx.full.min.js", &sz);
DOIT(file);
free(file);
}
/* get version string */
{
DOIT("XLSX.version")
if(!JSValueIsString(ctx, result)) {
printf("Could not get SheetJS version.\n");
res = 1; goto cleanup;
}
JS_STR_TO_C
printf("SheetJS library version %s\n", buf);
free(buf);
JSStringRelease(str);
}
/* read file */
file = read_file(argv[1], &sz);
{
/* push data to JSC */
JSValueRef u8 = JSObjectMakeTypedArrayWithBytesNoCopy(ctx, kJSTypedArrayTypeUint8Array, file, sz, NULL, NULL, NULL);
/* assign to `global.buf` */
JSObjectRef global = JSContextGetGlobalObject(ctx);
JSStringRef key = JSStringCreateWithUTF8CString("buf");
JSObjectSetProperty(ctx, global, key, u8, 0, NULL);
JSStringRelease(key);
}
/* parse workbook and print CSV */
{
DOIT(
"var wb = XLSX.read(global.buf);"
"var ws = wb.Sheets[wb.SheetNames[0]];"
"XLSX.utils.sheet_to_csv(ws)"
)
if(!JSValueIsString(ctx, result)) {
printf("Could not generate CSV.\n");
res = 2; goto cleanup;
}
JS_STR_TO_C
printf("%s\n", buf);
free(buf);
JSStringRelease(str);
}
/* write file */
{
DOIT("XLSX.write(wb, {type:'buffer', bookType:'xlsb'});")
/* pull Uint8Array data back to C */
JSObjectRef u8 = JSValueToObject(ctx, result, NULL);
size_t sz = JSObjectGetTypedArrayLength(ctx, u8, NULL);
char *buf = (char *)JSObjectGetTypedArrayBytesPtr(ctx, u8, NULL);
/* save file */
FILE *f = fopen("sheetjsw.xlsb", "wb"); fwrite(buf, 1, sz, f); fclose(f);
}
cleanup:
// Release the JavaScript context
JSGlobalContextRelease(ctx);
if(file) free(file);
return res;
}