byte_stream.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.ByteStream = void 0;
  4. class ByteStream {
  5. constructor(parameters = {}) {
  6. if ("view" in parameters) {
  7. this.fromUint8Array(parameters.view);
  8. }
  9. else if ("buffer" in parameters) {
  10. this.fromArrayBuffer(parameters.buffer);
  11. }
  12. else if ("string" in parameters) {
  13. this.fromString(parameters.string);
  14. }
  15. else if ("hexstring" in parameters) {
  16. this.fromHexString(parameters.hexstring);
  17. }
  18. else {
  19. if ("length" in parameters && parameters.length > 0) {
  20. this.length = parameters.length;
  21. if (parameters.stub) {
  22. for (let i = 0; i < this._view.length; i++) {
  23. this._view[i] = parameters.stub;
  24. }
  25. }
  26. }
  27. else {
  28. this.length = 0;
  29. }
  30. }
  31. }
  32. set buffer(value) {
  33. this._buffer = value;
  34. this._view = new Uint8Array(this._buffer);
  35. }
  36. get buffer() {
  37. return this._buffer;
  38. }
  39. set view(value) {
  40. this._buffer = new ArrayBuffer(value.length);
  41. this._view = new Uint8Array(this._buffer);
  42. this._view.set(value);
  43. }
  44. get view() {
  45. return this._view;
  46. }
  47. get length() {
  48. return this.view.byteLength;
  49. }
  50. set length(value) {
  51. this._buffer = new ArrayBuffer(value);
  52. this._view = new Uint8Array(this._buffer);
  53. }
  54. clear() {
  55. this._buffer = new ArrayBuffer(0);
  56. this._view = new Uint8Array(this._buffer);
  57. }
  58. fromArrayBuffer(array) {
  59. this._buffer = array;
  60. this._view = new Uint8Array(this._buffer);
  61. }
  62. fromUint8Array(array) {
  63. this.fromArrayBuffer(new Uint8Array(array).buffer);
  64. }
  65. fromString(string) {
  66. const stringLength = string.length;
  67. this.length = stringLength;
  68. for (let i = 0; i < stringLength; i++)
  69. this.view[i] = string.charCodeAt(i);
  70. }
  71. toString(start = 0, length = (this.view.length - start)) {
  72. let result = "";
  73. if ((start >= this.view.length) || (start < 0)) {
  74. start = 0;
  75. }
  76. if ((length >= this.view.length) || (length < 0)) {
  77. length = this.view.length - start;
  78. }
  79. for (let i = start; i < (start + length); i++)
  80. result += String.fromCharCode(this.view[i]);
  81. return result;
  82. }
  83. fromHexString(hexString) {
  84. const stringLength = hexString.length;
  85. this.buffer = new ArrayBuffer(stringLength >> 1);
  86. this.view = new Uint8Array(this.buffer);
  87. const hexMap = new Map();
  88. hexMap.set("0", 0x00);
  89. hexMap.set("1", 0x01);
  90. hexMap.set("2", 0x02);
  91. hexMap.set("3", 0x03);
  92. hexMap.set("4", 0x04);
  93. hexMap.set("5", 0x05);
  94. hexMap.set("6", 0x06);
  95. hexMap.set("7", 0x07);
  96. hexMap.set("8", 0x08);
  97. hexMap.set("9", 0x09);
  98. hexMap.set("A", 0x0A);
  99. hexMap.set("a", 0x0A);
  100. hexMap.set("B", 0x0B);
  101. hexMap.set("b", 0x0B);
  102. hexMap.set("C", 0x0C);
  103. hexMap.set("c", 0x0C);
  104. hexMap.set("D", 0x0D);
  105. hexMap.set("d", 0x0D);
  106. hexMap.set("E", 0x0E);
  107. hexMap.set("e", 0x0E);
  108. hexMap.set("F", 0x0F);
  109. hexMap.set("f", 0x0F);
  110. let j = 0;
  111. let temp = 0x00;
  112. for (let i = 0; i < stringLength; i++) {
  113. if (!(i % 2)) {
  114. temp = hexMap.get(hexString.charAt(i)) << 4;
  115. }
  116. else {
  117. temp |= hexMap.get(hexString.charAt(i));
  118. this.view[j] = temp;
  119. j++;
  120. }
  121. }
  122. }
  123. toHexString(start = 0, length = (this.view.length - start)) {
  124. let result = "";
  125. if ((start >= this.view.length) || (start < 0)) {
  126. start = 0;
  127. }
  128. if ((length >= this.view.length) || (length < 0)) {
  129. length = this.view.length - start;
  130. }
  131. for (let i = start; i < (start + length); i++) {
  132. const str = this.view[i].toString(16).toUpperCase();
  133. result = result + ((str.length == 1) ? "0" : "") + str;
  134. }
  135. return result;
  136. }
  137. copy(start = 0, length = (this.length - start)) {
  138. if (!start && !this.length) {
  139. return new ByteStream();
  140. }
  141. if ((start < 0) || (start > (this.length - 1))) {
  142. throw new Error(`Wrong start position: ${start}`);
  143. }
  144. const stream = new ByteStream({
  145. buffer: this._buffer.slice(start, start + length)
  146. });
  147. return stream;
  148. }
  149. slice(start = 0, end = this.length) {
  150. if (!start && !this.length) {
  151. return new ByteStream();
  152. }
  153. if ((start < 0) || (start > (this.length - 1))) {
  154. throw new Error(`Wrong start position: ${start}`);
  155. }
  156. const stream = new ByteStream({
  157. buffer: this._buffer.slice(start, end),
  158. });
  159. return stream;
  160. }
  161. realloc(size) {
  162. const buffer = new ArrayBuffer(size);
  163. const view = new Uint8Array(buffer);
  164. if (size > this._view.length)
  165. view.set(this._view);
  166. else {
  167. view.set(new Uint8Array(this._buffer, 0, size));
  168. }
  169. this._buffer = buffer;
  170. this._view = new Uint8Array(this._buffer);
  171. }
  172. append(stream) {
  173. const initialSize = this.length;
  174. const streamViewLength = stream.length;
  175. const subarrayView = stream._view.subarray();
  176. this.realloc(initialSize + streamViewLength);
  177. this._view.set(subarrayView, initialSize);
  178. }
  179. insert(stream, start = 0, length = (this.length - start)) {
  180. if (start > (this.length - 1))
  181. return false;
  182. if (length > (this.length - start)) {
  183. length = this.length - start;
  184. }
  185. if (length > stream.length) {
  186. length = stream.length;
  187. }
  188. if (length == stream.length)
  189. this._view.set(stream._view, start);
  190. else {
  191. this._view.set(stream._view.subarray(0, length), start);
  192. }
  193. return true;
  194. }
  195. isEqual(stream) {
  196. if (this.length != stream.length)
  197. return false;
  198. for (let i = 0; i < stream.length; i++) {
  199. if (this.view[i] != stream.view[i])
  200. return false;
  201. }
  202. return true;
  203. }
  204. isEqualView(view) {
  205. if (view.length != this.view.length)
  206. return false;
  207. for (let i = 0; i < view.length; i++) {
  208. if (this.view[i] != view[i])
  209. return false;
  210. }
  211. return true;
  212. }
  213. findPattern(pattern, start_, length_, backward_) {
  214. const { start, length, backward } = this.prepareFindParameters(start_, length_, backward_);
  215. const patternLength = pattern.length;
  216. if (patternLength > length) {
  217. return (-1);
  218. }
  219. const patternArray = [];
  220. for (let i = 0; i < patternLength; i++)
  221. patternArray.push(pattern.view[i]);
  222. for (let i = 0; i <= (length - patternLength); i++) {
  223. let equal = true;
  224. const equalStart = (backward) ? (start - patternLength - i) : (start + i);
  225. for (let j = 0; j < patternLength; j++) {
  226. if (this.view[j + equalStart] != patternArray[j]) {
  227. equal = false;
  228. break;
  229. }
  230. }
  231. if (equal) {
  232. return (backward) ? (start - patternLength - i) : (start + patternLength + i);
  233. }
  234. }
  235. return (-1);
  236. }
  237. findFirstIn(patterns, start_, length_, backward_) {
  238. const { start, length, backward } = this.prepareFindParameters(start_, length_, backward_);
  239. const result = {
  240. id: (-1),
  241. position: (backward) ? 0 : (start + length),
  242. length: 0
  243. };
  244. for (let i = 0; i < patterns.length; i++) {
  245. const position = this.findPattern(patterns[i], start, length, backward);
  246. if (position != (-1)) {
  247. let valid = false;
  248. const patternLength = patterns[i].length;
  249. if (backward) {
  250. if ((position - patternLength) >= (result.position - result.length))
  251. valid = true;
  252. }
  253. else {
  254. if ((position - patternLength) <= (result.position - result.length))
  255. valid = true;
  256. }
  257. if (valid) {
  258. result.position = position;
  259. result.id = i;
  260. result.length = patternLength;
  261. }
  262. }
  263. }
  264. return result;
  265. }
  266. findAllIn(patterns, start_, length_) {
  267. let { start, length } = this.prepareFindParameters(start_, length_);
  268. const result = [];
  269. let patternFound = {
  270. id: (-1),
  271. position: start
  272. };
  273. do {
  274. const position = patternFound.position;
  275. patternFound = this.findFirstIn(patterns, patternFound.position, length);
  276. if (patternFound.id == (-1)) {
  277. break;
  278. }
  279. length -= (patternFound.position - position);
  280. result.push({
  281. id: patternFound.id,
  282. position: patternFound.position
  283. });
  284. } while (true);
  285. return result;
  286. }
  287. findAllPatternIn(pattern, start_, length_) {
  288. const { start, length } = this.prepareFindParameters(start_, length_);
  289. const result = [];
  290. const patternLength = pattern.length;
  291. if (patternLength > length) {
  292. return (-1);
  293. }
  294. const patternArray = Array.from(pattern.view);
  295. for (let i = 0; i <= (length - patternLength); i++) {
  296. let equal = true;
  297. const equalStart = start + i;
  298. for (let j = 0; j < patternLength; j++) {
  299. if (this.view[j + equalStart] != patternArray[j]) {
  300. equal = false;
  301. break;
  302. }
  303. }
  304. if (equal) {
  305. result.push(start + patternLength + i);
  306. i += (patternLength - 1);
  307. }
  308. }
  309. return result;
  310. }
  311. findFirstNotIn(patterns, start_, length_, backward_) {
  312. let { start, length, backward } = this.prepareFindParameters(start_, length_, backward_);
  313. const result = {
  314. left: {
  315. id: (-1),
  316. position: start
  317. },
  318. right: {
  319. id: (-1),
  320. position: 0
  321. },
  322. value: new ByteStream()
  323. };
  324. let currentLength = length;
  325. while (currentLength > 0) {
  326. result.right = this.findFirstIn(patterns, (backward) ? (start - length + currentLength) : (start + length - currentLength), currentLength, backward);
  327. if (result.right.id == (-1)) {
  328. length = currentLength;
  329. if (backward) {
  330. start -= length;
  331. }
  332. else {
  333. start = result.left.position;
  334. }
  335. result.value = new ByteStream({
  336. buffer: this._buffer.slice(start, start + length),
  337. });
  338. break;
  339. }
  340. if (result.right.position != ((backward) ? (result.left.position - patterns[result.right.id].length) : (result.left.position + patterns[result.right.id].length))) {
  341. if (backward) {
  342. start = result.right.position + patterns[result.right.id].length;
  343. length = result.left.position - result.right.position - patterns[result.right.id].length;
  344. }
  345. else {
  346. start = result.left.position;
  347. length = result.right.position - result.left.position - patterns[result.right.id].length;
  348. }
  349. result.value = new ByteStream({
  350. buffer: this._buffer.slice(start, start + length),
  351. });
  352. break;
  353. }
  354. result.left = result.right;
  355. currentLength -= patterns[result.right.id].length;
  356. }
  357. if (backward) {
  358. const temp = result.right;
  359. result.right = result.left;
  360. result.left = temp;
  361. }
  362. return result;
  363. }
  364. findAllNotIn(patterns, start_, length_) {
  365. let { start, length } = this.prepareFindParameters(start_, length_);
  366. const result = [];
  367. let patternFound = {
  368. left: {
  369. id: (-1),
  370. position: start
  371. },
  372. right: {
  373. id: (-1),
  374. position: start
  375. },
  376. value: new ByteStream()
  377. };
  378. do {
  379. const position = patternFound.right.position;
  380. patternFound = this.findFirstNotIn(patterns, patternFound.right.position, length);
  381. length -= (patternFound.right.position - position);
  382. result.push({
  383. left: {
  384. id: patternFound.left.id,
  385. position: patternFound.left.position
  386. },
  387. right: {
  388. id: patternFound.right.id,
  389. position: patternFound.right.position
  390. },
  391. value: patternFound.value
  392. });
  393. } while (patternFound.right.id != (-1));
  394. return result;
  395. }
  396. findFirstSequence(patterns, start_, length_, backward_) {
  397. let { start, length, backward } = this.prepareFindParameters(start_, length_, backward_);
  398. const firstIn = this.skipNotPatterns(patterns, start, length, backward);
  399. if (firstIn == (-1)) {
  400. return {
  401. position: (-1),
  402. value: new ByteStream()
  403. };
  404. }
  405. const firstNotIn = this.skipPatterns(patterns, firstIn, length - ((backward) ? (start - firstIn) : (firstIn - start)), backward);
  406. if (backward) {
  407. start = firstNotIn;
  408. length = (firstIn - firstNotIn);
  409. }
  410. else {
  411. start = firstIn;
  412. length = (firstNotIn - firstIn);
  413. }
  414. const value = new ByteStream({
  415. buffer: this._buffer.slice(start, start + length),
  416. });
  417. return {
  418. position: firstNotIn,
  419. value
  420. };
  421. }
  422. findAllSequences(patterns, start_, length_) {
  423. let { start, length } = this.prepareFindParameters(start_, length_);
  424. const result = [];
  425. let patternFound = {
  426. position: start,
  427. value: new ByteStream()
  428. };
  429. do {
  430. const position = patternFound.position;
  431. patternFound = this.findFirstSequence(patterns, patternFound.position, length);
  432. if (patternFound.position != (-1)) {
  433. length -= (patternFound.position - position);
  434. result.push({
  435. position: patternFound.position,
  436. value: patternFound.value,
  437. });
  438. }
  439. } while (patternFound.position != (-1));
  440. return result;
  441. }
  442. findPairedPatterns(leftPattern, rightPattern, start_, length_) {
  443. const result = [];
  444. if (leftPattern.isEqual(rightPattern))
  445. return result;
  446. const { start, length } = this.prepareFindParameters(start_, length_);
  447. let currentPositionLeft = 0;
  448. const leftPatterns = this.findAllPatternIn(leftPattern, start, length);
  449. if (!Array.isArray(leftPatterns) || leftPatterns.length == 0) {
  450. return result;
  451. }
  452. const rightPatterns = this.findAllPatternIn(rightPattern, start, length);
  453. if (!Array.isArray(rightPatterns) || rightPatterns.length == 0) {
  454. return result;
  455. }
  456. while (currentPositionLeft < leftPatterns.length) {
  457. if (rightPatterns.length == 0) {
  458. break;
  459. }
  460. if (leftPatterns[0] == rightPatterns[0]) {
  461. result.push({
  462. left: leftPatterns[0],
  463. right: rightPatterns[0]
  464. });
  465. leftPatterns.splice(0, 1);
  466. rightPatterns.splice(0, 1);
  467. continue;
  468. }
  469. if (leftPatterns[currentPositionLeft] > rightPatterns[0]) {
  470. break;
  471. }
  472. while (leftPatterns[currentPositionLeft] < rightPatterns[0]) {
  473. currentPositionLeft++;
  474. if (currentPositionLeft >= leftPatterns.length) {
  475. break;
  476. }
  477. }
  478. result.push({
  479. left: leftPatterns[currentPositionLeft - 1],
  480. right: rightPatterns[0]
  481. });
  482. leftPatterns.splice(currentPositionLeft - 1, 1);
  483. rightPatterns.splice(0, 1);
  484. currentPositionLeft = 0;
  485. }
  486. result.sort((a, b) => (a.left - b.left));
  487. return result;
  488. }
  489. findPairedArrays(inputLeftPatterns, inputRightPatterns, start_, length_) {
  490. const { start, length } = this.prepareFindParameters(start_, length_);
  491. const result = [];
  492. let currentPositionLeft = 0;
  493. const leftPatterns = this.findAllIn(inputLeftPatterns, start, length);
  494. if (leftPatterns.length == 0)
  495. return result;
  496. const rightPatterns = this.findAllIn(inputRightPatterns, start, length);
  497. if (rightPatterns.length == 0)
  498. return result;
  499. while (currentPositionLeft < leftPatterns.length) {
  500. if (rightPatterns.length == 0) {
  501. break;
  502. }
  503. if (leftPatterns[0].position == rightPatterns[0].position) {
  504. result.push({
  505. left: leftPatterns[0],
  506. right: rightPatterns[0]
  507. });
  508. leftPatterns.splice(0, 1);
  509. rightPatterns.splice(0, 1);
  510. continue;
  511. }
  512. if (leftPatterns[currentPositionLeft].position > rightPatterns[0].position) {
  513. break;
  514. }
  515. while (leftPatterns[currentPositionLeft].position < rightPatterns[0].position) {
  516. currentPositionLeft++;
  517. if (currentPositionLeft >= leftPatterns.length) {
  518. break;
  519. }
  520. }
  521. result.push({
  522. left: leftPatterns[currentPositionLeft - 1],
  523. right: rightPatterns[0]
  524. });
  525. leftPatterns.splice(currentPositionLeft - 1, 1);
  526. rightPatterns.splice(0, 1);
  527. currentPositionLeft = 0;
  528. }
  529. result.sort((a, b) => (a.left.position - b.left.position));
  530. return result;
  531. }
  532. replacePattern(searchPattern, replacePattern, start_, length_, findAllResult = null) {
  533. let result = [];
  534. let i;
  535. const output = {
  536. status: (-1),
  537. searchPatternPositions: [],
  538. replacePatternPositions: []
  539. };
  540. const { start, length } = this.prepareFindParameters(start_, length_);
  541. if (findAllResult == null) {
  542. result = this.findAllIn([searchPattern], start, length);
  543. if (result.length == 0) {
  544. return output;
  545. }
  546. }
  547. else {
  548. result = findAllResult;
  549. }
  550. output.searchPatternPositions.push(...Array.from(result, element => element.position));
  551. const patternDifference = searchPattern.length - replacePattern.length;
  552. const changedBuffer = new ArrayBuffer(this.view.length - (result.length * patternDifference));
  553. const changedView = new Uint8Array(changedBuffer);
  554. changedView.set(new Uint8Array(this.buffer, 0, start));
  555. for (i = 0; i < result.length; i++) {
  556. const currentPosition = (i == 0) ? start : result[i - 1].position;
  557. changedView.set(new Uint8Array(this.buffer, currentPosition, result[i].position - searchPattern.length - currentPosition), currentPosition - i * patternDifference);
  558. changedView.set(replacePattern.view, result[i].position - searchPattern.length - i * patternDifference);
  559. output.replacePatternPositions.push(result[i].position - searchPattern.length - i * patternDifference);
  560. }
  561. i--;
  562. changedView.set(new Uint8Array(this.buffer, result[i].position, this.length - result[i].position), result[i].position - searchPattern.length + replacePattern.length - i * patternDifference);
  563. this.buffer = changedBuffer;
  564. this.view = new Uint8Array(this.buffer);
  565. output.status = 1;
  566. return output;
  567. }
  568. skipPatterns(patterns, start_, length_, backward_) {
  569. const { start, length, backward } = this.prepareFindParameters(start_, length_, backward_);
  570. let result = start;
  571. for (let k = 0; k < patterns.length; k++) {
  572. const patternLength = patterns[k].length;
  573. const equalStart = (backward) ? (result - patternLength) : (result);
  574. let equal = true;
  575. for (let j = 0; j < patternLength; j++) {
  576. if (this.view[j + equalStart] != patterns[k].view[j]) {
  577. equal = false;
  578. break;
  579. }
  580. }
  581. if (equal) {
  582. k = (-1);
  583. if (backward) {
  584. result -= patternLength;
  585. if (result <= 0)
  586. return result;
  587. }
  588. else {
  589. result += patternLength;
  590. if (result >= (start + length))
  591. return result;
  592. }
  593. }
  594. }
  595. return result;
  596. }
  597. skipNotPatterns(patterns, start_, length_, backward_) {
  598. const { start, length, backward } = this.prepareFindParameters(start_, length_, backward_);
  599. let result = (-1);
  600. for (let i = 0; i < length; i++) {
  601. for (let k = 0; k < patterns.length; k++) {
  602. const patternLength = patterns[k].length;
  603. const equalStart = (backward) ? (start - i - patternLength) : (start + i);
  604. let equal = true;
  605. for (let j = 0; j < patternLength; j++) {
  606. if (this.view[j + equalStart] != patterns[k].view[j]) {
  607. equal = false;
  608. break;
  609. }
  610. }
  611. if (equal) {
  612. result = (backward) ? (start - i) : (start + i);
  613. break;
  614. }
  615. }
  616. if (result != (-1)) {
  617. break;
  618. }
  619. }
  620. return result;
  621. }
  622. prepareFindParameters(start = null, length = null, backward = false) {
  623. if (start === null) {
  624. start = (backward) ? this.length : 0;
  625. }
  626. if (start > this.length) {
  627. start = this.length;
  628. }
  629. if (backward) {
  630. if (length === null) {
  631. length = start;
  632. }
  633. if (length > start) {
  634. length = start;
  635. }
  636. }
  637. else {
  638. if (length === null) {
  639. length = this.length - start;
  640. }
  641. if (length > (this.length - start)) {
  642. length = this.length - start;
  643. }
  644. }
  645. return { start, length, backward };
  646. }
  647. }
  648. exports.ByteStream = ByteStream;