Last active
February 16, 2021 18:02
-
-
Save mattdesl/3f4aff12a85182226bd654f56088ebe1 to your computer and use it in GitHub Desktop.
simple expandable in-memory file utility, inspired by Emscripten's FS
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
export default function createFile(initialCapacity = 256) { | |
let cursor = 0; | |
let usedBytes = 0; | |
let contents = new Uint8Array(initialCapacity); | |
return { | |
contents: function () { | |
return contents.slice(0, usedBytes); | |
}, | |
seek: function (offset) { | |
// offset in bytes | |
cursor = offset; | |
}, | |
write: function (data) { | |
const size = data.byteLength; | |
expand(cursor + size); | |
contents.set(data, cursor); | |
cursor += size; | |
usedBytes = Math.max(usedBytes, cursor); | |
return size; | |
}, | |
}; | |
function expand(newCapacity) { | |
var prevCapacity = contents.length; | |
if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough. | |
// Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity. | |
// For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to | |
// avoid overshooting the allocation cap by a very large margin. | |
var CAPACITY_DOUBLING_MAX = 1024 * 1024; | |
newCapacity = Math.max( | |
newCapacity, | |
(prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> | |
0 | |
); | |
if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding. | |
const oldContents = contents; | |
contents = new Uint8Array(newCapacity); // Allocate new storage. | |
if (usedBytes > 0) contents.set(oldContents.subarray(0, usedBytes), 0); | |
} | |
} |
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
import createFile from './createFile.js'; | |
const file = createFile(); | |
// write some data | |
file.write(new Uint8Array([ 1, 5, 2, 5 ])); | |
file.write(new Uint8Array([ 50, 25, 10 ])); | |
file.seek(0); | |
file.write(new Uint8Array([ 10, 20 ])); | |
// get the final file buffer | |
console.log(file.contents()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment