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"); | ||
|  | } |