|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- const rx = /^[a-f0-9]{32}\+[0-9]+/;
- const rootDir = {};
- const streams = [];
-
- onmessage = function(e) {
- switch (e.data[0]) {
- case 'precreatePaths':
- precreatePaths(e.data[1]);
- postMessage([ 'precreatePathsResult' ]);
- break;
- case 'parseStream':
- parseStream(e.data[1]);
- postMessage([ 'parseStreamResult' ]);
- break;
- case 'listDirectory': {
- const lst = listDirectory(rootDir, e.data[1], e.data[2]);
- postMessage([ 'listDirectoryResult', lst ])
- break; }
- case 'getData':
- postMessage([ 'getDataResult', rootDir, streams ]);
- break;
- case 'getFile':
- postMessage([ 'getFileResult', getFile(rootDir, streams, e.data[1]) ]);
- break;
- default: {
- const err = Error('Unknown verb: ' + e.data[0]);
- postMessage([ 'error', err.message ]);
- throw err; }
- }
- }
-
- function precreatePaths(paths) {
- for (let i = 0; i < paths.length; i++) {
- mkpath(rootDir, paths[i]);
- }
- }
-
- function parseStream(s) {
- if (!s) return;
-
- const tokens = s.split(' ');
- const streamName = unescapeName(tokens[0]);
-
- let n = tokens.map(t => rx.exec(t));
- n = n.indexOf(null, 1);
-
- let locators = tokens.slice(1, n);
- let pos = 0;
- locators = locators.map(loc => {
- const sz = parseInt(loc.split('+')[1], 10);
- return [ loc, pos, pos += sz ];
- });
-
- let fileTokens = tokens.slice(n);
- let lastFile = null;
- let lastPath = null;
- fileTokens.map(t => {
- let seg = t.split(':');
- seg = [ parseInt(seg[0], 10), parseInt(seg[1], 10),
- unescapeName(seg.slice(2).join(':')) ]
- const path = streamName + '/' + seg[2];
- let f;
- if (path === lastPath) {
- f = lastFile;
- } else {
- let dirName = path.split('/');
- const name = dirName[dirName.length - 1];
- dirName = dirName.slice(0, dirName.length - 1);
- const d = mkpath(rootDir, dirName);
- lastFile = f = makeFile(d, name);
- lastPath = path;
- }
- appendFile(f, streams.length, seg);
- });
-
- streams.push(locators);
- }
-
- function mkdir(parent, name) {
- if (name in parent && (parent[name] instanceof Array))
- throw Error('File with the same name already exists');
- if (name in parent)
- return parent[name];
- const dir = {};
- parent[name] = dir;
- return dir;
- }
-
- function mkpath(parent, path) {
- if (typeof(path) === 'string')
- path = path.split('/');
- let dir = parent;
- for (let i = 1; i < path.length; i++) {
- dir = mkdir(dir, path[i]);
- }
- return dir;
- }
-
- function makeFile(dir, name) {
- if (name in dir) {
- if (!(dir[name] instanceof Array))
- throw Error('Directory with the same name already exists');
- return dir[name];
- }
- const f = [[], 0];
- dir[name] = f;
- return f;
- }
-
- function appendFile(f, sidx, seg) {
- f[0].push([ sidx, seg[0], seg[1] ]);
- f[1] += seg[1];
- return f;
- }
-
- function unescapeName(name) {
- return name.replace(/(\\\\|\\[0-9]{3})/g,
- (_, $1) => ($1 === '\\\\' ? '\\' : String.fromCharCode(parseInt($1.substr(1), 8))));
- }
-
- function findDir(parent, path, lenient=false) {
- if (typeof(path) === 'string')
- path = path.split('/');
- if (path[0] !== '.')
- throw Error('Path must start with a dot (.)');
- let dir = parent;
- for (let i = 1; i < path.length; i++) {
- if (!(path[i] in dir)) {
- if (lenient)
- return {};
- else
- throw Error('Directory not found');
- }
- dir = dir[path[i]];
- }
- return dir;
- }
-
- function listDirectory(rootDir, path, lenient=false) {
- let dir = findDir(rootDir, path, lenient);
- let keys = Object.keys(dir);
- keys.sort();
- let subdirs = keys.filter(k => !(dir[k] instanceof Array));
- let files = keys.filter(k => (dir[k] instanceof Array));
- let res = subdirs.map(k => [ 'd', k, null ]);
- res = res.concat(files.map(k => [ 'f', k, dir[k][1] ]));
- return res;
- }
-
- function getFile(rootDir, streams, path) {
- if (typeof(path) === 'string')
- path = path.split('/');
-
- if (path.length < 2)
- throw Error('Invalid file path');
-
- const name = path[path.length - 1];
-
- const dir = findDir(rootDir, path.slice(0, path.length - 1));
-
- if (!(name in dir))
- throw Error('File not found');
-
- if (!(dir[name] instanceof Array))
- throw Error('Path points to a directory not a file');
-
- let file = dir[name];
- file = [ file[0].map(seg => {
- const stm = streams[seg[0]];
- const used = stm.map(loc => !( loc[2] <= seg[1] || loc[1] >= seg[1] + seg[2] ) );
- const start = used.indexOf(true);
- const end = used.lastIndexOf(true) + 1;
- if (start === -1)
- return [];
- const res = [];
- for (let i = start; i < end; i++) {
- const loc = stm[i];
- res.push([ loc[0], Math.max(0, seg[1] - loc[1]),
- Math.min(loc[2] - loc[1], seg[1] + seg[2] - loc[1]) ]);
- }
- return res;
- }), file[1] ];
- file[0] = file[0].reduce((a, b) => a.concat(b));
-
- return file;
- }
|