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!
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

181 řádky
5.2KB

  1. //
  2. // Directory: Hash[string, [Directory, File]]
  3. // File = [blockRefs, size]
  4. // blockRefs: Array[blockRef]
  5. // blockRef: [locator, position, size]
  6. // locator: String
  7. // position: Number
  8. // size: Number
  9. //
  10. class WBManifestReader {
  11. constructor(manifest_text) {
  12. this.rootDir = {};
  13. if (!manifest_text)
  14. return;
  15. this.parse(manifest_text);
  16. }
  17. makeDir(parent, name) {
  18. if (!(name in parent))
  19. parent[name] = {};
  20. if (parent[name] instanceof Array)
  21. throw Error('Conflict trying to create a directory - a file with the same name already exists: ' + name);
  22. return parent[name];
  23. }
  24. makePath(path) {
  25. if (typeof(path) === 'string')
  26. path = path.split('/');
  27. let dir = this.rootDir;
  28. for (let i = 1; i < path.length; i++)
  29. dir = this.makeDir(dir, path[i]);
  30. return dir;
  31. }
  32. appendFile(streamName, locators, position, size, fileName) {
  33. let path = streamName + '/' + fileName;
  34. path = path.split('/');
  35. let dir = this.makePath(path.slice(0, path.length - 1));
  36. if (!(fileName in dir))
  37. dir[fileName] = [[], 0];
  38. if (!(dir[fileName] instanceof Array))
  39. throw Error('Conflict trying to create a file - a directory with the same name already exists: ' + fileName);
  40. //this.appendReferences(dir[fileName], locators, position, size);
  41. }
  42. appendReferences(file, locators, position, size) {
  43. if (size === 0)
  44. return;
  45. let cum = 0;
  46. let locHashes = locators.map(loc => loc[0]);
  47. let locSizes = locators.map(loc => loc[1]);
  48. let locPositions = locators.map(loc => {
  49. let res = cum;
  50. cum += loc[1];
  51. return res;
  52. });
  53. let used = locators.map((_, i) => (locPositions[i] + locSizes[i] > position &&
  54. locPositions[i] < position + size));
  55. let startBlock = used.indexOf(true);
  56. let endBlock = used.lastIndexOf(true) + 1;
  57. // console.log('startBlock: ' + startBlock + ', endBlock: ' + endBlock);
  58. if (startBlock === -1)
  59. return;
  60. let blockRefs = [];
  61. let runPos = position;
  62. let runSize = size;
  63. for (let i = startBlock; i < endBlock; i++) {
  64. let blockPos = runPos - locPositions[i];
  65. let blockSize = Math.min(runSize, locSizes[i] - blockPos);
  66. blockRefs.push([ locHashes[i], blockPos, blockSize ]);
  67. runPos += blockSize;
  68. runSize -= blockSize;
  69. }
  70. file[0] = file[0].concat(blockRefs);
  71. file[1] += size;
  72. }
  73. parse(manifest_text) {
  74. let rx = /^[a-f0-9]{32}\+[0-9]+/;
  75. let streams = manifest_text.split('\n');
  76. if (!streams[streams.length - 1])
  77. streams = streams.slice(0, streams.length - 1);
  78. streams.map(s => {
  79. let tokens = s.split(' ');
  80. let streamName = this.unescapeName(tokens[0]);
  81. let n = tokens.map(t => rx.exec(t));
  82. n = n.indexOf(null, 1);
  83. let locators = tokens.slice(1, n);
  84. locators = locators.map(loc => [ loc, Number(loc.split('+')[1]) ]);
  85. let fileTokens = tokens.slice(n);
  86. fileTokens.map(t => {
  87. let [ position, size, ...fileName ] = t.split(':');
  88. fileName = fileName.join(':');
  89. fileName = this.unescapeName(fileName);
  90. this.appendFile(streamName, locators,
  91. Number(position), Number(size), fileName);
  92. });
  93. });
  94. }
  95. findDir(path) {
  96. if (typeof(path) === 'string')
  97. path = path.split('/');
  98. if (path[0] !== '.')
  99. throw Error('Path must begin with a dot component');
  100. let dir = this.rootDir;
  101. for (let i = 1; i < path.length; i++) {
  102. if (!(path[i] in dir))
  103. throw Error('Directory not found');
  104. if (dir[path[i]] instanceof Array)
  105. throw Error('Path is a file not directory');
  106. dir = dir[path[i]];
  107. }
  108. return dir;
  109. }
  110. listDirectory(path) {
  111. let dir = this.findDir(path);
  112. let keys = Object.keys(dir);
  113. keys.sort();
  114. let subdirs = keys.filter(k => !(dir[k] instanceof Array));
  115. let files = keys.filter(k => (dir[k] instanceof Array));
  116. let res = subdirs.map(k => [ 'd', k, null ]);
  117. res = res.concat(files.map(k => [ 'f', k, dir[k][1] ]));
  118. return res;
  119. }
  120. unescapeName(name) {
  121. return name.replace(/(\\\\|\\[0-9]{3})/g, (_, $1) => ($1 === '\\\\' ? '\\' : String.fromCharCode(parseInt($1.substr(1), 8))));
  122. }
  123. escapeName(name) {
  124. return name.replace(/ /g, '\\040');
  125. }
  126. /* let ids = { '\\': 1, '0': 2, '4': 3 };
  127. let transitions = [
  128. [ [0, 0], [1, ''], [0, 0], [0, 0] ],
  129. [ [0, 0], [0, '\\'], [2, ''], [0, 0] ],
  130. ];
  131. let mode = 0;
  132. for (let i = 0; i < name.length; i++) {
  133. let b = name[i];
  134. let tokenId = Number(ids[b]);
  135. [ mode, out ] = transitions[mode][tokenId];
  136. if (out === 0)
  137. out = b;
  138. }
  139. }*/
  140. getFile(path) {
  141. if (typeof(path) === 'string')
  142. path = path.split('/');
  143. if (path.length < 2)
  144. throw Error('Invalid file path');
  145. let name = path[path.length - 1];
  146. let dir = this.findDir(path.slice(0, path.length - 1));
  147. if (!(name in dir))
  148. throw Error('File not found');
  149. if (!(dir[name] instanceof Array))
  150. throw Error('Path points to a directory not a file');
  151. return dir[name];
  152. }
  153. }
  154. export { WBManifestReader };