Tim van der Lippe | 706ec96 | 2021-06-04 13:24:42 +0100 | [diff] [blame] | 1 | var adoptBuffer = require('./adopt-buffer'); |
| 2 | var isBOM = require('../tokenizer').isBOM; |
| 3 | |
| 4 | var N = 10; |
| 5 | var F = 12; |
| 6 | var R = 13; |
| 7 | |
| 8 | function computeLinesAndColumns(host, source) { |
| 9 | var sourceLength = source.length; |
| 10 | var lines = adoptBuffer(host.lines, sourceLength); // +1 |
| 11 | var line = host.startLine; |
| 12 | var columns = adoptBuffer(host.columns, sourceLength); |
| 13 | var column = host.startColumn; |
| 14 | var startOffset = source.length > 0 ? isBOM(source.charCodeAt(0)) : 0; |
| 15 | |
| 16 | for (var i = startOffset; i < sourceLength; i++) { // -1 |
| 17 | var code = source.charCodeAt(i); |
| 18 | |
| 19 | lines[i] = line; |
| 20 | columns[i] = column++; |
| 21 | |
| 22 | if (code === N || code === R || code === F) { |
| 23 | if (code === R && i + 1 < sourceLength && source.charCodeAt(i + 1) === N) { |
| 24 | i++; |
| 25 | lines[i] = line; |
| 26 | columns[i] = column; |
| 27 | } |
| 28 | |
| 29 | line++; |
| 30 | column = 1; |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | lines[i] = line; |
| 35 | columns[i] = column; |
| 36 | |
| 37 | host.lines = lines; |
| 38 | host.columns = columns; |
| 39 | } |
| 40 | |
| 41 | var OffsetToLocation = function() { |
| 42 | this.lines = null; |
| 43 | this.columns = null; |
| 44 | this.linesAndColumnsComputed = false; |
| 45 | }; |
| 46 | |
| 47 | OffsetToLocation.prototype = { |
| 48 | setSource: function(source, startOffset, startLine, startColumn) { |
| 49 | this.source = source; |
| 50 | this.startOffset = typeof startOffset === 'undefined' ? 0 : startOffset; |
| 51 | this.startLine = typeof startLine === 'undefined' ? 1 : startLine; |
| 52 | this.startColumn = typeof startColumn === 'undefined' ? 1 : startColumn; |
| 53 | this.linesAndColumnsComputed = false; |
| 54 | }, |
| 55 | |
| 56 | ensureLinesAndColumnsComputed: function() { |
| 57 | if (!this.linesAndColumnsComputed) { |
| 58 | computeLinesAndColumns(this, this.source); |
| 59 | this.linesAndColumnsComputed = true; |
| 60 | } |
| 61 | }, |
| 62 | getLocation: function(offset, filename) { |
| 63 | this.ensureLinesAndColumnsComputed(); |
| 64 | |
| 65 | return { |
| 66 | source: filename, |
| 67 | offset: this.startOffset + offset, |
| 68 | line: this.lines[offset], |
| 69 | column: this.columns[offset] |
| 70 | }; |
| 71 | }, |
| 72 | getLocationRange: function(start, end, filename) { |
| 73 | this.ensureLinesAndColumnsComputed(); |
| 74 | |
| 75 | return { |
| 76 | source: filename, |
| 77 | start: { |
| 78 | offset: this.startOffset + start, |
| 79 | line: this.lines[start], |
| 80 | column: this.columns[start] |
| 81 | }, |
| 82 | end: { |
| 83 | offset: this.startOffset + end, |
| 84 | line: this.lines[end], |
| 85 | column: this.columns[end] |
| 86 | } |
| 87 | }; |
| 88 | } |
| 89 | }; |
| 90 | |
| 91 | module.exports = OffsetToLocation; |