IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an email to s dot adaszewski at gmail dot com. User accounts are meant only to report issues and/or generate pull requests. This is a purpose-specific Git hosting for ADARED projects. Thank you for your understanding!
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

144 lines
3.6KB

  1. const rx = /^[a-f0-9]{32}\+[0-9]+/;
  2. const rootDir = {};
  3. const streams = [];
  4. onmessage = function(e) {
  5. switch (e.data[0]) {
  6. case 'precreatePaths':
  7. precreatePaths(e.data[1]);
  8. postMessage([ 'precreatePathsResult' ]);
  9. break;
  10. case 'parseStream':
  11. parseStream(e.data[1]);
  12. postMessage([ 'parseStreamResult' ]);
  13. break;
  14. case 'listDirectory': {
  15. const lst = listDirectory(rootDir, e.data[1], e.data[2]);
  16. postMessage([ 'listDirectoryResult', lst ])
  17. break; }
  18. case 'getData': {
  19. postMessage([ 'getDataResult', rootDir, streams ]);
  20. break; }
  21. default:
  22. throw Error('Unknown verb: ' + e.data[0]);
  23. }
  24. }
  25. function precreatePaths(paths) {
  26. for (let i = 0; i < paths.length; i++) {
  27. mkpath(rootDir, paths[i]);
  28. }
  29. }
  30. function parseStream(s) {
  31. if (!s) return;
  32. const tokens = s.split(' ');
  33. const streamName = unescapeName(tokens[0]);
  34. let n = tokens.map(t => rx.exec(t));
  35. n = n.indexOf(null, 1);
  36. let locators = tokens.slice(1, n);
  37. let pos = 0;
  38. locators = locators.map(loc => {
  39. const sz = parseInt(loc.split('+')[1], 10);
  40. return [ loc, pos, pos += sz ];
  41. });
  42. let fileTokens = tokens.slice(n);
  43. let lastFile = null;
  44. let lastPath = null;
  45. fileTokens.map(t => {
  46. let seg = t.split(':');
  47. seg = [ parseInt(seg[0], 10), parseInt(seg[1], 10),
  48. unescapeName(seg.slice(2).join(':')) ]
  49. const path = streamName + '/' + seg[2];
  50. let f;
  51. if (path === lastPath) {
  52. f = lastFile;
  53. } else {
  54. let dirName = path.split('/');
  55. const name = dirName[dirName.length - 1];
  56. dirName = dirName.slice(0, dirName.length - 1);
  57. const d = mkpath(rootDir, dirName);
  58. lastFile = f = makeFile(d, name);
  59. lastPath = path;
  60. }
  61. appendFile(f, streams.length, seg);
  62. });
  63. streams.push(locators);
  64. }
  65. function mkdir(parent, name) {
  66. if (name in parent && (parent[name] instanceof Array))
  67. throw Error('File with the same name already exists');
  68. if (name in parent)
  69. return parent[name];
  70. const dir = {};
  71. parent[name] = dir;
  72. return dir;
  73. }
  74. function mkpath(parent, path) {
  75. if (typeof(path) === 'string')
  76. path = path.split('/');
  77. let dir = parent;
  78. for (let i = 1; i < path.length; i++) {
  79. dir = mkdir(dir, path[i]);
  80. }
  81. return dir;
  82. }
  83. function makeFile(dir, name) {
  84. if (name in dir) {
  85. if (!(dir[name] instanceof Array))
  86. throw Error('Directory with the same name already exists');
  87. return dir[name];
  88. }
  89. const f = [[], 0];
  90. dir[name] = f;
  91. return f;
  92. }
  93. function appendFile(f, sidx, seg) {
  94. f[0].push([ sidx, seg[0], seg[1] ]);
  95. f[1] += seg[1];
  96. return f;
  97. }
  98. function unescapeName(name) {
  99. return name.replace(/(\\\\|\\[0-9]{3})/g,
  100. (_, $1) => ($1 === '\\\\' ? '\\' : String.fromCharCode(parseInt($1.substr(1), 8))));
  101. }
  102. function findDir(parent, path, lenient=false) {
  103. if (typeof(path) === 'string')
  104. path = path.split('/');
  105. if (path[0] !== '.')
  106. throw Error('Path must start with a dot (.)');
  107. let dir = parent;
  108. for (let i = 1; i < path.length; i++) {
  109. if (!(path[i] in dir)) {
  110. if (lenient)
  111. return {};
  112. else
  113. throw Error('Directory not found');
  114. }
  115. dir = dir[path[i]];
  116. }
  117. return dir;
  118. }
  119. function listDirectory(rootDir, path, lenient=false) {
  120. let dir = findDir(rootDir, path, lenient);
  121. let keys = Object.keys(dir);
  122. keys.sort();
  123. let subdirs = keys.filter(k => !(dir[k] instanceof Array));
  124. let files = keys.filter(k => (dir[k] instanceof Array));
  125. let res = subdirs.map(k => [ 'd', k, null ]);
  126. res = res.concat(files.map(k => [ 'f', k, dir[k][1] ]));
  127. return res;
  128. }