Created
July 7, 2024 23:36
-
-
Save palaniraja/15f013e720c709c452a623e328934dcc to your computer and use it in GitHub Desktop.
wasm file merger
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cmake_minimum_required(VERSION 3.12) | |
project(concat_files) | |
set(CMAKE_CXX_STANDARD 14) | |
# set(CMAKE_CXX_COMPILER em++) | |
add_executable(concat_files main.cpp) | |
set_target_properties(concat_files PROPERTIES LINK_FLAGS "\ | |
-s WASM=1 \ | |
-s EXPORTED_RUNTIME_METHODS=['ccall','cwrap','FS','stringToUTF8','setValue'] \ | |
-s EXPORTED_FUNCTIONS=['_malloc','_free','_concat_files'] \ | |
-s FORCE_FILESYSTEM=1 \ | |
-lidbfs.js \ | |
") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>File Dropzone</title> | |
<link rel="icon" href="data:;base64,="> | |
<script src="build/concat_files.js"></script> | |
<style> | |
ul { | |
list-style-type: none; | |
} | |
li { | |
margin: 0.5em 0.5em; | |
} | |
#dropzone { | |
width: 300px; | |
height: 300px; | |
border: 1px solid black; | |
background-color: lightgray; | |
} | |
</style> | |
</head> | |
<body> | |
<ul> | |
<li> <div id="dropzone" style="">Drop files here</div> | |
<li> <button onclick="listFiles()">List Files</button> | |
<li> <textarea id="fileContent"></textarea> | |
<li> <button onclick="writeTextareaContent()">write to userinput.txt</button> | |
<li><button onclick="processFiles()">Process Files with wasm</button> | |
</ul> | |
<script> | |
var fileNameArray = [] | |
window.addEventListener('load', function () { | |
console.log("window loaded") | |
let droppedFiles = []; | |
let dropzone = document.getElementById('dropzone'); | |
dropzone.ondragover = function (e) { | |
e.preventDefault(); | |
this.className = 'dropzone dragover'; | |
return false; | |
}; | |
dropzone.ondragleave = function (e) { | |
e.preventDefault(); | |
this.className = 'dropzone'; | |
return false; | |
}; | |
dropzone.ondrop = function (e) { | |
e.preventDefault(); | |
this.className = 'dropzone'; | |
droppedFiles = e.dataTransfer.files; | |
console.log("dropped files: ", droppedFiles.length) | |
// Write each file to the Emscripten file system | |
let promises = Array.from(droppedFiles).map(file => { | |
return new Promise((resolve, reject) => { | |
let reader = new FileReader(); | |
reader.onload = function () { | |
let data = new Uint8Array(reader.result); | |
var fname = '/testdir/' + file.name | |
fileNameArray.push(fname) | |
FS.writeFile(fname, data); | |
resolve(); | |
}; | |
reader.onerror = function () { | |
reject(reader.error); | |
}; | |
reader.readAsArrayBuffer(file); | |
}); | |
}); | |
// Wait for all files to be written | |
Promise.all(promises) | |
.then(() => console.log('All files written successfully')) | |
.catch(error => console.error('Error writing files:', error)); | |
}; | |
}); | |
var fileName = '/testdir/userinput.txt' | |
// Assuming Module is the Emscripten module | |
Module['onRuntimeInitialized'] = function () { | |
console.log('onRuntimeInitialized') | |
FS.mkdir('/testdir'); | |
// Module['FS'].mount(IDBFS, {root: '.'}, '/testdir') | |
// document.querySelector('button').addEventListener('click', processFiles); | |
} | |
function listFiles() { | |
var list = FS.readdir('/testdir'); | |
console.log(list); | |
} | |
function writeTextareaContent() { | |
fileContent = document.querySelector("#fileContent").value; | |
let data = new TextEncoder().encode(fileContent); | |
FS.writeFile(fileName, data, { encoding: 'utf8' }); | |
fileNameArray.push(fileName) | |
setTimeout(function () { | |
var contents = FS.readFile(fileName, { encoding: 'binary' }); | |
var stringContents = new TextDecoder().decode(contents); | |
console.log(`content of ${fileName}`) | |
console.log(stringContents); | |
// Synchronize the filesystem | |
FS.syncfs(true, function (err) { | |
if (err) { | |
console.error('Failed to sync the filesystem:', err); | |
} else { | |
console.log('Filesystem synced successfully'); | |
} | |
}); | |
}, 300) | |
} | |
function processFiles() { | |
// var fileNameArray = [fileName]; // This should be an array of file names | |
var fileNamePtrs = new Array(fileNameArray.length); | |
for (var i = 0; i < fileNameArray.length; i++) { | |
var fileNamePtr = Module._malloc(fileNameArray[i].length + 1); | |
Module.stringToUTF8(fileNameArray[i], fileNamePtr, fileNameArray[i].length + 1); | |
fileNamePtrs[i] = fileNamePtr; | |
} | |
var fileNameArrayPtr = Module._malloc(fileNamePtrs.length * 4); // assumes 4 bytes per pointer | |
Module.HEAP32.set(fileNamePtrs, fileNameArrayPtr / 4); // Copy the array of pointers to the WebAssembly memory | |
var result = Module.ccall('concat_files', 'string', ['number', 'number'], [fileNameArray.length, fileNameArrayPtr]); | |
console.log(result); | |
// Free the memory allocated for the file names and the array of pointers | |
fileNamePtrs.forEach(p => Module._free(p)); | |
Module._free(fileNameArrayPtr); | |
} | |
</script> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <fstream> | |
#include <string> | |
#include <sstream> | |
#include <cstring> | |
#include <emscripten.h> | |
extern "C" { | |
char* concat_files(int numFiles, char* filenames[]) { | |
std::stringstream buffer; | |
// buffer << "numFiles: " << numFiles << std::endl; | |
for (int i = 0; i < numFiles; i++) { | |
if (filenames[i] == nullptr || strlen(filenames[i]) == 0) { | |
buffer << " file: (empty)"; | |
} else { | |
// buffer << " file: " << filenames[i] << std::endl; | |
std::ifstream file(filenames[i]); | |
if (!file.is_open()) { | |
buffer << " could not open file: " << filenames[i] << std::endl; | |
continue; // Skip to the next filename | |
} | |
buffer << file.rdbuf(); | |
} | |
} | |
std::string str = buffer.str(); | |
char* cstr = new char[str.length() + 1]; | |
std::strcpy(cstr, str.c_str()); | |
return cstr; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment