| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- import * as strings from '../../../../base/common/strings.js';
- import { StringBuffer, createLineStarts, createLineStartsFast } from './pieceTreeBase.js';
- import { PieceTreeTextBuffer } from './pieceTreeTextBuffer.js';
- export class PieceTreeTextBufferFactory {
- constructor(_chunks, _bom, _cr, _lf, _crlf, _containsRTL, _containsUnusualLineTerminators, _isBasicASCII, _normalizeEOL) {
- this._chunks = _chunks;
- this._bom = _bom;
- this._cr = _cr;
- this._lf = _lf;
- this._crlf = _crlf;
- this._containsRTL = _containsRTL;
- this._containsUnusualLineTerminators = _containsUnusualLineTerminators;
- this._isBasicASCII = _isBasicASCII;
- this._normalizeEOL = _normalizeEOL;
- }
- _getEOL(defaultEOL) {
- const totalEOLCount = this._cr + this._lf + this._crlf;
- const totalCRCount = this._cr + this._crlf;
- if (totalEOLCount === 0) {
- // This is an empty file or a file with precisely one line
- return (defaultEOL === 1 /* DefaultEndOfLine.LF */ ? '\n' : '\r\n');
- }
- if (totalCRCount > totalEOLCount / 2) {
- // More than half of the file contains \r\n ending lines
- return '\r\n';
- }
- // At least one line more ends in \n
- return '\n';
- }
- create(defaultEOL) {
- const eol = this._getEOL(defaultEOL);
- const chunks = this._chunks;
- if (this._normalizeEOL &&
- ((eol === '\r\n' && (this._cr > 0 || this._lf > 0))
- || (eol === '\n' && (this._cr > 0 || this._crlf > 0)))) {
- // Normalize pieces
- for (let i = 0, len = chunks.length; i < len; i++) {
- const str = chunks[i].buffer.replace(/\r\n|\r|\n/g, eol);
- const newLineStart = createLineStartsFast(str);
- chunks[i] = new StringBuffer(str, newLineStart);
- }
- }
- const textBuffer = new PieceTreeTextBuffer(chunks, this._bom, eol, this._containsRTL, this._containsUnusualLineTerminators, this._isBasicASCII, this._normalizeEOL);
- return { textBuffer: textBuffer, disposable: textBuffer };
- }
- }
- export class PieceTreeTextBufferBuilder {
- constructor() {
- this.chunks = [];
- this.BOM = '';
- this._hasPreviousChar = false;
- this._previousChar = 0;
- this._tmpLineStarts = [];
- this.cr = 0;
- this.lf = 0;
- this.crlf = 0;
- this.containsRTL = false;
- this.containsUnusualLineTerminators = false;
- this.isBasicASCII = true;
- }
- acceptChunk(chunk) {
- if (chunk.length === 0) {
- return;
- }
- if (this.chunks.length === 0) {
- if (strings.startsWithUTF8BOM(chunk)) {
- this.BOM = strings.UTF8_BOM_CHARACTER;
- chunk = chunk.substr(1);
- }
- }
- const lastChar = chunk.charCodeAt(chunk.length - 1);
- if (lastChar === 13 /* CharCode.CarriageReturn */ || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {
- // last character is \r or a high surrogate => keep it back
- this._acceptChunk1(chunk.substr(0, chunk.length - 1), false);
- this._hasPreviousChar = true;
- this._previousChar = lastChar;
- }
- else {
- this._acceptChunk1(chunk, false);
- this._hasPreviousChar = false;
- this._previousChar = lastChar;
- }
- }
- _acceptChunk1(chunk, allowEmptyStrings) {
- if (!allowEmptyStrings && chunk.length === 0) {
- // Nothing to do
- return;
- }
- if (this._hasPreviousChar) {
- this._acceptChunk2(String.fromCharCode(this._previousChar) + chunk);
- }
- else {
- this._acceptChunk2(chunk);
- }
- }
- _acceptChunk2(chunk) {
- const lineStarts = createLineStarts(this._tmpLineStarts, chunk);
- this.chunks.push(new StringBuffer(chunk, lineStarts.lineStarts));
- this.cr += lineStarts.cr;
- this.lf += lineStarts.lf;
- this.crlf += lineStarts.crlf;
- if (this.isBasicASCII) {
- this.isBasicASCII = lineStarts.isBasicASCII;
- }
- if (!this.isBasicASCII && !this.containsRTL) {
- // No need to check if it is basic ASCII
- this.containsRTL = strings.containsRTL(chunk);
- }
- if (!this.isBasicASCII && !this.containsUnusualLineTerminators) {
- // No need to check if it is basic ASCII
- this.containsUnusualLineTerminators = strings.containsUnusualLineTerminators(chunk);
- }
- }
- finish(normalizeEOL = true) {
- this._finish();
- return new PieceTreeTextBufferFactory(this.chunks, this.BOM, this.cr, this.lf, this.crlf, this.containsRTL, this.containsUnusualLineTerminators, this.isBasicASCII, normalizeEOL);
- }
- _finish() {
- if (this.chunks.length === 0) {
- this._acceptChunk1('', true);
- }
- if (this._hasPreviousChar) {
- this._hasPreviousChar = false;
- // recreate last chunk
- const lastChunk = this.chunks[this.chunks.length - 1];
- lastChunk.buffer += String.fromCharCode(this._previousChar);
- const newLineStarts = createLineStartsFast(lastChunk.buffer);
- lastChunk.lineStarts = newLineStarts;
- if (this._previousChar === 13 /* CharCode.CarriageReturn */) {
- this.cr++;
- }
- }
- }
- }
|