monaco-editor-core 0.55.0-dev-20251021 → 0.55.0-dev-20251023
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/nls.keys.json +1 -1
- package/esm/nls.messages.cs.js +2 -2
- package/esm/nls.messages.de.js +2 -2
- package/esm/nls.messages.es.js +2 -2
- package/esm/nls.messages.fr.js +2 -2
- package/esm/nls.messages.it.js +2 -2
- package/esm/nls.messages.ja.js +2 -2
- package/esm/nls.messages.js +1 -1
- package/esm/nls.messages.json +1 -1
- package/esm/nls.messages.ko.js +2 -2
- package/esm/nls.messages.pl.js +2 -2
- package/esm/nls.messages.pt-br.js +2 -2
- package/esm/nls.messages.ru.js +2 -2
- package/esm/nls.messages.tr.js +2 -2
- package/esm/nls.messages.zh-cn.js +2 -2
- package/esm/nls.messages.zh-tw.js +2 -2
- package/esm/nls.metadata.json +23 -5
- package/esm/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
- package/esm/vs/base/browser/ui/iconLabel/iconlabel.css +2 -3
- package/esm/vs/base/browser/ui/list/listPaging.js +5 -1
- package/esm/vs/base/browser/ui/list/listPaging.js.map +1 -1
- package/esm/vs/base/browser/ui/list/listView.js +4 -3
- package/esm/vs/base/browser/ui/list/listView.js.map +1 -1
- package/esm/vs/base/common/arrays.js +10 -0
- package/esm/vs/base/common/arrays.js.map +1 -1
- package/esm/vs/base/common/codiconsLibrary.js +1 -0
- package/esm/vs/base/common/codiconsLibrary.js.map +1 -1
- package/esm/vs/base/common/paging.js.map +1 -1
- package/esm/vs/base/common/platform.js +1 -0
- package/esm/vs/base/common/platform.js.map +1 -1
- package/esm/vs/base/common/policy.js +40 -1
- package/esm/vs/base/common/policy.js.map +1 -1
- package/esm/vs/base/common/validation.js +157 -0
- package/esm/vs/base/common/validation.js.map +1 -0
- package/esm/vs/editor/browser/controller/editContext/native/screenReaderSupport.js +1 -1
- package/esm/vs/editor/browser/controller/editContext/screenReaderUtils.js +4 -4
- package/esm/vs/editor/browser/controller/editContext/textArea/textAreaEditContext.js +1 -1
- package/esm/vs/editor/browser/coreCommands.js +3 -3
- package/esm/vs/editor/browser/editorExtensions.js +9 -9
- package/esm/vs/editor/browser/gpu/viewGpuContext.js +1 -1
- package/esm/vs/editor/browser/services/hoverService/hoverWidget.js +1 -1
- package/esm/vs/editor/browser/services/hoverService/updatableHoverWidget.js +1 -1
- package/esm/vs/editor/browser/services/inlineCompletionsService.js +4 -4
- package/esm/vs/editor/browser/services/inlineCompletionsService.js.map +1 -1
- package/esm/vs/editor/browser/widget/codeEditor/codeEditorWidget.js +2 -2
- package/esm/vs/editor/browser/widget/diffEditor/commands.js +12 -12
- package/esm/vs/editor/browser/widget/diffEditor/components/accessibleDiffViewer.js +14 -14
- package/esm/vs/editor/browser/widget/diffEditor/components/accessibleDiffViewer.js.map +1 -1
- package/esm/vs/editor/browser/widget/diffEditor/components/diffEditorEditors.js +1 -1
- package/esm/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/copySelection.js +1 -1
- package/esm/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/inlineDiffDeletedCodeMargin.js +7 -7
- package/esm/vs/editor/browser/widget/diffEditor/diffEditor.contribution.js +5 -5
- package/esm/vs/editor/browser/widget/diffEditor/features/hideUnchangedRegionsFeature.js +7 -7
- package/esm/vs/editor/browser/widget/diffEditor/features/movedBlocksLinesFeature.js +2 -2
- package/esm/vs/editor/browser/widget/diffEditor/features/revertButtonsFeature.js +2 -2
- package/esm/vs/editor/browser/widget/diffEditor/registrations.contribution.js +5 -5
- package/esm/vs/editor/browser/widget/multiDiffEditor/colors.js +3 -3
- package/esm/vs/editor/browser/widget/multiDiffEditor/multiDiffEditorWidgetImpl.js +2 -2
- package/esm/vs/editor/common/config/editorConfigurationSchema.js +54 -54
- package/esm/vs/editor/common/config/editorOptions.js +406 -406
- package/esm/vs/editor/common/core/editorColorRegistry.js +68 -68
- package/esm/vs/editor/common/editorContextKeys.js +46 -46
- package/esm/vs/editor/common/languages/modesRegistry.js +1 -1
- package/esm/vs/editor/common/languages.js +66 -56
- package/esm/vs/editor/common/languages.js.map +1 -1
- package/esm/vs/editor/common/model/editStack.js +1 -1
- package/esm/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.js.map +1 -1
- package/esm/vs/editor/common/model/tokens/treeSitter/treeSitterSyntaxTokenBackend.js +1 -1
- package/esm/vs/editor/common/model/tokens/treeSitter/treeSitterSyntaxTokenBackend.js.map +1 -1
- package/esm/vs/editor/common/services/treeSitter/treeSitterLibraryService.js.map +1 -1
- package/esm/vs/editor/common/standaloneStrings.js +10 -10
- package/esm/vs/editor/common/viewLayout/viewLineRenderer.js +2 -2
- package/esm/vs/editor/common/viewModel/viewModelLines.js.map +1 -1
- package/esm/vs/editor/contrib/anchorSelect/browser/anchorSelect.js +6 -6
- package/esm/vs/editor/contrib/bracketMatching/browser/bracketMatching.js +6 -6
- package/esm/vs/editor/contrib/caretOperations/browser/caretOperations.js +2 -2
- package/esm/vs/editor/contrib/caretOperations/browser/transpose.js +1 -1
- package/esm/vs/editor/contrib/clipboard/browser/clipboard.js +17 -17
- package/esm/vs/editor/contrib/codeAction/browser/codeAction.js +1 -1
- package/esm/vs/editor/contrib/codeAction/browser/codeActionCommands.js +29 -29
- package/esm/vs/editor/contrib/codeAction/browser/codeActionContributions.js +3 -3
- package/esm/vs/editor/contrib/codeAction/browser/codeActionController.js +3 -3
- package/esm/vs/editor/contrib/codeAction/browser/codeActionMenu.js +8 -8
- package/esm/vs/editor/contrib/codeAction/browser/lightBulbWidget.js +9 -9
- package/esm/vs/editor/contrib/codelens/browser/codelensController.js +2 -2
- package/esm/vs/editor/contrib/colorPicker/browser/colorPickerParts/colorPickerCloseButton.js +1 -1
- package/esm/vs/editor/contrib/colorPicker/browser/colorPickerParts/colorPickerHeader.js +1 -1
- package/esm/vs/editor/contrib/colorPicker/browser/standaloneColorPicker/standaloneColorPickerActions.js +7 -7
- package/esm/vs/editor/contrib/comment/browser/comment.js +6 -6
- package/esm/vs/editor/contrib/contextmenu/browser/contextmenu.js +10 -10
- package/esm/vs/editor/contrib/cursorUndo/browser/cursorUndo.js +2 -2
- package/esm/vs/editor/contrib/dropOrPasteInto/browser/copyPasteContribution.js +4 -4
- package/esm/vs/editor/contrib/dropOrPasteInto/browser/copyPasteController.js +9 -9
- package/esm/vs/editor/contrib/dropOrPasteInto/browser/defaultProviders.js +8 -8
- package/esm/vs/editor/contrib/dropOrPasteInto/browser/dropIntoEditorController.js +3 -3
- package/esm/vs/editor/contrib/dropOrPasteInto/browser/postEditWidget.js +2 -2
- package/esm/vs/editor/contrib/editorState/browser/keybindingCancellation.js +1 -1
- package/esm/vs/editor/contrib/find/browser/findController.js +16 -16
- package/esm/vs/editor/contrib/find/browser/findWidget.js +26 -26
- package/esm/vs/editor/contrib/folding/browser/folding.js +20 -20
- package/esm/vs/editor/contrib/folding/browser/folding.js.map +1 -1
- package/esm/vs/editor/contrib/folding/browser/foldingDecorations.js +9 -9
- package/esm/vs/editor/contrib/folding/browser/foldingDecorations.js.map +1 -1
- package/esm/vs/editor/contrib/fontZoom/browser/fontZoom.js +3 -3
- package/esm/vs/editor/contrib/format/browser/formatActions.js +2 -2
- package/esm/vs/editor/contrib/gotoError/browser/gotoError.js +8 -8
- package/esm/vs/editor/contrib/gotoError/browser/gotoErrorWidget.js +14 -14
- package/esm/vs/editor/contrib/gotoSymbol/browser/goToCommands.js +39 -39
- package/esm/vs/editor/contrib/gotoSymbol/browser/link/goToDefinitionAtPosition.js +1 -1
- package/esm/vs/editor/contrib/gotoSymbol/browser/peek/referencesController.js +3 -3
- package/esm/vs/editor/contrib/gotoSymbol/browser/peek/referencesTree.js +3 -3
- package/esm/vs/editor/contrib/gotoSymbol/browser/peek/referencesWidget.js +3 -3
- package/esm/vs/editor/contrib/gotoSymbol/browser/referencesModel.js +8 -8
- package/esm/vs/editor/contrib/gotoSymbol/browser/symbolNavigation.js +3 -3
- package/esm/vs/editor/contrib/gpu/browser/gpuActions.js +4 -4
- package/esm/vs/editor/contrib/hover/browser/hoverActionIds.js +2 -2
- package/esm/vs/editor/contrib/hover/browser/hoverActions.js +24 -24
- package/esm/vs/editor/contrib/hover/browser/markdownHoverParticipant.js +9 -9
- package/esm/vs/editor/contrib/hover/browser/markerHoverParticipant.js +5 -5
- package/esm/vs/editor/contrib/inPlaceReplace/browser/inPlaceReplace.js +2 -2
- package/esm/vs/editor/contrib/indentation/browser/indentation.js +20 -20
- package/esm/vs/editor/contrib/inlayHints/browser/inlayHintsHover.js +8 -8
- package/esm/vs/editor/contrib/inlineCompletions/browser/controller/commands.js +63 -52
- package/esm/vs/editor/contrib/inlineCompletions/browser/controller/commands.js.map +1 -1
- package/esm/vs/editor/contrib/inlineCompletions/browser/controller/inlineCompletionContextKeys.js +12 -12
- package/esm/vs/editor/contrib/inlineCompletions/browser/controller/inlineCompletionsController.js +1 -1
- package/esm/vs/editor/contrib/inlineCompletions/browser/hintsWidget/hoverParticipant.js +1 -1
- package/esm/vs/editor/contrib/inlineCompletions/browser/hintsWidget/inlineCompletionsHintsWidget.js +5 -5
- package/esm/vs/editor/contrib/inlineCompletions/browser/inlineCompletions.contribution.js +2 -4
- package/esm/vs/editor/contrib/inlineCompletions/browser/inlineCompletions.contribution.js.map +1 -1
- package/esm/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.js +11 -12
- package/esm/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.js.map +1 -1
- package/esm/vs/editor/contrib/inlineCompletions/browser/model/inlineSuggestionItem.js +4 -4
- package/esm/vs/editor/contrib/inlineCompletions/browser/model/inlineSuggestionItem.js.map +1 -1
- package/esm/vs/editor/contrib/inlineCompletions/browser/model/suggestWidgetAdapter.js.map +1 -1
- package/esm/vs/editor/contrib/inlineCompletions/browser/telemetry.js.map +1 -1
- package/esm/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/components/gutterIndicatorMenu.js +6 -6
- package/esm/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditWithChanges.js +3 -0
- package/esm/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditWithChanges.js.map +1 -1
- package/esm/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsModel.js +1 -1
- package/esm/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsView.js +5 -5
- package/esm/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsView.js.map +1 -1
- package/esm/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/theme.js +20 -20
- package/esm/vs/editor/contrib/insertFinalNewLine/browser/insertFinalNewLine.js +1 -1
- package/esm/vs/editor/contrib/lineSelection/browser/lineSelection.js +1 -1
- package/esm/vs/editor/contrib/linesOperations/browser/linesOperations.js +31 -31
- package/esm/vs/editor/contrib/linkedEditing/browser/linkedEditing.js +2 -2
- package/esm/vs/editor/contrib/links/browser/links.js +10 -10
- package/esm/vs/editor/contrib/message/browser/messageController.js +1 -1
- package/esm/vs/editor/contrib/multicursor/browser/multicursor.js +22 -22
- package/esm/vs/editor/contrib/parameterHints/browser/parameterHints.js +1 -1
- package/esm/vs/editor/contrib/parameterHints/browser/parameterHintsWidget.js +4 -4
- package/esm/vs/editor/contrib/peekView/browser/peekView.js +18 -18
- package/esm/vs/editor/contrib/placeholderText/browser/placeholderText.contribution.js +1 -1
- package/esm/vs/editor/contrib/quickAccess/browser/gotoLineQuickAccess.js +35 -28
- package/esm/vs/editor/contrib/quickAccess/browser/gotoLineQuickAccess.js.map +1 -1
- package/esm/vs/editor/contrib/quickAccess/browser/gotoSymbolQuickAccess.js +32 -32
- package/esm/vs/editor/contrib/readOnlyMessage/browser/contribution.js +2 -2
- package/esm/vs/editor/contrib/rename/browser/rename.js +11 -11
- package/esm/vs/editor/contrib/rename/browser/renameWidget.js +7 -7
- package/esm/vs/editor/contrib/smartSelect/browser/smartSelect.js +4 -4
- package/esm/vs/editor/contrib/snippet/browser/snippetController2.js +4 -4
- package/esm/vs/editor/contrib/snippet/browser/snippetVariables.js +4 -4
- package/esm/vs/editor/contrib/stickyScroll/browser/stickyScrollActions.js +11 -11
- package/esm/vs/editor/contrib/suggest/browser/suggest.js +8 -8
- package/esm/vs/editor/contrib/suggest/browser/suggestController.js +10 -10
- package/esm/vs/editor/contrib/suggest/browser/suggestWidget.js +17 -17
- package/esm/vs/editor/contrib/suggest/browser/suggestWidgetDetails.js +2 -2
- package/esm/vs/editor/contrib/suggest/browser/suggestWidgetRenderer.js +2 -2
- package/esm/vs/editor/contrib/suggest/browser/wordContextKey.js +1 -1
- package/esm/vs/editor/contrib/symbolIcons/browser/symbolIcons.js +33 -33
- package/esm/vs/editor/contrib/toggleTabFocusMode/browser/toggleTabFocusMode.js +4 -4
- package/esm/vs/editor/contrib/tokenization/browser/tokenization.js +1 -1
- package/esm/vs/editor/contrib/unicodeHighlighter/browser/bannerController.js +1 -1
- package/esm/vs/editor/contrib/unicodeHighlighter/browser/unicodeHighlighter.js +24 -24
- package/esm/vs/editor/contrib/unusualLineTerminators/browser/unusualLineTerminators.js +5 -5
- package/esm/vs/editor/contrib/wordHighlighter/browser/highlightDecorations.js +9 -9
- package/esm/vs/editor/contrib/wordHighlighter/browser/wordHighlighter.js +3 -3
- package/esm/vs/editor/contrib/wordOperations/browser/wordOperations.js +1 -1
- package/esm/vs/editor/standalone/browser/standaloneTreeSitterLibraryService.js +2 -12
- package/esm/vs/editor/standalone/browser/standaloneTreeSitterLibraryService.js.map +1 -1
- package/esm/vs/platform/accessibilitySignal/browser/accessibilitySignalService.js +62 -62
- package/esm/vs/platform/action/common/actionCommonCategories.js +6 -6
- package/esm/vs/platform/actionWidget/browser/actionList.js +4 -4
- package/esm/vs/platform/actionWidget/browser/actionWidget.js +7 -7
- package/esm/vs/platform/actions/browser/menuEntryActionViewItem.js +5 -5
- package/esm/vs/platform/actions/browser/toolbar.js +2 -2
- package/esm/vs/platform/actions/common/actions.js +1 -0
- package/esm/vs/platform/actions/common/actions.js.map +1 -1
- package/esm/vs/platform/actions/common/menuService.js +2 -2
- package/esm/vs/platform/configuration/common/configurationRegistry.js +10 -10
- package/esm/vs/platform/contextkey/browser/contextKeyService.js +1 -1
- package/esm/vs/platform/contextkey/common/contextkey.js +9 -9
- package/esm/vs/platform/contextkey/common/contextkeys.js +9 -9
- package/esm/vs/platform/contextkey/common/scanner.js +5 -5
- package/esm/vs/platform/history/browser/contextScopedHistoryWidget.js +1 -1
- package/esm/vs/platform/keybinding/common/abstractKeybindingService.js +4 -4
- package/esm/vs/platform/list/browser/listService.js +27 -27
- package/esm/vs/platform/markers/common/markerService.js +2 -2
- package/esm/vs/platform/markers/common/markers.js +6 -6
- package/esm/vs/platform/quickinput/browser/commandsQuickAccess.js +19 -9
- package/esm/vs/platform/quickinput/browser/commandsQuickAccess.js.map +1 -1
- package/esm/vs/platform/quickinput/browser/helpQuickAccess.js +1 -1
- package/esm/vs/platform/quickinput/browser/quickInput.js +10 -10
- package/esm/vs/platform/quickinput/browser/quickInputActions.js +5 -5
- package/esm/vs/platform/quickinput/browser/quickInputController.js +6 -6
- package/esm/vs/platform/quickinput/browser/quickInputList.js +1 -1
- package/esm/vs/platform/quickinput/browser/quickInputUtils.js +1 -1
- package/esm/vs/platform/quickinput/browser/tree/quickInputTreeAccessibilityProvider.js +2 -2
- package/esm/vs/platform/quickinput/browser/tree/quickInputTreeAccessibilityProvider.js.map +1 -1
- package/esm/vs/platform/theme/common/colorUtils.js +2 -2
- package/esm/vs/platform/theme/common/colors/baseColors.js +17 -17
- package/esm/vs/platform/theme/common/colors/chartsColors.js +8 -8
- package/esm/vs/platform/theme/common/colors/editorColors.js +95 -95
- package/esm/vs/platform/theme/common/colors/inputColors.js +47 -47
- package/esm/vs/platform/theme/common/colors/listColors.js +36 -36
- package/esm/vs/platform/theme/common/colors/menuColors.js +7 -7
- package/esm/vs/platform/theme/common/colors/minimapColors.js +11 -11
- package/esm/vs/platform/theme/common/colors/miscColors.js +15 -15
- package/esm/vs/platform/theme/common/colors/quickpickColors.js +9 -9
- package/esm/vs/platform/theme/common/colors/searchColors.js +3 -3
- package/esm/vs/platform/theme/common/iconRegistry.js +6 -6
- package/esm/vs/platform/undoRedo/common/undoRedoService.js +20 -20
- package/esm/vs/platform/workspace/common/workspace.js +1 -1
- package/package.json +2 -2
- package/version.txt +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts","vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts"],"names":[],"mappings":"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","file":"pieceTreeBase.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from '../../../../base/common/charCode.js';\nimport { Position } from '../../core/position.js';\nimport { Range } from '../../core/range.js';\nimport { FindMatch, ITextSnapshot, SearchData } from '../../model.js';\nimport { NodeColor, SENTINEL, TreeNode, fixInsert, leftest, rbDelete, righttest, updateTreeMetadata } from './rbTreeBase.js';\nimport { Searcher, createFindMatch, isValidMatch } from '../textModelSearch.js';\n\n// const lfRegex = new RegExp(/\\r\\n|\\r|\\n/g);\nconst AverageBufferSize = 65535;\n\nfunction createUintArray(arr: number[]): Uint32Array | Uint16Array {\n\tlet r;\n\tif (arr[arr.length - 1] < 65536) {\n\t\tr = new Uint16Array(arr.length);\n\t} else {\n\t\tr = new Uint32Array(arr.length);\n\t}\n\tr.set(arr, 0);\n\treturn r;\n}\n\nclass LineStarts {\n\tconstructor(\n\t\tpublic readonly lineStarts: Uint32Array | Uint16Array | number[],\n\t\tpublic readonly cr: number,\n\t\tpublic readonly lf: number,\n\t\tpublic readonly crlf: number,\n\t\tpublic readonly isBasicASCII: boolean\n\t) { }\n}\n\nexport function createLineStartsFast(str: string, readonly: boolean = true): Uint32Array | Uint16Array | number[] {\n\tconst r: number[] = [0];\n\tlet rLength = 1;\n\n\tfor (let i = 0, len = str.length; i < len; i++) {\n\t\tconst chr = str.charCodeAt(i);\n\n\t\tif (chr === CharCode.CarriageReturn) {\n\t\t\tif (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) {\n\t\t\t\t// \\r\\n... case\n\t\t\t\tr[rLength++] = i + 2;\n\t\t\t\ti++; // skip \\n\n\t\t\t} else {\n\t\t\t\t// \\r... case\n\t\t\t\tr[rLength++] = i + 1;\n\t\t\t}\n\t\t} else if (chr === CharCode.LineFeed) {\n\t\t\tr[rLength++] = i + 1;\n\t\t}\n\t}\n\tif (readonly) {\n\t\treturn createUintArray(r);\n\t} else {\n\t\treturn r;\n\t}\n}\n\nexport function createLineStarts(r: number[], str: string): LineStarts {\n\tr.length = 0;\n\tr[0] = 0;\n\tlet rLength = 1;\n\tlet cr = 0, lf = 0, crlf = 0;\n\tlet isBasicASCII = true;\n\tfor (let i = 0, len = str.length; i < len; i++) {\n\t\tconst chr = str.charCodeAt(i);\n\n\t\tif (chr === CharCode.CarriageReturn) {\n\t\t\tif (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) {\n\t\t\t\t// \\r\\n... case\n\t\t\t\tcrlf++;\n\t\t\t\tr[rLength++] = i + 2;\n\t\t\t\ti++; // skip \\n\n\t\t\t} else {\n\t\t\t\tcr++;\n\t\t\t\t// \\r... case\n\t\t\t\tr[rLength++] = i + 1;\n\t\t\t}\n\t\t} else if (chr === CharCode.LineFeed) {\n\t\t\tlf++;\n\t\t\tr[rLength++] = i + 1;\n\t\t} else {\n\t\t\tif (isBasicASCII) {\n\t\t\t\tif (chr !== CharCode.Tab && (chr < 32 || chr > 126)) {\n\t\t\t\t\tisBasicASCII = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tconst result = new LineStarts(createUintArray(r), cr, lf, crlf, isBasicASCII);\n\tr.length = 0;\n\n\treturn result;\n}\n\ninterface NodePosition {\n\t/**\n\t * Piece Index\n\t */\n\tnode: TreeNode;\n\t/**\n\t * remainder in current piece.\n\t*/\n\tremainder: number;\n\t/**\n\t * node start offset in document.\n\t */\n\tnodeStartOffset: number;\n}\n\ninterface BufferCursor {\n\t/**\n\t * Line number in current buffer\n\t */\n\tline: number;\n\t/**\n\t * Column number in current buffer\n\t */\n\tcolumn: number;\n}\n\nexport class Piece {\n\treadonly bufferIndex: number;\n\treadonly start: BufferCursor;\n\treadonly end: BufferCursor;\n\treadonly length: number;\n\treadonly lineFeedCnt: number;\n\n\tconstructor(bufferIndex: number, start: BufferCursor, end: BufferCursor, lineFeedCnt: number, length: number) {\n\t\tthis.bufferIndex = bufferIndex;\n\t\tthis.start = start;\n\t\tthis.end = end;\n\t\tthis.lineFeedCnt = lineFeedCnt;\n\t\tthis.length = length;\n\t}\n}\n\nexport class StringBuffer {\n\tbuffer: string;\n\tlineStarts: Uint32Array | Uint16Array | number[];\n\n\tconstructor(buffer: string, lineStarts: Uint32Array | Uint16Array | number[]) {\n\t\tthis.buffer = buffer;\n\t\tthis.lineStarts = lineStarts;\n\t}\n}\n\n/**\n * Readonly snapshot for piece tree.\n * In a real multiple thread environment, to make snapshot reading always work correctly, we need to\n * 1. Make TreeNode.piece immutable, then reading and writing can run in parallel.\n * 2. TreeNode/Buffers normalization should not happen during snapshot reading.\n */\nclass PieceTreeSnapshot implements ITextSnapshot {\n\tprivate readonly _pieces: Piece[];\n\tprivate _index: number;\n\tprivate readonly _tree: PieceTreeBase;\n\tprivate readonly _BOM: string;\n\n\tconstructor(tree: PieceTreeBase, BOM: string) {\n\t\tthis._pieces = [];\n\t\tthis._tree = tree;\n\t\tthis._BOM = BOM;\n\t\tthis._index = 0;\n\t\tif (tree.root !== SENTINEL) {\n\t\t\ttree.iterate(tree.root, node => {\n\t\t\t\tif (node !== SENTINEL) {\n\t\t\t\t\tthis._pieces.push(node.piece);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t});\n\t\t}\n\t}\n\n\tread(): string | null {\n\t\tif (this._pieces.length === 0) {\n\t\t\tif (this._index === 0) {\n\t\t\t\tthis._index++;\n\t\t\t\treturn this._BOM;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tif (this._index > this._pieces.length - 1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (this._index === 0) {\n\t\t\treturn this._BOM + this._tree.getPieceContent(this._pieces[this._index++]);\n\t\t}\n\t\treturn this._tree.getPieceContent(this._pieces[this._index++]);\n\t}\n}\n\ninterface CacheEntry {\n\tnode: TreeNode;\n\tnodeStartOffset: number;\n\tnodeStartLineNumber?: number;\n}\n\nclass PieceTreeSearchCache {\n\tprivate readonly _limit: number;\n\tprivate _cache: CacheEntry[];\n\n\tconstructor(limit: number) {\n\t\tthis._limit = limit;\n\t\tthis._cache = [];\n\t}\n\n\tpublic get(offset: number): CacheEntry | null {\n\t\tfor (let i = this._cache.length - 1; i >= 0; i--) {\n\t\t\tconst nodePos = this._cache[i];\n\t\t\tif (nodePos.nodeStartOffset <= offset && nodePos.nodeStartOffset + nodePos.node.piece.length >= offset) {\n\t\t\t\treturn nodePos;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic get2(lineNumber: number): { node: TreeNode; nodeStartOffset: number; nodeStartLineNumber: number } | null {\n\t\tfor (let i = this._cache.length - 1; i >= 0; i--) {\n\t\t\tconst nodePos = this._cache[i];\n\t\t\tif (nodePos.nodeStartLineNumber && nodePos.nodeStartLineNumber < lineNumber && nodePos.nodeStartLineNumber + nodePos.node.piece.lineFeedCnt >= lineNumber) {\n\t\t\t\treturn <{ node: TreeNode; nodeStartOffset: number; nodeStartLineNumber: number }>nodePos;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic set(nodePosition: CacheEntry) {\n\t\tif (this._cache.length >= this._limit) {\n\t\t\tthis._cache.shift();\n\t\t}\n\t\tthis._cache.push(nodePosition);\n\t}\n\n\tpublic validate(offset: number) {\n\t\tlet hasInvalidVal = false;\n\t\tconst tmp: Array<CacheEntry | null> = this._cache;\n\t\tfor (let i = 0; i < tmp.length; i++) {\n\t\t\tconst nodePos = tmp[i]!;\n\t\t\tif (nodePos.node.parent === null || nodePos.nodeStartOffset >= offset) {\n\t\t\t\ttmp[i] = null;\n\t\t\t\thasInvalidVal = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif (hasInvalidVal) {\n\t\t\tconst newArr: CacheEntry[] = [];\n\t\t\tfor (const entry of tmp) {\n\t\t\t\tif (entry !== null) {\n\t\t\t\t\tnewArr.push(entry);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._cache = newArr;\n\t\t}\n\t}\n}\n\nexport class PieceTreeBase {\n\troot!: TreeNode;\n\tprotected _buffers!: StringBuffer[]; // 0 is change buffer, others are readonly original buffer.\n\tprotected _lineCnt!: number;\n\tprotected _length!: number;\n\tprotected _EOL!: '\\r\\n' | '\\n';\n\tprotected _EOLLength!: number;\n\tprotected _EOLNormalized!: boolean;\n\tprivate _lastChangeBufferPos!: BufferCursor;\n\tprivate _searchCache!: PieceTreeSearchCache;\n\tprivate _lastVisitedLine!: { lineNumber: number; value: string };\n\n\tconstructor(chunks: StringBuffer[], eol: '\\r\\n' | '\\n', eolNormalized: boolean) {\n\t\tthis.create(chunks, eol, eolNormalized);\n\t}\n\n\tcreate(chunks: StringBuffer[], eol: '\\r\\n' | '\\n', eolNormalized: boolean) {\n\t\tthis._buffers = [\n\t\t\tnew StringBuffer('', [0])\n\t\t];\n\t\tthis._lastChangeBufferPos = { line: 0, column: 0 };\n\t\tthis.root = SENTINEL;\n\t\tthis._lineCnt = 1;\n\t\tthis._length = 0;\n\t\tthis._EOL = eol;\n\t\tthis._EOLLength = eol.length;\n\t\tthis._EOLNormalized = eolNormalized;\n\n\t\tlet lastNode: TreeNode | null = null;\n\t\tfor (let i = 0, len = chunks.length; i < len; i++) {\n\t\t\tif (chunks[i].buffer.length > 0) {\n\t\t\t\tif (!chunks[i].lineStarts) {\n\t\t\t\t\tchunks[i].lineStarts = createLineStartsFast(chunks[i].buffer);\n\t\t\t\t}\n\n\t\t\t\tconst piece = new Piece(\n\t\t\t\t\ti + 1,\n\t\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t\t{ line: chunks[i].lineStarts.length - 1, column: chunks[i].buffer.length - chunks[i].lineStarts[chunks[i].lineStarts.length - 1] },\n\t\t\t\t\tchunks[i].lineStarts.length - 1,\n\t\t\t\t\tchunks[i].buffer.length\n\t\t\t\t);\n\t\t\t\tthis._buffers.push(chunks[i]);\n\t\t\t\tlastNode = this.rbInsertRight(lastNode, piece);\n\t\t\t}\n\t\t}\n\n\t\tthis._searchCache = new PieceTreeSearchCache(1);\n\t\tthis._lastVisitedLine = { lineNumber: 0, value: '' };\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tnormalizeEOL(eol: '\\r\\n' | '\\n') {\n\t\tconst averageBufferSize = AverageBufferSize;\n\t\tconst min = averageBufferSize - Math.floor(averageBufferSize / 3);\n\t\tconst max = min * 2;\n\n\t\tlet tempChunk = '';\n\t\tlet tempChunkLen = 0;\n\t\tconst chunks: StringBuffer[] = [];\n\n\t\tthis.iterate(this.root, node => {\n\t\t\tconst str = this.getNodeContent(node);\n\t\t\tconst len = str.length;\n\t\t\tif (tempChunkLen <= min || tempChunkLen + len < max) {\n\t\t\t\ttempChunk += str;\n\t\t\t\ttempChunkLen += len;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// flush anyways\n\t\t\tconst text = tempChunk.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\tchunks.push(new StringBuffer(text, createLineStartsFast(text)));\n\t\t\ttempChunk = str;\n\t\t\ttempChunkLen = len;\n\t\t\treturn true;\n\t\t});\n\n\t\tif (tempChunkLen > 0) {\n\t\t\tconst text = tempChunk.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\tchunks.push(new StringBuffer(text, createLineStartsFast(text)));\n\t\t}\n\n\t\tthis.create(chunks, eol, true);\n\t}\n\n\t// #region Buffer API\n\tpublic getEOL(): '\\r\\n' | '\\n' {\n\t\treturn this._EOL;\n\t}\n\n\tpublic setEOL(newEOL: '\\r\\n' | '\\n'): void {\n\t\tthis._EOL = newEOL;\n\t\tthis._EOLLength = this._EOL.length;\n\t\tthis.normalizeEOL(newEOL);\n\t}\n\n\tpublic createSnapshot(BOM: string): ITextSnapshot {\n\t\treturn new PieceTreeSnapshot(this, BOM);\n\t}\n\n\tpublic getOffsetAt(lineNumber: number, column: number): number {\n\t\tlet leftLen = 0; // inorder\n\n\t\tlet x = this.root;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.left !== SENTINEL && x.lf_left + 1 >= lineNumber) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt + 1 >= lineNumber) {\n\t\t\t\tleftLen += x.size_left;\n\t\t\t\t// lineNumber >= 2\n\t\t\t\tconst accumualtedValInCurrentIndex = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\treturn leftLen += accumualtedValInCurrentIndex + column - 1;\n\t\t\t} else {\n\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\tleftLen += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\treturn leftLen;\n\t}\n\n\tpublic getPositionAt(offset: number): Position {\n\t\toffset = Math.floor(offset);\n\t\toffset = Math.max(0, offset);\n\n\t\tlet x = this.root;\n\t\tlet lfCnt = 0;\n\t\tconst originalOffset = offset;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.size_left !== 0 && x.size_left >= offset) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.size_left + x.piece.length >= offset) {\n\t\t\t\tconst out = this.getIndexOf(x, offset - x.size_left);\n\n\t\t\t\tlfCnt += x.lf_left + out.index;\n\n\t\t\t\tif (out.index === 0) {\n\t\t\t\t\tconst lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);\n\t\t\t\t\tconst column = originalOffset - lineStartOffset;\n\t\t\t\t\treturn new Position(lfCnt + 1, column + 1);\n\t\t\t\t}\n\n\t\t\t\treturn new Position(lfCnt + 1, out.remainder + 1);\n\t\t\t} else {\n\t\t\t\toffset -= x.size_left + x.piece.length;\n\t\t\t\tlfCnt += x.lf_left + x.piece.lineFeedCnt;\n\n\t\t\t\tif (x.right === SENTINEL) {\n\t\t\t\t\t// last node\n\t\t\t\t\tconst lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);\n\t\t\t\t\tconst column = originalOffset - offset - lineStartOffset;\n\t\t\t\t\treturn new Position(lfCnt + 1, column + 1);\n\t\t\t\t} else {\n\t\t\t\t\tx = x.right;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn new Position(1, 1);\n\t}\n\n\tpublic getValueInRange(range: Range, eol?: string): string {\n\t\tif (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst startPosition = this.nodeAt2(range.startLineNumber, range.startColumn);\n\t\tconst endPosition = this.nodeAt2(range.endLineNumber, range.endColumn);\n\n\t\tconst value = this.getValueInRange2(startPosition, endPosition);\n\t\tif (eol) {\n\t\t\tif (eol !== this._EOL || !this._EOLNormalized) {\n\t\t\t\treturn value.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\t}\n\n\t\t\tif (eol === this.getEOL() && this._EOLNormalized) {\n\t\t\t\tif (eol === '\\r\\n') {\n\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t}\n\t\t\treturn value.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t}\n\t\treturn value;\n\t}\n\n\tpublic getValueInRange2(startPosition: NodePosition, endPosition: NodePosition): string {\n\t\tif (startPosition.node === endPosition.node) {\n\t\t\tconst node = startPosition.node;\n\t\t\tconst buffer = this._buffers[node.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);\n\t\t\treturn buffer.substring(startOffset + startPosition.remainder, startOffset + endPosition.remainder);\n\t\t}\n\n\t\tlet x = startPosition.node;\n\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\tlet ret = buffer.substring(startOffset + startPosition.remainder, startOffset + x.piece.length);\n\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\tif (x === endPosition.node) {\n\t\t\t\tret += buffer.substring(startOffset, startOffset + endPosition.remainder);\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tret += buffer.substr(startOffset, x.piece.length);\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tpublic getLinesContent(): string[] {\n\t\tconst lines: string[] = [];\n\t\tlet linesLength = 0;\n\t\tlet currentLine = '';\n\t\tlet danglingCR = false;\n\n\t\tthis.iterate(this.root, node => {\n\t\t\tif (node === SENTINEL) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst piece = node.piece;\n\t\t\tlet pieceLength = piece.length;\n\t\t\tif (pieceLength === 0) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[piece.bufferIndex].buffer;\n\t\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\n\t\t\tconst pieceStartLine = piece.start.line;\n\t\t\tconst pieceEndLine = piece.end.line;\n\t\t\tlet pieceStartOffset = lineStarts[pieceStartLine] + piece.start.column;\n\n\t\t\tif (danglingCR) {\n\t\t\t\tif (buffer.charCodeAt(pieceStartOffset) === CharCode.LineFeed) {\n\t\t\t\t\t// pretend the \\n was in the previous piece..\n\t\t\t\t\tpieceStartOffset++;\n\t\t\t\t\tpieceLength--;\n\t\t\t\t}\n\t\t\t\tlines[linesLength++] = currentLine;\n\t\t\t\tcurrentLine = '';\n\t\t\t\tdanglingCR = false;\n\t\t\t\tif (pieceLength === 0) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (pieceStartLine === pieceEndLine) {\n\t\t\t\t// this piece has no new lines\n\t\t\t\tif (!this._EOLNormalized && buffer.charCodeAt(pieceStartOffset + pieceLength - 1) === CharCode.CarriageReturn) {\n\t\t\t\t\tdanglingCR = true;\n\t\t\t\t\tcurrentLine += buffer.substr(pieceStartOffset, pieceLength - 1);\n\t\t\t\t} else {\n\t\t\t\t\tcurrentLine += buffer.substr(pieceStartOffset, pieceLength);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// add the text before the first line start in this piece\n\t\t\tcurrentLine += (\n\t\t\t\tthis._EOLNormalized\n\t\t\t\t\t? buffer.substring(pieceStartOffset, Math.max(pieceStartOffset, lineStarts[pieceStartLine + 1] - this._EOLLength))\n\t\t\t\t\t: buffer.substring(pieceStartOffset, lineStarts[pieceStartLine + 1]).replace(/(\\r\\n|\\r|\\n)$/, '')\n\t\t\t);\n\t\t\tlines[linesLength++] = currentLine;\n\n\t\t\tfor (let line = pieceStartLine + 1; line < pieceEndLine; line++) {\n\t\t\t\tcurrentLine = (\n\t\t\t\t\tthis._EOLNormalized\n\t\t\t\t\t\t? buffer.substring(lineStarts[line], lineStarts[line + 1] - this._EOLLength)\n\t\t\t\t\t\t: buffer.substring(lineStarts[line], lineStarts[line + 1]).replace(/(\\r\\n|\\r|\\n)$/, '')\n\t\t\t\t);\n\t\t\t\tlines[linesLength++] = currentLine;\n\t\t\t}\n\n\t\t\tif (!this._EOLNormalized && buffer.charCodeAt(lineStarts[pieceEndLine] + piece.end.column - 1) === CharCode.CarriageReturn) {\n\t\t\t\tdanglingCR = true;\n\t\t\t\tif (piece.end.column === 0) {\n\t\t\t\t\t// The last line ended with a \\r, let's undo the push, it will be pushed by next iteration\n\t\t\t\t\tlinesLength--;\n\t\t\t\t} else {\n\t\t\t\t\tcurrentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column - 1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcurrentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column);\n\t\t\t}\n\n\t\t\treturn true;\n\t\t});\n\n\t\tif (danglingCR) {\n\t\t\tlines[linesLength++] = currentLine;\n\t\t\tcurrentLine = '';\n\t\t}\n\n\t\tlines[linesLength++] = currentLine;\n\t\treturn lines;\n\t}\n\n\tpublic getLength(): number {\n\t\treturn this._length;\n\t}\n\n\tpublic getLineCount(): number {\n\t\treturn this._lineCnt;\n\t}\n\n\tpublic getLineContent(lineNumber: number): string {\n\t\tif (this._lastVisitedLine.lineNumber === lineNumber) {\n\t\t\treturn this._lastVisitedLine.value;\n\t\t}\n\n\t\tthis._lastVisitedLine.lineNumber = lineNumber;\n\n\t\tif (lineNumber === this._lineCnt) {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber);\n\t\t} else if (this._EOLNormalized) {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber, this._EOLLength);\n\t\t} else {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber).replace(/(\\r\\n|\\r|\\n)$/, '');\n\t\t}\n\n\t\treturn this._lastVisitedLine.value;\n\t}\n\n\tprivate _getCharCode(nodePos: NodePosition): number {\n\t\tif (nodePos.remainder === nodePos.node.piece.length) {\n\t\t\t// the char we want to fetch is at the head of next node.\n\t\t\tconst matchingNode = nodePos.node.next();\n\t\t\tif (!matchingNode) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[matchingNode.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);\n\t\t\treturn buffer.buffer.charCodeAt(startOffset);\n\t\t} else {\n\t\t\tconst buffer = this._buffers[nodePos.node.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);\n\t\t\tconst targetOffset = startOffset + nodePos.remainder;\n\n\t\t\treturn buffer.buffer.charCodeAt(targetOffset);\n\t\t}\n\t}\n\n\tpublic getLineCharCode(lineNumber: number, index: number): number {\n\t\tconst nodePos = this.nodeAt2(lineNumber, index + 1);\n\t\treturn this._getCharCode(nodePos);\n\t}\n\n\tpublic getLineLength(lineNumber: number): number {\n\t\tif (lineNumber === this.getLineCount()) {\n\t\t\tconst startOffset = this.getOffsetAt(lineNumber, 1);\n\t\t\treturn this.getLength() - startOffset;\n\t\t}\n\t\treturn this.getOffsetAt(lineNumber + 1, 1) - this.getOffsetAt(lineNumber, 1) - this._EOLLength;\n\t}\n\n\tpublic getNearestChunk(offset: number): string {\n\t\tconst nodePos = this.nodeAt(offset);\n\t\tif (nodePos.remainder === nodePos.node.piece.length) {\n\t\t\t// the offset is at the head of next node.\n\t\t\tconst matchingNode = nodePos.node.next();\n\t\t\tif (!matchingNode || matchingNode === SENTINEL) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[matchingNode.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);\n\t\t\treturn buffer.buffer.substring(startOffset, startOffset + matchingNode.piece.length);\n\t\t} else {\n\t\t\tconst buffer = this._buffers[nodePos.node.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);\n\t\t\tconst targetOffset = startOffset + nodePos.remainder;\n\t\t\tconst targetEnd = startOffset + nodePos.node.piece.length;\n\t\t\treturn buffer.buffer.substring(targetOffset, targetEnd);\n\t\t}\n\t}\n\n\tpublic findMatchesInNode(node: TreeNode, searcher: Searcher, startLineNumber: number, startColumn: number, startCursor: BufferCursor, endCursor: BufferCursor, searchData: SearchData, captureMatches: boolean, limitResultCount: number, resultLen: number, result: FindMatch[]) {\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst startOffsetInBuffer = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);\n\t\tconst start = this.offsetInBuffer(node.piece.bufferIndex, startCursor);\n\t\tconst end = this.offsetInBuffer(node.piece.bufferIndex, endCursor);\n\n\t\tlet m: RegExpExecArray | null;\n\t\t// Reset regex to search from the beginning\n\t\tconst ret: BufferCursor = { line: 0, column: 0 };\n\t\tlet searchText: string;\n\t\tlet offsetInBuffer: (offset: number) => number;\n\n\t\tif (searcher._wordSeparators) {\n\t\t\tsearchText = buffer.buffer.substring(start, end);\n\t\t\toffsetInBuffer = (offset: number) => offset + start;\n\t\t\tsearcher.reset(0);\n\t\t} else {\n\t\t\tsearchText = buffer.buffer;\n\t\t\toffsetInBuffer = (offset: number) => offset;\n\t\t\tsearcher.reset(start);\n\t\t}\n\n\t\tdo {\n\t\t\tm = searcher.next(searchText);\n\n\t\t\tif (m) {\n\t\t\t\tif (offsetInBuffer(m.index) >= end) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t\tthis.positionInBuffer(node, offsetInBuffer(m.index) - startOffsetInBuffer, ret);\n\t\t\t\tconst lineFeedCnt = this.getLineFeedCnt(node.piece.bufferIndex, startCursor, ret);\n\t\t\t\tconst retStartColumn = ret.line === startCursor.line ? ret.column - startCursor.column + startColumn : ret.column + 1;\n\t\t\t\tconst retEndColumn = retStartColumn + m[0].length;\n\t\t\t\tresult[resultLen++] = createFindMatch(new Range(startLineNumber + lineFeedCnt, retStartColumn, startLineNumber + lineFeedCnt, retEndColumn), m, captureMatches);\n\n\t\t\t\tif (offsetInBuffer(m.index) + m[0].length >= end) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} while (m);\n\n\t\treturn resultLen;\n\t}\n\n\tpublic findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[] {\n\t\tconst result: FindMatch[] = [];\n\t\tlet resultLen = 0;\n\t\tconst searcher = new Searcher(searchData.wordSeparators, searchData.regex);\n\n\t\tlet startPosition = this.nodeAt2(searchRange.startLineNumber, searchRange.startColumn);\n\t\tif (startPosition === null) {\n\t\t\treturn [];\n\t\t}\n\t\tconst endPosition = this.nodeAt2(searchRange.endLineNumber, searchRange.endColumn);\n\t\tif (endPosition === null) {\n\t\t\treturn [];\n\t\t}\n\t\tlet start = this.positionInBuffer(startPosition.node, startPosition.remainder);\n\t\tconst end = this.positionInBuffer(endPosition.node, endPosition.remainder);\n\n\t\tif (startPosition.node === endPosition.node) {\n\t\t\tthis.findMatchesInNode(startPosition.node, searcher, searchRange.startLineNumber, searchRange.startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);\n\t\t\treturn result;\n\t\t}\n\n\t\tlet startLineNumber = searchRange.startLineNumber;\n\n\t\tlet currentNode = startPosition.node;\n\t\twhile (currentNode !== endPosition.node) {\n\t\t\tconst lineBreakCnt = this.getLineFeedCnt(currentNode.piece.bufferIndex, start, currentNode.piece.end);\n\n\t\t\tif (lineBreakCnt >= 1) {\n\t\t\t\t// last line break position\n\t\t\t\tconst lineStarts = this._buffers[currentNode.piece.bufferIndex].lineStarts;\n\t\t\t\tconst startOffsetInBuffer = this.offsetInBuffer(currentNode.piece.bufferIndex, currentNode.piece.start);\n\t\t\t\tconst nextLineStartOffset = lineStarts[start.line + lineBreakCnt];\n\t\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;\n\t\t\t\tresultLen = this.findMatchesInNode(currentNode, searcher, startLineNumber, startColumn, start, this.positionInBuffer(currentNode, nextLineStartOffset - startOffsetInBuffer), searchData, captureMatches, limitResultCount, resultLen, result);\n\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\tstartLineNumber += lineBreakCnt;\n\t\t\t}\n\n\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;\n\t\t\t// search for the remaining content\n\t\t\tif (startLineNumber === searchRange.endLineNumber) {\n\t\t\t\tconst text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);\n\t\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, this.getLineContent(startLineNumber).substr(startColumn), startLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\n\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tstartLineNumber++;\n\t\t\tstartPosition = this.nodeAt2(startLineNumber, 1);\n\t\t\tcurrentNode = startPosition.node;\n\t\t\tstart = this.positionInBuffer(startPosition.node, startPosition.remainder);\n\t\t}\n\n\t\tif (startLineNumber === searchRange.endLineNumber) {\n\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;\n\t\t\tconst text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);\n\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\t\t\treturn result;\n\t\t}\n\n\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;\n\t\tresultLen = this.findMatchesInNode(endPosition.node, searcher, startLineNumber, startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);\n\t\treturn result;\n\t}\n\n\tprivate _findMatchesInLine(searchData: SearchData, searcher: Searcher, text: string, lineNumber: number, deltaOffset: number, resultLen: number, result: FindMatch[], captureMatches: boolean, limitResultCount: number): number {\n\t\tconst wordSeparators = searchData.wordSeparators;\n\t\tif (!captureMatches && searchData.simpleSearch) {\n\t\t\tconst searchString = searchData.simpleSearch;\n\t\t\tconst searchStringLen = searchString.length;\n\t\t\tconst textLength = text.length;\n\n\t\t\tlet lastMatchIndex = -searchStringLen;\n\t\t\twhile ((lastMatchIndex = text.indexOf(searchString, lastMatchIndex + searchStringLen)) !== -1) {\n\t\t\t\tif (!wordSeparators || isValidMatch(wordSeparators, text, textLength, lastMatchIndex, searchStringLen)) {\n\t\t\t\t\tresult[resultLen++] = new FindMatch(new Range(lineNumber, lastMatchIndex + 1 + deltaOffset, lineNumber, lastMatchIndex + 1 + searchStringLen + deltaOffset), null);\n\t\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\t\treturn resultLen;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn resultLen;\n\t\t}\n\n\t\tlet m: RegExpExecArray | null;\n\t\t// Reset regex to search from the beginning\n\t\tsearcher.reset(0);\n\t\tdo {\n\t\t\tm = searcher.next(text);\n\t\t\tif (m) {\n\t\t\t\tresult[resultLen++] = createFindMatch(new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset), m, captureMatches);\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (m);\n\t\treturn resultLen;\n\t}\n\n\t// #endregion\n\n\t// #region Piece Table\n\tpublic insert(offset: number, value: string, eolNormalized: boolean = false): void {\n\t\tthis._EOLNormalized = this._EOLNormalized && eolNormalized;\n\t\tthis._lastVisitedLine.lineNumber = 0;\n\t\tthis._lastVisitedLine.value = '';\n\n\t\tif (this.root !== SENTINEL) {\n\t\t\tconst { node, remainder, nodeStartOffset } = this.nodeAt(offset);\n\t\t\tconst piece = node.piece;\n\t\t\tconst bufferIndex = piece.bufferIndex;\n\t\t\tconst insertPosInBuffer = this.positionInBuffer(node, remainder);\n\t\t\tif (node.piece.bufferIndex === 0 &&\n\t\t\t\tpiece.end.line === this._lastChangeBufferPos.line &&\n\t\t\t\tpiece.end.column === this._lastChangeBufferPos.column &&\n\t\t\t\t(nodeStartOffset + piece.length === offset) &&\n\t\t\t\tvalue.length < AverageBufferSize\n\t\t\t) {\n\t\t\t\t// changed buffer\n\t\t\t\tthis.appendToNode(node, value);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (nodeStartOffset === offset) {\n\t\t\t\tthis.insertContentToNodeLeft(value, node);\n\t\t\t\tthis._searchCache.validate(offset);\n\t\t\t} else if (nodeStartOffset + node.piece.length > offset) {\n\t\t\t\t// we are inserting into the middle of a node.\n\t\t\t\tconst nodesToDel: TreeNode[] = [];\n\t\t\t\tlet newRightPiece = new Piece(\n\t\t\t\t\tpiece.bufferIndex,\n\t\t\t\t\tinsertPosInBuffer,\n\t\t\t\t\tpiece.end,\n\t\t\t\t\tthis.getLineFeedCnt(piece.bufferIndex, insertPosInBuffer, piece.end),\n\t\t\t\t\tthis.offsetInBuffer(bufferIndex, piece.end) - this.offsetInBuffer(bufferIndex, insertPosInBuffer)\n\t\t\t\t);\n\n\t\t\t\tif (this.shouldCheckCRLF() && this.endWithCR(value)) {\n\t\t\t\t\tconst headOfRight = this.nodeCharCodeAt(node, remainder);\n\n\t\t\t\t\tif (headOfRight === 10 /** \\n */) {\n\t\t\t\t\t\tconst newStart: BufferCursor = { line: newRightPiece.start.line + 1, column: 0 };\n\t\t\t\t\t\tnewRightPiece = new Piece(\n\t\t\t\t\t\t\tnewRightPiece.bufferIndex,\n\t\t\t\t\t\t\tnewStart,\n\t\t\t\t\t\t\tnewRightPiece.end,\n\t\t\t\t\t\t\tthis.getLineFeedCnt(newRightPiece.bufferIndex, newStart, newRightPiece.end),\n\t\t\t\t\t\t\tnewRightPiece.length - 1\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tvalue += '\\n';\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// reuse node for content before insertion point.\n\t\t\t\tif (this.shouldCheckCRLF() && this.startWithLF(value)) {\n\t\t\t\t\tconst tailOfLeft = this.nodeCharCodeAt(node, remainder - 1);\n\t\t\t\t\tif (tailOfLeft === 13 /** \\r */) {\n\t\t\t\t\t\tconst previousPos = this.positionInBuffer(node, remainder - 1);\n\t\t\t\t\t\tthis.deleteNodeTail(node, previousPos);\n\t\t\t\t\t\tvalue = '\\r' + value;\n\n\t\t\t\t\t\tif (node.piece.length === 0) {\n\t\t\t\t\t\t\tnodesToDel.push(node);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.deleteNodeTail(node, insertPosInBuffer);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.deleteNodeTail(node, insertPosInBuffer);\n\t\t\t\t}\n\n\t\t\t\tconst newPieces = this.createNewPieces(value);\n\t\t\t\tif (newRightPiece.length > 0) {\n\t\t\t\t\tthis.rbInsertRight(node, newRightPiece);\n\t\t\t\t}\n\n\t\t\t\tlet tmpNode = node;\n\t\t\t\tfor (let k = 0; k < newPieces.length; k++) {\n\t\t\t\t\ttmpNode = this.rbInsertRight(tmpNode, newPieces[k]);\n\t\t\t\t}\n\t\t\t\tthis.deleteNodes(nodesToDel);\n\t\t\t} else {\n\t\t\t\tthis.insertContentToNodeRight(value, node);\n\t\t\t}\n\t\t} else {\n\t\t\t// insert new node\n\t\t\tconst pieces = this.createNewPieces(value);\n\t\t\tlet node = this.rbInsertLeft(null, pieces[0]);\n\n\t\t\tfor (let k = 1; k < pieces.length; k++) {\n\t\t\t\tnode = this.rbInsertRight(node, pieces[k]);\n\t\t\t}\n\t\t}\n\n\t\t// todo, this is too brutal. Total line feed count should be updated the same way as lf_left.\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tpublic delete(offset: number, cnt: number): void {\n\t\tthis._lastVisitedLine.lineNumber = 0;\n\t\tthis._lastVisitedLine.value = '';\n\n\t\tif (cnt <= 0 || this.root === SENTINEL) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst startPosition = this.nodeAt(offset);\n\t\tconst endPosition = this.nodeAt(offset + cnt);\n\t\tconst startNode = startPosition.node;\n\t\tconst endNode = endPosition.node;\n\n\t\tif (startNode === endNode) {\n\t\t\tconst startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);\n\t\t\tconst endSplitPosInBuffer = this.positionInBuffer(startNode, endPosition.remainder);\n\n\t\t\tif (startPosition.nodeStartOffset === offset) {\n\t\t\t\tif (cnt === startNode.piece.length) { // delete node\n\t\t\t\t\tconst next = startNode.next();\n\t\t\t\t\trbDelete(this, startNode);\n\t\t\t\t\tthis.validateCRLFWithPrevNode(next);\n\t\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.deleteNodeHead(startNode, endSplitPosInBuffer);\n\t\t\t\tthis._searchCache.validate(offset);\n\t\t\t\tthis.validateCRLFWithPrevNode(startNode);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (startPosition.nodeStartOffset + startNode.piece.length === offset + cnt) {\n\t\t\t\tthis.deleteNodeTail(startNode, startSplitPosInBuffer);\n\t\t\t\tthis.validateCRLFWithNextNode(startNode);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// delete content in the middle, this node will be splitted to nodes\n\t\t\tthis.shrinkNode(startNode, startSplitPosInBuffer, endSplitPosInBuffer);\n\t\t\tthis.computeBufferMetadata();\n\t\t\treturn;\n\t\t}\n\n\t\tconst nodesToDel: TreeNode[] = [];\n\n\t\tconst startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);\n\t\tthis.deleteNodeTail(startNode, startSplitPosInBuffer);\n\t\tthis._searchCache.validate(offset);\n\t\tif (startNode.piece.length === 0) {\n\t\t\tnodesToDel.push(startNode);\n\t\t}\n\n\t\t// update last touched node\n\t\tconst endSplitPosInBuffer = this.positionInBuffer(endNode, endPosition.remainder);\n\t\tthis.deleteNodeHead(endNode, endSplitPosInBuffer);\n\t\tif (endNode.piece.length === 0) {\n\t\t\tnodesToDel.push(endNode);\n\t\t}\n\n\t\t// delete nodes in between\n\t\tconst secondNode = startNode.next();\n\t\tfor (let node = secondNode; node !== SENTINEL && node !== endNode; node = node.next()) {\n\t\t\tnodesToDel.push(node);\n\t\t}\n\n\t\tconst prev = startNode.piece.length === 0 ? startNode.prev() : startNode;\n\t\tthis.deleteNodes(nodesToDel);\n\t\tthis.validateCRLFWithNextNode(prev);\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tprivate insertContentToNodeLeft(value: string, node: TreeNode) {\n\t\t// we are inserting content to the beginning of node\n\t\tconst nodesToDel: TreeNode[] = [];\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(value) && this.startWithLF(node)) {\n\t\t\t// move `\\n` to new node.\n\n\t\t\tconst piece = node.piece;\n\t\t\tconst newStart: BufferCursor = { line: piece.start.line + 1, column: 0 };\n\t\t\tconst nPiece = new Piece(\n\t\t\t\tpiece.bufferIndex,\n\t\t\t\tnewStart,\n\t\t\t\tpiece.end,\n\t\t\t\tthis.getLineFeedCnt(piece.bufferIndex, newStart, piece.end),\n\t\t\t\tpiece.length - 1\n\t\t\t);\n\n\t\t\tnode.piece = nPiece;\n\n\t\t\tvalue += '\\n';\n\t\t\tupdateTreeMetadata(this, node, -1, -1);\n\n\t\t\tif (node.piece.length === 0) {\n\t\t\t\tnodesToDel.push(node);\n\t\t\t}\n\t\t}\n\n\t\tconst newPieces = this.createNewPieces(value);\n\t\tlet newNode = this.rbInsertLeft(node, newPieces[newPieces.length - 1]);\n\t\tfor (let k = newPieces.length - 2; k >= 0; k--) {\n\t\t\tnewNode = this.rbInsertLeft(newNode, newPieces[k]);\n\t\t}\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t\tthis.deleteNodes(nodesToDel);\n\t}\n\n\tprivate insertContentToNodeRight(value: string, node: TreeNode) {\n\t\t// we are inserting to the right of this node.\n\t\tif (this.adjustCarriageReturnFromNext(value, node)) {\n\t\t\t// move \\n to the new node.\n\t\t\tvalue += '\\n';\n\t\t}\n\n\t\tconst newPieces = this.createNewPieces(value);\n\t\tconst newNode = this.rbInsertRight(node, newPieces[0]);\n\t\tlet tmpNode = newNode;\n\n\t\tfor (let k = 1; k < newPieces.length; k++) {\n\t\t\ttmpNode = this.rbInsertRight(tmpNode, newPieces[k]);\n\t\t}\n\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t}\n\n\tprivate positionInBuffer(node: TreeNode, remainder: number): BufferCursor;\n\tprivate positionInBuffer(node: TreeNode, remainder: number, ret: BufferCursor): null;\n\tprivate positionInBuffer(node: TreeNode, remainder: number, ret?: BufferCursor): BufferCursor | null {\n\t\tconst piece = node.piece;\n\t\tconst bufferIndex = node.piece.bufferIndex;\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\n\t\tconst startOffset = lineStarts[piece.start.line] + piece.start.column;\n\n\t\tconst offset = startOffset + remainder;\n\n\t\t// binary search offset between startOffset and endOffset\n\t\tlet low = piece.start.line;\n\t\tlet high = piece.end.line;\n\n\t\tlet mid: number = 0;\n\t\tlet midStop: number = 0;\n\t\tlet midStart: number = 0;\n\n\t\twhile (low <= high) {\n\t\t\tmid = low + ((high - low) / 2) | 0;\n\t\t\tmidStart = lineStarts[mid];\n\n\t\t\tif (mid === high) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tmidStop = lineStarts[mid + 1];\n\n\t\t\tif (offset < midStart) {\n\t\t\t\thigh = mid - 1;\n\t\t\t} else if (offset >= midStop) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (ret) {\n\t\t\tret.line = mid;\n\t\t\tret.column = offset - midStart;\n\t\t\treturn null;\n\t\t}\n\n\t\treturn {\n\t\t\tline: mid,\n\t\t\tcolumn: offset - midStart\n\t\t};\n\t}\n\n\tprivate getLineFeedCnt(bufferIndex: number, start: BufferCursor, end: BufferCursor): number {\n\t\t// we don't need to worry about start: abc\\r|\\n, or abc|\\r, or abc|\\n, or abc|\\r\\n doesn't change the fact that, there is one line break after start.\n\t\t// now let's take care of end: abc\\r|\\n, if end is in between \\r and \\n, we need to add line feed count by 1\n\t\tif (end.column === 0) {\n\t\t\treturn end.line - start.line;\n\t\t}\n\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\t\tif (end.line === lineStarts.length - 1) { // it means, there is no \\n after end, otherwise, there will be one more lineStart.\n\t\t\treturn end.line - start.line;\n\t\t}\n\n\t\tconst nextLineStartOffset = lineStarts[end.line + 1];\n\t\tconst endOffset = lineStarts[end.line] + end.column;\n\t\tif (nextLineStartOffset > endOffset + 1) { // there are more than 1 character after end, which means it can't be \\n\n\t\t\treturn end.line - start.line;\n\t\t}\n\t\t// endOffset + 1 === nextLineStartOffset\n\t\t// character at endOffset is \\n, so we check the character before first\n\t\t// if character at endOffset is \\r, end.column is 0 and we can't get here.\n\t\tconst previousCharOffset = endOffset - 1; // end.column > 0 so it's okay.\n\t\tconst buffer = this._buffers[bufferIndex].buffer;\n\n\t\tif (buffer.charCodeAt(previousCharOffset) === 13) {\n\t\t\treturn end.line - start.line + 1;\n\t\t} else {\n\t\t\treturn end.line - start.line;\n\t\t}\n\t}\n\n\tprivate offsetInBuffer(bufferIndex: number, cursor: BufferCursor): number {\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\t\treturn lineStarts[cursor.line] + cursor.column;\n\t}\n\n\tprivate deleteNodes(nodes: TreeNode[]): void {\n\t\tfor (let i = 0; i < nodes.length; i++) {\n\t\t\trbDelete(this, nodes[i]);\n\t\t}\n\t}\n\n\tprivate createNewPieces(text: string): Piece[] {\n\t\tif (text.length > AverageBufferSize) {\n\t\t\t// the content is large, operations like substring, charCode becomes slow\n\t\t\t// so here we split it into smaller chunks, just like what we did for CR/LF normalization\n\t\t\tconst newPieces: Piece[] = [];\n\t\t\twhile (text.length > AverageBufferSize) {\n\t\t\t\tconst lastChar = text.charCodeAt(AverageBufferSize - 1);\n\t\t\t\tlet splitText;\n\t\t\t\tif (lastChar === CharCode.CarriageReturn || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {\n\t\t\t\t\t// last character is \\r or a high surrogate => keep it back\n\t\t\t\t\tsplitText = text.substring(0, AverageBufferSize - 1);\n\t\t\t\t\ttext = text.substring(AverageBufferSize - 1);\n\t\t\t\t} else {\n\t\t\t\t\tsplitText = text.substring(0, AverageBufferSize);\n\t\t\t\t\ttext = text.substring(AverageBufferSize);\n\t\t\t\t}\n\n\t\t\t\tconst lineStarts = createLineStartsFast(splitText);\n\t\t\t\tnewPieces.push(new Piece(\n\t\t\t\t\tthis._buffers.length, /* buffer index */\n\t\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t\t{ line: lineStarts.length - 1, column: splitText.length - lineStarts[lineStarts.length - 1] },\n\t\t\t\t\tlineStarts.length - 1,\n\t\t\t\t\tsplitText.length\n\t\t\t\t));\n\t\t\t\tthis._buffers.push(new StringBuffer(splitText, lineStarts));\n\t\t\t}\n\n\t\t\tconst lineStarts = createLineStartsFast(text);\n\t\t\tnewPieces.push(new Piece(\n\t\t\t\tthis._buffers.length, /* buffer index */\n\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t{ line: lineStarts.length - 1, column: text.length - lineStarts[lineStarts.length - 1] },\n\t\t\t\tlineStarts.length - 1,\n\t\t\t\ttext.length\n\t\t\t));\n\t\t\tthis._buffers.push(new StringBuffer(text, lineStarts));\n\n\t\t\treturn newPieces;\n\t\t}\n\n\t\tlet startOffset = this._buffers[0].buffer.length;\n\t\tconst lineStarts = createLineStartsFast(text, false);\n\n\t\tlet start = this._lastChangeBufferPos;\n\t\tif (this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 1] === startOffset\n\t\t\t&& startOffset !== 0\n\t\t\t&& this.startWithLF(text)\n\t\t\t&& this.endWithCR(this._buffers[0].buffer) // todo, we can check this._lastChangeBufferPos's column as it's the last one\n\t\t) {\n\t\t\tthis._lastChangeBufferPos = { line: this._lastChangeBufferPos.line, column: this._lastChangeBufferPos.column + 1 };\n\t\t\tstart = this._lastChangeBufferPos;\n\n\t\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\t\tlineStarts[i] += startOffset + 1;\n\t\t\t}\n\n\t\t\tthis._buffers[0].lineStarts = (<number[]>this._buffers[0].lineStarts).concat(<number[]>lineStarts.slice(1));\n\t\t\tthis._buffers[0].buffer += '_' + text;\n\t\t\tstartOffset += 1;\n\t\t} else {\n\t\t\tif (startOffset !== 0) {\n\t\t\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\t\t\tlineStarts[i] += startOffset;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._buffers[0].lineStarts = (<number[]>this._buffers[0].lineStarts).concat(<number[]>lineStarts.slice(1));\n\t\t\tthis._buffers[0].buffer += text;\n\t\t}\n\n\t\tconst endOffset = this._buffers[0].buffer.length;\n\t\tconst endIndex = this._buffers[0].lineStarts.length - 1;\n\t\tconst endColumn = endOffset - this._buffers[0].lineStarts[endIndex];\n\t\tconst endPos = { line: endIndex, column: endColumn };\n\t\tconst newPiece = new Piece(\n\t\t\t0, /** todo@peng */\n\t\t\tstart,\n\t\t\tendPos,\n\t\t\tthis.getLineFeedCnt(0, start, endPos),\n\t\t\tendOffset - startOffset\n\t\t);\n\t\tthis._lastChangeBufferPos = endPos;\n\t\treturn [newPiece];\n\t}\n\n\tpublic getLineRawContent(lineNumber: number, endOffset: number = 0): string {\n\t\tlet x = this.root;\n\n\t\tlet ret = '';\n\t\tconst cache = this._searchCache.get2(lineNumber);\n\t\tif (cache) {\n\t\t\tx = cache.node;\n\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber - 1);\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\tif (cache.nodeStartLineNumber + x.piece.lineFeedCnt === lineNumber) {\n\t\t\t\tret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);\n\t\t\t} else {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber);\n\t\t\t\treturn buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);\n\t\t\t}\n\t\t} else {\n\t\t\tlet nodeStartOffset = 0;\n\t\t\tconst originalLineNumber = lineNumber;\n\t\t\twhile (x !== SENTINEL) {\n\t\t\t\tif (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {\n\t\t\t\t\tx = x.left;\n\t\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {\n\t\t\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);\n\t\t\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\t\t\tnodeStartOffset += x.size_left;\n\t\t\t\t\tthis._searchCache.set({\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tnodeStartOffset,\n\t\t\t\t\t\tnodeStartLineNumber: originalLineNumber - (lineNumber - 1 - x.lf_left)\n\t\t\t\t\t});\n\n\t\t\t\t\treturn buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);\n\t\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {\n\t\t\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\t\t\tret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\t\tx = x.right;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// search in order, to find the node contains end column\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\n\t\t\tif (x.piece.lineFeedCnt > 0) {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, 0);\n\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\t\tret += buffer.substring(startOffset, startOffset + accumulatedValue - endOffset);\n\t\t\t\treturn ret;\n\t\t\t} else {\n\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\t\tret += buffer.substr(startOffset, x.piece.length);\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tprivate computeBufferMetadata() {\n\t\tlet x = this.root;\n\n\t\tlet lfCnt = 1;\n\t\tlet len = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tlfCnt += x.lf_left + x.piece.lineFeedCnt;\n\t\t\tlen += x.size_left + x.piece.length;\n\t\t\tx = x.right;\n\t\t}\n\n\t\tthis._lineCnt = lfCnt;\n\t\tthis._length = len;\n\t\tthis._searchCache.validate(this._length);\n\t}\n\n\t// #region node operations\n\tprivate getIndexOf(node: TreeNode, accumulatedValue: number): { index: number; remainder: number } {\n\t\tconst piece = node.piece;\n\t\tconst pos = this.positionInBuffer(node, accumulatedValue);\n\t\tconst lineCnt = pos.line - piece.start.line;\n\n\t\tif (this.offsetInBuffer(piece.bufferIndex, piece.end) - this.offsetInBuffer(piece.bufferIndex, piece.start) === accumulatedValue) {\n\t\t\t// we are checking the end of this node, so a CRLF check is necessary.\n\t\t\tconst realLineCnt = this.getLineFeedCnt(node.piece.bufferIndex, piece.start, pos);\n\t\t\tif (realLineCnt !== lineCnt) {\n\t\t\t\t// aha yes, CRLF\n\t\t\t\treturn { index: realLineCnt, remainder: 0 };\n\t\t\t}\n\t\t}\n\n\t\treturn { index: lineCnt, remainder: pos.column };\n\t}\n\n\tprivate getAccumulatedValue(node: TreeNode, index: number) {\n\t\tif (index < 0) {\n\t\t\treturn 0;\n\t\t}\n\t\tconst piece = node.piece;\n\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\t\tconst expectedLineStartIndex = piece.start.line + index + 1;\n\t\tif (expectedLineStartIndex > piece.end.line) {\n\t\t\treturn lineStarts[piece.end.line] + piece.end.column - lineStarts[piece.start.line] - piece.start.column;\n\t\t} else {\n\t\t\treturn lineStarts[expectedLineStartIndex] - lineStarts[piece.start.line] - piece.start.column;\n\t\t}\n\t}\n\n\tprivate deleteNodeTail(node: TreeNode, pos: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalLFCnt = piece.lineFeedCnt;\n\t\tconst originalEndOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\n\t\tconst newEnd = pos;\n\t\tconst newEndOffset = this.offsetInBuffer(piece.bufferIndex, newEnd);\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);\n\n\t\tconst lf_delta = newLineFeedCnt - originalLFCnt;\n\t\tconst size_delta = newEndOffset - originalEndOffset;\n\t\tconst newLength = piece.length + size_delta;\n\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tpiece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, size_delta, lf_delta);\n\t}\n\n\tprivate deleteNodeHead(node: TreeNode, pos: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalLFCnt = piece.lineFeedCnt;\n\t\tconst originalStartOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\n\t\tconst newStart = pos;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);\n\t\tconst newStartOffset = this.offsetInBuffer(piece.bufferIndex, newStart);\n\t\tconst lf_delta = newLineFeedCnt - originalLFCnt;\n\t\tconst size_delta = originalStartOffset - newStartOffset;\n\t\tconst newLength = piece.length + size_delta;\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tnewStart,\n\t\t\tpiece.end,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, size_delta, lf_delta);\n\t}\n\n\tprivate shrinkNode(node: TreeNode, start: BufferCursor, end: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalStartPos = piece.start;\n\t\tconst originalEndPos = piece.end;\n\n\t\t// old piece, originalStartPos, start\n\t\tconst oldLength = piece.length;\n\t\tconst oldLFCnt = piece.lineFeedCnt;\n\t\tconst newEnd = start;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);\n\t\tconst newLength = this.offsetInBuffer(piece.bufferIndex, start) - this.offsetInBuffer(piece.bufferIndex, originalStartPos);\n\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tpiece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, newLength - oldLength, newLineFeedCnt - oldLFCnt);\n\n\t\t// new right piece, end, originalEndPos\n\t\tconst newPiece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tend,\n\t\t\toriginalEndPos,\n\t\t\tthis.getLineFeedCnt(piece.bufferIndex, end, originalEndPos),\n\t\t\tthis.offsetInBuffer(piece.bufferIndex, originalEndPos) - this.offsetInBuffer(piece.bufferIndex, end)\n\t\t);\n\n\t\tconst newNode = this.rbInsertRight(node, newPiece);\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t}\n\n\tprivate appendToNode(node: TreeNode, value: string): void {\n\t\tif (this.adjustCarriageReturnFromNext(value, node)) {\n\t\t\tvalue += '\\n';\n\t\t}\n\n\t\tconst hitCRLF = this.shouldCheckCRLF() && this.startWithLF(value) && this.endWithCR(node);\n\t\tconst startOffset = this._buffers[0].buffer.length;\n\t\tthis._buffers[0].buffer += value;\n\t\tconst lineStarts = createLineStartsFast(value, false);\n\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\tlineStarts[i] += startOffset;\n\t\t}\n\t\tif (hitCRLF) {\n\t\t\tconst prevStartOffset = this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 2];\n\t\t\t(<number[]>this._buffers[0].lineStarts).pop();\n\t\t\t// _lastChangeBufferPos is already wrong\n\t\t\tthis._lastChangeBufferPos = { line: this._lastChangeBufferPos.line - 1, column: startOffset - prevStartOffset };\n\t\t}\n\n\t\tthis._buffers[0].lineStarts = (<number[]>this._buffers[0].lineStarts).concat(<number[]>lineStarts.slice(1));\n\t\tconst endIndex = this._buffers[0].lineStarts.length - 1;\n\t\tconst endColumn = this._buffers[0].buffer.length - this._buffers[0].lineStarts[endIndex];\n\t\tconst newEnd = { line: endIndex, column: endColumn };\n\t\tconst newLength = node.piece.length + value.length;\n\t\tconst oldLineFeedCnt = node.piece.lineFeedCnt;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(0, node.piece.start, newEnd);\n\t\tconst lf_delta = newLineFeedCnt - oldLineFeedCnt;\n\n\t\tnode.piece = new Piece(\n\t\t\tnode.piece.bufferIndex,\n\t\t\tnode.piece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tthis._lastChangeBufferPos = newEnd;\n\t\tupdateTreeMetadata(this, node, value.length, lf_delta);\n\t}\n\n\tprivate nodeAt(offset: number): NodePosition {\n\t\tlet x = this.root;\n\t\tconst cache = this._searchCache.get(offset);\n\t\tif (cache) {\n\t\t\treturn {\n\t\t\t\tnode: cache.node,\n\t\t\t\tnodeStartOffset: cache.nodeStartOffset,\n\t\t\t\tremainder: offset - cache.nodeStartOffset\n\t\t\t};\n\t\t}\n\n\t\tlet nodeStartOffset = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.size_left > offset) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.size_left + x.piece.length >= offset) {\n\t\t\t\tnodeStartOffset += x.size_left;\n\t\t\t\tconst ret = {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: offset - x.size_left,\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t\tthis._searchCache.set(ret);\n\t\t\t\treturn ret;\n\t\t\t} else {\n\t\t\t\toffset -= x.size_left + x.piece.length;\n\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\treturn null!;\n\t}\n\n\tprivate nodeAt2(lineNumber: number, column: number): NodePosition {\n\t\tlet x = this.root;\n\t\tlet nodeStartOffset = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {\n\t\t\t\tconst prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);\n\t\t\t\tnodeStartOffset += x.size_left;\n\n\t\t\t\treturn {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: Math.min(prevAccumualtedValue + column - 1, accumulatedValue),\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {\n\t\t\t\tconst prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\tif (prevAccumualtedValue + column - 1 <= x.piece.length) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tremainder: prevAccumualtedValue + column - 1,\n\t\t\t\t\t\tnodeStartOffset\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tcolumn -= x.piece.length - prevAccumualtedValue;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\t// search in order, to find the node contains position.column\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\n\t\t\tif (x.piece.lineFeedCnt > 0) {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, 0);\n\t\t\t\tconst nodeStartOffset = this.offsetOfNode(x);\n\t\t\t\treturn {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: Math.min(column - 1, accumulatedValue),\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tif (x.piece.length >= column - 1) {\n\t\t\t\t\tconst nodeStartOffset = this.offsetOfNode(x);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tremainder: column - 1,\n\t\t\t\t\t\tnodeStartOffset\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tcolumn -= x.piece.length;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn null!;\n\t}\n\n\tprivate nodeCharCodeAt(node: TreeNode, offset: number): number {\n\t\tif (node.piece.lineFeedCnt < 1) {\n\t\t\treturn -1;\n\t\t}\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst newOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start) + offset;\n\t\treturn buffer.buffer.charCodeAt(newOffset);\n\t}\n\n\tprivate offsetOfNode(node: TreeNode): number {\n\t\tif (!node) {\n\t\t\treturn 0;\n\t\t}\n\t\tlet pos = node.size_left;\n\t\twhile (node !== this.root) {\n\t\t\tif (node.parent.right === node) {\n\t\t\t\tpos += node.parent.size_left + node.parent.piece.length;\n\t\t\t}\n\n\t\t\tnode = node.parent;\n\t\t}\n\n\t\treturn pos;\n\t}\n\n\t// #endregion\n\n\t// #region CRLF\n\tprivate shouldCheckCRLF() {\n\t\treturn !(this._EOLNormalized && this._EOL === '\\n');\n\t}\n\n\tprivate startWithLF(val: string | TreeNode): boolean {\n\t\tif (typeof val === 'string') {\n\t\t\treturn val.charCodeAt(0) === 10;\n\t\t}\n\n\t\tif (val === SENTINEL || val.piece.lineFeedCnt === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst piece = val.piece;\n\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\t\tconst line = piece.start.line;\n\t\tconst startOffset = lineStarts[line] + piece.start.column;\n\t\tif (line === lineStarts.length - 1) {\n\t\t\t// last line, so there is no line feed at the end of this line\n\t\t\treturn false;\n\t\t}\n\t\tconst nextLineOffset = lineStarts[line + 1];\n\t\tif (nextLineOffset > startOffset + 1) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this._buffers[piece.bufferIndex].buffer.charCodeAt(startOffset) === 10;\n\t}\n\n\tprivate endWithCR(val: string | TreeNode): boolean {\n\t\tif (typeof val === 'string') {\n\t\t\treturn val.charCodeAt(val.length - 1) === 13;\n\t\t}\n\n\t\tif (val === SENTINEL || val.piece.lineFeedCnt === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.nodeCharCodeAt(val, val.piece.length - 1) === 13;\n\t}\n\n\tprivate validateCRLFWithPrevNode(nextNode: TreeNode) {\n\t\tif (this.shouldCheckCRLF() && this.startWithLF(nextNode)) {\n\t\t\tconst node = nextNode.prev();\n\t\t\tif (this.endWithCR(node)) {\n\t\t\t\tthis.fixCRLF(node, nextNode);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate validateCRLFWithNextNode(node: TreeNode) {\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(node)) {\n\t\t\tconst nextNode = node.next();\n\t\t\tif (this.startWithLF(nextNode)) {\n\t\t\t\tthis.fixCRLF(node, nextNode);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fixCRLF(prev: TreeNode, next: TreeNode) {\n\t\tconst nodesToDel: TreeNode[] = [];\n\t\t// update node\n\t\tconst lineStarts = this._buffers[prev.piece.bufferIndex].lineStarts;\n\t\tlet newEnd: BufferCursor;\n\t\tif (prev.piece.end.column === 0) {\n\t\t\t// it means, last line ends with \\r, not \\r\\n\n\t\t\tnewEnd = { line: prev.piece.end.line - 1, column: lineStarts[prev.piece.end.line] - lineStarts[prev.piece.end.line - 1] - 1 };\n\t\t} else {\n\t\t\t// \\r\\n\n\t\t\tnewEnd = { line: prev.piece.end.line, column: prev.piece.end.column - 1 };\n\t\t}\n\n\t\tconst prevNewLength = prev.piece.length - 1;\n\t\tconst prevNewLFCnt = prev.piece.lineFeedCnt - 1;\n\t\tprev.piece = new Piece(\n\t\t\tprev.piece.bufferIndex,\n\t\t\tprev.piece.start,\n\t\t\tnewEnd,\n\t\t\tprevNewLFCnt,\n\t\t\tprevNewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, prev, - 1, -1);\n\t\tif (prev.piece.length === 0) {\n\t\t\tnodesToDel.push(prev);\n\t\t}\n\n\t\t// update nextNode\n\t\tconst newStart: BufferCursor = { line: next.piece.start.line + 1, column: 0 };\n\t\tconst newLength = next.piece.length - 1;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(next.piece.bufferIndex, newStart, next.piece.end);\n\t\tnext.piece = new Piece(\n\t\t\tnext.piece.bufferIndex,\n\t\t\tnewStart,\n\t\t\tnext.piece.end,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, next, - 1, -1);\n\t\tif (next.piece.length === 0) {\n\t\t\tnodesToDel.push(next);\n\t\t}\n\n\t\t// create new piece which contains \\r\\n\n\t\tconst pieces = this.createNewPieces('\\r\\n');\n\t\tthis.rbInsertRight(prev, pieces[0]);\n\t\t// delete empty nodes\n\n\t\tfor (let i = 0; i < nodesToDel.length; i++) {\n\t\t\trbDelete(this, nodesToDel[i]);\n\t\t}\n\t}\n\n\tprivate adjustCarriageReturnFromNext(value: string, node: TreeNode): boolean {\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(value)) {\n\t\t\tconst nextNode = node.next();\n\t\t\tif (this.startWithLF(nextNode)) {\n\t\t\t\t// move `\\n` forward\n\t\t\t\tvalue += '\\n';\n\n\t\t\t\tif (nextNode.piece.length === 1) {\n\t\t\t\t\trbDelete(this, nextNode);\n\t\t\t\t} else {\n\n\t\t\t\t\tconst piece = nextNode.piece;\n\t\t\t\t\tconst newStart: BufferCursor = { line: piece.start.line + 1, column: 0 };\n\t\t\t\t\tconst newLength = piece.length - 1;\n\t\t\t\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);\n\t\t\t\t\tnextNode.piece = new Piece(\n\t\t\t\t\t\tpiece.bufferIndex,\n\t\t\t\t\t\tnewStart,\n\t\t\t\t\t\tpiece.end,\n\t\t\t\t\t\tnewLineFeedCnt,\n\t\t\t\t\t\tnewLength\n\t\t\t\t\t);\n\n\t\t\t\t\tupdateTreeMetadata(this, nextNode, -1, -1);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t// #endregion\n\n\t// #endregion\n\n\t// #region Tree operations\n\titerate(node: TreeNode, callback: (node: TreeNode) => boolean): boolean {\n\t\tif (node === SENTINEL) {\n\t\t\treturn callback(SENTINEL);\n\t\t}\n\n\t\tconst leftRet = this.iterate(node.left, callback);\n\t\tif (!leftRet) {\n\t\t\treturn leftRet;\n\t\t}\n\n\t\treturn callback(node) && this.iterate(node.right, callback);\n\t}\n\n\tprivate getNodeContent(node: TreeNode) {\n\t\tif (node === SENTINEL) {\n\t\t\treturn '';\n\t\t}\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst piece = node.piece;\n\t\tconst startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\t\tconst endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\t\tconst currentContent = buffer.buffer.substring(startOffset, endOffset);\n\t\treturn currentContent;\n\t}\n\n\tgetPieceContent(piece: Piece) {\n\t\tconst buffer = this._buffers[piece.bufferIndex];\n\t\tconst startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\t\tconst endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\t\tconst currentContent = buffer.buffer.substring(startOffset, endOffset);\n\t\treturn currentContent;\n\t}\n\n\t/**\n\t * node node\n\t * / \\ / \\\n\t * a b <---- a b\n\t * /\n\t * z\n\t */\n\tprivate rbInsertRight(node: TreeNode | null, p: Piece): TreeNode {\n\t\tconst z = new TreeNode(p, NodeColor.Red);\n\t\tz.left = SENTINEL;\n\t\tz.right = SENTINEL;\n\t\tz.parent = SENTINEL;\n\t\tz.size_left = 0;\n\t\tz.lf_left = 0;\n\n\t\tconst x = this.root;\n\t\tif (x === SENTINEL) {\n\t\t\tthis.root = z;\n\t\t\tz.color = NodeColor.Black;\n\t\t} else if (node!.right === SENTINEL) {\n\t\t\tnode!.right = z;\n\t\t\tz.parent = node!;\n\t\t} else {\n\t\t\tconst nextNode = leftest(node!.right);\n\t\t\tnextNode.left = z;\n\t\t\tz.parent = nextNode;\n\t\t}\n\n\t\tfixInsert(this, z);\n\t\treturn z;\n\t}\n\n\t/**\n\t * node node\n\t * / \\ / \\\n\t * a b ----> a b\n\t * \\\n\t * z\n\t */\n\tprivate rbInsertLeft(node: TreeNode | null, p: Piece): TreeNode {\n\t\tconst z = new TreeNode(p, NodeColor.Red);\n\t\tz.left = SENTINEL;\n\t\tz.right = SENTINEL;\n\t\tz.parent = SENTINEL;\n\t\tz.size_left = 0;\n\t\tz.lf_left = 0;\n\n\t\tif (this.root === SENTINEL) {\n\t\t\tthis.root = z;\n\t\t\tz.color = NodeColor.Black;\n\t\t} else if (node!.left === SENTINEL) {\n\t\t\tnode!.left = z;\n\t\t\tz.parent = node!;\n\t\t} else {\n\t\t\tconst prevNode = righttest(node!.left); // a\n\t\t\tprevNode.right = z;\n\t\t\tz.parent = prevNode;\n\t\t}\n\n\t\tfixInsert(this, z);\n\t\treturn z;\n\t}\n\t// #endregion\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from '../../../../base/common/charCode.js';\nimport { Position } from '../../core/position.js';\nimport { Range } from '../../core/range.js';\nimport { FindMatch, ITextSnapshot, SearchData } from '../../model.js';\nimport { NodeColor, SENTINEL, TreeNode, fixInsert, leftest, rbDelete, righttest, updateTreeMetadata } from './rbTreeBase.js';\nimport { Searcher, createFindMatch, isValidMatch } from '../textModelSearch.js';\n\n// const lfRegex = new RegExp(/\\r\\n|\\r|\\n/g);\nconst AverageBufferSize = 65535;\n\nfunction createUintArray(arr: number[]): Uint32Array | Uint16Array {\n\tlet r;\n\tif (arr[arr.length - 1] < 65536) {\n\t\tr = new Uint16Array(arr.length);\n\t} else {\n\t\tr = new Uint32Array(arr.length);\n\t}\n\tr.set(arr, 0);\n\treturn r;\n}\n\nclass LineStarts {\n\tconstructor(\n\t\tpublic readonly lineStarts: Uint32Array | Uint16Array | number[],\n\t\tpublic readonly cr: number,\n\t\tpublic readonly lf: number,\n\t\tpublic readonly crlf: number,\n\t\tpublic readonly isBasicASCII: boolean\n\t) { }\n}\n\nexport function createLineStartsFast(str: string, readonly: boolean = true): Uint32Array | Uint16Array | number[] {\n\tconst r: number[] = [0];\n\tlet rLength = 1;\n\n\tfor (let i = 0, len = str.length; i < len; i++) {\n\t\tconst chr = str.charCodeAt(i);\n\n\t\tif (chr === CharCode.CarriageReturn) {\n\t\t\tif (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) {\n\t\t\t\t// \\r\\n... case\n\t\t\t\tr[rLength++] = i + 2;\n\t\t\t\ti++; // skip \\n\n\t\t\t} else {\n\t\t\t\t// \\r... case\n\t\t\t\tr[rLength++] = i + 1;\n\t\t\t}\n\t\t} else if (chr === CharCode.LineFeed) {\n\t\t\tr[rLength++] = i + 1;\n\t\t}\n\t}\n\tif (readonly) {\n\t\treturn createUintArray(r);\n\t} else {\n\t\treturn r;\n\t}\n}\n\nexport function createLineStarts(r: number[], str: string): LineStarts {\n\tr.length = 0;\n\tr[0] = 0;\n\tlet rLength = 1;\n\tlet cr = 0, lf = 0, crlf = 0;\n\tlet isBasicASCII = true;\n\tfor (let i = 0, len = str.length; i < len; i++) {\n\t\tconst chr = str.charCodeAt(i);\n\n\t\tif (chr === CharCode.CarriageReturn) {\n\t\t\tif (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) {\n\t\t\t\t// \\r\\n... case\n\t\t\t\tcrlf++;\n\t\t\t\tr[rLength++] = i + 2;\n\t\t\t\ti++; // skip \\n\n\t\t\t} else {\n\t\t\t\tcr++;\n\t\t\t\t// \\r... case\n\t\t\t\tr[rLength++] = i + 1;\n\t\t\t}\n\t\t} else if (chr === CharCode.LineFeed) {\n\t\t\tlf++;\n\t\t\tr[rLength++] = i + 1;\n\t\t} else {\n\t\t\tif (isBasicASCII) {\n\t\t\t\tif (chr !== CharCode.Tab && (chr < 32 || chr > 126)) {\n\t\t\t\t\tisBasicASCII = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tconst result = new LineStarts(createUintArray(r), cr, lf, crlf, isBasicASCII);\n\tr.length = 0;\n\n\treturn result;\n}\n\ninterface NodePosition {\n\t/**\n\t * Piece Index\n\t */\n\tnode: TreeNode;\n\t/**\n\t * remainder in current piece.\n\t*/\n\tremainder: number;\n\t/**\n\t * node start offset in document.\n\t */\n\tnodeStartOffset: number;\n}\n\ninterface BufferCursor {\n\t/**\n\t * Line number in current buffer\n\t */\n\tline: number;\n\t/**\n\t * Column number in current buffer\n\t */\n\tcolumn: number;\n}\n\nexport class Piece {\n\treadonly bufferIndex: number;\n\treadonly start: BufferCursor;\n\treadonly end: BufferCursor;\n\treadonly length: number;\n\treadonly lineFeedCnt: number;\n\n\tconstructor(bufferIndex: number, start: BufferCursor, end: BufferCursor, lineFeedCnt: number, length: number) {\n\t\tthis.bufferIndex = bufferIndex;\n\t\tthis.start = start;\n\t\tthis.end = end;\n\t\tthis.lineFeedCnt = lineFeedCnt;\n\t\tthis.length = length;\n\t}\n}\n\nexport class StringBuffer {\n\tbuffer: string;\n\tlineStarts: Uint32Array | Uint16Array | number[];\n\n\tconstructor(buffer: string, lineStarts: Uint32Array | Uint16Array | number[]) {\n\t\tthis.buffer = buffer;\n\t\tthis.lineStarts = lineStarts;\n\t}\n}\n\n/**\n * Readonly snapshot for piece tree.\n * In a real multiple thread environment, to make snapshot reading always work correctly, we need to\n * 1. Make TreeNode.piece immutable, then reading and writing can run in parallel.\n * 2. TreeNode/Buffers normalization should not happen during snapshot reading.\n */\nclass PieceTreeSnapshot implements ITextSnapshot {\n\tprivate readonly _pieces: Piece[];\n\tprivate _index: number;\n\tprivate readonly _tree: PieceTreeBase;\n\tprivate readonly _BOM: string;\n\n\tconstructor(tree: PieceTreeBase, BOM: string) {\n\t\tthis._pieces = [];\n\t\tthis._tree = tree;\n\t\tthis._BOM = BOM;\n\t\tthis._index = 0;\n\t\tif (tree.root !== SENTINEL) {\n\t\t\ttree.iterate(tree.root, node => {\n\t\t\t\tif (node !== SENTINEL) {\n\t\t\t\t\tthis._pieces.push(node.piece);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t});\n\t\t}\n\t}\n\n\tread(): string | null {\n\t\tif (this._pieces.length === 0) {\n\t\t\tif (this._index === 0) {\n\t\t\t\tthis._index++;\n\t\t\t\treturn this._BOM;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tif (this._index > this._pieces.length - 1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (this._index === 0) {\n\t\t\treturn this._BOM + this._tree.getPieceContent(this._pieces[this._index++]);\n\t\t}\n\t\treturn this._tree.getPieceContent(this._pieces[this._index++]);\n\t}\n}\n\ninterface CacheEntry {\n\tnode: TreeNode;\n\tnodeStartOffset: number;\n\tnodeStartLineNumber?: number;\n}\n\nclass PieceTreeSearchCache {\n\tprivate readonly _limit: number;\n\tprivate _cache: CacheEntry[];\n\n\tconstructor(limit: number) {\n\t\tthis._limit = limit;\n\t\tthis._cache = [];\n\t}\n\n\tpublic get(offset: number): CacheEntry | null {\n\t\tfor (let i = this._cache.length - 1; i >= 0; i--) {\n\t\t\tconst nodePos = this._cache[i];\n\t\t\tif (nodePos.nodeStartOffset <= offset && nodePos.nodeStartOffset + nodePos.node.piece.length >= offset) {\n\t\t\t\treturn nodePos;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic get2(lineNumber: number): { node: TreeNode; nodeStartOffset: number; nodeStartLineNumber: number } | null {\n\t\tfor (let i = this._cache.length - 1; i >= 0; i--) {\n\t\t\tconst nodePos = this._cache[i];\n\t\t\tif (nodePos.nodeStartLineNumber && nodePos.nodeStartLineNumber < lineNumber && nodePos.nodeStartLineNumber + nodePos.node.piece.lineFeedCnt >= lineNumber) {\n\t\t\t\treturn <{ node: TreeNode; nodeStartOffset: number; nodeStartLineNumber: number }>nodePos;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic set(nodePosition: CacheEntry) {\n\t\tif (this._cache.length >= this._limit) {\n\t\t\tthis._cache.shift();\n\t\t}\n\t\tthis._cache.push(nodePosition);\n\t}\n\n\tpublic validate(offset: number) {\n\t\tlet hasInvalidVal = false;\n\t\tconst tmp: Array<CacheEntry | null> = this._cache;\n\t\tfor (let i = 0; i < tmp.length; i++) {\n\t\t\tconst nodePos = tmp[i]!;\n\t\t\tif (nodePos.node.parent === null || nodePos.nodeStartOffset >= offset) {\n\t\t\t\ttmp[i] = null;\n\t\t\t\thasInvalidVal = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif (hasInvalidVal) {\n\t\t\tconst newArr: CacheEntry[] = [];\n\t\t\tfor (const entry of tmp) {\n\t\t\t\tif (entry !== null) {\n\t\t\t\t\tnewArr.push(entry);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._cache = newArr;\n\t\t}\n\t}\n}\n\nexport class PieceTreeBase {\n\troot!: TreeNode;\n\tprotected _buffers!: StringBuffer[]; // 0 is change buffer, others are readonly original buffer.\n\tprotected _lineCnt!: number;\n\tprotected _length!: number;\n\tprotected _EOL!: '\\r\\n' | '\\n';\n\tprotected _EOLLength!: number;\n\tprotected _EOLNormalized!: boolean;\n\tprivate _lastChangeBufferPos!: BufferCursor;\n\tprivate _searchCache!: PieceTreeSearchCache;\n\tprivate _lastVisitedLine!: { lineNumber: number; value: string };\n\n\tconstructor(chunks: StringBuffer[], eol: '\\r\\n' | '\\n', eolNormalized: boolean) {\n\t\tthis.create(chunks, eol, eolNormalized);\n\t}\n\n\tcreate(chunks: StringBuffer[], eol: '\\r\\n' | '\\n', eolNormalized: boolean) {\n\t\tthis._buffers = [\n\t\t\tnew StringBuffer('', [0])\n\t\t];\n\t\tthis._lastChangeBufferPos = { line: 0, column: 0 };\n\t\tthis.root = SENTINEL;\n\t\tthis._lineCnt = 1;\n\t\tthis._length = 0;\n\t\tthis._EOL = eol;\n\t\tthis._EOLLength = eol.length;\n\t\tthis._EOLNormalized = eolNormalized;\n\n\t\tlet lastNode: TreeNode | null = null;\n\t\tfor (let i = 0, len = chunks.length; i < len; i++) {\n\t\t\tif (chunks[i].buffer.length > 0) {\n\t\t\t\tif (!chunks[i].lineStarts) {\n\t\t\t\t\tchunks[i].lineStarts = createLineStartsFast(chunks[i].buffer);\n\t\t\t\t}\n\n\t\t\t\tconst piece = new Piece(\n\t\t\t\t\ti + 1,\n\t\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t\t{ line: chunks[i].lineStarts.length - 1, column: chunks[i].buffer.length - chunks[i].lineStarts[chunks[i].lineStarts.length - 1] },\n\t\t\t\t\tchunks[i].lineStarts.length - 1,\n\t\t\t\t\tchunks[i].buffer.length\n\t\t\t\t);\n\t\t\t\tthis._buffers.push(chunks[i]);\n\t\t\t\tlastNode = this.rbInsertRight(lastNode, piece);\n\t\t\t}\n\t\t}\n\n\t\tthis._searchCache = new PieceTreeSearchCache(1);\n\t\tthis._lastVisitedLine = { lineNumber: 0, value: '' };\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tnormalizeEOL(eol: '\\r\\n' | '\\n') {\n\t\tconst averageBufferSize = AverageBufferSize;\n\t\tconst min = averageBufferSize - Math.floor(averageBufferSize / 3);\n\t\tconst max = min * 2;\n\n\t\tlet tempChunk = '';\n\t\tlet tempChunkLen = 0;\n\t\tconst chunks: StringBuffer[] = [];\n\n\t\tthis.iterate(this.root, node => {\n\t\t\tconst str = this.getNodeContent(node);\n\t\t\tconst len = str.length;\n\t\t\tif (tempChunkLen <= min || tempChunkLen + len < max) {\n\t\t\t\ttempChunk += str;\n\t\t\t\ttempChunkLen += len;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// flush anyways\n\t\t\tconst text = tempChunk.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\tchunks.push(new StringBuffer(text, createLineStartsFast(text)));\n\t\t\ttempChunk = str;\n\t\t\ttempChunkLen = len;\n\t\t\treturn true;\n\t\t});\n\n\t\tif (tempChunkLen > 0) {\n\t\t\tconst text = tempChunk.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\tchunks.push(new StringBuffer(text, createLineStartsFast(text)));\n\t\t}\n\n\t\tthis.create(chunks, eol, true);\n\t}\n\n\t// #region Buffer API\n\tpublic getEOL(): '\\r\\n' | '\\n' {\n\t\treturn this._EOL;\n\t}\n\n\tpublic setEOL(newEOL: '\\r\\n' | '\\n'): void {\n\t\tthis._EOL = newEOL;\n\t\tthis._EOLLength = this._EOL.length;\n\t\tthis.normalizeEOL(newEOL);\n\t}\n\n\tpublic createSnapshot(BOM: string): ITextSnapshot {\n\t\treturn new PieceTreeSnapshot(this, BOM);\n\t}\n\n\tpublic getOffsetAt(lineNumber: number, column: number): number {\n\t\tlet leftLen = 0; // inorder\n\n\t\tlet x = this.root;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.left !== SENTINEL && x.lf_left + 1 >= lineNumber) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt + 1 >= lineNumber) {\n\t\t\t\tleftLen += x.size_left;\n\t\t\t\t// lineNumber >= 2\n\t\t\t\tconst accumualtedValInCurrentIndex = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\treturn leftLen += accumualtedValInCurrentIndex + column - 1;\n\t\t\t} else {\n\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\tleftLen += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\treturn leftLen;\n\t}\n\n\tpublic getPositionAt(offset: number): Position {\n\t\toffset = Math.floor(offset);\n\t\toffset = Math.max(0, offset);\n\n\t\tlet x = this.root;\n\t\tlet lfCnt = 0;\n\t\tconst originalOffset = offset;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.size_left !== 0 && x.size_left >= offset) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.size_left + x.piece.length >= offset) {\n\t\t\t\tconst out = this.getIndexOf(x, offset - x.size_left);\n\n\t\t\t\tlfCnt += x.lf_left + out.index;\n\n\t\t\t\tif (out.index === 0) {\n\t\t\t\t\tconst lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);\n\t\t\t\t\tconst column = originalOffset - lineStartOffset;\n\t\t\t\t\treturn new Position(lfCnt + 1, column + 1);\n\t\t\t\t}\n\n\t\t\t\treturn new Position(lfCnt + 1, out.remainder + 1);\n\t\t\t} else {\n\t\t\t\toffset -= x.size_left + x.piece.length;\n\t\t\t\tlfCnt += x.lf_left + x.piece.lineFeedCnt;\n\n\t\t\t\tif (x.right === SENTINEL) {\n\t\t\t\t\t// last node\n\t\t\t\t\tconst lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);\n\t\t\t\t\tconst column = originalOffset - offset - lineStartOffset;\n\t\t\t\t\treturn new Position(lfCnt + 1, column + 1);\n\t\t\t\t} else {\n\t\t\t\t\tx = x.right;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn new Position(1, 1);\n\t}\n\n\tpublic getValueInRange(range: Range, eol?: string): string {\n\t\tif (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst startPosition = this.nodeAt2(range.startLineNumber, range.startColumn);\n\t\tconst endPosition = this.nodeAt2(range.endLineNumber, range.endColumn);\n\n\t\tconst value = this.getValueInRange2(startPosition, endPosition);\n\t\tif (eol) {\n\t\t\tif (eol !== this._EOL || !this._EOLNormalized) {\n\t\t\t\treturn value.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\t}\n\n\t\t\tif (eol === this.getEOL() && this._EOLNormalized) {\n\t\t\t\tif (eol === '\\r\\n') {\n\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t}\n\t\t\treturn value.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t}\n\t\treturn value;\n\t}\n\n\tpublic getValueInRange2(startPosition: NodePosition, endPosition: NodePosition): string {\n\t\tif (startPosition.node === endPosition.node) {\n\t\t\tconst node = startPosition.node;\n\t\t\tconst buffer = this._buffers[node.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);\n\t\t\treturn buffer.substring(startOffset + startPosition.remainder, startOffset + endPosition.remainder);\n\t\t}\n\n\t\tlet x = startPosition.node;\n\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\tlet ret = buffer.substring(startOffset + startPosition.remainder, startOffset + x.piece.length);\n\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\tif (x === endPosition.node) {\n\t\t\t\tret += buffer.substring(startOffset, startOffset + endPosition.remainder);\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tret += buffer.substr(startOffset, x.piece.length);\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tpublic getLinesContent(): string[] {\n\t\tconst lines: string[] = [];\n\t\tlet linesLength = 0;\n\t\tlet currentLine = '';\n\t\tlet danglingCR = false;\n\n\t\tthis.iterate(this.root, node => {\n\t\t\tif (node === SENTINEL) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst piece = node.piece;\n\t\t\tlet pieceLength = piece.length;\n\t\t\tif (pieceLength === 0) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[piece.bufferIndex].buffer;\n\t\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\n\t\t\tconst pieceStartLine = piece.start.line;\n\t\t\tconst pieceEndLine = piece.end.line;\n\t\t\tlet pieceStartOffset = lineStarts[pieceStartLine] + piece.start.column;\n\n\t\t\tif (danglingCR) {\n\t\t\t\tif (buffer.charCodeAt(pieceStartOffset) === CharCode.LineFeed) {\n\t\t\t\t\t// pretend the \\n was in the previous piece..\n\t\t\t\t\tpieceStartOffset++;\n\t\t\t\t\tpieceLength--;\n\t\t\t\t}\n\t\t\t\tlines[linesLength++] = currentLine;\n\t\t\t\tcurrentLine = '';\n\t\t\t\tdanglingCR = false;\n\t\t\t\tif (pieceLength === 0) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (pieceStartLine === pieceEndLine) {\n\t\t\t\t// this piece has no new lines\n\t\t\t\tif (!this._EOLNormalized && buffer.charCodeAt(pieceStartOffset + pieceLength - 1) === CharCode.CarriageReturn) {\n\t\t\t\t\tdanglingCR = true;\n\t\t\t\t\tcurrentLine += buffer.substr(pieceStartOffset, pieceLength - 1);\n\t\t\t\t} else {\n\t\t\t\t\tcurrentLine += buffer.substr(pieceStartOffset, pieceLength);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// add the text before the first line start in this piece\n\t\t\tcurrentLine += (\n\t\t\t\tthis._EOLNormalized\n\t\t\t\t\t? buffer.substring(pieceStartOffset, Math.max(pieceStartOffset, lineStarts[pieceStartLine + 1] - this._EOLLength))\n\t\t\t\t\t: buffer.substring(pieceStartOffset, lineStarts[pieceStartLine + 1]).replace(/(\\r\\n|\\r|\\n)$/, '')\n\t\t\t);\n\t\t\tlines[linesLength++] = currentLine;\n\n\t\t\tfor (let line = pieceStartLine + 1; line < pieceEndLine; line++) {\n\t\t\t\tcurrentLine = (\n\t\t\t\t\tthis._EOLNormalized\n\t\t\t\t\t\t? buffer.substring(lineStarts[line], lineStarts[line + 1] - this._EOLLength)\n\t\t\t\t\t\t: buffer.substring(lineStarts[line], lineStarts[line + 1]).replace(/(\\r\\n|\\r|\\n)$/, '')\n\t\t\t\t);\n\t\t\t\tlines[linesLength++] = currentLine;\n\t\t\t}\n\n\t\t\tif (!this._EOLNormalized && buffer.charCodeAt(lineStarts[pieceEndLine] + piece.end.column - 1) === CharCode.CarriageReturn) {\n\t\t\t\tdanglingCR = true;\n\t\t\t\tif (piece.end.column === 0) {\n\t\t\t\t\t// The last line ended with a \\r, let's undo the push, it will be pushed by next iteration\n\t\t\t\t\tlinesLength--;\n\t\t\t\t} else {\n\t\t\t\t\tcurrentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column - 1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcurrentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column);\n\t\t\t}\n\n\t\t\treturn true;\n\t\t});\n\n\t\tif (danglingCR) {\n\t\t\tlines[linesLength++] = currentLine;\n\t\t\tcurrentLine = '';\n\t\t}\n\n\t\tlines[linesLength++] = currentLine;\n\t\treturn lines;\n\t}\n\n\tpublic getLength(): number {\n\t\treturn this._length;\n\t}\n\n\tpublic getLineCount(): number {\n\t\treturn this._lineCnt;\n\t}\n\n\tpublic getLineContent(lineNumber: number): string {\n\t\tif (this._lastVisitedLine.lineNumber === lineNumber) {\n\t\t\treturn this._lastVisitedLine.value;\n\t\t}\n\n\t\tthis._lastVisitedLine.lineNumber = lineNumber;\n\n\t\tif (lineNumber === this._lineCnt) {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber);\n\t\t} else if (this._EOLNormalized) {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber, this._EOLLength);\n\t\t} else {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber).replace(/(\\r\\n|\\r|\\n)$/, '');\n\t\t}\n\n\t\treturn this._lastVisitedLine.value;\n\t}\n\n\tprivate _getCharCode(nodePos: NodePosition): number {\n\t\tif (nodePos.remainder === nodePos.node.piece.length) {\n\t\t\t// the char we want to fetch is at the head of next node.\n\t\t\tconst matchingNode = nodePos.node.next();\n\t\t\tif (!matchingNode) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[matchingNode.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);\n\t\t\treturn buffer.buffer.charCodeAt(startOffset);\n\t\t} else {\n\t\t\tconst buffer = this._buffers[nodePos.node.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);\n\t\t\tconst targetOffset = startOffset + nodePos.remainder;\n\n\t\t\treturn buffer.buffer.charCodeAt(targetOffset);\n\t\t}\n\t}\n\n\tpublic getLineCharCode(lineNumber: number, index: number): number {\n\t\tconst nodePos = this.nodeAt2(lineNumber, index + 1);\n\t\treturn this._getCharCode(nodePos);\n\t}\n\n\tpublic getLineLength(lineNumber: number): number {\n\t\tif (lineNumber === this.getLineCount()) {\n\t\t\tconst startOffset = this.getOffsetAt(lineNumber, 1);\n\t\t\treturn this.getLength() - startOffset;\n\t\t}\n\t\treturn this.getOffsetAt(lineNumber + 1, 1) - this.getOffsetAt(lineNumber, 1) - this._EOLLength;\n\t}\n\n\tpublic getNearestChunk(offset: number): string {\n\t\tconst nodePos = this.nodeAt(offset);\n\t\tif (nodePos.remainder === nodePos.node.piece.length) {\n\t\t\t// the offset is at the head of next node.\n\t\t\tconst matchingNode = nodePos.node.next();\n\t\t\tif (!matchingNode || matchingNode === SENTINEL) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[matchingNode.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);\n\t\t\treturn buffer.buffer.substring(startOffset, startOffset + matchingNode.piece.length);\n\t\t} else {\n\t\t\tconst buffer = this._buffers[nodePos.node.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);\n\t\t\tconst targetOffset = startOffset + nodePos.remainder;\n\t\t\tconst targetEnd = startOffset + nodePos.node.piece.length;\n\t\t\treturn buffer.buffer.substring(targetOffset, targetEnd);\n\t\t}\n\t}\n\n\tpublic findMatchesInNode(node: TreeNode, searcher: Searcher, startLineNumber: number, startColumn: number, startCursor: BufferCursor, endCursor: BufferCursor, searchData: SearchData, captureMatches: boolean, limitResultCount: number, resultLen: number, result: FindMatch[]) {\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst startOffsetInBuffer = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);\n\t\tconst start = this.offsetInBuffer(node.piece.bufferIndex, startCursor);\n\t\tconst end = this.offsetInBuffer(node.piece.bufferIndex, endCursor);\n\n\t\tlet m: RegExpExecArray | null;\n\t\t// Reset regex to search from the beginning\n\t\tconst ret: BufferCursor = { line: 0, column: 0 };\n\t\tlet searchText: string;\n\t\tlet offsetInBuffer: (offset: number) => number;\n\n\t\tif (searcher._wordSeparators) {\n\t\t\tsearchText = buffer.buffer.substring(start, end);\n\t\t\toffsetInBuffer = (offset: number) => offset + start;\n\t\t\tsearcher.reset(0);\n\t\t} else {\n\t\t\tsearchText = buffer.buffer;\n\t\t\toffsetInBuffer = (offset: number) => offset;\n\t\t\tsearcher.reset(start);\n\t\t}\n\n\t\tdo {\n\t\t\tm = searcher.next(searchText);\n\n\t\t\tif (m) {\n\t\t\t\tif (offsetInBuffer(m.index) >= end) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t\tthis.positionInBuffer(node, offsetInBuffer(m.index) - startOffsetInBuffer, ret);\n\t\t\t\tconst lineFeedCnt = this.getLineFeedCnt(node.piece.bufferIndex, startCursor, ret);\n\t\t\t\tconst retStartColumn = ret.line === startCursor.line ? ret.column - startCursor.column + startColumn : ret.column + 1;\n\t\t\t\tconst retEndColumn = retStartColumn + m[0].length;\n\t\t\t\tresult[resultLen++] = createFindMatch(new Range(startLineNumber + lineFeedCnt, retStartColumn, startLineNumber + lineFeedCnt, retEndColumn), m, captureMatches);\n\n\t\t\t\tif (offsetInBuffer(m.index) + m[0].length >= end) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} while (m);\n\n\t\treturn resultLen;\n\t}\n\n\tpublic findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[] {\n\t\tconst result: FindMatch[] = [];\n\t\tlet resultLen = 0;\n\t\tconst searcher = new Searcher(searchData.wordSeparators, searchData.regex);\n\n\t\tlet startPosition = this.nodeAt2(searchRange.startLineNumber, searchRange.startColumn);\n\t\tif (startPosition === null) {\n\t\t\treturn [];\n\t\t}\n\t\tconst endPosition = this.nodeAt2(searchRange.endLineNumber, searchRange.endColumn);\n\t\tif (endPosition === null) {\n\t\t\treturn [];\n\t\t}\n\t\tlet start = this.positionInBuffer(startPosition.node, startPosition.remainder);\n\t\tconst end = this.positionInBuffer(endPosition.node, endPosition.remainder);\n\n\t\tif (startPosition.node === endPosition.node) {\n\t\t\tthis.findMatchesInNode(startPosition.node, searcher, searchRange.startLineNumber, searchRange.startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);\n\t\t\treturn result;\n\t\t}\n\n\t\tlet startLineNumber = searchRange.startLineNumber;\n\n\t\tlet currentNode = startPosition.node;\n\t\twhile (currentNode !== endPosition.node) {\n\t\t\tconst lineBreakCnt = this.getLineFeedCnt(currentNode.piece.bufferIndex, start, currentNode.piece.end);\n\n\t\t\tif (lineBreakCnt >= 1) {\n\t\t\t\t// last line break position\n\t\t\t\tconst lineStarts = this._buffers[currentNode.piece.bufferIndex].lineStarts;\n\t\t\t\tconst startOffsetInBuffer = this.offsetInBuffer(currentNode.piece.bufferIndex, currentNode.piece.start);\n\t\t\t\tconst nextLineStartOffset = lineStarts[start.line + lineBreakCnt];\n\t\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;\n\t\t\t\tresultLen = this.findMatchesInNode(currentNode, searcher, startLineNumber, startColumn, start, this.positionInBuffer(currentNode, nextLineStartOffset - startOffsetInBuffer), searchData, captureMatches, limitResultCount, resultLen, result);\n\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\tstartLineNumber += lineBreakCnt;\n\t\t\t}\n\n\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;\n\t\t\t// search for the remaining content\n\t\t\tif (startLineNumber === searchRange.endLineNumber) {\n\t\t\t\tconst text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);\n\t\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, this.getLineContent(startLineNumber).substr(startColumn), startLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\n\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tstartLineNumber++;\n\t\t\tstartPosition = this.nodeAt2(startLineNumber, 1);\n\t\t\tcurrentNode = startPosition.node;\n\t\t\tstart = this.positionInBuffer(startPosition.node, startPosition.remainder);\n\t\t}\n\n\t\tif (startLineNumber === searchRange.endLineNumber) {\n\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;\n\t\t\tconst text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);\n\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\t\t\treturn result;\n\t\t}\n\n\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;\n\t\tresultLen = this.findMatchesInNode(endPosition.node, searcher, startLineNumber, startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);\n\t\treturn result;\n\t}\n\n\tprivate _findMatchesInLine(searchData: SearchData, searcher: Searcher, text: string, lineNumber: number, deltaOffset: number, resultLen: number, result: FindMatch[], captureMatches: boolean, limitResultCount: number): number {\n\t\tconst wordSeparators = searchData.wordSeparators;\n\t\tif (!captureMatches && searchData.simpleSearch) {\n\t\t\tconst searchString = searchData.simpleSearch;\n\t\t\tconst searchStringLen = searchString.length;\n\t\t\tconst textLength = text.length;\n\n\t\t\tlet lastMatchIndex = -searchStringLen;\n\t\t\twhile ((lastMatchIndex = text.indexOf(searchString, lastMatchIndex + searchStringLen)) !== -1) {\n\t\t\t\tif (!wordSeparators || isValidMatch(wordSeparators, text, textLength, lastMatchIndex, searchStringLen)) {\n\t\t\t\t\tresult[resultLen++] = new FindMatch(new Range(lineNumber, lastMatchIndex + 1 + deltaOffset, lineNumber, lastMatchIndex + 1 + searchStringLen + deltaOffset), null);\n\t\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\t\treturn resultLen;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn resultLen;\n\t\t}\n\n\t\tlet m: RegExpExecArray | null;\n\t\t// Reset regex to search from the beginning\n\t\tsearcher.reset(0);\n\t\tdo {\n\t\t\tm = searcher.next(text);\n\t\t\tif (m) {\n\t\t\t\tresult[resultLen++] = createFindMatch(new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset), m, captureMatches);\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (m);\n\t\treturn resultLen;\n\t}\n\n\t// #endregion\n\n\t// #region Piece Table\n\tpublic insert(offset: number, value: string, eolNormalized: boolean = false): void {\n\t\tthis._EOLNormalized = this._EOLNormalized && eolNormalized;\n\t\tthis._lastVisitedLine.lineNumber = 0;\n\t\tthis._lastVisitedLine.value = '';\n\n\t\tif (this.root !== SENTINEL) {\n\t\t\tconst { node, remainder, nodeStartOffset } = this.nodeAt(offset);\n\t\t\tconst piece = node.piece;\n\t\t\tconst bufferIndex = piece.bufferIndex;\n\t\t\tconst insertPosInBuffer = this.positionInBuffer(node, remainder);\n\t\t\tif (node.piece.bufferIndex === 0 &&\n\t\t\t\tpiece.end.line === this._lastChangeBufferPos.line &&\n\t\t\t\tpiece.end.column === this._lastChangeBufferPos.column &&\n\t\t\t\t(nodeStartOffset + piece.length === offset) &&\n\t\t\t\tvalue.length < AverageBufferSize\n\t\t\t) {\n\t\t\t\t// changed buffer\n\t\t\t\tthis.appendToNode(node, value);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (nodeStartOffset === offset) {\n\t\t\t\tthis.insertContentToNodeLeft(value, node);\n\t\t\t\tthis._searchCache.validate(offset);\n\t\t\t} else if (nodeStartOffset + node.piece.length > offset) {\n\t\t\t\t// we are inserting into the middle of a node.\n\t\t\t\tconst nodesToDel: TreeNode[] = [];\n\t\t\t\tlet newRightPiece = new Piece(\n\t\t\t\t\tpiece.bufferIndex,\n\t\t\t\t\tinsertPosInBuffer,\n\t\t\t\t\tpiece.end,\n\t\t\t\t\tthis.getLineFeedCnt(piece.bufferIndex, insertPosInBuffer, piece.end),\n\t\t\t\t\tthis.offsetInBuffer(bufferIndex, piece.end) - this.offsetInBuffer(bufferIndex, insertPosInBuffer)\n\t\t\t\t);\n\n\t\t\t\tif (this.shouldCheckCRLF() && this.endWithCR(value)) {\n\t\t\t\t\tconst headOfRight = this.nodeCharCodeAt(node, remainder);\n\n\t\t\t\t\tif (headOfRight === 10 /** \\n */) {\n\t\t\t\t\t\tconst newStart: BufferCursor = { line: newRightPiece.start.line + 1, column: 0 };\n\t\t\t\t\t\tnewRightPiece = new Piece(\n\t\t\t\t\t\t\tnewRightPiece.bufferIndex,\n\t\t\t\t\t\t\tnewStart,\n\t\t\t\t\t\t\tnewRightPiece.end,\n\t\t\t\t\t\t\tthis.getLineFeedCnt(newRightPiece.bufferIndex, newStart, newRightPiece.end),\n\t\t\t\t\t\t\tnewRightPiece.length - 1\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tvalue += '\\n';\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// reuse node for content before insertion point.\n\t\t\t\tif (this.shouldCheckCRLF() && this.startWithLF(value)) {\n\t\t\t\t\tconst tailOfLeft = this.nodeCharCodeAt(node, remainder - 1);\n\t\t\t\t\tif (tailOfLeft === 13 /** \\r */) {\n\t\t\t\t\t\tconst previousPos = this.positionInBuffer(node, remainder - 1);\n\t\t\t\t\t\tthis.deleteNodeTail(node, previousPos);\n\t\t\t\t\t\tvalue = '\\r' + value;\n\n\t\t\t\t\t\tif (node.piece.length === 0) {\n\t\t\t\t\t\t\tnodesToDel.push(node);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.deleteNodeTail(node, insertPosInBuffer);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.deleteNodeTail(node, insertPosInBuffer);\n\t\t\t\t}\n\n\t\t\t\tconst newPieces = this.createNewPieces(value);\n\t\t\t\tif (newRightPiece.length > 0) {\n\t\t\t\t\tthis.rbInsertRight(node, newRightPiece);\n\t\t\t\t}\n\n\t\t\t\tlet tmpNode = node;\n\t\t\t\tfor (let k = 0; k < newPieces.length; k++) {\n\t\t\t\t\ttmpNode = this.rbInsertRight(tmpNode, newPieces[k]);\n\t\t\t\t}\n\t\t\t\tthis.deleteNodes(nodesToDel);\n\t\t\t} else {\n\t\t\t\tthis.insertContentToNodeRight(value, node);\n\t\t\t}\n\t\t} else {\n\t\t\t// insert new node\n\t\t\tconst pieces = this.createNewPieces(value);\n\t\t\tlet node = this.rbInsertLeft(null, pieces[0]);\n\n\t\t\tfor (let k = 1; k < pieces.length; k++) {\n\t\t\t\tnode = this.rbInsertRight(node, pieces[k]);\n\t\t\t}\n\t\t}\n\n\t\t// todo, this is too brutal. Total line feed count should be updated the same way as lf_left.\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tpublic delete(offset: number, cnt: number): void {\n\t\tthis._lastVisitedLine.lineNumber = 0;\n\t\tthis._lastVisitedLine.value = '';\n\n\t\tif (cnt <= 0 || this.root === SENTINEL) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst startPosition = this.nodeAt(offset);\n\t\tconst endPosition = this.nodeAt(offset + cnt);\n\t\tconst startNode = startPosition.node;\n\t\tconst endNode = endPosition.node;\n\n\t\tif (startNode === endNode) {\n\t\t\tconst startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);\n\t\t\tconst endSplitPosInBuffer = this.positionInBuffer(startNode, endPosition.remainder);\n\n\t\t\tif (startPosition.nodeStartOffset === offset) {\n\t\t\t\tif (cnt === startNode.piece.length) { // delete node\n\t\t\t\t\tconst next = startNode.next();\n\t\t\t\t\trbDelete(this, startNode);\n\t\t\t\t\tthis.validateCRLFWithPrevNode(next);\n\t\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.deleteNodeHead(startNode, endSplitPosInBuffer);\n\t\t\t\tthis._searchCache.validate(offset);\n\t\t\t\tthis.validateCRLFWithPrevNode(startNode);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (startPosition.nodeStartOffset + startNode.piece.length === offset + cnt) {\n\t\t\t\tthis.deleteNodeTail(startNode, startSplitPosInBuffer);\n\t\t\t\tthis.validateCRLFWithNextNode(startNode);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// delete content in the middle, this node will be splitted to nodes\n\t\t\tthis.shrinkNode(startNode, startSplitPosInBuffer, endSplitPosInBuffer);\n\t\t\tthis.computeBufferMetadata();\n\t\t\treturn;\n\t\t}\n\n\t\tconst nodesToDel: TreeNode[] = [];\n\n\t\tconst startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);\n\t\tthis.deleteNodeTail(startNode, startSplitPosInBuffer);\n\t\tthis._searchCache.validate(offset);\n\t\tif (startNode.piece.length === 0) {\n\t\t\tnodesToDel.push(startNode);\n\t\t}\n\n\t\t// update last touched node\n\t\tconst endSplitPosInBuffer = this.positionInBuffer(endNode, endPosition.remainder);\n\t\tthis.deleteNodeHead(endNode, endSplitPosInBuffer);\n\t\tif (endNode.piece.length === 0) {\n\t\t\tnodesToDel.push(endNode);\n\t\t}\n\n\t\t// delete nodes in between\n\t\tconst secondNode = startNode.next();\n\t\tfor (let node = secondNode; node !== SENTINEL && node !== endNode; node = node.next()) {\n\t\t\tnodesToDel.push(node);\n\t\t}\n\n\t\tconst prev = startNode.piece.length === 0 ? startNode.prev() : startNode;\n\t\tthis.deleteNodes(nodesToDel);\n\t\tthis.validateCRLFWithNextNode(prev);\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tprivate insertContentToNodeLeft(value: string, node: TreeNode) {\n\t\t// we are inserting content to the beginning of node\n\t\tconst nodesToDel: TreeNode[] = [];\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(value) && this.startWithLF(node)) {\n\t\t\t// move `\\n` to new node.\n\n\t\t\tconst piece = node.piece;\n\t\t\tconst newStart: BufferCursor = { line: piece.start.line + 1, column: 0 };\n\t\t\tconst nPiece = new Piece(\n\t\t\t\tpiece.bufferIndex,\n\t\t\t\tnewStart,\n\t\t\t\tpiece.end,\n\t\t\t\tthis.getLineFeedCnt(piece.bufferIndex, newStart, piece.end),\n\t\t\t\tpiece.length - 1\n\t\t\t);\n\n\t\t\tnode.piece = nPiece;\n\n\t\t\tvalue += '\\n';\n\t\t\tupdateTreeMetadata(this, node, -1, -1);\n\n\t\t\tif (node.piece.length === 0) {\n\t\t\t\tnodesToDel.push(node);\n\t\t\t}\n\t\t}\n\n\t\tconst newPieces = this.createNewPieces(value);\n\t\tlet newNode = this.rbInsertLeft(node, newPieces[newPieces.length - 1]);\n\t\tfor (let k = newPieces.length - 2; k >= 0; k--) {\n\t\t\tnewNode = this.rbInsertLeft(newNode, newPieces[k]);\n\t\t}\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t\tthis.deleteNodes(nodesToDel);\n\t}\n\n\tprivate insertContentToNodeRight(value: string, node: TreeNode) {\n\t\t// we are inserting to the right of this node.\n\t\tif (this.adjustCarriageReturnFromNext(value, node)) {\n\t\t\t// move \\n to the new node.\n\t\t\tvalue += '\\n';\n\t\t}\n\n\t\tconst newPieces = this.createNewPieces(value);\n\t\tconst newNode = this.rbInsertRight(node, newPieces[0]);\n\t\tlet tmpNode = newNode;\n\n\t\tfor (let k = 1; k < newPieces.length; k++) {\n\t\t\ttmpNode = this.rbInsertRight(tmpNode, newPieces[k]);\n\t\t}\n\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t}\n\n\tprivate positionInBuffer(node: TreeNode, remainder: number): BufferCursor;\n\tprivate positionInBuffer(node: TreeNode, remainder: number, ret: BufferCursor): null;\n\tprivate positionInBuffer(node: TreeNode, remainder: number, ret?: BufferCursor): BufferCursor | null {\n\t\tconst piece = node.piece;\n\t\tconst bufferIndex = node.piece.bufferIndex;\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\n\t\tconst startOffset = lineStarts[piece.start.line] + piece.start.column;\n\n\t\tconst offset = startOffset + remainder;\n\n\t\t// binary search offset between startOffset and endOffset\n\t\tlet low = piece.start.line;\n\t\tlet high = piece.end.line;\n\n\t\tlet mid: number = 0;\n\t\tlet midStop: number = 0;\n\t\tlet midStart: number = 0;\n\n\t\twhile (low <= high) {\n\t\t\tmid = low + ((high - low) / 2) | 0;\n\t\t\tmidStart = lineStarts[mid];\n\n\t\t\tif (mid === high) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tmidStop = lineStarts[mid + 1];\n\n\t\t\tif (offset < midStart) {\n\t\t\t\thigh = mid - 1;\n\t\t\t} else if (offset >= midStop) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (ret) {\n\t\t\tret.line = mid;\n\t\t\tret.column = offset - midStart;\n\t\t\treturn null;\n\t\t}\n\n\t\treturn {\n\t\t\tline: mid,\n\t\t\tcolumn: offset - midStart\n\t\t};\n\t}\n\n\tprivate getLineFeedCnt(bufferIndex: number, start: BufferCursor, end: BufferCursor): number {\n\t\t// we don't need to worry about start: abc\\r|\\n, or abc|\\r, or abc|\\n, or abc|\\r\\n doesn't change the fact that, there is one line break after start.\n\t\t// now let's take care of end: abc\\r|\\n, if end is in between \\r and \\n, we need to add line feed count by 1\n\t\tif (end.column === 0) {\n\t\t\treturn end.line - start.line;\n\t\t}\n\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\t\tif (end.line === lineStarts.length - 1) { // it means, there is no \\n after end, otherwise, there will be one more lineStart.\n\t\t\treturn end.line - start.line;\n\t\t}\n\n\t\tconst nextLineStartOffset = lineStarts[end.line + 1];\n\t\tconst endOffset = lineStarts[end.line] + end.column;\n\t\tif (nextLineStartOffset > endOffset + 1) { // there are more than 1 character after end, which means it can't be \\n\n\t\t\treturn end.line - start.line;\n\t\t}\n\t\t// endOffset + 1 === nextLineStartOffset\n\t\t// character at endOffset is \\n, so we check the character before first\n\t\t// if character at endOffset is \\r, end.column is 0 and we can't get here.\n\t\tconst previousCharOffset = endOffset - 1; // end.column > 0 so it's okay.\n\t\tconst buffer = this._buffers[bufferIndex].buffer;\n\n\t\tif (buffer.charCodeAt(previousCharOffset) === 13) {\n\t\t\treturn end.line - start.line + 1;\n\t\t} else {\n\t\t\treturn end.line - start.line;\n\t\t}\n\t}\n\n\tprivate offsetInBuffer(bufferIndex: number, cursor: BufferCursor): number {\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\t\treturn lineStarts[cursor.line] + cursor.column;\n\t}\n\n\tprivate deleteNodes(nodes: TreeNode[]): void {\n\t\tfor (let i = 0; i < nodes.length; i++) {\n\t\t\trbDelete(this, nodes[i]);\n\t\t}\n\t}\n\n\tprivate createNewPieces(text: string): Piece[] {\n\t\tif (text.length > AverageBufferSize) {\n\t\t\t// the content is large, operations like substring, charCode becomes slow\n\t\t\t// so here we split it into smaller chunks, just like what we did for CR/LF normalization\n\t\t\tconst newPieces: Piece[] = [];\n\t\t\twhile (text.length > AverageBufferSize) {\n\t\t\t\tconst lastChar = text.charCodeAt(AverageBufferSize - 1);\n\t\t\t\tlet splitText;\n\t\t\t\tif (lastChar === CharCode.CarriageReturn || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {\n\t\t\t\t\t// last character is \\r or a high surrogate => keep it back\n\t\t\t\t\tsplitText = text.substring(0, AverageBufferSize - 1);\n\t\t\t\t\ttext = text.substring(AverageBufferSize - 1);\n\t\t\t\t} else {\n\t\t\t\t\tsplitText = text.substring(0, AverageBufferSize);\n\t\t\t\t\ttext = text.substring(AverageBufferSize);\n\t\t\t\t}\n\n\t\t\t\tconst lineStarts = createLineStartsFast(splitText);\n\t\t\t\tnewPieces.push(new Piece(\n\t\t\t\t\tthis._buffers.length, /* buffer index */\n\t\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t\t{ line: lineStarts.length - 1, column: splitText.length - lineStarts[lineStarts.length - 1] },\n\t\t\t\t\tlineStarts.length - 1,\n\t\t\t\t\tsplitText.length\n\t\t\t\t));\n\t\t\t\tthis._buffers.push(new StringBuffer(splitText, lineStarts));\n\t\t\t}\n\n\t\t\tconst lineStarts = createLineStartsFast(text);\n\t\t\tnewPieces.push(new Piece(\n\t\t\t\tthis._buffers.length, /* buffer index */\n\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t{ line: lineStarts.length - 1, column: text.length - lineStarts[lineStarts.length - 1] },\n\t\t\t\tlineStarts.length - 1,\n\t\t\t\ttext.length\n\t\t\t));\n\t\t\tthis._buffers.push(new StringBuffer(text, lineStarts));\n\n\t\t\treturn newPieces;\n\t\t}\n\n\t\tlet startOffset = this._buffers[0].buffer.length;\n\t\tconst lineStarts = createLineStartsFast(text, false);\n\n\t\tlet start = this._lastChangeBufferPos;\n\t\tif (this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 1] === startOffset\n\t\t\t&& startOffset !== 0\n\t\t\t&& this.startWithLF(text)\n\t\t\t&& this.endWithCR(this._buffers[0].buffer) // todo, we can check this._lastChangeBufferPos's column as it's the last one\n\t\t) {\n\t\t\tthis._lastChangeBufferPos = { line: this._lastChangeBufferPos.line, column: this._lastChangeBufferPos.column + 1 };\n\t\t\tstart = this._lastChangeBufferPos;\n\n\t\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\t\tlineStarts[i] += startOffset + 1;\n\t\t\t}\n\n\t\t\tthis._buffers[0].lineStarts = (<number[]>this._buffers[0].lineStarts).concat(<number[]>lineStarts.slice(1));\n\t\t\tthis._buffers[0].buffer += '_' + text;\n\t\t\tstartOffset += 1;\n\t\t} else {\n\t\t\tif (startOffset !== 0) {\n\t\t\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\t\t\tlineStarts[i] += startOffset;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._buffers[0].lineStarts = (<number[]>this._buffers[0].lineStarts).concat(<number[]>lineStarts.slice(1));\n\t\t\tthis._buffers[0].buffer += text;\n\t\t}\n\n\t\tconst endOffset = this._buffers[0].buffer.length;\n\t\tconst endIndex = this._buffers[0].lineStarts.length - 1;\n\t\tconst endColumn = endOffset - this._buffers[0].lineStarts[endIndex];\n\t\tconst endPos = { line: endIndex, column: endColumn };\n\t\tconst newPiece = new Piece(\n\t\t\t0, /** todo@peng */\n\t\t\tstart,\n\t\t\tendPos,\n\t\t\tthis.getLineFeedCnt(0, start, endPos),\n\t\t\tendOffset - startOffset\n\t\t);\n\t\tthis._lastChangeBufferPos = endPos;\n\t\treturn [newPiece];\n\t}\n\n\tpublic getLineRawContent(lineNumber: number, endOffset: number = 0): string {\n\t\tlet x = this.root;\n\n\t\tlet ret = '';\n\t\tconst cache = this._searchCache.get2(lineNumber);\n\t\tif (cache) {\n\t\t\tx = cache.node;\n\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber - 1);\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\tif (cache.nodeStartLineNumber + x.piece.lineFeedCnt === lineNumber) {\n\t\t\t\tret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);\n\t\t\t} else {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber);\n\t\t\t\treturn buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);\n\t\t\t}\n\t\t} else {\n\t\t\tlet nodeStartOffset = 0;\n\t\t\tconst originalLineNumber = lineNumber;\n\t\t\twhile (x !== SENTINEL) {\n\t\t\t\tif (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {\n\t\t\t\t\tx = x.left;\n\t\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {\n\t\t\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);\n\t\t\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\t\t\tnodeStartOffset += x.size_left;\n\t\t\t\t\tthis._searchCache.set({\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tnodeStartOffset,\n\t\t\t\t\t\tnodeStartLineNumber: originalLineNumber - (lineNumber - 1 - x.lf_left)\n\t\t\t\t\t});\n\n\t\t\t\t\treturn buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);\n\t\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {\n\t\t\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\t\t\tret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\t\tx = x.right;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// search in order, to find the node contains end column\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\n\t\t\tif (x.piece.lineFeedCnt > 0) {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, 0);\n\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\t\tret += buffer.substring(startOffset, startOffset + accumulatedValue - endOffset);\n\t\t\t\treturn ret;\n\t\t\t} else {\n\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\t\tret += buffer.substr(startOffset, x.piece.length);\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tprivate computeBufferMetadata() {\n\t\tlet x = this.root;\n\n\t\tlet lfCnt = 1;\n\t\tlet len = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tlfCnt += x.lf_left + x.piece.lineFeedCnt;\n\t\t\tlen += x.size_left + x.piece.length;\n\t\t\tx = x.right;\n\t\t}\n\n\t\tthis._lineCnt = lfCnt;\n\t\tthis._length = len;\n\t\tthis._searchCache.validate(this._length);\n\t}\n\n\t// #region node operations\n\tprivate getIndexOf(node: TreeNode, accumulatedValue: number): { index: number; remainder: number } {\n\t\tconst piece = node.piece;\n\t\tconst pos = this.positionInBuffer(node, accumulatedValue);\n\t\tconst lineCnt = pos.line - piece.start.line;\n\n\t\tif (this.offsetInBuffer(piece.bufferIndex, piece.end) - this.offsetInBuffer(piece.bufferIndex, piece.start) === accumulatedValue) {\n\t\t\t// we are checking the end of this node, so a CRLF check is necessary.\n\t\t\tconst realLineCnt = this.getLineFeedCnt(node.piece.bufferIndex, piece.start, pos);\n\t\t\tif (realLineCnt !== lineCnt) {\n\t\t\t\t// aha yes, CRLF\n\t\t\t\treturn { index: realLineCnt, remainder: 0 };\n\t\t\t}\n\t\t}\n\n\t\treturn { index: lineCnt, remainder: pos.column };\n\t}\n\n\tprivate getAccumulatedValue(node: TreeNode, index: number) {\n\t\tif (index < 0) {\n\t\t\treturn 0;\n\t\t}\n\t\tconst piece = node.piece;\n\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\t\tconst expectedLineStartIndex = piece.start.line + index + 1;\n\t\tif (expectedLineStartIndex > piece.end.line) {\n\t\t\treturn lineStarts[piece.end.line] + piece.end.column - lineStarts[piece.start.line] - piece.start.column;\n\t\t} else {\n\t\t\treturn lineStarts[expectedLineStartIndex] - lineStarts[piece.start.line] - piece.start.column;\n\t\t}\n\t}\n\n\tprivate deleteNodeTail(node: TreeNode, pos: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalLFCnt = piece.lineFeedCnt;\n\t\tconst originalEndOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\n\t\tconst newEnd = pos;\n\t\tconst newEndOffset = this.offsetInBuffer(piece.bufferIndex, newEnd);\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);\n\n\t\tconst lf_delta = newLineFeedCnt - originalLFCnt;\n\t\tconst size_delta = newEndOffset - originalEndOffset;\n\t\tconst newLength = piece.length + size_delta;\n\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tpiece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, size_delta, lf_delta);\n\t}\n\n\tprivate deleteNodeHead(node: TreeNode, pos: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalLFCnt = piece.lineFeedCnt;\n\t\tconst originalStartOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\n\t\tconst newStart = pos;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);\n\t\tconst newStartOffset = this.offsetInBuffer(piece.bufferIndex, newStart);\n\t\tconst lf_delta = newLineFeedCnt - originalLFCnt;\n\t\tconst size_delta = originalStartOffset - newStartOffset;\n\t\tconst newLength = piece.length + size_delta;\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tnewStart,\n\t\t\tpiece.end,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, size_delta, lf_delta);\n\t}\n\n\tprivate shrinkNode(node: TreeNode, start: BufferCursor, end: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalStartPos = piece.start;\n\t\tconst originalEndPos = piece.end;\n\n\t\t// old piece, originalStartPos, start\n\t\tconst oldLength = piece.length;\n\t\tconst oldLFCnt = piece.lineFeedCnt;\n\t\tconst newEnd = start;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);\n\t\tconst newLength = this.offsetInBuffer(piece.bufferIndex, start) - this.offsetInBuffer(piece.bufferIndex, originalStartPos);\n\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tpiece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, newLength - oldLength, newLineFeedCnt - oldLFCnt);\n\n\t\t// new right piece, end, originalEndPos\n\t\tconst newPiece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tend,\n\t\t\toriginalEndPos,\n\t\t\tthis.getLineFeedCnt(piece.bufferIndex, end, originalEndPos),\n\t\t\tthis.offsetInBuffer(piece.bufferIndex, originalEndPos) - this.offsetInBuffer(piece.bufferIndex, end)\n\t\t);\n\n\t\tconst newNode = this.rbInsertRight(node, newPiece);\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t}\n\n\tprivate appendToNode(node: TreeNode, value: string): void {\n\t\tif (this.adjustCarriageReturnFromNext(value, node)) {\n\t\t\tvalue += '\\n';\n\t\t}\n\n\t\tconst hitCRLF = this.shouldCheckCRLF() && this.startWithLF(value) && this.endWithCR(node);\n\t\tconst startOffset = this._buffers[0].buffer.length;\n\t\tthis._buffers[0].buffer += value;\n\t\tconst lineStarts = createLineStartsFast(value, false);\n\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\tlineStarts[i] += startOffset;\n\t\t}\n\t\tif (hitCRLF) {\n\t\t\tconst prevStartOffset = this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 2];\n\t\t\t(<number[]>this._buffers[0].lineStarts).pop();\n\t\t\t// _lastChangeBufferPos is already wrong\n\t\t\tthis._lastChangeBufferPos = { line: this._lastChangeBufferPos.line - 1, column: startOffset - prevStartOffset };\n\t\t}\n\n\t\tthis._buffers[0].lineStarts = (<number[]>this._buffers[0].lineStarts).concat(<number[]>lineStarts.slice(1));\n\t\tconst endIndex = this._buffers[0].lineStarts.length - 1;\n\t\tconst endColumn = this._buffers[0].buffer.length - this._buffers[0].lineStarts[endIndex];\n\t\tconst newEnd = { line: endIndex, column: endColumn };\n\t\tconst newLength = node.piece.length + value.length;\n\t\tconst oldLineFeedCnt = node.piece.lineFeedCnt;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(0, node.piece.start, newEnd);\n\t\tconst lf_delta = newLineFeedCnt - oldLineFeedCnt;\n\n\t\tnode.piece = new Piece(\n\t\t\tnode.piece.bufferIndex,\n\t\t\tnode.piece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tthis._lastChangeBufferPos = newEnd;\n\t\tupdateTreeMetadata(this, node, value.length, lf_delta);\n\t}\n\n\tprivate nodeAt(offset: number): NodePosition {\n\t\tlet x = this.root;\n\t\tconst cache = this._searchCache.get(offset);\n\t\tif (cache) {\n\t\t\treturn {\n\t\t\t\tnode: cache.node,\n\t\t\t\tnodeStartOffset: cache.nodeStartOffset,\n\t\t\t\tremainder: offset - cache.nodeStartOffset\n\t\t\t};\n\t\t}\n\n\t\tlet nodeStartOffset = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.size_left > offset) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.size_left + x.piece.length >= offset) {\n\t\t\t\tnodeStartOffset += x.size_left;\n\t\t\t\tconst ret = {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: offset - x.size_left,\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t\tthis._searchCache.set(ret);\n\t\t\t\treturn ret;\n\t\t\t} else {\n\t\t\t\toffset -= x.size_left + x.piece.length;\n\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\treturn null!;\n\t}\n\n\tprivate nodeAt2(lineNumber: number, column: number): NodePosition {\n\t\tlet x = this.root;\n\t\tlet nodeStartOffset = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {\n\t\t\t\tconst prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);\n\t\t\t\tnodeStartOffset += x.size_left;\n\n\t\t\t\treturn {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: Math.min(prevAccumualtedValue + column - 1, accumulatedValue),\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {\n\t\t\t\tconst prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\tif (prevAccumualtedValue + column - 1 <= x.piece.length) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tremainder: prevAccumualtedValue + column - 1,\n\t\t\t\t\t\tnodeStartOffset\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tcolumn -= x.piece.length - prevAccumualtedValue;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\t// search in order, to find the node contains position.column\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\n\t\t\tif (x.piece.lineFeedCnt > 0) {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, 0);\n\t\t\t\tconst nodeStartOffset = this.offsetOfNode(x);\n\t\t\t\treturn {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: Math.min(column - 1, accumulatedValue),\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tif (x.piece.length >= column - 1) {\n\t\t\t\t\tconst nodeStartOffset = this.offsetOfNode(x);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tremainder: column - 1,\n\t\t\t\t\t\tnodeStartOffset\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tcolumn -= x.piece.length;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn null!;\n\t}\n\n\tprivate nodeCharCodeAt(node: TreeNode, offset: number): number {\n\t\tif (node.piece.lineFeedCnt < 1) {\n\t\t\treturn -1;\n\t\t}\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst newOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start) + offset;\n\t\treturn buffer.buffer.charCodeAt(newOffset);\n\t}\n\n\tprivate offsetOfNode(node: TreeNode): number {\n\t\tif (!node) {\n\t\t\treturn 0;\n\t\t}\n\t\tlet pos = node.size_left;\n\t\twhile (node !== this.root) {\n\t\t\tif (node.parent.right === node) {\n\t\t\t\tpos += node.parent.size_left + node.parent.piece.length;\n\t\t\t}\n\n\t\t\tnode = node.parent;\n\t\t}\n\n\t\treturn pos;\n\t}\n\n\t// #endregion\n\n\t// #region CRLF\n\tprivate shouldCheckCRLF() {\n\t\treturn !(this._EOLNormalized && this._EOL === '\\n');\n\t}\n\n\tprivate startWithLF(val: string | TreeNode): boolean {\n\t\tif (typeof val === 'string') {\n\t\t\treturn val.charCodeAt(0) === 10;\n\t\t}\n\n\t\tif (val === SENTINEL || val.piece.lineFeedCnt === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst piece = val.piece;\n\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\t\tconst line = piece.start.line;\n\t\tconst startOffset = lineStarts[line] + piece.start.column;\n\t\tif (line === lineStarts.length - 1) {\n\t\t\t// last line, so there is no line feed at the end of this line\n\t\t\treturn false;\n\t\t}\n\t\tconst nextLineOffset = lineStarts[line + 1];\n\t\tif (nextLineOffset > startOffset + 1) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this._buffers[piece.bufferIndex].buffer.charCodeAt(startOffset) === 10;\n\t}\n\n\tprivate endWithCR(val: string | TreeNode): boolean {\n\t\tif (typeof val === 'string') {\n\t\t\treturn val.charCodeAt(val.length - 1) === 13;\n\t\t}\n\n\t\tif (val === SENTINEL || val.piece.lineFeedCnt === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.nodeCharCodeAt(val, val.piece.length - 1) === 13;\n\t}\n\n\tprivate validateCRLFWithPrevNode(nextNode: TreeNode) {\n\t\tif (this.shouldCheckCRLF() && this.startWithLF(nextNode)) {\n\t\t\tconst node = nextNode.prev();\n\t\t\tif (this.endWithCR(node)) {\n\t\t\t\tthis.fixCRLF(node, nextNode);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate validateCRLFWithNextNode(node: TreeNode) {\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(node)) {\n\t\t\tconst nextNode = node.next();\n\t\t\tif (this.startWithLF(nextNode)) {\n\t\t\t\tthis.fixCRLF(node, nextNode);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fixCRLF(prev: TreeNode, next: TreeNode) {\n\t\tconst nodesToDel: TreeNode[] = [];\n\t\t// update node\n\t\tconst lineStarts = this._buffers[prev.piece.bufferIndex].lineStarts;\n\t\tlet newEnd: BufferCursor;\n\t\tif (prev.piece.end.column === 0) {\n\t\t\t// it means, last line ends with \\r, not \\r\\n\n\t\t\tnewEnd = { line: prev.piece.end.line - 1, column: lineStarts[prev.piece.end.line] - lineStarts[prev.piece.end.line - 1] - 1 };\n\t\t} else {\n\t\t\t// \\r\\n\n\t\t\tnewEnd = { line: prev.piece.end.line, column: prev.piece.end.column - 1 };\n\t\t}\n\n\t\tconst prevNewLength = prev.piece.length - 1;\n\t\tconst prevNewLFCnt = prev.piece.lineFeedCnt - 1;\n\t\tprev.piece = new Piece(\n\t\t\tprev.piece.bufferIndex,\n\t\t\tprev.piece.start,\n\t\t\tnewEnd,\n\t\t\tprevNewLFCnt,\n\t\t\tprevNewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, prev, - 1, -1);\n\t\tif (prev.piece.length === 0) {\n\t\t\tnodesToDel.push(prev);\n\t\t}\n\n\t\t// update nextNode\n\t\tconst newStart: BufferCursor = { line: next.piece.start.line + 1, column: 0 };\n\t\tconst newLength = next.piece.length - 1;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(next.piece.bufferIndex, newStart, next.piece.end);\n\t\tnext.piece = new Piece(\n\t\t\tnext.piece.bufferIndex,\n\t\t\tnewStart,\n\t\t\tnext.piece.end,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, next, - 1, -1);\n\t\tif (next.piece.length === 0) {\n\t\t\tnodesToDel.push(next);\n\t\t}\n\n\t\t// create new piece which contains \\r\\n\n\t\tconst pieces = this.createNewPieces('\\r\\n');\n\t\tthis.rbInsertRight(prev, pieces[0]);\n\t\t// delete empty nodes\n\n\t\tfor (let i = 0; i < nodesToDel.length; i++) {\n\t\t\trbDelete(this, nodesToDel[i]);\n\t\t}\n\t}\n\n\tprivate adjustCarriageReturnFromNext(value: string, node: TreeNode): boolean {\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(value)) {\n\t\t\tconst nextNode = node.next();\n\t\t\tif (this.startWithLF(nextNode)) {\n\t\t\t\t// move `\\n` forward\n\t\t\t\tvalue += '\\n';\n\n\t\t\t\tif (nextNode.piece.length === 1) {\n\t\t\t\t\trbDelete(this, nextNode);\n\t\t\t\t} else {\n\n\t\t\t\t\tconst piece = nextNode.piece;\n\t\t\t\t\tconst newStart: BufferCursor = { line: piece.start.line + 1, column: 0 };\n\t\t\t\t\tconst newLength = piece.length - 1;\n\t\t\t\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);\n\t\t\t\t\tnextNode.piece = new Piece(\n\t\t\t\t\t\tpiece.bufferIndex,\n\t\t\t\t\t\tnewStart,\n\t\t\t\t\t\tpiece.end,\n\t\t\t\t\t\tnewLineFeedCnt,\n\t\t\t\t\t\tnewLength\n\t\t\t\t\t);\n\n\t\t\t\t\tupdateTreeMetadata(this, nextNode, -1, -1);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t// #endregion\n\n\t// #endregion\n\n\t// #region Tree operations\n\titerate(node: TreeNode, callback: (node: TreeNode) => boolean): boolean {\n\t\tif (node === SENTINEL) {\n\t\t\treturn callback(SENTINEL);\n\t\t}\n\n\t\tconst leftRet = this.iterate(node.left, callback);\n\t\tif (!leftRet) {\n\t\t\treturn leftRet;\n\t\t}\n\n\t\treturn callback(node) && this.iterate(node.right, callback);\n\t}\n\n\tprivate getNodeContent(node: TreeNode) {\n\t\tif (node === SENTINEL) {\n\t\t\treturn '';\n\t\t}\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst piece = node.piece;\n\t\tconst startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\t\tconst endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\t\tconst currentContent = buffer.buffer.substring(startOffset, endOffset);\n\t\treturn currentContent;\n\t}\n\n\tgetPieceContent(piece: Piece) {\n\t\tconst buffer = this._buffers[piece.bufferIndex];\n\t\tconst startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\t\tconst endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\t\tconst currentContent = buffer.buffer.substring(startOffset, endOffset);\n\t\treturn currentContent;\n\t}\n\n\t/**\n\t * node node\n\t * / \\ / \\\n\t * a b <---- a b\n\t * /\n\t * z\n\t */\n\tprivate rbInsertRight(node: TreeNode | null, p: Piece): TreeNode {\n\t\tconst z = new TreeNode(p, NodeColor.Red);\n\t\tz.left = SENTINEL;\n\t\tz.right = SENTINEL;\n\t\tz.parent = SENTINEL;\n\t\tz.size_left = 0;\n\t\tz.lf_left = 0;\n\n\t\tconst x = this.root;\n\t\tif (x === SENTINEL) {\n\t\t\tthis.root = z;\n\t\t\tz.color = NodeColor.Black;\n\t\t} else if (node!.right === SENTINEL) {\n\t\t\tnode!.right = z;\n\t\t\tz.parent = node!;\n\t\t} else {\n\t\t\tconst nextNode = leftest(node!.right);\n\t\t\tnextNode.left = z;\n\t\t\tz.parent = nextNode;\n\t\t}\n\n\t\tfixInsert(this, z);\n\t\treturn z;\n\t}\n\n\t/**\n\t * node node\n\t * / \\ / \\\n\t * a b ----> a b\n\t * \\\n\t * z\n\t */\n\tprivate rbInsertLeft(node: TreeNode | null, p: Piece): TreeNode {\n\t\tconst z = new TreeNode(p, NodeColor.Red);\n\t\tz.left = SENTINEL;\n\t\tz.right = SENTINEL;\n\t\tz.parent = SENTINEL;\n\t\tz.size_left = 0;\n\t\tz.lf_left = 0;\n\n\t\tif (this.root === SENTINEL) {\n\t\t\tthis.root = z;\n\t\t\tz.color = NodeColor.Black;\n\t\t} else if (node!.left === SENTINEL) {\n\t\t\tnode!.left = z;\n\t\t\tz.parent = node!;\n\t\t} else {\n\t\t\tconst prevNode = righttest(node!.left); // a\n\t\t\tprevNode.right = z;\n\t\t\tz.parent = prevNode;\n\t\t}\n\n\t\tfixInsert(this, z);\n\t\treturn z;\n\t}\n\t// #endregion\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts","vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts"],"names":[],"mappings":"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","file":"pieceTreeBase.js","sourceRoot":"file:///mnt/vss/_work/1/s/dependencies/vscode/out-editor-src","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from '../../../../base/common/charCode.js';\nimport { Position } from '../../core/position.js';\nimport { Range } from '../../core/range.js';\nimport { FindMatch, ITextSnapshot, SearchData } from '../../model.js';\nimport { NodeColor, SENTINEL, TreeNode, fixInsert, leftest, rbDelete, righttest, updateTreeMetadata } from './rbTreeBase.js';\nimport { Searcher, createFindMatch, isValidMatch } from '../textModelSearch.js';\n\n// const lfRegex = new RegExp(/\\r\\n|\\r|\\n/g);\nconst AverageBufferSize = 65535;\n\nfunction createUintArray(arr: number[]): Uint32Array | Uint16Array {\n\tlet r;\n\tif (arr[arr.length - 1] < 65536) {\n\t\tr = new Uint16Array(arr.length);\n\t} else {\n\t\tr = new Uint32Array(arr.length);\n\t}\n\tr.set(arr, 0);\n\treturn r;\n}\n\nclass LineStarts {\n\tconstructor(\n\t\tpublic readonly lineStarts: Uint32Array | Uint16Array | number[],\n\t\tpublic readonly cr: number,\n\t\tpublic readonly lf: number,\n\t\tpublic readonly crlf: number,\n\t\tpublic readonly isBasicASCII: boolean\n\t) { }\n}\n\nexport function createLineStartsFast(str: string, readonly: boolean = true): Uint32Array | Uint16Array | number[] {\n\tconst r: number[] = [0];\n\tlet rLength = 1;\n\n\tfor (let i = 0, len = str.length; i < len; i++) {\n\t\tconst chr = str.charCodeAt(i);\n\n\t\tif (chr === CharCode.CarriageReturn) {\n\t\t\tif (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) {\n\t\t\t\t// \\r\\n... case\n\t\t\t\tr[rLength++] = i + 2;\n\t\t\t\ti++; // skip \\n\n\t\t\t} else {\n\t\t\t\t// \\r... case\n\t\t\t\tr[rLength++] = i + 1;\n\t\t\t}\n\t\t} else if (chr === CharCode.LineFeed) {\n\t\t\tr[rLength++] = i + 1;\n\t\t}\n\t}\n\tif (readonly) {\n\t\treturn createUintArray(r);\n\t} else {\n\t\treturn r;\n\t}\n}\n\nexport function createLineStarts(r: number[], str: string): LineStarts {\n\tr.length = 0;\n\tr[0] = 0;\n\tlet rLength = 1;\n\tlet cr = 0, lf = 0, crlf = 0;\n\tlet isBasicASCII = true;\n\tfor (let i = 0, len = str.length; i < len; i++) {\n\t\tconst chr = str.charCodeAt(i);\n\n\t\tif (chr === CharCode.CarriageReturn) {\n\t\t\tif (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) {\n\t\t\t\t// \\r\\n... case\n\t\t\t\tcrlf++;\n\t\t\t\tr[rLength++] = i + 2;\n\t\t\t\ti++; // skip \\n\n\t\t\t} else {\n\t\t\t\tcr++;\n\t\t\t\t// \\r... case\n\t\t\t\tr[rLength++] = i + 1;\n\t\t\t}\n\t\t} else if (chr === CharCode.LineFeed) {\n\t\t\tlf++;\n\t\t\tr[rLength++] = i + 1;\n\t\t} else {\n\t\t\tif (isBasicASCII) {\n\t\t\t\tif (chr !== CharCode.Tab && (chr < 32 || chr > 126)) {\n\t\t\t\t\tisBasicASCII = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tconst result = new LineStarts(createUintArray(r), cr, lf, crlf, isBasicASCII);\n\tr.length = 0;\n\n\treturn result;\n}\n\ninterface NodePosition {\n\t/**\n\t * Piece Index\n\t */\n\tnode: TreeNode;\n\t/**\n\t * remainder in current piece.\n\t*/\n\tremainder: number;\n\t/**\n\t * node start offset in document.\n\t */\n\tnodeStartOffset: number;\n}\n\ninterface BufferCursor {\n\t/**\n\t * Line number in current buffer\n\t */\n\tline: number;\n\t/**\n\t * Column number in current buffer\n\t */\n\tcolumn: number;\n}\n\nexport class Piece {\n\treadonly bufferIndex: number;\n\treadonly start: BufferCursor;\n\treadonly end: BufferCursor;\n\treadonly length: number;\n\treadonly lineFeedCnt: number;\n\n\tconstructor(bufferIndex: number, start: BufferCursor, end: BufferCursor, lineFeedCnt: number, length: number) {\n\t\tthis.bufferIndex = bufferIndex;\n\t\tthis.start = start;\n\t\tthis.end = end;\n\t\tthis.lineFeedCnt = lineFeedCnt;\n\t\tthis.length = length;\n\t}\n}\n\nexport class StringBuffer {\n\tbuffer: string;\n\tlineStarts: Uint32Array | Uint16Array | number[];\n\n\tconstructor(buffer: string, lineStarts: Uint32Array | Uint16Array | number[]) {\n\t\tthis.buffer = buffer;\n\t\tthis.lineStarts = lineStarts;\n\t}\n}\n\n/**\n * Readonly snapshot for piece tree.\n * In a real multiple thread environment, to make snapshot reading always work correctly, we need to\n * 1. Make TreeNode.piece immutable, then reading and writing can run in parallel.\n * 2. TreeNode/Buffers normalization should not happen during snapshot reading.\n */\nclass PieceTreeSnapshot implements ITextSnapshot {\n\tprivate readonly _pieces: Piece[];\n\tprivate _index: number;\n\tprivate readonly _tree: PieceTreeBase;\n\tprivate readonly _BOM: string;\n\n\tconstructor(tree: PieceTreeBase, BOM: string) {\n\t\tthis._pieces = [];\n\t\tthis._tree = tree;\n\t\tthis._BOM = BOM;\n\t\tthis._index = 0;\n\t\tif (tree.root !== SENTINEL) {\n\t\t\ttree.iterate(tree.root, node => {\n\t\t\t\tif (node !== SENTINEL) {\n\t\t\t\t\tthis._pieces.push(node.piece);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t});\n\t\t}\n\t}\n\n\tread(): string | null {\n\t\tif (this._pieces.length === 0) {\n\t\t\tif (this._index === 0) {\n\t\t\t\tthis._index++;\n\t\t\t\treturn this._BOM;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tif (this._index > this._pieces.length - 1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (this._index === 0) {\n\t\t\treturn this._BOM + this._tree.getPieceContent(this._pieces[this._index++]);\n\t\t}\n\t\treturn this._tree.getPieceContent(this._pieces[this._index++]);\n\t}\n}\n\ninterface CacheEntry {\n\tnode: TreeNode;\n\tnodeStartOffset: number;\n\tnodeStartLineNumber?: number;\n}\n\nclass PieceTreeSearchCache {\n\tprivate readonly _limit: number;\n\tprivate _cache: CacheEntry[];\n\n\tconstructor(limit: number) {\n\t\tthis._limit = limit;\n\t\tthis._cache = [];\n\t}\n\n\tpublic get(offset: number): CacheEntry | null {\n\t\tfor (let i = this._cache.length - 1; i >= 0; i--) {\n\t\t\tconst nodePos = this._cache[i];\n\t\t\tif (nodePos.nodeStartOffset <= offset && nodePos.nodeStartOffset + nodePos.node.piece.length >= offset) {\n\t\t\t\treturn nodePos;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic get2(lineNumber: number): { node: TreeNode; nodeStartOffset: number; nodeStartLineNumber: number } | null {\n\t\tfor (let i = this._cache.length - 1; i >= 0; i--) {\n\t\t\tconst nodePos = this._cache[i];\n\t\t\tif (nodePos.nodeStartLineNumber && nodePos.nodeStartLineNumber < lineNumber && nodePos.nodeStartLineNumber + nodePos.node.piece.lineFeedCnt >= lineNumber) {\n\t\t\t\treturn <{ node: TreeNode; nodeStartOffset: number; nodeStartLineNumber: number }>nodePos;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic set(nodePosition: CacheEntry) {\n\t\tif (this._cache.length >= this._limit) {\n\t\t\tthis._cache.shift();\n\t\t}\n\t\tthis._cache.push(nodePosition);\n\t}\n\n\tpublic validate(offset: number) {\n\t\tlet hasInvalidVal = false;\n\t\tconst tmp: Array<CacheEntry | null> = this._cache;\n\t\tfor (let i = 0; i < tmp.length; i++) {\n\t\t\tconst nodePos = tmp[i]!;\n\t\t\tif (nodePos.node.parent === null || nodePos.nodeStartOffset >= offset) {\n\t\t\t\ttmp[i] = null;\n\t\t\t\thasInvalidVal = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif (hasInvalidVal) {\n\t\t\tconst newArr: CacheEntry[] = [];\n\t\t\tfor (const entry of tmp) {\n\t\t\t\tif (entry !== null) {\n\t\t\t\t\tnewArr.push(entry);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._cache = newArr;\n\t\t}\n\t}\n}\n\nexport class PieceTreeBase {\n\troot!: TreeNode;\n\tprotected _buffers!: StringBuffer[]; // 0 is change buffer, others are readonly original buffer.\n\tprotected _lineCnt!: number;\n\tprotected _length!: number;\n\tprotected _EOL!: '\\r\\n' | '\\n';\n\tprotected _EOLLength!: number;\n\tprotected _EOLNormalized!: boolean;\n\tprivate _lastChangeBufferPos!: BufferCursor;\n\tprivate _searchCache!: PieceTreeSearchCache;\n\tprivate _lastVisitedLine!: { lineNumber: number; value: string };\n\n\tconstructor(chunks: StringBuffer[], eol: '\\r\\n' | '\\n', eolNormalized: boolean) {\n\t\tthis.create(chunks, eol, eolNormalized);\n\t}\n\n\tcreate(chunks: StringBuffer[], eol: '\\r\\n' | '\\n', eolNormalized: boolean) {\n\t\tthis._buffers = [\n\t\t\tnew StringBuffer('', [0])\n\t\t];\n\t\tthis._lastChangeBufferPos = { line: 0, column: 0 };\n\t\tthis.root = SENTINEL;\n\t\tthis._lineCnt = 1;\n\t\tthis._length = 0;\n\t\tthis._EOL = eol;\n\t\tthis._EOLLength = eol.length;\n\t\tthis._EOLNormalized = eolNormalized;\n\n\t\tlet lastNode: TreeNode | null = null;\n\t\tfor (let i = 0, len = chunks.length; i < len; i++) {\n\t\t\tif (chunks[i].buffer.length > 0) {\n\t\t\t\tif (!chunks[i].lineStarts) {\n\t\t\t\t\tchunks[i].lineStarts = createLineStartsFast(chunks[i].buffer);\n\t\t\t\t}\n\n\t\t\t\tconst piece = new Piece(\n\t\t\t\t\ti + 1,\n\t\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t\t{ line: chunks[i].lineStarts.length - 1, column: chunks[i].buffer.length - chunks[i].lineStarts[chunks[i].lineStarts.length - 1] },\n\t\t\t\t\tchunks[i].lineStarts.length - 1,\n\t\t\t\t\tchunks[i].buffer.length\n\t\t\t\t);\n\t\t\t\tthis._buffers.push(chunks[i]);\n\t\t\t\tlastNode = this.rbInsertRight(lastNode, piece);\n\t\t\t}\n\t\t}\n\n\t\tthis._searchCache = new PieceTreeSearchCache(1);\n\t\tthis._lastVisitedLine = { lineNumber: 0, value: '' };\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tnormalizeEOL(eol: '\\r\\n' | '\\n') {\n\t\tconst averageBufferSize = AverageBufferSize;\n\t\tconst min = averageBufferSize - Math.floor(averageBufferSize / 3);\n\t\tconst max = min * 2;\n\n\t\tlet tempChunk = '';\n\t\tlet tempChunkLen = 0;\n\t\tconst chunks: StringBuffer[] = [];\n\n\t\tthis.iterate(this.root, node => {\n\t\t\tconst str = this.getNodeContent(node);\n\t\t\tconst len = str.length;\n\t\t\tif (tempChunkLen <= min || tempChunkLen + len < max) {\n\t\t\t\ttempChunk += str;\n\t\t\t\ttempChunkLen += len;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// flush anyways\n\t\t\tconst text = tempChunk.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\tchunks.push(new StringBuffer(text, createLineStartsFast(text)));\n\t\t\ttempChunk = str;\n\t\t\ttempChunkLen = len;\n\t\t\treturn true;\n\t\t});\n\n\t\tif (tempChunkLen > 0) {\n\t\t\tconst text = tempChunk.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\tchunks.push(new StringBuffer(text, createLineStartsFast(text)));\n\t\t}\n\n\t\tthis.create(chunks, eol, true);\n\t}\n\n\t// #region Buffer API\n\tpublic getEOL(): '\\r\\n' | '\\n' {\n\t\treturn this._EOL;\n\t}\n\n\tpublic setEOL(newEOL: '\\r\\n' | '\\n'): void {\n\t\tthis._EOL = newEOL;\n\t\tthis._EOLLength = this._EOL.length;\n\t\tthis.normalizeEOL(newEOL);\n\t}\n\n\tpublic createSnapshot(BOM: string): ITextSnapshot {\n\t\treturn new PieceTreeSnapshot(this, BOM);\n\t}\n\n\tpublic getOffsetAt(lineNumber: number, column: number): number {\n\t\tlet leftLen = 0; // inorder\n\n\t\tlet x = this.root;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.left !== SENTINEL && x.lf_left + 1 >= lineNumber) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt + 1 >= lineNumber) {\n\t\t\t\tleftLen += x.size_left;\n\t\t\t\t// lineNumber >= 2\n\t\t\t\tconst accumualtedValInCurrentIndex = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\treturn leftLen += accumualtedValInCurrentIndex + column - 1;\n\t\t\t} else {\n\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\tleftLen += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\treturn leftLen;\n\t}\n\n\tpublic getPositionAt(offset: number): Position {\n\t\toffset = Math.floor(offset);\n\t\toffset = Math.max(0, offset);\n\n\t\tlet x = this.root;\n\t\tlet lfCnt = 0;\n\t\tconst originalOffset = offset;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.size_left !== 0 && x.size_left >= offset) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.size_left + x.piece.length >= offset) {\n\t\t\t\tconst out = this.getIndexOf(x, offset - x.size_left);\n\n\t\t\t\tlfCnt += x.lf_left + out.index;\n\n\t\t\t\tif (out.index === 0) {\n\t\t\t\t\tconst lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);\n\t\t\t\t\tconst column = originalOffset - lineStartOffset;\n\t\t\t\t\treturn new Position(lfCnt + 1, column + 1);\n\t\t\t\t}\n\n\t\t\t\treturn new Position(lfCnt + 1, out.remainder + 1);\n\t\t\t} else {\n\t\t\t\toffset -= x.size_left + x.piece.length;\n\t\t\t\tlfCnt += x.lf_left + x.piece.lineFeedCnt;\n\n\t\t\t\tif (x.right === SENTINEL) {\n\t\t\t\t\t// last node\n\t\t\t\t\tconst lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);\n\t\t\t\t\tconst column = originalOffset - offset - lineStartOffset;\n\t\t\t\t\treturn new Position(lfCnt + 1, column + 1);\n\t\t\t\t} else {\n\t\t\t\t\tx = x.right;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn new Position(1, 1);\n\t}\n\n\tpublic getValueInRange(range: Range, eol?: string): string {\n\t\tif (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst startPosition = this.nodeAt2(range.startLineNumber, range.startColumn);\n\t\tconst endPosition = this.nodeAt2(range.endLineNumber, range.endColumn);\n\n\t\tconst value = this.getValueInRange2(startPosition, endPosition);\n\t\tif (eol) {\n\t\t\tif (eol !== this._EOL || !this._EOLNormalized) {\n\t\t\t\treturn value.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\t}\n\n\t\t\tif (eol === this.getEOL() && this._EOLNormalized) {\n\t\t\t\tif (eol === '\\r\\n') {\n\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t}\n\t\t\treturn value.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t}\n\t\treturn value;\n\t}\n\n\tpublic getValueInRange2(startPosition: NodePosition, endPosition: NodePosition): string {\n\t\tif (startPosition.node === endPosition.node) {\n\t\t\tconst node = startPosition.node;\n\t\t\tconst buffer = this._buffers[node.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);\n\t\t\treturn buffer.substring(startOffset + startPosition.remainder, startOffset + endPosition.remainder);\n\t\t}\n\n\t\tlet x = startPosition.node;\n\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\tlet ret = buffer.substring(startOffset + startPosition.remainder, startOffset + x.piece.length);\n\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\tif (x === endPosition.node) {\n\t\t\t\tret += buffer.substring(startOffset, startOffset + endPosition.remainder);\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tret += buffer.substr(startOffset, x.piece.length);\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tpublic getLinesContent(): string[] {\n\t\tconst lines: string[] = [];\n\t\tlet linesLength = 0;\n\t\tlet currentLine = '';\n\t\tlet danglingCR = false;\n\n\t\tthis.iterate(this.root, node => {\n\t\t\tif (node === SENTINEL) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst piece = node.piece;\n\t\t\tlet pieceLength = piece.length;\n\t\t\tif (pieceLength === 0) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[piece.bufferIndex].buffer;\n\t\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\n\t\t\tconst pieceStartLine = piece.start.line;\n\t\t\tconst pieceEndLine = piece.end.line;\n\t\t\tlet pieceStartOffset = lineStarts[pieceStartLine] + piece.start.column;\n\n\t\t\tif (danglingCR) {\n\t\t\t\tif (buffer.charCodeAt(pieceStartOffset) === CharCode.LineFeed) {\n\t\t\t\t\t// pretend the \\n was in the previous piece..\n\t\t\t\t\tpieceStartOffset++;\n\t\t\t\t\tpieceLength--;\n\t\t\t\t}\n\t\t\t\tlines[linesLength++] = currentLine;\n\t\t\t\tcurrentLine = '';\n\t\t\t\tdanglingCR = false;\n\t\t\t\tif (pieceLength === 0) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (pieceStartLine === pieceEndLine) {\n\t\t\t\t// this piece has no new lines\n\t\t\t\tif (!this._EOLNormalized && buffer.charCodeAt(pieceStartOffset + pieceLength - 1) === CharCode.CarriageReturn) {\n\t\t\t\t\tdanglingCR = true;\n\t\t\t\t\tcurrentLine += buffer.substr(pieceStartOffset, pieceLength - 1);\n\t\t\t\t} else {\n\t\t\t\t\tcurrentLine += buffer.substr(pieceStartOffset, pieceLength);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// add the text before the first line start in this piece\n\t\t\tcurrentLine += (\n\t\t\t\tthis._EOLNormalized\n\t\t\t\t\t? buffer.substring(pieceStartOffset, Math.max(pieceStartOffset, lineStarts[pieceStartLine + 1] - this._EOLLength))\n\t\t\t\t\t: buffer.substring(pieceStartOffset, lineStarts[pieceStartLine + 1]).replace(/(\\r\\n|\\r|\\n)$/, '')\n\t\t\t);\n\t\t\tlines[linesLength++] = currentLine;\n\n\t\t\tfor (let line = pieceStartLine + 1; line < pieceEndLine; line++) {\n\t\t\t\tcurrentLine = (\n\t\t\t\t\tthis._EOLNormalized\n\t\t\t\t\t\t? buffer.substring(lineStarts[line], lineStarts[line + 1] - this._EOLLength)\n\t\t\t\t\t\t: buffer.substring(lineStarts[line], lineStarts[line + 1]).replace(/(\\r\\n|\\r|\\n)$/, '')\n\t\t\t\t);\n\t\t\t\tlines[linesLength++] = currentLine;\n\t\t\t}\n\n\t\t\tif (!this._EOLNormalized && buffer.charCodeAt(lineStarts[pieceEndLine] + piece.end.column - 1) === CharCode.CarriageReturn) {\n\t\t\t\tdanglingCR = true;\n\t\t\t\tif (piece.end.column === 0) {\n\t\t\t\t\t// The last line ended with a \\r, let's undo the push, it will be pushed by next iteration\n\t\t\t\t\tlinesLength--;\n\t\t\t\t} else {\n\t\t\t\t\tcurrentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column - 1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcurrentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column);\n\t\t\t}\n\n\t\t\treturn true;\n\t\t});\n\n\t\tif (danglingCR) {\n\t\t\tlines[linesLength++] = currentLine;\n\t\t\tcurrentLine = '';\n\t\t}\n\n\t\tlines[linesLength++] = currentLine;\n\t\treturn lines;\n\t}\n\n\tpublic getLength(): number {\n\t\treturn this._length;\n\t}\n\n\tpublic getLineCount(): number {\n\t\treturn this._lineCnt;\n\t}\n\n\tpublic getLineContent(lineNumber: number): string {\n\t\tif (this._lastVisitedLine.lineNumber === lineNumber) {\n\t\t\treturn this._lastVisitedLine.value;\n\t\t}\n\n\t\tthis._lastVisitedLine.lineNumber = lineNumber;\n\n\t\tif (lineNumber === this._lineCnt) {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber);\n\t\t} else if (this._EOLNormalized) {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber, this._EOLLength);\n\t\t} else {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber).replace(/(\\r\\n|\\r|\\n)$/, '');\n\t\t}\n\n\t\treturn this._lastVisitedLine.value;\n\t}\n\n\tprivate _getCharCode(nodePos: NodePosition): number {\n\t\tif (nodePos.remainder === nodePos.node.piece.length) {\n\t\t\t// the char we want to fetch is at the head of next node.\n\t\t\tconst matchingNode = nodePos.node.next();\n\t\t\tif (!matchingNode) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[matchingNode.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);\n\t\t\treturn buffer.buffer.charCodeAt(startOffset);\n\t\t} else {\n\t\t\tconst buffer = this._buffers[nodePos.node.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);\n\t\t\tconst targetOffset = startOffset + nodePos.remainder;\n\n\t\t\treturn buffer.buffer.charCodeAt(targetOffset);\n\t\t}\n\t}\n\n\tpublic getLineCharCode(lineNumber: number, index: number): number {\n\t\tconst nodePos = this.nodeAt2(lineNumber, index + 1);\n\t\treturn this._getCharCode(nodePos);\n\t}\n\n\tpublic getLineLength(lineNumber: number): number {\n\t\tif (lineNumber === this.getLineCount()) {\n\t\t\tconst startOffset = this.getOffsetAt(lineNumber, 1);\n\t\t\treturn this.getLength() - startOffset;\n\t\t}\n\t\treturn this.getOffsetAt(lineNumber + 1, 1) - this.getOffsetAt(lineNumber, 1) - this._EOLLength;\n\t}\n\n\tpublic getNearestChunk(offset: number): string {\n\t\tconst nodePos = this.nodeAt(offset);\n\t\tif (nodePos.remainder === nodePos.node.piece.length) {\n\t\t\t// the offset is at the head of next node.\n\t\t\tconst matchingNode = nodePos.node.next();\n\t\t\tif (!matchingNode || matchingNode === SENTINEL) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[matchingNode.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);\n\t\t\treturn buffer.buffer.substring(startOffset, startOffset + matchingNode.piece.length);\n\t\t} else {\n\t\t\tconst buffer = this._buffers[nodePos.node.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);\n\t\t\tconst targetOffset = startOffset + nodePos.remainder;\n\t\t\tconst targetEnd = startOffset + nodePos.node.piece.length;\n\t\t\treturn buffer.buffer.substring(targetOffset, targetEnd);\n\t\t}\n\t}\n\n\tpublic findMatchesInNode(node: TreeNode, searcher: Searcher, startLineNumber: number, startColumn: number, startCursor: BufferCursor, endCursor: BufferCursor, searchData: SearchData, captureMatches: boolean, limitResultCount: number, resultLen: number, result: FindMatch[]) {\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst startOffsetInBuffer = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);\n\t\tconst start = this.offsetInBuffer(node.piece.bufferIndex, startCursor);\n\t\tconst end = this.offsetInBuffer(node.piece.bufferIndex, endCursor);\n\n\t\tlet m: RegExpExecArray | null;\n\t\t// Reset regex to search from the beginning\n\t\tconst ret: BufferCursor = { line: 0, column: 0 };\n\t\tlet searchText: string;\n\t\tlet offsetInBuffer: (offset: number) => number;\n\n\t\tif (searcher._wordSeparators) {\n\t\t\tsearchText = buffer.buffer.substring(start, end);\n\t\t\toffsetInBuffer = (offset: number) => offset + start;\n\t\t\tsearcher.reset(0);\n\t\t} else {\n\t\t\tsearchText = buffer.buffer;\n\t\t\toffsetInBuffer = (offset: number) => offset;\n\t\t\tsearcher.reset(start);\n\t\t}\n\n\t\tdo {\n\t\t\tm = searcher.next(searchText);\n\n\t\t\tif (m) {\n\t\t\t\tif (offsetInBuffer(m.index) >= end) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t\tthis.positionInBuffer(node, offsetInBuffer(m.index) - startOffsetInBuffer, ret);\n\t\t\t\tconst lineFeedCnt = this.getLineFeedCnt(node.piece.bufferIndex, startCursor, ret);\n\t\t\t\tconst retStartColumn = ret.line === startCursor.line ? ret.column - startCursor.column + startColumn : ret.column + 1;\n\t\t\t\tconst retEndColumn = retStartColumn + m[0].length;\n\t\t\t\tresult[resultLen++] = createFindMatch(new Range(startLineNumber + lineFeedCnt, retStartColumn, startLineNumber + lineFeedCnt, retEndColumn), m, captureMatches);\n\n\t\t\t\tif (offsetInBuffer(m.index) + m[0].length >= end) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} while (m);\n\n\t\treturn resultLen;\n\t}\n\n\tpublic findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[] {\n\t\tconst result: FindMatch[] = [];\n\t\tlet resultLen = 0;\n\t\tconst searcher = new Searcher(searchData.wordSeparators, searchData.regex);\n\n\t\tlet startPosition = this.nodeAt2(searchRange.startLineNumber, searchRange.startColumn);\n\t\tif (startPosition === null) {\n\t\t\treturn [];\n\t\t}\n\t\tconst endPosition = this.nodeAt2(searchRange.endLineNumber, searchRange.endColumn);\n\t\tif (endPosition === null) {\n\t\t\treturn [];\n\t\t}\n\t\tlet start = this.positionInBuffer(startPosition.node, startPosition.remainder);\n\t\tconst end = this.positionInBuffer(endPosition.node, endPosition.remainder);\n\n\t\tif (startPosition.node === endPosition.node) {\n\t\t\tthis.findMatchesInNode(startPosition.node, searcher, searchRange.startLineNumber, searchRange.startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);\n\t\t\treturn result;\n\t\t}\n\n\t\tlet startLineNumber = searchRange.startLineNumber;\n\n\t\tlet currentNode = startPosition.node;\n\t\twhile (currentNode !== endPosition.node) {\n\t\t\tconst lineBreakCnt = this.getLineFeedCnt(currentNode.piece.bufferIndex, start, currentNode.piece.end);\n\n\t\t\tif (lineBreakCnt >= 1) {\n\t\t\t\t// last line break position\n\t\t\t\tconst lineStarts = this._buffers[currentNode.piece.bufferIndex].lineStarts;\n\t\t\t\tconst startOffsetInBuffer = this.offsetInBuffer(currentNode.piece.bufferIndex, currentNode.piece.start);\n\t\t\t\tconst nextLineStartOffset = lineStarts[start.line + lineBreakCnt];\n\t\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;\n\t\t\t\tresultLen = this.findMatchesInNode(currentNode, searcher, startLineNumber, startColumn, start, this.positionInBuffer(currentNode, nextLineStartOffset - startOffsetInBuffer), searchData, captureMatches, limitResultCount, resultLen, result);\n\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\tstartLineNumber += lineBreakCnt;\n\t\t\t}\n\n\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;\n\t\t\t// search for the remaining content\n\t\t\tif (startLineNumber === searchRange.endLineNumber) {\n\t\t\t\tconst text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);\n\t\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, this.getLineContent(startLineNumber).substr(startColumn), startLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\n\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tstartLineNumber++;\n\t\t\tstartPosition = this.nodeAt2(startLineNumber, 1);\n\t\t\tcurrentNode = startPosition.node;\n\t\t\tstart = this.positionInBuffer(startPosition.node, startPosition.remainder);\n\t\t}\n\n\t\tif (startLineNumber === searchRange.endLineNumber) {\n\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;\n\t\t\tconst text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);\n\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\t\t\treturn result;\n\t\t}\n\n\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;\n\t\tresultLen = this.findMatchesInNode(endPosition.node, searcher, startLineNumber, startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);\n\t\treturn result;\n\t}\n\n\tprivate _findMatchesInLine(searchData: SearchData, searcher: Searcher, text: string, lineNumber: number, deltaOffset: number, resultLen: number, result: FindMatch[], captureMatches: boolean, limitResultCount: number): number {\n\t\tconst wordSeparators = searchData.wordSeparators;\n\t\tif (!captureMatches && searchData.simpleSearch) {\n\t\t\tconst searchString = searchData.simpleSearch;\n\t\t\tconst searchStringLen = searchString.length;\n\t\t\tconst textLength = text.length;\n\n\t\t\tlet lastMatchIndex = -searchStringLen;\n\t\t\twhile ((lastMatchIndex = text.indexOf(searchString, lastMatchIndex + searchStringLen)) !== -1) {\n\t\t\t\tif (!wordSeparators || isValidMatch(wordSeparators, text, textLength, lastMatchIndex, searchStringLen)) {\n\t\t\t\t\tresult[resultLen++] = new FindMatch(new Range(lineNumber, lastMatchIndex + 1 + deltaOffset, lineNumber, lastMatchIndex + 1 + searchStringLen + deltaOffset), null);\n\t\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\t\treturn resultLen;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn resultLen;\n\t\t}\n\n\t\tlet m: RegExpExecArray | null;\n\t\t// Reset regex to search from the beginning\n\t\tsearcher.reset(0);\n\t\tdo {\n\t\t\tm = searcher.next(text);\n\t\t\tif (m) {\n\t\t\t\tresult[resultLen++] = createFindMatch(new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset), m, captureMatches);\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (m);\n\t\treturn resultLen;\n\t}\n\n\t// #endregion\n\n\t// #region Piece Table\n\tpublic insert(offset: number, value: string, eolNormalized: boolean = false): void {\n\t\tthis._EOLNormalized = this._EOLNormalized && eolNormalized;\n\t\tthis._lastVisitedLine.lineNumber = 0;\n\t\tthis._lastVisitedLine.value = '';\n\n\t\tif (this.root !== SENTINEL) {\n\t\t\tconst { node, remainder, nodeStartOffset } = this.nodeAt(offset);\n\t\t\tconst piece = node.piece;\n\t\t\tconst bufferIndex = piece.bufferIndex;\n\t\t\tconst insertPosInBuffer = this.positionInBuffer(node, remainder);\n\t\t\tif (node.piece.bufferIndex === 0 &&\n\t\t\t\tpiece.end.line === this._lastChangeBufferPos.line &&\n\t\t\t\tpiece.end.column === this._lastChangeBufferPos.column &&\n\t\t\t\t(nodeStartOffset + piece.length === offset) &&\n\t\t\t\tvalue.length < AverageBufferSize\n\t\t\t) {\n\t\t\t\t// changed buffer\n\t\t\t\tthis.appendToNode(node, value);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (nodeStartOffset === offset) {\n\t\t\t\tthis.insertContentToNodeLeft(value, node);\n\t\t\t\tthis._searchCache.validate(offset);\n\t\t\t} else if (nodeStartOffset + node.piece.length > offset) {\n\t\t\t\t// we are inserting into the middle of a node.\n\t\t\t\tconst nodesToDel: TreeNode[] = [];\n\t\t\t\tlet newRightPiece = new Piece(\n\t\t\t\t\tpiece.bufferIndex,\n\t\t\t\t\tinsertPosInBuffer,\n\t\t\t\t\tpiece.end,\n\t\t\t\t\tthis.getLineFeedCnt(piece.bufferIndex, insertPosInBuffer, piece.end),\n\t\t\t\t\tthis.offsetInBuffer(bufferIndex, piece.end) - this.offsetInBuffer(bufferIndex, insertPosInBuffer)\n\t\t\t\t);\n\n\t\t\t\tif (this.shouldCheckCRLF() && this.endWithCR(value)) {\n\t\t\t\t\tconst headOfRight = this.nodeCharCodeAt(node, remainder);\n\n\t\t\t\t\tif (headOfRight === 10 /** \\n */) {\n\t\t\t\t\t\tconst newStart: BufferCursor = { line: newRightPiece.start.line + 1, column: 0 };\n\t\t\t\t\t\tnewRightPiece = new Piece(\n\t\t\t\t\t\t\tnewRightPiece.bufferIndex,\n\t\t\t\t\t\t\tnewStart,\n\t\t\t\t\t\t\tnewRightPiece.end,\n\t\t\t\t\t\t\tthis.getLineFeedCnt(newRightPiece.bufferIndex, newStart, newRightPiece.end),\n\t\t\t\t\t\t\tnewRightPiece.length - 1\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tvalue += '\\n';\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// reuse node for content before insertion point.\n\t\t\t\tif (this.shouldCheckCRLF() && this.startWithLF(value)) {\n\t\t\t\t\tconst tailOfLeft = this.nodeCharCodeAt(node, remainder - 1);\n\t\t\t\t\tif (tailOfLeft === 13 /** \\r */) {\n\t\t\t\t\t\tconst previousPos = this.positionInBuffer(node, remainder - 1);\n\t\t\t\t\t\tthis.deleteNodeTail(node, previousPos);\n\t\t\t\t\t\tvalue = '\\r' + value;\n\n\t\t\t\t\t\tif (node.piece.length === 0) {\n\t\t\t\t\t\t\tnodesToDel.push(node);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.deleteNodeTail(node, insertPosInBuffer);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.deleteNodeTail(node, insertPosInBuffer);\n\t\t\t\t}\n\n\t\t\t\tconst newPieces = this.createNewPieces(value);\n\t\t\t\tif (newRightPiece.length > 0) {\n\t\t\t\t\tthis.rbInsertRight(node, newRightPiece);\n\t\t\t\t}\n\n\t\t\t\tlet tmpNode = node;\n\t\t\t\tfor (let k = 0; k < newPieces.length; k++) {\n\t\t\t\t\ttmpNode = this.rbInsertRight(tmpNode, newPieces[k]);\n\t\t\t\t}\n\t\t\t\tthis.deleteNodes(nodesToDel);\n\t\t\t} else {\n\t\t\t\tthis.insertContentToNodeRight(value, node);\n\t\t\t}\n\t\t} else {\n\t\t\t// insert new node\n\t\t\tconst pieces = this.createNewPieces(value);\n\t\t\tlet node = this.rbInsertLeft(null, pieces[0]);\n\n\t\t\tfor (let k = 1; k < pieces.length; k++) {\n\t\t\t\tnode = this.rbInsertRight(node, pieces[k]);\n\t\t\t}\n\t\t}\n\n\t\t// todo, this is too brutal. Total line feed count should be updated the same way as lf_left.\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tpublic delete(offset: number, cnt: number): void {\n\t\tthis._lastVisitedLine.lineNumber = 0;\n\t\tthis._lastVisitedLine.value = '';\n\n\t\tif (cnt <= 0 || this.root === SENTINEL) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst startPosition = this.nodeAt(offset);\n\t\tconst endPosition = this.nodeAt(offset + cnt);\n\t\tconst startNode = startPosition.node;\n\t\tconst endNode = endPosition.node;\n\n\t\tif (startNode === endNode) {\n\t\t\tconst startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);\n\t\t\tconst endSplitPosInBuffer = this.positionInBuffer(startNode, endPosition.remainder);\n\n\t\t\tif (startPosition.nodeStartOffset === offset) {\n\t\t\t\tif (cnt === startNode.piece.length) { // delete node\n\t\t\t\t\tconst next = startNode.next();\n\t\t\t\t\trbDelete(this, startNode);\n\t\t\t\t\tthis.validateCRLFWithPrevNode(next);\n\t\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.deleteNodeHead(startNode, endSplitPosInBuffer);\n\t\t\t\tthis._searchCache.validate(offset);\n\t\t\t\tthis.validateCRLFWithPrevNode(startNode);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (startPosition.nodeStartOffset + startNode.piece.length === offset + cnt) {\n\t\t\t\tthis.deleteNodeTail(startNode, startSplitPosInBuffer);\n\t\t\t\tthis.validateCRLFWithNextNode(startNode);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// delete content in the middle, this node will be splitted to nodes\n\t\t\tthis.shrinkNode(startNode, startSplitPosInBuffer, endSplitPosInBuffer);\n\t\t\tthis.computeBufferMetadata();\n\t\t\treturn;\n\t\t}\n\n\t\tconst nodesToDel: TreeNode[] = [];\n\n\t\tconst startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);\n\t\tthis.deleteNodeTail(startNode, startSplitPosInBuffer);\n\t\tthis._searchCache.validate(offset);\n\t\tif (startNode.piece.length === 0) {\n\t\t\tnodesToDel.push(startNode);\n\t\t}\n\n\t\t// update last touched node\n\t\tconst endSplitPosInBuffer = this.positionInBuffer(endNode, endPosition.remainder);\n\t\tthis.deleteNodeHead(endNode, endSplitPosInBuffer);\n\t\tif (endNode.piece.length === 0) {\n\t\t\tnodesToDel.push(endNode);\n\t\t}\n\n\t\t// delete nodes in between\n\t\tconst secondNode = startNode.next();\n\t\tfor (let node = secondNode; node !== SENTINEL && node !== endNode; node = node.next()) {\n\t\t\tnodesToDel.push(node);\n\t\t}\n\n\t\tconst prev = startNode.piece.length === 0 ? startNode.prev() : startNode;\n\t\tthis.deleteNodes(nodesToDel);\n\t\tthis.validateCRLFWithNextNode(prev);\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tprivate insertContentToNodeLeft(value: string, node: TreeNode) {\n\t\t// we are inserting content to the beginning of node\n\t\tconst nodesToDel: TreeNode[] = [];\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(value) && this.startWithLF(node)) {\n\t\t\t// move `\\n` to new node.\n\n\t\t\tconst piece = node.piece;\n\t\t\tconst newStart: BufferCursor = { line: piece.start.line + 1, column: 0 };\n\t\t\tconst nPiece = new Piece(\n\t\t\t\tpiece.bufferIndex,\n\t\t\t\tnewStart,\n\t\t\t\tpiece.end,\n\t\t\t\tthis.getLineFeedCnt(piece.bufferIndex, newStart, piece.end),\n\t\t\t\tpiece.length - 1\n\t\t\t);\n\n\t\t\tnode.piece = nPiece;\n\n\t\t\tvalue += '\\n';\n\t\t\tupdateTreeMetadata(this, node, -1, -1);\n\n\t\t\tif (node.piece.length === 0) {\n\t\t\t\tnodesToDel.push(node);\n\t\t\t}\n\t\t}\n\n\t\tconst newPieces = this.createNewPieces(value);\n\t\tlet newNode = this.rbInsertLeft(node, newPieces[newPieces.length - 1]);\n\t\tfor (let k = newPieces.length - 2; k >= 0; k--) {\n\t\t\tnewNode = this.rbInsertLeft(newNode, newPieces[k]);\n\t\t}\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t\tthis.deleteNodes(nodesToDel);\n\t}\n\n\tprivate insertContentToNodeRight(value: string, node: TreeNode) {\n\t\t// we are inserting to the right of this node.\n\t\tif (this.adjustCarriageReturnFromNext(value, node)) {\n\t\t\t// move \\n to the new node.\n\t\t\tvalue += '\\n';\n\t\t}\n\n\t\tconst newPieces = this.createNewPieces(value);\n\t\tconst newNode = this.rbInsertRight(node, newPieces[0]);\n\t\tlet tmpNode = newNode;\n\n\t\tfor (let k = 1; k < newPieces.length; k++) {\n\t\t\ttmpNode = this.rbInsertRight(tmpNode, newPieces[k]);\n\t\t}\n\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t}\n\n\tprivate positionInBuffer(node: TreeNode, remainder: number): BufferCursor;\n\tprivate positionInBuffer(node: TreeNode, remainder: number, ret: BufferCursor): null;\n\tprivate positionInBuffer(node: TreeNode, remainder: number, ret?: BufferCursor): BufferCursor | null {\n\t\tconst piece = node.piece;\n\t\tconst bufferIndex = node.piece.bufferIndex;\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\n\t\tconst startOffset = lineStarts[piece.start.line] + piece.start.column;\n\n\t\tconst offset = startOffset + remainder;\n\n\t\t// binary search offset between startOffset and endOffset\n\t\tlet low = piece.start.line;\n\t\tlet high = piece.end.line;\n\n\t\tlet mid: number = 0;\n\t\tlet midStop: number = 0;\n\t\tlet midStart: number = 0;\n\n\t\twhile (low <= high) {\n\t\t\tmid = low + ((high - low) / 2) | 0;\n\t\t\tmidStart = lineStarts[mid];\n\n\t\t\tif (mid === high) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tmidStop = lineStarts[mid + 1];\n\n\t\t\tif (offset < midStart) {\n\t\t\t\thigh = mid - 1;\n\t\t\t} else if (offset >= midStop) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (ret) {\n\t\t\tret.line = mid;\n\t\t\tret.column = offset - midStart;\n\t\t\treturn null;\n\t\t}\n\n\t\treturn {\n\t\t\tline: mid,\n\t\t\tcolumn: offset - midStart\n\t\t};\n\t}\n\n\tprivate getLineFeedCnt(bufferIndex: number, start: BufferCursor, end: BufferCursor): number {\n\t\t// we don't need to worry about start: abc\\r|\\n, or abc|\\r, or abc|\\n, or abc|\\r\\n doesn't change the fact that, there is one line break after start.\n\t\t// now let's take care of end: abc\\r|\\n, if end is in between \\r and \\n, we need to add line feed count by 1\n\t\tif (end.column === 0) {\n\t\t\treturn end.line - start.line;\n\t\t}\n\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\t\tif (end.line === lineStarts.length - 1) { // it means, there is no \\n after end, otherwise, there will be one more lineStart.\n\t\t\treturn end.line - start.line;\n\t\t}\n\n\t\tconst nextLineStartOffset = lineStarts[end.line + 1];\n\t\tconst endOffset = lineStarts[end.line] + end.column;\n\t\tif (nextLineStartOffset > endOffset + 1) { // there are more than 1 character after end, which means it can't be \\n\n\t\t\treturn end.line - start.line;\n\t\t}\n\t\t// endOffset + 1 === nextLineStartOffset\n\t\t// character at endOffset is \\n, so we check the character before first\n\t\t// if character at endOffset is \\r, end.column is 0 and we can't get here.\n\t\tconst previousCharOffset = endOffset - 1; // end.column > 0 so it's okay.\n\t\tconst buffer = this._buffers[bufferIndex].buffer;\n\n\t\tif (buffer.charCodeAt(previousCharOffset) === 13) {\n\t\t\treturn end.line - start.line + 1;\n\t\t} else {\n\t\t\treturn end.line - start.line;\n\t\t}\n\t}\n\n\tprivate offsetInBuffer(bufferIndex: number, cursor: BufferCursor): number {\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\t\treturn lineStarts[cursor.line] + cursor.column;\n\t}\n\n\tprivate deleteNodes(nodes: TreeNode[]): void {\n\t\tfor (let i = 0; i < nodes.length; i++) {\n\t\t\trbDelete(this, nodes[i]);\n\t\t}\n\t}\n\n\tprivate createNewPieces(text: string): Piece[] {\n\t\tif (text.length > AverageBufferSize) {\n\t\t\t// the content is large, operations like substring, charCode becomes slow\n\t\t\t// so here we split it into smaller chunks, just like what we did for CR/LF normalization\n\t\t\tconst newPieces: Piece[] = [];\n\t\t\twhile (text.length > AverageBufferSize) {\n\t\t\t\tconst lastChar = text.charCodeAt(AverageBufferSize - 1);\n\t\t\t\tlet splitText;\n\t\t\t\tif (lastChar === CharCode.CarriageReturn || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {\n\t\t\t\t\t// last character is \\r or a high surrogate => keep it back\n\t\t\t\t\tsplitText = text.substring(0, AverageBufferSize - 1);\n\t\t\t\t\ttext = text.substring(AverageBufferSize - 1);\n\t\t\t\t} else {\n\t\t\t\t\tsplitText = text.substring(0, AverageBufferSize);\n\t\t\t\t\ttext = text.substring(AverageBufferSize);\n\t\t\t\t}\n\n\t\t\t\tconst lineStarts = createLineStartsFast(splitText);\n\t\t\t\tnewPieces.push(new Piece(\n\t\t\t\t\tthis._buffers.length, /* buffer index */\n\t\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t\t{ line: lineStarts.length - 1, column: splitText.length - lineStarts[lineStarts.length - 1] },\n\t\t\t\t\tlineStarts.length - 1,\n\t\t\t\t\tsplitText.length\n\t\t\t\t));\n\t\t\t\tthis._buffers.push(new StringBuffer(splitText, lineStarts));\n\t\t\t}\n\n\t\t\tconst lineStarts = createLineStartsFast(text);\n\t\t\tnewPieces.push(new Piece(\n\t\t\t\tthis._buffers.length, /* buffer index */\n\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t{ line: lineStarts.length - 1, column: text.length - lineStarts[lineStarts.length - 1] },\n\t\t\t\tlineStarts.length - 1,\n\t\t\t\ttext.length\n\t\t\t));\n\t\t\tthis._buffers.push(new StringBuffer(text, lineStarts));\n\n\t\t\treturn newPieces;\n\t\t}\n\n\t\tlet startOffset = this._buffers[0].buffer.length;\n\t\tconst lineStarts = createLineStartsFast(text, false);\n\n\t\tlet start = this._lastChangeBufferPos;\n\t\tif (this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 1] === startOffset\n\t\t\t&& startOffset !== 0\n\t\t\t&& this.startWithLF(text)\n\t\t\t&& this.endWithCR(this._buffers[0].buffer) // todo, we can check this._lastChangeBufferPos's column as it's the last one\n\t\t) {\n\t\t\tthis._lastChangeBufferPos = { line: this._lastChangeBufferPos.line, column: this._lastChangeBufferPos.column + 1 };\n\t\t\tstart = this._lastChangeBufferPos;\n\n\t\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\t\tlineStarts[i] += startOffset + 1;\n\t\t\t}\n\n\t\t\tthis._buffers[0].lineStarts = (<number[]>this._buffers[0].lineStarts).concat(<number[]>lineStarts.slice(1));\n\t\t\tthis._buffers[0].buffer += '_' + text;\n\t\t\tstartOffset += 1;\n\t\t} else {\n\t\t\tif (startOffset !== 0) {\n\t\t\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\t\t\tlineStarts[i] += startOffset;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._buffers[0].lineStarts = (<number[]>this._buffers[0].lineStarts).concat(<number[]>lineStarts.slice(1));\n\t\t\tthis._buffers[0].buffer += text;\n\t\t}\n\n\t\tconst endOffset = this._buffers[0].buffer.length;\n\t\tconst endIndex = this._buffers[0].lineStarts.length - 1;\n\t\tconst endColumn = endOffset - this._buffers[0].lineStarts[endIndex];\n\t\tconst endPos = { line: endIndex, column: endColumn };\n\t\tconst newPiece = new Piece(\n\t\t\t0, /** todo@peng */\n\t\t\tstart,\n\t\t\tendPos,\n\t\t\tthis.getLineFeedCnt(0, start, endPos),\n\t\t\tendOffset - startOffset\n\t\t);\n\t\tthis._lastChangeBufferPos = endPos;\n\t\treturn [newPiece];\n\t}\n\n\tpublic getLineRawContent(lineNumber: number, endOffset: number = 0): string {\n\t\tlet x = this.root;\n\n\t\tlet ret = '';\n\t\tconst cache = this._searchCache.get2(lineNumber);\n\t\tif (cache) {\n\t\t\tx = cache.node;\n\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber - 1);\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\tif (cache.nodeStartLineNumber + x.piece.lineFeedCnt === lineNumber) {\n\t\t\t\tret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);\n\t\t\t} else {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber);\n\t\t\t\treturn buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);\n\t\t\t}\n\t\t} else {\n\t\t\tlet nodeStartOffset = 0;\n\t\t\tconst originalLineNumber = lineNumber;\n\t\t\twhile (x !== SENTINEL) {\n\t\t\t\tif (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {\n\t\t\t\t\tx = x.left;\n\t\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {\n\t\t\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);\n\t\t\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\t\t\tnodeStartOffset += x.size_left;\n\t\t\t\t\tthis._searchCache.set({\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tnodeStartOffset,\n\t\t\t\t\t\tnodeStartLineNumber: originalLineNumber - (lineNumber - 1 - x.lf_left)\n\t\t\t\t\t});\n\n\t\t\t\t\treturn buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);\n\t\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {\n\t\t\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\t\t\tret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\t\tx = x.right;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// search in order, to find the node contains end column\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\n\t\t\tif (x.piece.lineFeedCnt > 0) {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, 0);\n\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\t\tret += buffer.substring(startOffset, startOffset + accumulatedValue - endOffset);\n\t\t\t\treturn ret;\n\t\t\t} else {\n\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\t\tret += buffer.substr(startOffset, x.piece.length);\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tprivate computeBufferMetadata() {\n\t\tlet x = this.root;\n\n\t\tlet lfCnt = 1;\n\t\tlet len = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tlfCnt += x.lf_left + x.piece.lineFeedCnt;\n\t\t\tlen += x.size_left + x.piece.length;\n\t\t\tx = x.right;\n\t\t}\n\n\t\tthis._lineCnt = lfCnt;\n\t\tthis._length = len;\n\t\tthis._searchCache.validate(this._length);\n\t}\n\n\t// #region node operations\n\tprivate getIndexOf(node: TreeNode, accumulatedValue: number): { index: number; remainder: number } {\n\t\tconst piece = node.piece;\n\t\tconst pos = this.positionInBuffer(node, accumulatedValue);\n\t\tconst lineCnt = pos.line - piece.start.line;\n\n\t\tif (this.offsetInBuffer(piece.bufferIndex, piece.end) - this.offsetInBuffer(piece.bufferIndex, piece.start) === accumulatedValue) {\n\t\t\t// we are checking the end of this node, so a CRLF check is necessary.\n\t\t\tconst realLineCnt = this.getLineFeedCnt(node.piece.bufferIndex, piece.start, pos);\n\t\t\tif (realLineCnt !== lineCnt) {\n\t\t\t\t// aha yes, CRLF\n\t\t\t\treturn { index: realLineCnt, remainder: 0 };\n\t\t\t}\n\t\t}\n\n\t\treturn { index: lineCnt, remainder: pos.column };\n\t}\n\n\tprivate getAccumulatedValue(node: TreeNode, index: number) {\n\t\tif (index < 0) {\n\t\t\treturn 0;\n\t\t}\n\t\tconst piece = node.piece;\n\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\t\tconst expectedLineStartIndex = piece.start.line + index + 1;\n\t\tif (expectedLineStartIndex > piece.end.line) {\n\t\t\treturn lineStarts[piece.end.line] + piece.end.column - lineStarts[piece.start.line] - piece.start.column;\n\t\t} else {\n\t\t\treturn lineStarts[expectedLineStartIndex] - lineStarts[piece.start.line] - piece.start.column;\n\t\t}\n\t}\n\n\tprivate deleteNodeTail(node: TreeNode, pos: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalLFCnt = piece.lineFeedCnt;\n\t\tconst originalEndOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\n\t\tconst newEnd = pos;\n\t\tconst newEndOffset = this.offsetInBuffer(piece.bufferIndex, newEnd);\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);\n\n\t\tconst lf_delta = newLineFeedCnt - originalLFCnt;\n\t\tconst size_delta = newEndOffset - originalEndOffset;\n\t\tconst newLength = piece.length + size_delta;\n\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tpiece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, size_delta, lf_delta);\n\t}\n\n\tprivate deleteNodeHead(node: TreeNode, pos: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalLFCnt = piece.lineFeedCnt;\n\t\tconst originalStartOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\n\t\tconst newStart = pos;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);\n\t\tconst newStartOffset = this.offsetInBuffer(piece.bufferIndex, newStart);\n\t\tconst lf_delta = newLineFeedCnt - originalLFCnt;\n\t\tconst size_delta = originalStartOffset - newStartOffset;\n\t\tconst newLength = piece.length + size_delta;\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tnewStart,\n\t\t\tpiece.end,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, size_delta, lf_delta);\n\t}\n\n\tprivate shrinkNode(node: TreeNode, start: BufferCursor, end: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalStartPos = piece.start;\n\t\tconst originalEndPos = piece.end;\n\n\t\t// old piece, originalStartPos, start\n\t\tconst oldLength = piece.length;\n\t\tconst oldLFCnt = piece.lineFeedCnt;\n\t\tconst newEnd = start;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);\n\t\tconst newLength = this.offsetInBuffer(piece.bufferIndex, start) - this.offsetInBuffer(piece.bufferIndex, originalStartPos);\n\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tpiece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, newLength - oldLength, newLineFeedCnt - oldLFCnt);\n\n\t\t// new right piece, end, originalEndPos\n\t\tconst newPiece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tend,\n\t\t\toriginalEndPos,\n\t\t\tthis.getLineFeedCnt(piece.bufferIndex, end, originalEndPos),\n\t\t\tthis.offsetInBuffer(piece.bufferIndex, originalEndPos) - this.offsetInBuffer(piece.bufferIndex, end)\n\t\t);\n\n\t\tconst newNode = this.rbInsertRight(node, newPiece);\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t}\n\n\tprivate appendToNode(node: TreeNode, value: string): void {\n\t\tif (this.adjustCarriageReturnFromNext(value, node)) {\n\t\t\tvalue += '\\n';\n\t\t}\n\n\t\tconst hitCRLF = this.shouldCheckCRLF() && this.startWithLF(value) && this.endWithCR(node);\n\t\tconst startOffset = this._buffers[0].buffer.length;\n\t\tthis._buffers[0].buffer += value;\n\t\tconst lineStarts = createLineStartsFast(value, false);\n\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\tlineStarts[i] += startOffset;\n\t\t}\n\t\tif (hitCRLF) {\n\t\t\tconst prevStartOffset = this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 2];\n\t\t\t(<number[]>this._buffers[0].lineStarts).pop();\n\t\t\t// _lastChangeBufferPos is already wrong\n\t\t\tthis._lastChangeBufferPos = { line: this._lastChangeBufferPos.line - 1, column: startOffset - prevStartOffset };\n\t\t}\n\n\t\tthis._buffers[0].lineStarts = (<number[]>this._buffers[0].lineStarts).concat(<number[]>lineStarts.slice(1));\n\t\tconst endIndex = this._buffers[0].lineStarts.length - 1;\n\t\tconst endColumn = this._buffers[0].buffer.length - this._buffers[0].lineStarts[endIndex];\n\t\tconst newEnd = { line: endIndex, column: endColumn };\n\t\tconst newLength = node.piece.length + value.length;\n\t\tconst oldLineFeedCnt = node.piece.lineFeedCnt;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(0, node.piece.start, newEnd);\n\t\tconst lf_delta = newLineFeedCnt - oldLineFeedCnt;\n\n\t\tnode.piece = new Piece(\n\t\t\tnode.piece.bufferIndex,\n\t\t\tnode.piece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tthis._lastChangeBufferPos = newEnd;\n\t\tupdateTreeMetadata(this, node, value.length, lf_delta);\n\t}\n\n\tprivate nodeAt(offset: number): NodePosition {\n\t\tlet x = this.root;\n\t\tconst cache = this._searchCache.get(offset);\n\t\tif (cache) {\n\t\t\treturn {\n\t\t\t\tnode: cache.node,\n\t\t\t\tnodeStartOffset: cache.nodeStartOffset,\n\t\t\t\tremainder: offset - cache.nodeStartOffset\n\t\t\t};\n\t\t}\n\n\t\tlet nodeStartOffset = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.size_left > offset) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.size_left + x.piece.length >= offset) {\n\t\t\t\tnodeStartOffset += x.size_left;\n\t\t\t\tconst ret = {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: offset - x.size_left,\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t\tthis._searchCache.set(ret);\n\t\t\t\treturn ret;\n\t\t\t} else {\n\t\t\t\toffset -= x.size_left + x.piece.length;\n\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\treturn null!;\n\t}\n\n\tprivate nodeAt2(lineNumber: number, column: number): NodePosition {\n\t\tlet x = this.root;\n\t\tlet nodeStartOffset = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {\n\t\t\t\tconst prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);\n\t\t\t\tnodeStartOffset += x.size_left;\n\n\t\t\t\treturn {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: Math.min(prevAccumualtedValue + column - 1, accumulatedValue),\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {\n\t\t\t\tconst prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\tif (prevAccumualtedValue + column - 1 <= x.piece.length) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tremainder: prevAccumualtedValue + column - 1,\n\t\t\t\t\t\tnodeStartOffset\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tcolumn -= x.piece.length - prevAccumualtedValue;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\t// search in order, to find the node contains position.column\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\n\t\t\tif (x.piece.lineFeedCnt > 0) {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, 0);\n\t\t\t\tconst nodeStartOffset = this.offsetOfNode(x);\n\t\t\t\treturn {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: Math.min(column - 1, accumulatedValue),\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tif (x.piece.length >= column - 1) {\n\t\t\t\t\tconst nodeStartOffset = this.offsetOfNode(x);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tremainder: column - 1,\n\t\t\t\t\t\tnodeStartOffset\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tcolumn -= x.piece.length;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn null!;\n\t}\n\n\tprivate nodeCharCodeAt(node: TreeNode, offset: number): number {\n\t\tif (node.piece.lineFeedCnt < 1) {\n\t\t\treturn -1;\n\t\t}\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst newOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start) + offset;\n\t\treturn buffer.buffer.charCodeAt(newOffset);\n\t}\n\n\tprivate offsetOfNode(node: TreeNode): number {\n\t\tif (!node) {\n\t\t\treturn 0;\n\t\t}\n\t\tlet pos = node.size_left;\n\t\twhile (node !== this.root) {\n\t\t\tif (node.parent.right === node) {\n\t\t\t\tpos += node.parent.size_left + node.parent.piece.length;\n\t\t\t}\n\n\t\t\tnode = node.parent;\n\t\t}\n\n\t\treturn pos;\n\t}\n\n\t// #endregion\n\n\t// #region CRLF\n\tprivate shouldCheckCRLF() {\n\t\treturn !(this._EOLNormalized && this._EOL === '\\n');\n\t}\n\n\tprivate startWithLF(val: string | TreeNode): boolean {\n\t\tif (typeof val === 'string') {\n\t\t\treturn val.charCodeAt(0) === 10;\n\t\t}\n\n\t\tif (val === SENTINEL || val.piece.lineFeedCnt === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst piece = val.piece;\n\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\t\tconst line = piece.start.line;\n\t\tconst startOffset = lineStarts[line] + piece.start.column;\n\t\tif (line === lineStarts.length - 1) {\n\t\t\t// last line, so there is no line feed at the end of this line\n\t\t\treturn false;\n\t\t}\n\t\tconst nextLineOffset = lineStarts[line + 1];\n\t\tif (nextLineOffset > startOffset + 1) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this._buffers[piece.bufferIndex].buffer.charCodeAt(startOffset) === 10;\n\t}\n\n\tprivate endWithCR(val: string | TreeNode): boolean {\n\t\tif (typeof val === 'string') {\n\t\t\treturn val.charCodeAt(val.length - 1) === 13;\n\t\t}\n\n\t\tif (val === SENTINEL || val.piece.lineFeedCnt === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.nodeCharCodeAt(val, val.piece.length - 1) === 13;\n\t}\n\n\tprivate validateCRLFWithPrevNode(nextNode: TreeNode) {\n\t\tif (this.shouldCheckCRLF() && this.startWithLF(nextNode)) {\n\t\t\tconst node = nextNode.prev();\n\t\t\tif (this.endWithCR(node)) {\n\t\t\t\tthis.fixCRLF(node, nextNode);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate validateCRLFWithNextNode(node: TreeNode) {\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(node)) {\n\t\t\tconst nextNode = node.next();\n\t\t\tif (this.startWithLF(nextNode)) {\n\t\t\t\tthis.fixCRLF(node, nextNode);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fixCRLF(prev: TreeNode, next: TreeNode) {\n\t\tconst nodesToDel: TreeNode[] = [];\n\t\t// update node\n\t\tconst lineStarts = this._buffers[prev.piece.bufferIndex].lineStarts;\n\t\tlet newEnd: BufferCursor;\n\t\tif (prev.piece.end.column === 0) {\n\t\t\t// it means, last line ends with \\r, not \\r\\n\n\t\t\tnewEnd = { line: prev.piece.end.line - 1, column: lineStarts[prev.piece.end.line] - lineStarts[prev.piece.end.line - 1] - 1 };\n\t\t} else {\n\t\t\t// \\r\\n\n\t\t\tnewEnd = { line: prev.piece.end.line, column: prev.piece.end.column - 1 };\n\t\t}\n\n\t\tconst prevNewLength = prev.piece.length - 1;\n\t\tconst prevNewLFCnt = prev.piece.lineFeedCnt - 1;\n\t\tprev.piece = new Piece(\n\t\t\tprev.piece.bufferIndex,\n\t\t\tprev.piece.start,\n\t\t\tnewEnd,\n\t\t\tprevNewLFCnt,\n\t\t\tprevNewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, prev, -1, -1);\n\t\tif (prev.piece.length === 0) {\n\t\t\tnodesToDel.push(prev);\n\t\t}\n\n\t\t// update nextNode\n\t\tconst newStart: BufferCursor = { line: next.piece.start.line + 1, column: 0 };\n\t\tconst newLength = next.piece.length - 1;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(next.piece.bufferIndex, newStart, next.piece.end);\n\t\tnext.piece = new Piece(\n\t\t\tnext.piece.bufferIndex,\n\t\t\tnewStart,\n\t\t\tnext.piece.end,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, next, -1, -1);\n\t\tif (next.piece.length === 0) {\n\t\t\tnodesToDel.push(next);\n\t\t}\n\n\t\t// create new piece which contains \\r\\n\n\t\tconst pieces = this.createNewPieces('\\r\\n');\n\t\tthis.rbInsertRight(prev, pieces[0]);\n\t\t// delete empty nodes\n\n\t\tfor (let i = 0; i < nodesToDel.length; i++) {\n\t\t\trbDelete(this, nodesToDel[i]);\n\t\t}\n\t}\n\n\tprivate adjustCarriageReturnFromNext(value: string, node: TreeNode): boolean {\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(value)) {\n\t\t\tconst nextNode = node.next();\n\t\t\tif (this.startWithLF(nextNode)) {\n\t\t\t\t// move `\\n` forward\n\t\t\t\tvalue += '\\n';\n\n\t\t\t\tif (nextNode.piece.length === 1) {\n\t\t\t\t\trbDelete(this, nextNode);\n\t\t\t\t} else {\n\n\t\t\t\t\tconst piece = nextNode.piece;\n\t\t\t\t\tconst newStart: BufferCursor = { line: piece.start.line + 1, column: 0 };\n\t\t\t\t\tconst newLength = piece.length - 1;\n\t\t\t\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);\n\t\t\t\t\tnextNode.piece = new Piece(\n\t\t\t\t\t\tpiece.bufferIndex,\n\t\t\t\t\t\tnewStart,\n\t\t\t\t\t\tpiece.end,\n\t\t\t\t\t\tnewLineFeedCnt,\n\t\t\t\t\t\tnewLength\n\t\t\t\t\t);\n\n\t\t\t\t\tupdateTreeMetadata(this, nextNode, -1, -1);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t// #endregion\n\n\t// #endregion\n\n\t// #region Tree operations\n\titerate(node: TreeNode, callback: (node: TreeNode) => boolean): boolean {\n\t\tif (node === SENTINEL) {\n\t\t\treturn callback(SENTINEL);\n\t\t}\n\n\t\tconst leftRet = this.iterate(node.left, callback);\n\t\tif (!leftRet) {\n\t\t\treturn leftRet;\n\t\t}\n\n\t\treturn callback(node) && this.iterate(node.right, callback);\n\t}\n\n\tprivate getNodeContent(node: TreeNode) {\n\t\tif (node === SENTINEL) {\n\t\t\treturn '';\n\t\t}\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst piece = node.piece;\n\t\tconst startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\t\tconst endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\t\tconst currentContent = buffer.buffer.substring(startOffset, endOffset);\n\t\treturn currentContent;\n\t}\n\n\tgetPieceContent(piece: Piece) {\n\t\tconst buffer = this._buffers[piece.bufferIndex];\n\t\tconst startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\t\tconst endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\t\tconst currentContent = buffer.buffer.substring(startOffset, endOffset);\n\t\treturn currentContent;\n\t}\n\n\t/**\n\t * node node\n\t * / \\ / \\\n\t * a b <---- a b\n\t * /\n\t * z\n\t */\n\tprivate rbInsertRight(node: TreeNode | null, p: Piece): TreeNode {\n\t\tconst z = new TreeNode(p, NodeColor.Red);\n\t\tz.left = SENTINEL;\n\t\tz.right = SENTINEL;\n\t\tz.parent = SENTINEL;\n\t\tz.size_left = 0;\n\t\tz.lf_left = 0;\n\n\t\tconst x = this.root;\n\t\tif (x === SENTINEL) {\n\t\t\tthis.root = z;\n\t\t\tz.color = NodeColor.Black;\n\t\t} else if (node!.right === SENTINEL) {\n\t\t\tnode!.right = z;\n\t\t\tz.parent = node!;\n\t\t} else {\n\t\t\tconst nextNode = leftest(node!.right);\n\t\t\tnextNode.left = z;\n\t\t\tz.parent = nextNode;\n\t\t}\n\n\t\tfixInsert(this, z);\n\t\treturn z;\n\t}\n\n\t/**\n\t * node node\n\t * / \\ / \\\n\t * a b ----> a b\n\t * \\\n\t * z\n\t */\n\tprivate rbInsertLeft(node: TreeNode | null, p: Piece): TreeNode {\n\t\tconst z = new TreeNode(p, NodeColor.Red);\n\t\tz.left = SENTINEL;\n\t\tz.right = SENTINEL;\n\t\tz.parent = SENTINEL;\n\t\tz.size_left = 0;\n\t\tz.lf_left = 0;\n\n\t\tif (this.root === SENTINEL) {\n\t\t\tthis.root = z;\n\t\t\tz.color = NodeColor.Black;\n\t\t} else if (node!.left === SENTINEL) {\n\t\t\tnode!.left = z;\n\t\t\tz.parent = node!;\n\t\t} else {\n\t\t\tconst prevNode = righttest(node!.left); // a\n\t\t\tprevNode.right = z;\n\t\t\tz.parent = prevNode;\n\t\t}\n\n\t\tfixInsert(this, z);\n\t\treturn z;\n\t}\n\t// #endregion\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { CharCode } from '../../../../base/common/charCode.js';\nimport { Position } from '../../core/position.js';\nimport { Range } from '../../core/range.js';\nimport { FindMatch, ITextSnapshot, SearchData } from '../../model.js';\nimport { NodeColor, SENTINEL, TreeNode, fixInsert, leftest, rbDelete, righttest, updateTreeMetadata } from './rbTreeBase.js';\nimport { Searcher, createFindMatch, isValidMatch } from '../textModelSearch.js';\n\n// const lfRegex = new RegExp(/\\r\\n|\\r|\\n/g);\nconst AverageBufferSize = 65535;\n\nfunction createUintArray(arr: number[]): Uint32Array | Uint16Array {\n\tlet r;\n\tif (arr[arr.length - 1] < 65536) {\n\t\tr = new Uint16Array(arr.length);\n\t} else {\n\t\tr = new Uint32Array(arr.length);\n\t}\n\tr.set(arr, 0);\n\treturn r;\n}\n\nclass LineStarts {\n\tconstructor(\n\t\tpublic readonly lineStarts: Uint32Array | Uint16Array | number[],\n\t\tpublic readonly cr: number,\n\t\tpublic readonly lf: number,\n\t\tpublic readonly crlf: number,\n\t\tpublic readonly isBasicASCII: boolean\n\t) { }\n}\n\nexport function createLineStartsFast(str: string, readonly: boolean = true): Uint32Array | Uint16Array | number[] {\n\tconst r: number[] = [0];\n\tlet rLength = 1;\n\n\tfor (let i = 0, len = str.length; i < len; i++) {\n\t\tconst chr = str.charCodeAt(i);\n\n\t\tif (chr === CharCode.CarriageReturn) {\n\t\t\tif (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) {\n\t\t\t\t// \\r\\n... case\n\t\t\t\tr[rLength++] = i + 2;\n\t\t\t\ti++; // skip \\n\n\t\t\t} else {\n\t\t\t\t// \\r... case\n\t\t\t\tr[rLength++] = i + 1;\n\t\t\t}\n\t\t} else if (chr === CharCode.LineFeed) {\n\t\t\tr[rLength++] = i + 1;\n\t\t}\n\t}\n\tif (readonly) {\n\t\treturn createUintArray(r);\n\t} else {\n\t\treturn r;\n\t}\n}\n\nexport function createLineStarts(r: number[], str: string): LineStarts {\n\tr.length = 0;\n\tr[0] = 0;\n\tlet rLength = 1;\n\tlet cr = 0, lf = 0, crlf = 0;\n\tlet isBasicASCII = true;\n\tfor (let i = 0, len = str.length; i < len; i++) {\n\t\tconst chr = str.charCodeAt(i);\n\n\t\tif (chr === CharCode.CarriageReturn) {\n\t\t\tif (i + 1 < len && str.charCodeAt(i + 1) === CharCode.LineFeed) {\n\t\t\t\t// \\r\\n... case\n\t\t\t\tcrlf++;\n\t\t\t\tr[rLength++] = i + 2;\n\t\t\t\ti++; // skip \\n\n\t\t\t} else {\n\t\t\t\tcr++;\n\t\t\t\t// \\r... case\n\t\t\t\tr[rLength++] = i + 1;\n\t\t\t}\n\t\t} else if (chr === CharCode.LineFeed) {\n\t\t\tlf++;\n\t\t\tr[rLength++] = i + 1;\n\t\t} else {\n\t\t\tif (isBasicASCII) {\n\t\t\t\tif (chr !== CharCode.Tab && (chr < 32 || chr > 126)) {\n\t\t\t\t\tisBasicASCII = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tconst result = new LineStarts(createUintArray(r), cr, lf, crlf, isBasicASCII);\n\tr.length = 0;\n\n\treturn result;\n}\n\ninterface NodePosition {\n\t/**\n\t * Piece Index\n\t */\n\tnode: TreeNode;\n\t/**\n\t * remainder in current piece.\n\t*/\n\tremainder: number;\n\t/**\n\t * node start offset in document.\n\t */\n\tnodeStartOffset: number;\n}\n\ninterface BufferCursor {\n\t/**\n\t * Line number in current buffer\n\t */\n\tline: number;\n\t/**\n\t * Column number in current buffer\n\t */\n\tcolumn: number;\n}\n\nexport class Piece {\n\treadonly bufferIndex: number;\n\treadonly start: BufferCursor;\n\treadonly end: BufferCursor;\n\treadonly length: number;\n\treadonly lineFeedCnt: number;\n\n\tconstructor(bufferIndex: number, start: BufferCursor, end: BufferCursor, lineFeedCnt: number, length: number) {\n\t\tthis.bufferIndex = bufferIndex;\n\t\tthis.start = start;\n\t\tthis.end = end;\n\t\tthis.lineFeedCnt = lineFeedCnt;\n\t\tthis.length = length;\n\t}\n}\n\nexport class StringBuffer {\n\tbuffer: string;\n\tlineStarts: Uint32Array | Uint16Array | number[];\n\n\tconstructor(buffer: string, lineStarts: Uint32Array | Uint16Array | number[]) {\n\t\tthis.buffer = buffer;\n\t\tthis.lineStarts = lineStarts;\n\t}\n}\n\n/**\n * Readonly snapshot for piece tree.\n * In a real multiple thread environment, to make snapshot reading always work correctly, we need to\n * 1. Make TreeNode.piece immutable, then reading and writing can run in parallel.\n * 2. TreeNode/Buffers normalization should not happen during snapshot reading.\n */\nclass PieceTreeSnapshot implements ITextSnapshot {\n\tprivate readonly _pieces: Piece[];\n\tprivate _index: number;\n\tprivate readonly _tree: PieceTreeBase;\n\tprivate readonly _BOM: string;\n\n\tconstructor(tree: PieceTreeBase, BOM: string) {\n\t\tthis._pieces = [];\n\t\tthis._tree = tree;\n\t\tthis._BOM = BOM;\n\t\tthis._index = 0;\n\t\tif (tree.root !== SENTINEL) {\n\t\t\ttree.iterate(tree.root, node => {\n\t\t\t\tif (node !== SENTINEL) {\n\t\t\t\t\tthis._pieces.push(node.piece);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t});\n\t\t}\n\t}\n\n\tread(): string | null {\n\t\tif (this._pieces.length === 0) {\n\t\t\tif (this._index === 0) {\n\t\t\t\tthis._index++;\n\t\t\t\treturn this._BOM;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tif (this._index > this._pieces.length - 1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (this._index === 0) {\n\t\t\treturn this._BOM + this._tree.getPieceContent(this._pieces[this._index++]);\n\t\t}\n\t\treturn this._tree.getPieceContent(this._pieces[this._index++]);\n\t}\n}\n\ninterface CacheEntry {\n\tnode: TreeNode;\n\tnodeStartOffset: number;\n\tnodeStartLineNumber?: number;\n}\n\nclass PieceTreeSearchCache {\n\tprivate readonly _limit: number;\n\tprivate _cache: CacheEntry[];\n\n\tconstructor(limit: number) {\n\t\tthis._limit = limit;\n\t\tthis._cache = [];\n\t}\n\n\tpublic get(offset: number): CacheEntry | null {\n\t\tfor (let i = this._cache.length - 1; i >= 0; i--) {\n\t\t\tconst nodePos = this._cache[i];\n\t\t\tif (nodePos.nodeStartOffset <= offset && nodePos.nodeStartOffset + nodePos.node.piece.length >= offset) {\n\t\t\t\treturn nodePos;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic get2(lineNumber: number): { node: TreeNode; nodeStartOffset: number; nodeStartLineNumber: number } | null {\n\t\tfor (let i = this._cache.length - 1; i >= 0; i--) {\n\t\t\tconst nodePos = this._cache[i];\n\t\t\tif (nodePos.nodeStartLineNumber && nodePos.nodeStartLineNumber < lineNumber && nodePos.nodeStartLineNumber + nodePos.node.piece.lineFeedCnt >= lineNumber) {\n\t\t\t\treturn <{ node: TreeNode; nodeStartOffset: number; nodeStartLineNumber: number }>nodePos;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic set(nodePosition: CacheEntry) {\n\t\tif (this._cache.length >= this._limit) {\n\t\t\tthis._cache.shift();\n\t\t}\n\t\tthis._cache.push(nodePosition);\n\t}\n\n\tpublic validate(offset: number) {\n\t\tlet hasInvalidVal = false;\n\t\tconst tmp: Array<CacheEntry | null> = this._cache;\n\t\tfor (let i = 0; i < tmp.length; i++) {\n\t\t\tconst nodePos = tmp[i]!;\n\t\t\tif (nodePos.node.parent === null || nodePos.nodeStartOffset >= offset) {\n\t\t\t\ttmp[i] = null;\n\t\t\t\thasInvalidVal = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif (hasInvalidVal) {\n\t\t\tconst newArr: CacheEntry[] = [];\n\t\t\tfor (const entry of tmp) {\n\t\t\t\tif (entry !== null) {\n\t\t\t\t\tnewArr.push(entry);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._cache = newArr;\n\t\t}\n\t}\n}\n\nexport class PieceTreeBase {\n\troot!: TreeNode;\n\tprotected _buffers!: StringBuffer[]; // 0 is change buffer, others are readonly original buffer.\n\tprotected _lineCnt!: number;\n\tprotected _length!: number;\n\tprotected _EOL!: '\\r\\n' | '\\n';\n\tprotected _EOLLength!: number;\n\tprotected _EOLNormalized!: boolean;\n\tprivate _lastChangeBufferPos!: BufferCursor;\n\tprivate _searchCache!: PieceTreeSearchCache;\n\tprivate _lastVisitedLine!: { lineNumber: number; value: string };\n\n\tconstructor(chunks: StringBuffer[], eol: '\\r\\n' | '\\n', eolNormalized: boolean) {\n\t\tthis.create(chunks, eol, eolNormalized);\n\t}\n\n\tcreate(chunks: StringBuffer[], eol: '\\r\\n' | '\\n', eolNormalized: boolean) {\n\t\tthis._buffers = [\n\t\t\tnew StringBuffer('', [0])\n\t\t];\n\t\tthis._lastChangeBufferPos = { line: 0, column: 0 };\n\t\tthis.root = SENTINEL;\n\t\tthis._lineCnt = 1;\n\t\tthis._length = 0;\n\t\tthis._EOL = eol;\n\t\tthis._EOLLength = eol.length;\n\t\tthis._EOLNormalized = eolNormalized;\n\n\t\tlet lastNode: TreeNode | null = null;\n\t\tfor (let i = 0, len = chunks.length; i < len; i++) {\n\t\t\tif (chunks[i].buffer.length > 0) {\n\t\t\t\tif (!chunks[i].lineStarts) {\n\t\t\t\t\tchunks[i].lineStarts = createLineStartsFast(chunks[i].buffer);\n\t\t\t\t}\n\n\t\t\t\tconst piece = new Piece(\n\t\t\t\t\ti + 1,\n\t\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t\t{ line: chunks[i].lineStarts.length - 1, column: chunks[i].buffer.length - chunks[i].lineStarts[chunks[i].lineStarts.length - 1] },\n\t\t\t\t\tchunks[i].lineStarts.length - 1,\n\t\t\t\t\tchunks[i].buffer.length\n\t\t\t\t);\n\t\t\t\tthis._buffers.push(chunks[i]);\n\t\t\t\tlastNode = this.rbInsertRight(lastNode, piece);\n\t\t\t}\n\t\t}\n\n\t\tthis._searchCache = new PieceTreeSearchCache(1);\n\t\tthis._lastVisitedLine = { lineNumber: 0, value: '' };\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tnormalizeEOL(eol: '\\r\\n' | '\\n') {\n\t\tconst averageBufferSize = AverageBufferSize;\n\t\tconst min = averageBufferSize - Math.floor(averageBufferSize / 3);\n\t\tconst max = min * 2;\n\n\t\tlet tempChunk = '';\n\t\tlet tempChunkLen = 0;\n\t\tconst chunks: StringBuffer[] = [];\n\n\t\tthis.iterate(this.root, node => {\n\t\t\tconst str = this.getNodeContent(node);\n\t\t\tconst len = str.length;\n\t\t\tif (tempChunkLen <= min || tempChunkLen + len < max) {\n\t\t\t\ttempChunk += str;\n\t\t\t\ttempChunkLen += len;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// flush anyways\n\t\t\tconst text = tempChunk.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\tchunks.push(new StringBuffer(text, createLineStartsFast(text)));\n\t\t\ttempChunk = str;\n\t\t\ttempChunkLen = len;\n\t\t\treturn true;\n\t\t});\n\n\t\tif (tempChunkLen > 0) {\n\t\t\tconst text = tempChunk.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\tchunks.push(new StringBuffer(text, createLineStartsFast(text)));\n\t\t}\n\n\t\tthis.create(chunks, eol, true);\n\t}\n\n\t// #region Buffer API\n\tpublic getEOL(): '\\r\\n' | '\\n' {\n\t\treturn this._EOL;\n\t}\n\n\tpublic setEOL(newEOL: '\\r\\n' | '\\n'): void {\n\t\tthis._EOL = newEOL;\n\t\tthis._EOLLength = this._EOL.length;\n\t\tthis.normalizeEOL(newEOL);\n\t}\n\n\tpublic createSnapshot(BOM: string): ITextSnapshot {\n\t\treturn new PieceTreeSnapshot(this, BOM);\n\t}\n\n\tpublic getOffsetAt(lineNumber: number, column: number): number {\n\t\tlet leftLen = 0; // inorder\n\n\t\tlet x = this.root;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.left !== SENTINEL && x.lf_left + 1 >= lineNumber) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt + 1 >= lineNumber) {\n\t\t\t\tleftLen += x.size_left;\n\t\t\t\t// lineNumber >= 2\n\t\t\t\tconst accumualtedValInCurrentIndex = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\treturn leftLen += accumualtedValInCurrentIndex + column - 1;\n\t\t\t} else {\n\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\tleftLen += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\treturn leftLen;\n\t}\n\n\tpublic getPositionAt(offset: number): Position {\n\t\toffset = Math.floor(offset);\n\t\toffset = Math.max(0, offset);\n\n\t\tlet x = this.root;\n\t\tlet lfCnt = 0;\n\t\tconst originalOffset = offset;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.size_left !== 0 && x.size_left >= offset) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.size_left + x.piece.length >= offset) {\n\t\t\t\tconst out = this.getIndexOf(x, offset - x.size_left);\n\n\t\t\t\tlfCnt += x.lf_left + out.index;\n\n\t\t\t\tif (out.index === 0) {\n\t\t\t\t\tconst lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);\n\t\t\t\t\tconst column = originalOffset - lineStartOffset;\n\t\t\t\t\treturn new Position(lfCnt + 1, column + 1);\n\t\t\t\t}\n\n\t\t\t\treturn new Position(lfCnt + 1, out.remainder + 1);\n\t\t\t} else {\n\t\t\t\toffset -= x.size_left + x.piece.length;\n\t\t\t\tlfCnt += x.lf_left + x.piece.lineFeedCnt;\n\n\t\t\t\tif (x.right === SENTINEL) {\n\t\t\t\t\t// last node\n\t\t\t\t\tconst lineStartOffset = this.getOffsetAt(lfCnt + 1, 1);\n\t\t\t\t\tconst column = originalOffset - offset - lineStartOffset;\n\t\t\t\t\treturn new Position(lfCnt + 1, column + 1);\n\t\t\t\t} else {\n\t\t\t\t\tx = x.right;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn new Position(1, 1);\n\t}\n\n\tpublic getValueInRange(range: Range, eol?: string): string {\n\t\tif (range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn) {\n\t\t\treturn '';\n\t\t}\n\n\t\tconst startPosition = this.nodeAt2(range.startLineNumber, range.startColumn);\n\t\tconst endPosition = this.nodeAt2(range.endLineNumber, range.endColumn);\n\n\t\tconst value = this.getValueInRange2(startPosition, endPosition);\n\t\tif (eol) {\n\t\t\tif (eol !== this._EOL || !this._EOLNormalized) {\n\t\t\t\treturn value.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t\t}\n\n\t\t\tif (eol === this.getEOL() && this._EOLNormalized) {\n\t\t\t\tif (eol === '\\r\\n') {\n\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t}\n\t\t\treturn value.replace(/\\r\\n|\\r|\\n/g, eol);\n\t\t}\n\t\treturn value;\n\t}\n\n\tpublic getValueInRange2(startPosition: NodePosition, endPosition: NodePosition): string {\n\t\tif (startPosition.node === endPosition.node) {\n\t\t\tconst node = startPosition.node;\n\t\t\tconst buffer = this._buffers[node.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);\n\t\t\treturn buffer.substring(startOffset + startPosition.remainder, startOffset + endPosition.remainder);\n\t\t}\n\n\t\tlet x = startPosition.node;\n\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\tlet ret = buffer.substring(startOffset + startPosition.remainder, startOffset + x.piece.length);\n\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\tif (x === endPosition.node) {\n\t\t\t\tret += buffer.substring(startOffset, startOffset + endPosition.remainder);\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tret += buffer.substr(startOffset, x.piece.length);\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tpublic getLinesContent(): string[] {\n\t\tconst lines: string[] = [];\n\t\tlet linesLength = 0;\n\t\tlet currentLine = '';\n\t\tlet danglingCR = false;\n\n\t\tthis.iterate(this.root, node => {\n\t\t\tif (node === SENTINEL) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst piece = node.piece;\n\t\t\tlet pieceLength = piece.length;\n\t\t\tif (pieceLength === 0) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[piece.bufferIndex].buffer;\n\t\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\n\t\t\tconst pieceStartLine = piece.start.line;\n\t\t\tconst pieceEndLine = piece.end.line;\n\t\t\tlet pieceStartOffset = lineStarts[pieceStartLine] + piece.start.column;\n\n\t\t\tif (danglingCR) {\n\t\t\t\tif (buffer.charCodeAt(pieceStartOffset) === CharCode.LineFeed) {\n\t\t\t\t\t// pretend the \\n was in the previous piece..\n\t\t\t\t\tpieceStartOffset++;\n\t\t\t\t\tpieceLength--;\n\t\t\t\t}\n\t\t\t\tlines[linesLength++] = currentLine;\n\t\t\t\tcurrentLine = '';\n\t\t\t\tdanglingCR = false;\n\t\t\t\tif (pieceLength === 0) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (pieceStartLine === pieceEndLine) {\n\t\t\t\t// this piece has no new lines\n\t\t\t\tif (!this._EOLNormalized && buffer.charCodeAt(pieceStartOffset + pieceLength - 1) === CharCode.CarriageReturn) {\n\t\t\t\t\tdanglingCR = true;\n\t\t\t\t\tcurrentLine += buffer.substr(pieceStartOffset, pieceLength - 1);\n\t\t\t\t} else {\n\t\t\t\t\tcurrentLine += buffer.substr(pieceStartOffset, pieceLength);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// add the text before the first line start in this piece\n\t\t\tcurrentLine += (\n\t\t\t\tthis._EOLNormalized\n\t\t\t\t\t? buffer.substring(pieceStartOffset, Math.max(pieceStartOffset, lineStarts[pieceStartLine + 1] - this._EOLLength))\n\t\t\t\t\t: buffer.substring(pieceStartOffset, lineStarts[pieceStartLine + 1]).replace(/(\\r\\n|\\r|\\n)$/, '')\n\t\t\t);\n\t\t\tlines[linesLength++] = currentLine;\n\n\t\t\tfor (let line = pieceStartLine + 1; line < pieceEndLine; line++) {\n\t\t\t\tcurrentLine = (\n\t\t\t\t\tthis._EOLNormalized\n\t\t\t\t\t\t? buffer.substring(lineStarts[line], lineStarts[line + 1] - this._EOLLength)\n\t\t\t\t\t\t: buffer.substring(lineStarts[line], lineStarts[line + 1]).replace(/(\\r\\n|\\r|\\n)$/, '')\n\t\t\t\t);\n\t\t\t\tlines[linesLength++] = currentLine;\n\t\t\t}\n\n\t\t\tif (!this._EOLNormalized && buffer.charCodeAt(lineStarts[pieceEndLine] + piece.end.column - 1) === CharCode.CarriageReturn) {\n\t\t\t\tdanglingCR = true;\n\t\t\t\tif (piece.end.column === 0) {\n\t\t\t\t\t// The last line ended with a \\r, let's undo the push, it will be pushed by next iteration\n\t\t\t\t\tlinesLength--;\n\t\t\t\t} else {\n\t\t\t\t\tcurrentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column - 1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcurrentLine = buffer.substr(lineStarts[pieceEndLine], piece.end.column);\n\t\t\t}\n\n\t\t\treturn true;\n\t\t});\n\n\t\tif (danglingCR) {\n\t\t\tlines[linesLength++] = currentLine;\n\t\t\tcurrentLine = '';\n\t\t}\n\n\t\tlines[linesLength++] = currentLine;\n\t\treturn lines;\n\t}\n\n\tpublic getLength(): number {\n\t\treturn this._length;\n\t}\n\n\tpublic getLineCount(): number {\n\t\treturn this._lineCnt;\n\t}\n\n\tpublic getLineContent(lineNumber: number): string {\n\t\tif (this._lastVisitedLine.lineNumber === lineNumber) {\n\t\t\treturn this._lastVisitedLine.value;\n\t\t}\n\n\t\tthis._lastVisitedLine.lineNumber = lineNumber;\n\n\t\tif (lineNumber === this._lineCnt) {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber);\n\t\t} else if (this._EOLNormalized) {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber, this._EOLLength);\n\t\t} else {\n\t\t\tthis._lastVisitedLine.value = this.getLineRawContent(lineNumber).replace(/(\\r\\n|\\r|\\n)$/, '');\n\t\t}\n\n\t\treturn this._lastVisitedLine.value;\n\t}\n\n\tprivate _getCharCode(nodePos: NodePosition): number {\n\t\tif (nodePos.remainder === nodePos.node.piece.length) {\n\t\t\t// the char we want to fetch is at the head of next node.\n\t\t\tconst matchingNode = nodePos.node.next();\n\t\t\tif (!matchingNode) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[matchingNode.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);\n\t\t\treturn buffer.buffer.charCodeAt(startOffset);\n\t\t} else {\n\t\t\tconst buffer = this._buffers[nodePos.node.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);\n\t\t\tconst targetOffset = startOffset + nodePos.remainder;\n\n\t\t\treturn buffer.buffer.charCodeAt(targetOffset);\n\t\t}\n\t}\n\n\tpublic getLineCharCode(lineNumber: number, index: number): number {\n\t\tconst nodePos = this.nodeAt2(lineNumber, index + 1);\n\t\treturn this._getCharCode(nodePos);\n\t}\n\n\tpublic getLineLength(lineNumber: number): number {\n\t\tif (lineNumber === this.getLineCount()) {\n\t\t\tconst startOffset = this.getOffsetAt(lineNumber, 1);\n\t\t\treturn this.getLength() - startOffset;\n\t\t}\n\t\treturn this.getOffsetAt(lineNumber + 1, 1) - this.getOffsetAt(lineNumber, 1) - this._EOLLength;\n\t}\n\n\tpublic getNearestChunk(offset: number): string {\n\t\tconst nodePos = this.nodeAt(offset);\n\t\tif (nodePos.remainder === nodePos.node.piece.length) {\n\t\t\t// the offset is at the head of next node.\n\t\t\tconst matchingNode = nodePos.node.next();\n\t\t\tif (!matchingNode || matchingNode === SENTINEL) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tconst buffer = this._buffers[matchingNode.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(matchingNode.piece.bufferIndex, matchingNode.piece.start);\n\t\t\treturn buffer.buffer.substring(startOffset, startOffset + matchingNode.piece.length);\n\t\t} else {\n\t\t\tconst buffer = this._buffers[nodePos.node.piece.bufferIndex];\n\t\t\tconst startOffset = this.offsetInBuffer(nodePos.node.piece.bufferIndex, nodePos.node.piece.start);\n\t\t\tconst targetOffset = startOffset + nodePos.remainder;\n\t\t\tconst targetEnd = startOffset + nodePos.node.piece.length;\n\t\t\treturn buffer.buffer.substring(targetOffset, targetEnd);\n\t\t}\n\t}\n\n\tpublic findMatchesInNode(node: TreeNode, searcher: Searcher, startLineNumber: number, startColumn: number, startCursor: BufferCursor, endCursor: BufferCursor, searchData: SearchData, captureMatches: boolean, limitResultCount: number, resultLen: number, result: FindMatch[]) {\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst startOffsetInBuffer = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start);\n\t\tconst start = this.offsetInBuffer(node.piece.bufferIndex, startCursor);\n\t\tconst end = this.offsetInBuffer(node.piece.bufferIndex, endCursor);\n\n\t\tlet m: RegExpExecArray | null;\n\t\t// Reset regex to search from the beginning\n\t\tconst ret: BufferCursor = { line: 0, column: 0 };\n\t\tlet searchText: string;\n\t\tlet offsetInBuffer: (offset: number) => number;\n\n\t\tif (searcher._wordSeparators) {\n\t\t\tsearchText = buffer.buffer.substring(start, end);\n\t\t\toffsetInBuffer = (offset: number) => offset + start;\n\t\t\tsearcher.reset(0);\n\t\t} else {\n\t\t\tsearchText = buffer.buffer;\n\t\t\toffsetInBuffer = (offset: number) => offset;\n\t\t\tsearcher.reset(start);\n\t\t}\n\n\t\tdo {\n\t\t\tm = searcher.next(searchText);\n\n\t\t\tif (m) {\n\t\t\t\tif (offsetInBuffer(m.index) >= end) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t\tthis.positionInBuffer(node, offsetInBuffer(m.index) - startOffsetInBuffer, ret);\n\t\t\t\tconst lineFeedCnt = this.getLineFeedCnt(node.piece.bufferIndex, startCursor, ret);\n\t\t\t\tconst retStartColumn = ret.line === startCursor.line ? ret.column - startCursor.column + startColumn : ret.column + 1;\n\t\t\t\tconst retEndColumn = retStartColumn + m[0].length;\n\t\t\t\tresult[resultLen++] = createFindMatch(new Range(startLineNumber + lineFeedCnt, retStartColumn, startLineNumber + lineFeedCnt, retEndColumn), m, captureMatches);\n\n\t\t\t\tif (offsetInBuffer(m.index) + m[0].length >= end) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} while (m);\n\n\t\treturn resultLen;\n\t}\n\n\tpublic findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[] {\n\t\tconst result: FindMatch[] = [];\n\t\tlet resultLen = 0;\n\t\tconst searcher = new Searcher(searchData.wordSeparators, searchData.regex);\n\n\t\tlet startPosition = this.nodeAt2(searchRange.startLineNumber, searchRange.startColumn);\n\t\tif (startPosition === null) {\n\t\t\treturn [];\n\t\t}\n\t\tconst endPosition = this.nodeAt2(searchRange.endLineNumber, searchRange.endColumn);\n\t\tif (endPosition === null) {\n\t\t\treturn [];\n\t\t}\n\t\tlet start = this.positionInBuffer(startPosition.node, startPosition.remainder);\n\t\tconst end = this.positionInBuffer(endPosition.node, endPosition.remainder);\n\n\t\tif (startPosition.node === endPosition.node) {\n\t\t\tthis.findMatchesInNode(startPosition.node, searcher, searchRange.startLineNumber, searchRange.startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);\n\t\t\treturn result;\n\t\t}\n\n\t\tlet startLineNumber = searchRange.startLineNumber;\n\n\t\tlet currentNode = startPosition.node;\n\t\twhile (currentNode !== endPosition.node) {\n\t\t\tconst lineBreakCnt = this.getLineFeedCnt(currentNode.piece.bufferIndex, start, currentNode.piece.end);\n\n\t\t\tif (lineBreakCnt >= 1) {\n\t\t\t\t// last line break position\n\t\t\t\tconst lineStarts = this._buffers[currentNode.piece.bufferIndex].lineStarts;\n\t\t\t\tconst startOffsetInBuffer = this.offsetInBuffer(currentNode.piece.bufferIndex, currentNode.piece.start);\n\t\t\t\tconst nextLineStartOffset = lineStarts[start.line + lineBreakCnt];\n\t\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;\n\t\t\t\tresultLen = this.findMatchesInNode(currentNode, searcher, startLineNumber, startColumn, start, this.positionInBuffer(currentNode, nextLineStartOffset - startOffsetInBuffer), searchData, captureMatches, limitResultCount, resultLen, result);\n\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\tstartLineNumber += lineBreakCnt;\n\t\t\t}\n\n\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;\n\t\t\t// search for the remaining content\n\t\t\tif (startLineNumber === searchRange.endLineNumber) {\n\t\t\t\tconst text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);\n\t\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, this.getLineContent(startLineNumber).substr(startColumn), startLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\n\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tstartLineNumber++;\n\t\t\tstartPosition = this.nodeAt2(startLineNumber, 1);\n\t\t\tcurrentNode = startPosition.node;\n\t\t\tstart = this.positionInBuffer(startPosition.node, startPosition.remainder);\n\t\t}\n\n\t\tif (startLineNumber === searchRange.endLineNumber) {\n\t\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn - 1 : 0;\n\t\t\tconst text = this.getLineContent(startLineNumber).substring(startColumn, searchRange.endColumn - 1);\n\t\t\tresultLen = this._findMatchesInLine(searchData, searcher, text, searchRange.endLineNumber, startColumn, resultLen, result, captureMatches, limitResultCount);\n\t\t\treturn result;\n\t\t}\n\n\t\tconst startColumn = startLineNumber === searchRange.startLineNumber ? searchRange.startColumn : 1;\n\t\tresultLen = this.findMatchesInNode(endPosition.node, searcher, startLineNumber, startColumn, start, end, searchData, captureMatches, limitResultCount, resultLen, result);\n\t\treturn result;\n\t}\n\n\tprivate _findMatchesInLine(searchData: SearchData, searcher: Searcher, text: string, lineNumber: number, deltaOffset: number, resultLen: number, result: FindMatch[], captureMatches: boolean, limitResultCount: number): number {\n\t\tconst wordSeparators = searchData.wordSeparators;\n\t\tif (!captureMatches && searchData.simpleSearch) {\n\t\t\tconst searchString = searchData.simpleSearch;\n\t\t\tconst searchStringLen = searchString.length;\n\t\t\tconst textLength = text.length;\n\n\t\t\tlet lastMatchIndex = -searchStringLen;\n\t\t\twhile ((lastMatchIndex = text.indexOf(searchString, lastMatchIndex + searchStringLen)) !== -1) {\n\t\t\t\tif (!wordSeparators || isValidMatch(wordSeparators, text, textLength, lastMatchIndex, searchStringLen)) {\n\t\t\t\t\tresult[resultLen++] = new FindMatch(new Range(lineNumber, lastMatchIndex + 1 + deltaOffset, lineNumber, lastMatchIndex + 1 + searchStringLen + deltaOffset), null);\n\t\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\t\treturn resultLen;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn resultLen;\n\t\t}\n\n\t\tlet m: RegExpExecArray | null;\n\t\t// Reset regex to search from the beginning\n\t\tsearcher.reset(0);\n\t\tdo {\n\t\t\tm = searcher.next(text);\n\t\t\tif (m) {\n\t\t\t\tresult[resultLen++] = createFindMatch(new Range(lineNumber, m.index + 1 + deltaOffset, lineNumber, m.index + 1 + m[0].length + deltaOffset), m, captureMatches);\n\t\t\t\tif (resultLen >= limitResultCount) {\n\t\t\t\t\treturn resultLen;\n\t\t\t\t}\n\t\t\t}\n\t\t} while (m);\n\t\treturn resultLen;\n\t}\n\n\t// #endregion\n\n\t// #region Piece Table\n\tpublic insert(offset: number, value: string, eolNormalized: boolean = false): void {\n\t\tthis._EOLNormalized = this._EOLNormalized && eolNormalized;\n\t\tthis._lastVisitedLine.lineNumber = 0;\n\t\tthis._lastVisitedLine.value = '';\n\n\t\tif (this.root !== SENTINEL) {\n\t\t\tconst { node, remainder, nodeStartOffset } = this.nodeAt(offset);\n\t\t\tconst piece = node.piece;\n\t\t\tconst bufferIndex = piece.bufferIndex;\n\t\t\tconst insertPosInBuffer = this.positionInBuffer(node, remainder);\n\t\t\tif (node.piece.bufferIndex === 0 &&\n\t\t\t\tpiece.end.line === this._lastChangeBufferPos.line &&\n\t\t\t\tpiece.end.column === this._lastChangeBufferPos.column &&\n\t\t\t\t(nodeStartOffset + piece.length === offset) &&\n\t\t\t\tvalue.length < AverageBufferSize\n\t\t\t) {\n\t\t\t\t// changed buffer\n\t\t\t\tthis.appendToNode(node, value);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (nodeStartOffset === offset) {\n\t\t\t\tthis.insertContentToNodeLeft(value, node);\n\t\t\t\tthis._searchCache.validate(offset);\n\t\t\t} else if (nodeStartOffset + node.piece.length > offset) {\n\t\t\t\t// we are inserting into the middle of a node.\n\t\t\t\tconst nodesToDel: TreeNode[] = [];\n\t\t\t\tlet newRightPiece = new Piece(\n\t\t\t\t\tpiece.bufferIndex,\n\t\t\t\t\tinsertPosInBuffer,\n\t\t\t\t\tpiece.end,\n\t\t\t\t\tthis.getLineFeedCnt(piece.bufferIndex, insertPosInBuffer, piece.end),\n\t\t\t\t\tthis.offsetInBuffer(bufferIndex, piece.end) - this.offsetInBuffer(bufferIndex, insertPosInBuffer)\n\t\t\t\t);\n\n\t\t\t\tif (this.shouldCheckCRLF() && this.endWithCR(value)) {\n\t\t\t\t\tconst headOfRight = this.nodeCharCodeAt(node, remainder);\n\n\t\t\t\t\tif (headOfRight === 10 /** \\n */) {\n\t\t\t\t\t\tconst newStart: BufferCursor = { line: newRightPiece.start.line + 1, column: 0 };\n\t\t\t\t\t\tnewRightPiece = new Piece(\n\t\t\t\t\t\t\tnewRightPiece.bufferIndex,\n\t\t\t\t\t\t\tnewStart,\n\t\t\t\t\t\t\tnewRightPiece.end,\n\t\t\t\t\t\t\tthis.getLineFeedCnt(newRightPiece.bufferIndex, newStart, newRightPiece.end),\n\t\t\t\t\t\t\tnewRightPiece.length - 1\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tvalue += '\\n';\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// reuse node for content before insertion point.\n\t\t\t\tif (this.shouldCheckCRLF() && this.startWithLF(value)) {\n\t\t\t\t\tconst tailOfLeft = this.nodeCharCodeAt(node, remainder - 1);\n\t\t\t\t\tif (tailOfLeft === 13 /** \\r */) {\n\t\t\t\t\t\tconst previousPos = this.positionInBuffer(node, remainder - 1);\n\t\t\t\t\t\tthis.deleteNodeTail(node, previousPos);\n\t\t\t\t\t\tvalue = '\\r' + value;\n\n\t\t\t\t\t\tif (node.piece.length === 0) {\n\t\t\t\t\t\t\tnodesToDel.push(node);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.deleteNodeTail(node, insertPosInBuffer);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.deleteNodeTail(node, insertPosInBuffer);\n\t\t\t\t}\n\n\t\t\t\tconst newPieces = this.createNewPieces(value);\n\t\t\t\tif (newRightPiece.length > 0) {\n\t\t\t\t\tthis.rbInsertRight(node, newRightPiece);\n\t\t\t\t}\n\n\t\t\t\tlet tmpNode = node;\n\t\t\t\tfor (let k = 0; k < newPieces.length; k++) {\n\t\t\t\t\ttmpNode = this.rbInsertRight(tmpNode, newPieces[k]);\n\t\t\t\t}\n\t\t\t\tthis.deleteNodes(nodesToDel);\n\t\t\t} else {\n\t\t\t\tthis.insertContentToNodeRight(value, node);\n\t\t\t}\n\t\t} else {\n\t\t\t// insert new node\n\t\t\tconst pieces = this.createNewPieces(value);\n\t\t\tlet node = this.rbInsertLeft(null, pieces[0]);\n\n\t\t\tfor (let k = 1; k < pieces.length; k++) {\n\t\t\t\tnode = this.rbInsertRight(node, pieces[k]);\n\t\t\t}\n\t\t}\n\n\t\t// todo, this is too brutal. Total line feed count should be updated the same way as lf_left.\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tpublic delete(offset: number, cnt: number): void {\n\t\tthis._lastVisitedLine.lineNumber = 0;\n\t\tthis._lastVisitedLine.value = '';\n\n\t\tif (cnt <= 0 || this.root === SENTINEL) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst startPosition = this.nodeAt(offset);\n\t\tconst endPosition = this.nodeAt(offset + cnt);\n\t\tconst startNode = startPosition.node;\n\t\tconst endNode = endPosition.node;\n\n\t\tif (startNode === endNode) {\n\t\t\tconst startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);\n\t\t\tconst endSplitPosInBuffer = this.positionInBuffer(startNode, endPosition.remainder);\n\n\t\t\tif (startPosition.nodeStartOffset === offset) {\n\t\t\t\tif (cnt === startNode.piece.length) { // delete node\n\t\t\t\t\tconst next = startNode.next();\n\t\t\t\t\trbDelete(this, startNode);\n\t\t\t\t\tthis.validateCRLFWithPrevNode(next);\n\t\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.deleteNodeHead(startNode, endSplitPosInBuffer);\n\t\t\t\tthis._searchCache.validate(offset);\n\t\t\t\tthis.validateCRLFWithPrevNode(startNode);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (startPosition.nodeStartOffset + startNode.piece.length === offset + cnt) {\n\t\t\t\tthis.deleteNodeTail(startNode, startSplitPosInBuffer);\n\t\t\t\tthis.validateCRLFWithNextNode(startNode);\n\t\t\t\tthis.computeBufferMetadata();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// delete content in the middle, this node will be splitted to nodes\n\t\t\tthis.shrinkNode(startNode, startSplitPosInBuffer, endSplitPosInBuffer);\n\t\t\tthis.computeBufferMetadata();\n\t\t\treturn;\n\t\t}\n\n\t\tconst nodesToDel: TreeNode[] = [];\n\n\t\tconst startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);\n\t\tthis.deleteNodeTail(startNode, startSplitPosInBuffer);\n\t\tthis._searchCache.validate(offset);\n\t\tif (startNode.piece.length === 0) {\n\t\t\tnodesToDel.push(startNode);\n\t\t}\n\n\t\t// update last touched node\n\t\tconst endSplitPosInBuffer = this.positionInBuffer(endNode, endPosition.remainder);\n\t\tthis.deleteNodeHead(endNode, endSplitPosInBuffer);\n\t\tif (endNode.piece.length === 0) {\n\t\t\tnodesToDel.push(endNode);\n\t\t}\n\n\t\t// delete nodes in between\n\t\tconst secondNode = startNode.next();\n\t\tfor (let node = secondNode; node !== SENTINEL && node !== endNode; node = node.next()) {\n\t\t\tnodesToDel.push(node);\n\t\t}\n\n\t\tconst prev = startNode.piece.length === 0 ? startNode.prev() : startNode;\n\t\tthis.deleteNodes(nodesToDel);\n\t\tthis.validateCRLFWithNextNode(prev);\n\t\tthis.computeBufferMetadata();\n\t}\n\n\tprivate insertContentToNodeLeft(value: string, node: TreeNode) {\n\t\t// we are inserting content to the beginning of node\n\t\tconst nodesToDel: TreeNode[] = [];\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(value) && this.startWithLF(node)) {\n\t\t\t// move `\\n` to new node.\n\n\t\t\tconst piece = node.piece;\n\t\t\tconst newStart: BufferCursor = { line: piece.start.line + 1, column: 0 };\n\t\t\tconst nPiece = new Piece(\n\t\t\t\tpiece.bufferIndex,\n\t\t\t\tnewStart,\n\t\t\t\tpiece.end,\n\t\t\t\tthis.getLineFeedCnt(piece.bufferIndex, newStart, piece.end),\n\t\t\t\tpiece.length - 1\n\t\t\t);\n\n\t\t\tnode.piece = nPiece;\n\n\t\t\tvalue += '\\n';\n\t\t\tupdateTreeMetadata(this, node, -1, -1);\n\n\t\t\tif (node.piece.length === 0) {\n\t\t\t\tnodesToDel.push(node);\n\t\t\t}\n\t\t}\n\n\t\tconst newPieces = this.createNewPieces(value);\n\t\tlet newNode = this.rbInsertLeft(node, newPieces[newPieces.length - 1]);\n\t\tfor (let k = newPieces.length - 2; k >= 0; k--) {\n\t\t\tnewNode = this.rbInsertLeft(newNode, newPieces[k]);\n\t\t}\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t\tthis.deleteNodes(nodesToDel);\n\t}\n\n\tprivate insertContentToNodeRight(value: string, node: TreeNode) {\n\t\t// we are inserting to the right of this node.\n\t\tif (this.adjustCarriageReturnFromNext(value, node)) {\n\t\t\t// move \\n to the new node.\n\t\t\tvalue += '\\n';\n\t\t}\n\n\t\tconst newPieces = this.createNewPieces(value);\n\t\tconst newNode = this.rbInsertRight(node, newPieces[0]);\n\t\tlet tmpNode = newNode;\n\n\t\tfor (let k = 1; k < newPieces.length; k++) {\n\t\t\ttmpNode = this.rbInsertRight(tmpNode, newPieces[k]);\n\t\t}\n\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t}\n\n\tprivate positionInBuffer(node: TreeNode, remainder: number): BufferCursor;\n\tprivate positionInBuffer(node: TreeNode, remainder: number, ret: BufferCursor): null;\n\tprivate positionInBuffer(node: TreeNode, remainder: number, ret?: BufferCursor): BufferCursor | null {\n\t\tconst piece = node.piece;\n\t\tconst bufferIndex = node.piece.bufferIndex;\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\n\t\tconst startOffset = lineStarts[piece.start.line] + piece.start.column;\n\n\t\tconst offset = startOffset + remainder;\n\n\t\t// binary search offset between startOffset and endOffset\n\t\tlet low = piece.start.line;\n\t\tlet high = piece.end.line;\n\n\t\tlet mid: number = 0;\n\t\tlet midStop: number = 0;\n\t\tlet midStart: number = 0;\n\n\t\twhile (low <= high) {\n\t\t\tmid = low + ((high - low) / 2) | 0;\n\t\t\tmidStart = lineStarts[mid];\n\n\t\t\tif (mid === high) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tmidStop = lineStarts[mid + 1];\n\n\t\t\tif (offset < midStart) {\n\t\t\t\thigh = mid - 1;\n\t\t\t} else if (offset >= midStop) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (ret) {\n\t\t\tret.line = mid;\n\t\t\tret.column = offset - midStart;\n\t\t\treturn null;\n\t\t}\n\n\t\treturn {\n\t\t\tline: mid,\n\t\t\tcolumn: offset - midStart\n\t\t};\n\t}\n\n\tprivate getLineFeedCnt(bufferIndex: number, start: BufferCursor, end: BufferCursor): number {\n\t\t// we don't need to worry about start: abc\\r|\\n, or abc|\\r, or abc|\\n, or abc|\\r\\n doesn't change the fact that, there is one line break after start.\n\t\t// now let's take care of end: abc\\r|\\n, if end is in between \\r and \\n, we need to add line feed count by 1\n\t\tif (end.column === 0) {\n\t\t\treturn end.line - start.line;\n\t\t}\n\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\t\tif (end.line === lineStarts.length - 1) { // it means, there is no \\n after end, otherwise, there will be one more lineStart.\n\t\t\treturn end.line - start.line;\n\t\t}\n\n\t\tconst nextLineStartOffset = lineStarts[end.line + 1];\n\t\tconst endOffset = lineStarts[end.line] + end.column;\n\t\tif (nextLineStartOffset > endOffset + 1) { // there are more than 1 character after end, which means it can't be \\n\n\t\t\treturn end.line - start.line;\n\t\t}\n\t\t// endOffset + 1 === nextLineStartOffset\n\t\t// character at endOffset is \\n, so we check the character before first\n\t\t// if character at endOffset is \\r, end.column is 0 and we can't get here.\n\t\tconst previousCharOffset = endOffset - 1; // end.column > 0 so it's okay.\n\t\tconst buffer = this._buffers[bufferIndex].buffer;\n\n\t\tif (buffer.charCodeAt(previousCharOffset) === 13) {\n\t\t\treturn end.line - start.line + 1;\n\t\t} else {\n\t\t\treturn end.line - start.line;\n\t\t}\n\t}\n\n\tprivate offsetInBuffer(bufferIndex: number, cursor: BufferCursor): number {\n\t\tconst lineStarts = this._buffers[bufferIndex].lineStarts;\n\t\treturn lineStarts[cursor.line] + cursor.column;\n\t}\n\n\tprivate deleteNodes(nodes: TreeNode[]): void {\n\t\tfor (let i = 0; i < nodes.length; i++) {\n\t\t\trbDelete(this, nodes[i]);\n\t\t}\n\t}\n\n\tprivate createNewPieces(text: string): Piece[] {\n\t\tif (text.length > AverageBufferSize) {\n\t\t\t// the content is large, operations like substring, charCode becomes slow\n\t\t\t// so here we split it into smaller chunks, just like what we did for CR/LF normalization\n\t\t\tconst newPieces: Piece[] = [];\n\t\t\twhile (text.length > AverageBufferSize) {\n\t\t\t\tconst lastChar = text.charCodeAt(AverageBufferSize - 1);\n\t\t\t\tlet splitText;\n\t\t\t\tif (lastChar === CharCode.CarriageReturn || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {\n\t\t\t\t\t// last character is \\r or a high surrogate => keep it back\n\t\t\t\t\tsplitText = text.substring(0, AverageBufferSize - 1);\n\t\t\t\t\ttext = text.substring(AverageBufferSize - 1);\n\t\t\t\t} else {\n\t\t\t\t\tsplitText = text.substring(0, AverageBufferSize);\n\t\t\t\t\ttext = text.substring(AverageBufferSize);\n\t\t\t\t}\n\n\t\t\t\tconst lineStarts = createLineStartsFast(splitText);\n\t\t\t\tnewPieces.push(new Piece(\n\t\t\t\t\tthis._buffers.length, /* buffer index */\n\t\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t\t{ line: lineStarts.length - 1, column: splitText.length - lineStarts[lineStarts.length - 1] },\n\t\t\t\t\tlineStarts.length - 1,\n\t\t\t\t\tsplitText.length\n\t\t\t\t));\n\t\t\t\tthis._buffers.push(new StringBuffer(splitText, lineStarts));\n\t\t\t}\n\n\t\t\tconst lineStarts = createLineStartsFast(text);\n\t\t\tnewPieces.push(new Piece(\n\t\t\t\tthis._buffers.length, /* buffer index */\n\t\t\t\t{ line: 0, column: 0 },\n\t\t\t\t{ line: lineStarts.length - 1, column: text.length - lineStarts[lineStarts.length - 1] },\n\t\t\t\tlineStarts.length - 1,\n\t\t\t\ttext.length\n\t\t\t));\n\t\t\tthis._buffers.push(new StringBuffer(text, lineStarts));\n\n\t\t\treturn newPieces;\n\t\t}\n\n\t\tlet startOffset = this._buffers[0].buffer.length;\n\t\tconst lineStarts = createLineStartsFast(text, false);\n\n\t\tlet start = this._lastChangeBufferPos;\n\t\tif (this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 1] === startOffset\n\t\t\t&& startOffset !== 0\n\t\t\t&& this.startWithLF(text)\n\t\t\t&& this.endWithCR(this._buffers[0].buffer) // todo, we can check this._lastChangeBufferPos's column as it's the last one\n\t\t) {\n\t\t\tthis._lastChangeBufferPos = { line: this._lastChangeBufferPos.line, column: this._lastChangeBufferPos.column + 1 };\n\t\t\tstart = this._lastChangeBufferPos;\n\n\t\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\t\tlineStarts[i] += startOffset + 1;\n\t\t\t}\n\n\t\t\tthis._buffers[0].lineStarts = (<number[]>this._buffers[0].lineStarts).concat(<number[]>lineStarts.slice(1));\n\t\t\tthis._buffers[0].buffer += '_' + text;\n\t\t\tstartOffset += 1;\n\t\t} else {\n\t\t\tif (startOffset !== 0) {\n\t\t\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\t\t\tlineStarts[i] += startOffset;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._buffers[0].lineStarts = (<number[]>this._buffers[0].lineStarts).concat(<number[]>lineStarts.slice(1));\n\t\t\tthis._buffers[0].buffer += text;\n\t\t}\n\n\t\tconst endOffset = this._buffers[0].buffer.length;\n\t\tconst endIndex = this._buffers[0].lineStarts.length - 1;\n\t\tconst endColumn = endOffset - this._buffers[0].lineStarts[endIndex];\n\t\tconst endPos = { line: endIndex, column: endColumn };\n\t\tconst newPiece = new Piece(\n\t\t\t0, /** todo@peng */\n\t\t\tstart,\n\t\t\tendPos,\n\t\t\tthis.getLineFeedCnt(0, start, endPos),\n\t\t\tendOffset - startOffset\n\t\t);\n\t\tthis._lastChangeBufferPos = endPos;\n\t\treturn [newPiece];\n\t}\n\n\tpublic getLineRawContent(lineNumber: number, endOffset: number = 0): string {\n\t\tlet x = this.root;\n\n\t\tlet ret = '';\n\t\tconst cache = this._searchCache.get2(lineNumber);\n\t\tif (cache) {\n\t\t\tx = cache.node;\n\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber - 1);\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\tif (cache.nodeStartLineNumber + x.piece.lineFeedCnt === lineNumber) {\n\t\t\t\tret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);\n\t\t\t} else {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber);\n\t\t\t\treturn buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);\n\t\t\t}\n\t\t} else {\n\t\t\tlet nodeStartOffset = 0;\n\t\t\tconst originalLineNumber = lineNumber;\n\t\t\twhile (x !== SENTINEL) {\n\t\t\t\tif (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {\n\t\t\t\t\tx = x.left;\n\t\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {\n\t\t\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);\n\t\t\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\t\t\tnodeStartOffset += x.size_left;\n\t\t\t\t\tthis._searchCache.set({\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tnodeStartOffset,\n\t\t\t\t\t\tnodeStartLineNumber: originalLineNumber - (lineNumber - 1 - x.lf_left)\n\t\t\t\t\t});\n\n\t\t\t\t\treturn buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);\n\t\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {\n\t\t\t\t\tconst prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\t\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\t\t\tret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\t\tx = x.right;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// search in order, to find the node contains end column\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\t\t\tconst buffer = this._buffers[x.piece.bufferIndex].buffer;\n\n\t\t\tif (x.piece.lineFeedCnt > 0) {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, 0);\n\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\n\t\t\t\tret += buffer.substring(startOffset, startOffset + accumulatedValue - endOffset);\n\t\t\t\treturn ret;\n\t\t\t} else {\n\t\t\t\tconst startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);\n\t\t\t\tret += buffer.substr(startOffset, x.piece.length);\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\tprivate computeBufferMetadata() {\n\t\tlet x = this.root;\n\n\t\tlet lfCnt = 1;\n\t\tlet len = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tlfCnt += x.lf_left + x.piece.lineFeedCnt;\n\t\t\tlen += x.size_left + x.piece.length;\n\t\t\tx = x.right;\n\t\t}\n\n\t\tthis._lineCnt = lfCnt;\n\t\tthis._length = len;\n\t\tthis._searchCache.validate(this._length);\n\t}\n\n\t// #region node operations\n\tprivate getIndexOf(node: TreeNode, accumulatedValue: number): { index: number; remainder: number } {\n\t\tconst piece = node.piece;\n\t\tconst pos = this.positionInBuffer(node, accumulatedValue);\n\t\tconst lineCnt = pos.line - piece.start.line;\n\n\t\tif (this.offsetInBuffer(piece.bufferIndex, piece.end) - this.offsetInBuffer(piece.bufferIndex, piece.start) === accumulatedValue) {\n\t\t\t// we are checking the end of this node, so a CRLF check is necessary.\n\t\t\tconst realLineCnt = this.getLineFeedCnt(node.piece.bufferIndex, piece.start, pos);\n\t\t\tif (realLineCnt !== lineCnt) {\n\t\t\t\t// aha yes, CRLF\n\t\t\t\treturn { index: realLineCnt, remainder: 0 };\n\t\t\t}\n\t\t}\n\n\t\treturn { index: lineCnt, remainder: pos.column };\n\t}\n\n\tprivate getAccumulatedValue(node: TreeNode, index: number) {\n\t\tif (index < 0) {\n\t\t\treturn 0;\n\t\t}\n\t\tconst piece = node.piece;\n\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\t\tconst expectedLineStartIndex = piece.start.line + index + 1;\n\t\tif (expectedLineStartIndex > piece.end.line) {\n\t\t\treturn lineStarts[piece.end.line] + piece.end.column - lineStarts[piece.start.line] - piece.start.column;\n\t\t} else {\n\t\t\treturn lineStarts[expectedLineStartIndex] - lineStarts[piece.start.line] - piece.start.column;\n\t\t}\n\t}\n\n\tprivate deleteNodeTail(node: TreeNode, pos: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalLFCnt = piece.lineFeedCnt;\n\t\tconst originalEndOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\n\t\tconst newEnd = pos;\n\t\tconst newEndOffset = this.offsetInBuffer(piece.bufferIndex, newEnd);\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);\n\n\t\tconst lf_delta = newLineFeedCnt - originalLFCnt;\n\t\tconst size_delta = newEndOffset - originalEndOffset;\n\t\tconst newLength = piece.length + size_delta;\n\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tpiece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, size_delta, lf_delta);\n\t}\n\n\tprivate deleteNodeHead(node: TreeNode, pos: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalLFCnt = piece.lineFeedCnt;\n\t\tconst originalStartOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\n\t\tconst newStart = pos;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);\n\t\tconst newStartOffset = this.offsetInBuffer(piece.bufferIndex, newStart);\n\t\tconst lf_delta = newLineFeedCnt - originalLFCnt;\n\t\tconst size_delta = originalStartOffset - newStartOffset;\n\t\tconst newLength = piece.length + size_delta;\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tnewStart,\n\t\t\tpiece.end,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, size_delta, lf_delta);\n\t}\n\n\tprivate shrinkNode(node: TreeNode, start: BufferCursor, end: BufferCursor) {\n\t\tconst piece = node.piece;\n\t\tconst originalStartPos = piece.start;\n\t\tconst originalEndPos = piece.end;\n\n\t\t// old piece, originalStartPos, start\n\t\tconst oldLength = piece.length;\n\t\tconst oldLFCnt = piece.lineFeedCnt;\n\t\tconst newEnd = start;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, piece.start, newEnd);\n\t\tconst newLength = this.offsetInBuffer(piece.bufferIndex, start) - this.offsetInBuffer(piece.bufferIndex, originalStartPos);\n\n\t\tnode.piece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tpiece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, node, newLength - oldLength, newLineFeedCnt - oldLFCnt);\n\n\t\t// new right piece, end, originalEndPos\n\t\tconst newPiece = new Piece(\n\t\t\tpiece.bufferIndex,\n\t\t\tend,\n\t\t\toriginalEndPos,\n\t\t\tthis.getLineFeedCnt(piece.bufferIndex, end, originalEndPos),\n\t\t\tthis.offsetInBuffer(piece.bufferIndex, originalEndPos) - this.offsetInBuffer(piece.bufferIndex, end)\n\t\t);\n\n\t\tconst newNode = this.rbInsertRight(node, newPiece);\n\t\tthis.validateCRLFWithPrevNode(newNode);\n\t}\n\n\tprivate appendToNode(node: TreeNode, value: string): void {\n\t\tif (this.adjustCarriageReturnFromNext(value, node)) {\n\t\t\tvalue += '\\n';\n\t\t}\n\n\t\tconst hitCRLF = this.shouldCheckCRLF() && this.startWithLF(value) && this.endWithCR(node);\n\t\tconst startOffset = this._buffers[0].buffer.length;\n\t\tthis._buffers[0].buffer += value;\n\t\tconst lineStarts = createLineStartsFast(value, false);\n\t\tfor (let i = 0; i < lineStarts.length; i++) {\n\t\t\tlineStarts[i] += startOffset;\n\t\t}\n\t\tif (hitCRLF) {\n\t\t\tconst prevStartOffset = this._buffers[0].lineStarts[this._buffers[0].lineStarts.length - 2];\n\t\t\t(<number[]>this._buffers[0].lineStarts).pop();\n\t\t\t// _lastChangeBufferPos is already wrong\n\t\t\tthis._lastChangeBufferPos = { line: this._lastChangeBufferPos.line - 1, column: startOffset - prevStartOffset };\n\t\t}\n\n\t\tthis._buffers[0].lineStarts = (<number[]>this._buffers[0].lineStarts).concat(<number[]>lineStarts.slice(1));\n\t\tconst endIndex = this._buffers[0].lineStarts.length - 1;\n\t\tconst endColumn = this._buffers[0].buffer.length - this._buffers[0].lineStarts[endIndex];\n\t\tconst newEnd = { line: endIndex, column: endColumn };\n\t\tconst newLength = node.piece.length + value.length;\n\t\tconst oldLineFeedCnt = node.piece.lineFeedCnt;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(0, node.piece.start, newEnd);\n\t\tconst lf_delta = newLineFeedCnt - oldLineFeedCnt;\n\n\t\tnode.piece = new Piece(\n\t\t\tnode.piece.bufferIndex,\n\t\t\tnode.piece.start,\n\t\t\tnewEnd,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tthis._lastChangeBufferPos = newEnd;\n\t\tupdateTreeMetadata(this, node, value.length, lf_delta);\n\t}\n\n\tprivate nodeAt(offset: number): NodePosition {\n\t\tlet x = this.root;\n\t\tconst cache = this._searchCache.get(offset);\n\t\tif (cache) {\n\t\t\treturn {\n\t\t\t\tnode: cache.node,\n\t\t\t\tnodeStartOffset: cache.nodeStartOffset,\n\t\t\t\tremainder: offset - cache.nodeStartOffset\n\t\t\t};\n\t\t}\n\n\t\tlet nodeStartOffset = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.size_left > offset) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.size_left + x.piece.length >= offset) {\n\t\t\t\tnodeStartOffset += x.size_left;\n\t\t\t\tconst ret = {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: offset - x.size_left,\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t\tthis._searchCache.set(ret);\n\t\t\t\treturn ret;\n\t\t\t} else {\n\t\t\t\toffset -= x.size_left + x.piece.length;\n\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\treturn null!;\n\t}\n\n\tprivate nodeAt2(lineNumber: number, column: number): NodePosition {\n\t\tlet x = this.root;\n\t\tlet nodeStartOffset = 0;\n\n\t\twhile (x !== SENTINEL) {\n\t\t\tif (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {\n\t\t\t\tx = x.left;\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {\n\t\t\t\tconst prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);\n\t\t\t\tnodeStartOffset += x.size_left;\n\n\t\t\t\treturn {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: Math.min(prevAccumualtedValue + column - 1, accumulatedValue),\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t} else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {\n\t\t\t\tconst prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);\n\t\t\t\tif (prevAccumualtedValue + column - 1 <= x.piece.length) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tremainder: prevAccumualtedValue + column - 1,\n\t\t\t\t\t\tnodeStartOffset\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tcolumn -= x.piece.length - prevAccumualtedValue;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlineNumber -= x.lf_left + x.piece.lineFeedCnt;\n\t\t\t\tnodeStartOffset += x.size_left + x.piece.length;\n\t\t\t\tx = x.right;\n\t\t\t}\n\t\t}\n\n\t\t// search in order, to find the node contains position.column\n\t\tx = x.next();\n\t\twhile (x !== SENTINEL) {\n\n\t\t\tif (x.piece.lineFeedCnt > 0) {\n\t\t\t\tconst accumulatedValue = this.getAccumulatedValue(x, 0);\n\t\t\t\tconst nodeStartOffset = this.offsetOfNode(x);\n\t\t\t\treturn {\n\t\t\t\t\tnode: x,\n\t\t\t\t\tremainder: Math.min(column - 1, accumulatedValue),\n\t\t\t\t\tnodeStartOffset\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tif (x.piece.length >= column - 1) {\n\t\t\t\t\tconst nodeStartOffset = this.offsetOfNode(x);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnode: x,\n\t\t\t\t\t\tremainder: column - 1,\n\t\t\t\t\t\tnodeStartOffset\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tcolumn -= x.piece.length;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tx = x.next();\n\t\t}\n\n\t\treturn null!;\n\t}\n\n\tprivate nodeCharCodeAt(node: TreeNode, offset: number): number {\n\t\tif (node.piece.lineFeedCnt < 1) {\n\t\t\treturn -1;\n\t\t}\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst newOffset = this.offsetInBuffer(node.piece.bufferIndex, node.piece.start) + offset;\n\t\treturn buffer.buffer.charCodeAt(newOffset);\n\t}\n\n\tprivate offsetOfNode(node: TreeNode): number {\n\t\tif (!node) {\n\t\t\treturn 0;\n\t\t}\n\t\tlet pos = node.size_left;\n\t\twhile (node !== this.root) {\n\t\t\tif (node.parent.right === node) {\n\t\t\t\tpos += node.parent.size_left + node.parent.piece.length;\n\t\t\t}\n\n\t\t\tnode = node.parent;\n\t\t}\n\n\t\treturn pos;\n\t}\n\n\t// #endregion\n\n\t// #region CRLF\n\tprivate shouldCheckCRLF() {\n\t\treturn !(this._EOLNormalized && this._EOL === '\\n');\n\t}\n\n\tprivate startWithLF(val: string | TreeNode): boolean {\n\t\tif (typeof val === 'string') {\n\t\t\treturn val.charCodeAt(0) === 10;\n\t\t}\n\n\t\tif (val === SENTINEL || val.piece.lineFeedCnt === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst piece = val.piece;\n\t\tconst lineStarts = this._buffers[piece.bufferIndex].lineStarts;\n\t\tconst line = piece.start.line;\n\t\tconst startOffset = lineStarts[line] + piece.start.column;\n\t\tif (line === lineStarts.length - 1) {\n\t\t\t// last line, so there is no line feed at the end of this line\n\t\t\treturn false;\n\t\t}\n\t\tconst nextLineOffset = lineStarts[line + 1];\n\t\tif (nextLineOffset > startOffset + 1) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this._buffers[piece.bufferIndex].buffer.charCodeAt(startOffset) === 10;\n\t}\n\n\tprivate endWithCR(val: string | TreeNode): boolean {\n\t\tif (typeof val === 'string') {\n\t\t\treturn val.charCodeAt(val.length - 1) === 13;\n\t\t}\n\n\t\tif (val === SENTINEL || val.piece.lineFeedCnt === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.nodeCharCodeAt(val, val.piece.length - 1) === 13;\n\t}\n\n\tprivate validateCRLFWithPrevNode(nextNode: TreeNode) {\n\t\tif (this.shouldCheckCRLF() && this.startWithLF(nextNode)) {\n\t\t\tconst node = nextNode.prev();\n\t\t\tif (this.endWithCR(node)) {\n\t\t\t\tthis.fixCRLF(node, nextNode);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate validateCRLFWithNextNode(node: TreeNode) {\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(node)) {\n\t\t\tconst nextNode = node.next();\n\t\t\tif (this.startWithLF(nextNode)) {\n\t\t\t\tthis.fixCRLF(node, nextNode);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate fixCRLF(prev: TreeNode, next: TreeNode) {\n\t\tconst nodesToDel: TreeNode[] = [];\n\t\t// update node\n\t\tconst lineStarts = this._buffers[prev.piece.bufferIndex].lineStarts;\n\t\tlet newEnd: BufferCursor;\n\t\tif (prev.piece.end.column === 0) {\n\t\t\t// it means, last line ends with \\r, not \\r\\n\n\t\t\tnewEnd = { line: prev.piece.end.line - 1, column: lineStarts[prev.piece.end.line] - lineStarts[prev.piece.end.line - 1] - 1 };\n\t\t} else {\n\t\t\t// \\r\\n\n\t\t\tnewEnd = { line: prev.piece.end.line, column: prev.piece.end.column - 1 };\n\t\t}\n\n\t\tconst prevNewLength = prev.piece.length - 1;\n\t\tconst prevNewLFCnt = prev.piece.lineFeedCnt - 1;\n\t\tprev.piece = new Piece(\n\t\t\tprev.piece.bufferIndex,\n\t\t\tprev.piece.start,\n\t\t\tnewEnd,\n\t\t\tprevNewLFCnt,\n\t\t\tprevNewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, prev, -1, -1);\n\t\tif (prev.piece.length === 0) {\n\t\t\tnodesToDel.push(prev);\n\t\t}\n\n\t\t// update nextNode\n\t\tconst newStart: BufferCursor = { line: next.piece.start.line + 1, column: 0 };\n\t\tconst newLength = next.piece.length - 1;\n\t\tconst newLineFeedCnt = this.getLineFeedCnt(next.piece.bufferIndex, newStart, next.piece.end);\n\t\tnext.piece = new Piece(\n\t\t\tnext.piece.bufferIndex,\n\t\t\tnewStart,\n\t\t\tnext.piece.end,\n\t\t\tnewLineFeedCnt,\n\t\t\tnewLength\n\t\t);\n\n\t\tupdateTreeMetadata(this, next, -1, -1);\n\t\tif (next.piece.length === 0) {\n\t\t\tnodesToDel.push(next);\n\t\t}\n\n\t\t// create new piece which contains \\r\\n\n\t\tconst pieces = this.createNewPieces('\\r\\n');\n\t\tthis.rbInsertRight(prev, pieces[0]);\n\t\t// delete empty nodes\n\n\t\tfor (let i = 0; i < nodesToDel.length; i++) {\n\t\t\trbDelete(this, nodesToDel[i]);\n\t\t}\n\t}\n\n\tprivate adjustCarriageReturnFromNext(value: string, node: TreeNode): boolean {\n\t\tif (this.shouldCheckCRLF() && this.endWithCR(value)) {\n\t\t\tconst nextNode = node.next();\n\t\t\tif (this.startWithLF(nextNode)) {\n\t\t\t\t// move `\\n` forward\n\t\t\t\tvalue += '\\n';\n\n\t\t\t\tif (nextNode.piece.length === 1) {\n\t\t\t\t\trbDelete(this, nextNode);\n\t\t\t\t} else {\n\n\t\t\t\t\tconst piece = nextNode.piece;\n\t\t\t\t\tconst newStart: BufferCursor = { line: piece.start.line + 1, column: 0 };\n\t\t\t\t\tconst newLength = piece.length - 1;\n\t\t\t\t\tconst newLineFeedCnt = this.getLineFeedCnt(piece.bufferIndex, newStart, piece.end);\n\t\t\t\t\tnextNode.piece = new Piece(\n\t\t\t\t\t\tpiece.bufferIndex,\n\t\t\t\t\t\tnewStart,\n\t\t\t\t\t\tpiece.end,\n\t\t\t\t\t\tnewLineFeedCnt,\n\t\t\t\t\t\tnewLength\n\t\t\t\t\t);\n\n\t\t\t\t\tupdateTreeMetadata(this, nextNode, -1, -1);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t// #endregion\n\n\t// #endregion\n\n\t// #region Tree operations\n\titerate(node: TreeNode, callback: (node: TreeNode) => boolean): boolean {\n\t\tif (node === SENTINEL) {\n\t\t\treturn callback(SENTINEL);\n\t\t}\n\n\t\tconst leftRet = this.iterate(node.left, callback);\n\t\tif (!leftRet) {\n\t\t\treturn leftRet;\n\t\t}\n\n\t\treturn callback(node) && this.iterate(node.right, callback);\n\t}\n\n\tprivate getNodeContent(node: TreeNode) {\n\t\tif (node === SENTINEL) {\n\t\t\treturn '';\n\t\t}\n\t\tconst buffer = this._buffers[node.piece.bufferIndex];\n\t\tconst piece = node.piece;\n\t\tconst startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\t\tconst endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\t\tconst currentContent = buffer.buffer.substring(startOffset, endOffset);\n\t\treturn currentContent;\n\t}\n\n\tgetPieceContent(piece: Piece) {\n\t\tconst buffer = this._buffers[piece.bufferIndex];\n\t\tconst startOffset = this.offsetInBuffer(piece.bufferIndex, piece.start);\n\t\tconst endOffset = this.offsetInBuffer(piece.bufferIndex, piece.end);\n\t\tconst currentContent = buffer.buffer.substring(startOffset, endOffset);\n\t\treturn currentContent;\n\t}\n\n\t/**\n\t * node node\n\t * / \\ / \\\n\t * a b <---- a b\n\t * /\n\t * z\n\t */\n\tprivate rbInsertRight(node: TreeNode | null, p: Piece): TreeNode {\n\t\tconst z = new TreeNode(p, NodeColor.Red);\n\t\tz.left = SENTINEL;\n\t\tz.right = SENTINEL;\n\t\tz.parent = SENTINEL;\n\t\tz.size_left = 0;\n\t\tz.lf_left = 0;\n\n\t\tconst x = this.root;\n\t\tif (x === SENTINEL) {\n\t\t\tthis.root = z;\n\t\t\tz.color = NodeColor.Black;\n\t\t} else if (node!.right === SENTINEL) {\n\t\t\tnode!.right = z;\n\t\t\tz.parent = node!;\n\t\t} else {\n\t\t\tconst nextNode = leftest(node!.right);\n\t\t\tnextNode.left = z;\n\t\t\tz.parent = nextNode;\n\t\t}\n\n\t\tfixInsert(this, z);\n\t\treturn z;\n\t}\n\n\t/**\n\t * node node\n\t * / \\ / \\\n\t * a b ----> a b\n\t * \\\n\t * z\n\t */\n\tprivate rbInsertLeft(node: TreeNode | null, p: Piece): TreeNode {\n\t\tconst z = new TreeNode(p, NodeColor.Red);\n\t\tz.left = SENTINEL;\n\t\tz.right = SENTINEL;\n\t\tz.parent = SENTINEL;\n\t\tz.size_left = 0;\n\t\tz.lf_left = 0;\n\n\t\tif (this.root === SENTINEL) {\n\t\t\tthis.root = z;\n\t\t\tz.color = NodeColor.Black;\n\t\t} else if (node!.left === SENTINEL) {\n\t\t\tnode!.left = z;\n\t\t\tz.parent = node!;\n\t\t} else {\n\t\t\tconst prevNode = righttest(node!.left); // a\n\t\t\tprevNode.right = z;\n\t\t\tz.parent = prevNode;\n\t\t}\n\n\t\tfixInsert(this, z);\n\t\treturn z;\n\t}\n\t// #endregion\n}\n"]}
|