|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- 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 process(streams) {
- const rootDir = {};
-
- streams.map((s, sidx) => {
- const [ streamName, locators, segments ] = s;
- const streamDir = mkpath(rootDir, streamName);
- segments.map((seg, segidx) => {
- let name = seg[2].split('/');
- const dir = (name.length === 1 ? streamDir :
- mkpath(streamDir, ['.'].concat(name.slice(0, name.length - 1))));
- name = name[name.length - 1];
- appendFile(dir, name, sidx, seg);
- });
- });
-
- return rootDir;
- }
-
- function parse(manifestText) {
- const M_STREAM_NAME = 0;
- const M_LOCATORS = 1;
- const M_FILE_SEGMENTS = 2;
-
- let mode = M_STREAM_NAME;
-
- const streams = [];
- let locators = [];
-
- let streamName;
- let accum = '';
- let tokenStart = 0;
-
- let lastFile = null;
- let lastPath = null;
- const rootDir = {};
-
- for (let i = 0; i < manifestText.length; i++) {
- const c = manifestText[i];
-
- if (mode === M_STREAM_NAME) {
- if (c === ' ') {
- mode = M_LOCATORS;
- streamName = unescapeName(accum);
- accum = '';
- tokenStart = i + 1;
- } else {
- accum += c;
- }
-
- } else if (mode === M_LOCATORS) {
- if (c === ':') {
- mode = M_FILE_SEGMENTS;
- accum = '';
- i = tokenStart - 1;
- let pos = 0;
- locators = locators.map(loc => {
- const r = loc.concat([ pos, pos + loc[1] ]);
- pos += loc[1];
- return r;
- });
- } else if (c === ' ') {
- const sz = Number(accum.split('+')[1]);
- locators.push([accum, sz]);
- accum = '';
- tokenStart = i + 1;
- } else {
- accum += c;
- }
-
- } else if (mode === M_FILE_SEGMENTS) {
- if (c === ' ' || c === '\n') {
- let seg = accum.split(':');
- seg = [Number(seg[0]), Number(seg[1]), seg.slice(2).join(':')];
- const path = streamName + '/' + unescapeName(seg[2]);
- let f;
- if (path !== lastPath) {
- let dirName = path.split('/');
- const fileName = dirName[dirName.length - 1];
- dirName = dirName.slice(0, dirName.length - 1);
- const dir = mkpath(rootDir, dirName);
- f = makeFile(dir, fileName);
- lastPath = path;
- lastFile = f;
- } else {
- f = lastFile;
- }
- appendFile(f, streams.length, seg);
- accum = '';
- tokenStart = i + 1;
- if (c === '\n') {
- streams.push([ streamName, locators ]);
- locators = [];
- mode = M_STREAM_NAME;
- }
- } else {
- accum += c;
- }
-
- }
- }
-
- return { rootDir, streams };
- }
-
- function findDir(parent, path) {
- 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))
- throw Error('Directory not found');
- dir = dir[path[i]];
- }
- return dir;
- }
-
- class WBManifestReader {
- constructor(manifestText) {
- const {rootDir, streams} = parse(manifestText);
- this.rootDir = rootDir;
- this.streams = streams;
- //this.rootDir = process(this.streams);
- }
-
- listDirectory(path) {
- let dir = findDir(this.rootDir, path);
- 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;
- }
- }
-
- export default WBManifestReader;
|