cecc79a0de9edd7b41fcb5001505ddb3076ee592793826b81e9475ff263f041ad836661bb49c802dbf0f17fa93eb15c50ba5f333f5f1fe466aa398fd401476 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. import { LineTokens } from './lineTokens.js';
  6. export const EMPTY_LINE_TOKENS = (new Uint32Array(0)).buffer;
  7. export class ContiguousTokensEditing {
  8. static deleteBeginning(lineTokens, toChIndex) {
  9. if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {
  10. return lineTokens;
  11. }
  12. return ContiguousTokensEditing.delete(lineTokens, 0, toChIndex);
  13. }
  14. static deleteEnding(lineTokens, fromChIndex) {
  15. if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {
  16. return lineTokens;
  17. }
  18. const tokens = toUint32Array(lineTokens);
  19. const lineTextLength = tokens[tokens.length - 2];
  20. return ContiguousTokensEditing.delete(lineTokens, fromChIndex, lineTextLength);
  21. }
  22. static delete(lineTokens, fromChIndex, toChIndex) {
  23. if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS || fromChIndex === toChIndex) {
  24. return lineTokens;
  25. }
  26. const tokens = toUint32Array(lineTokens);
  27. const tokensCount = (tokens.length >>> 1);
  28. // special case: deleting everything
  29. if (fromChIndex === 0 && tokens[tokens.length - 2] === toChIndex) {
  30. return EMPTY_LINE_TOKENS;
  31. }
  32. const fromTokenIndex = LineTokens.findIndexInTokensArray(tokens, fromChIndex);
  33. const fromTokenStartOffset = (fromTokenIndex > 0 ? tokens[(fromTokenIndex - 1) << 1] : 0);
  34. const fromTokenEndOffset = tokens[fromTokenIndex << 1];
  35. if (toChIndex < fromTokenEndOffset) {
  36. // the delete range is inside a single token
  37. const delta = (toChIndex - fromChIndex);
  38. for (let i = fromTokenIndex; i < tokensCount; i++) {
  39. tokens[i << 1] -= delta;
  40. }
  41. return lineTokens;
  42. }
  43. let dest;
  44. let lastEnd;
  45. if (fromTokenStartOffset !== fromChIndex) {
  46. tokens[fromTokenIndex << 1] = fromChIndex;
  47. dest = ((fromTokenIndex + 1) << 1);
  48. lastEnd = fromChIndex;
  49. }
  50. else {
  51. dest = (fromTokenIndex << 1);
  52. lastEnd = fromTokenStartOffset;
  53. }
  54. const delta = (toChIndex - fromChIndex);
  55. for (let tokenIndex = fromTokenIndex + 1; tokenIndex < tokensCount; tokenIndex++) {
  56. const tokenEndOffset = tokens[tokenIndex << 1] - delta;
  57. if (tokenEndOffset > lastEnd) {
  58. tokens[dest++] = tokenEndOffset;
  59. tokens[dest++] = tokens[(tokenIndex << 1) + 1];
  60. lastEnd = tokenEndOffset;
  61. }
  62. }
  63. if (dest === tokens.length) {
  64. // nothing to trim
  65. return lineTokens;
  66. }
  67. const tmp = new Uint32Array(dest);
  68. tmp.set(tokens.subarray(0, dest), 0);
  69. return tmp.buffer;
  70. }
  71. static append(lineTokens, _otherTokens) {
  72. if (_otherTokens === EMPTY_LINE_TOKENS) {
  73. return lineTokens;
  74. }
  75. if (lineTokens === EMPTY_LINE_TOKENS) {
  76. return _otherTokens;
  77. }
  78. if (lineTokens === null) {
  79. return lineTokens;
  80. }
  81. if (_otherTokens === null) {
  82. // cannot determine combined line length...
  83. return null;
  84. }
  85. const myTokens = toUint32Array(lineTokens);
  86. const otherTokens = toUint32Array(_otherTokens);
  87. const otherTokensCount = (otherTokens.length >>> 1);
  88. const result = new Uint32Array(myTokens.length + otherTokens.length);
  89. result.set(myTokens, 0);
  90. let dest = myTokens.length;
  91. const delta = myTokens[myTokens.length - 2];
  92. for (let i = 0; i < otherTokensCount; i++) {
  93. result[dest++] = otherTokens[(i << 1)] + delta;
  94. result[dest++] = otherTokens[(i << 1) + 1];
  95. }
  96. return result.buffer;
  97. }
  98. static insert(lineTokens, chIndex, textLength) {
  99. if (lineTokens === null || lineTokens === EMPTY_LINE_TOKENS) {
  100. // nothing to do
  101. return lineTokens;
  102. }
  103. const tokens = toUint32Array(lineTokens);
  104. const tokensCount = (tokens.length >>> 1);
  105. let fromTokenIndex = LineTokens.findIndexInTokensArray(tokens, chIndex);
  106. if (fromTokenIndex > 0) {
  107. const fromTokenStartOffset = tokens[(fromTokenIndex - 1) << 1];
  108. if (fromTokenStartOffset === chIndex) {
  109. fromTokenIndex--;
  110. }
  111. }
  112. for (let tokenIndex = fromTokenIndex; tokenIndex < tokensCount; tokenIndex++) {
  113. tokens[tokenIndex << 1] += textLength;
  114. }
  115. return lineTokens;
  116. }
  117. }
  118. export function toUint32Array(arr) {
  119. if (arr instanceof Uint32Array) {
  120. return arr;
  121. }
  122. else {
  123. return new Uint32Array(arr);
  124. }
  125. }