forked from sheetjs/docs.sheetjs.com
		
	
		
			
				
	
	
		
			116 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include "maplec.h"
 | 
						|
#include "duktape.h"
 | 
						|
 | 
						|
/* --- EXPORT_DECL macro from official example --- */
 | 
						|
 | 
						|
#if !defined(EXPORT_DECL)
 | 
						|
#ifdef _MSC_VER
 | 
						|
#define EXPORT_DECL __declspec(dllexport)
 | 
						|
#else
 | 
						|
#define EXPORT_DECL
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
/* --- the SheetJS + Duktape demo cover these machinations --- */
 | 
						|
 | 
						|
#define FAIL_LOAD { \
 | 
						|
  duk_push_undefined(ctx); \
 | 
						|
  perror("Error in load_file"); \
 | 
						|
  return 1; \
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
static duk_int_t eval_file(duk_context *ctx, const char *filename) {
 | 
						|
  size_t len; char *buf = read_file(filename, &len);
 | 
						|
  if(!buf) FAIL_LOAD
 | 
						|
 | 
						|
  duk_push_lstring(ctx, (const char *)buf, (duk_size_t)len);
 | 
						|
  duk_int_t retval = duk_peval(ctx);
 | 
						|
  duk_pop(ctx);
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
static duk_int_t load_file(duk_context *ctx, const char *filename, const char *var) {
 | 
						|
  size_t len; char *buf = read_file(filename, &len);
 | 
						|
  if(!buf) FAIL_LOAD
 | 
						|
 | 
						|
  duk_push_external_buffer(ctx);
 | 
						|
  duk_config_buffer(ctx, -1, buf, len);
 | 
						|
  duk_put_global_string(ctx, var);
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static duk_int_t save_file(duk_context *ctx, const char *filename, const char *var) {
 | 
						|
  duk_get_global_string(ctx, var);
 | 
						|
  duk_size_t sz;
 | 
						|
  char *buf = (char *)duk_get_buffer_data(ctx, -1, &sz);
 | 
						|
 | 
						|
  if(!buf) return 1;
 | 
						|
  FILE *f = fopen(filename, "wb"); fwrite(buf, 1, sz, f); fclose(f);
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
#define FAIL_DUK(cmd) { \
 | 
						|
  const char *errmsg = duk_safe_to_string(ctx, -1); \
 | 
						|
  duk_destroy_heap(ctx); \
 | 
						|
  MapleRaiseError2(kv, "error in %1 : %2", ToMapleString(kv, cmd), ToMapleString(kv, errmsg)); \
 | 
						|
  return NULL; \
 | 
						|
}
 | 
						|
 | 
						|
#define DOIT(cmd) duk_eval_string_noresult(ctx, cmd);
 | 
						|
 | 
						|
/* SheetToXLSX function */
 | 
						|
EXPORT_DECL ALGEB M_DECL SheetToXLSX( MKernelVector kv, ALGEB *args ) {
 | 
						|
  duk_int_t res = 0;
 | 
						|
 | 
						|
  /* get filename */
 | 
						|
  if(MapleNumArgs(kv, (ALGEB)args) != 1) {
 | 
						|
    MapleRaiseError(kv, "must specify a filename");
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  if(!IsMapleString(kv, args[1])) {
 | 
						|
    MapleRaiseError(kv, "filename must be a string");
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  const char *filename = MapleToString(kv, args[1]);
 | 
						|
 | 
						|
  /* initialize duktape */
 | 
						|
  duk_context *ctx = duk_create_heap_default();
 | 
						|
  /* duktape does not expose a standard "global" by default */
 | 
						|
  DOIT("var global = (function(){ return this; }).call(null);");
 | 
						|
 | 
						|
  /* load SheetJS library */
 | 
						|
  res = eval_file(ctx, "shim.min.js");
 | 
						|
  if(res != 0) FAIL_DUK("shim load")
 | 
						|
  res = eval_file(ctx, "xlsx.full.min.js");
 | 
						|
  if(res != 0) FAIL_DUK("library load")
 | 
						|
 | 
						|
  /* read file */
 | 
						|
  res = load_file(ctx, filename, "buf");
 | 
						|
  if(res != 0) FAIL_DUK("file load")
 | 
						|
  printf("Loaded file %s\n", filename);
 | 
						|
 | 
						|
  /* parse workbook and write to XLSX */
 | 
						|
  DOIT("wb = XLSX.read(buf.slice(0, buf.length), {type:'buffer'});");
 | 
						|
  DOIT("newbuf = (XLSX.write(wb, {type:'array', bookType:'xlsx'}));");\
 | 
						|
 | 
						|
  /* write file */
 | 
						|
  res = save_file(ctx, "sheetjsw.xlsx", "newbuf");\
 | 
						|
  if(res != 0) FAIL_DUK("save sheetjsw.xlsx")
 | 
						|
 | 
						|
  /* return filename */
 | 
						|
  return ToMapleString(kv, "sheetjsw.xlsx");
 | 
						|
}
 |