1 package org.simantics.scl.compiler.internal.parsing.utils;
3 import gnu.trove.list.array.TIntArrayList;
5 public class LineLocators {
7 private static class ByteArrayLineLocator extends LineLocator {
8 private final byte[] lineNumbers;
9 private final int maxLine;
11 public ByteArrayLineLocator(int[] rowStarts) {
13 int lastRow = rowStarts.length-1;
14 this.lineNumbers = new byte[rowStarts[lastRow]];
15 this.maxLine = rowStarts.length-1;
19 while(line < maxLine) {
20 int endPosition = rowStarts[line+1];
21 while(position < endPosition)
22 lineNumbers[position++] = (byte)line;
28 public int lineNumberFromPosition(int position) {
31 if(position >= lineNumbers.length)
33 return (int)lineNumbers[position];
37 private static class CharArrayLineLocator extends LineLocator {
38 private final char[] lineNumbers;
39 private final int maxLine;
41 public CharArrayLineLocator(int[] rowStarts) {
43 int lastRow = rowStarts.length-1;
44 this.lineNumbers = new char[rowStarts[lastRow]];
45 this.maxLine = rowStarts.length-1;
49 while(line < maxLine) {
50 int endPosition = rowStarts[line+1];
51 while(position < endPosition)
52 lineNumbers[position++] = (char)line;
58 public int lineNumberFromPosition(int position) {
61 if(position >= lineNumbers.length)
63 return (int)lineNumbers[position];
67 private static class IntArrayLineLocator extends LineLocator {
68 private final int[] lineNumbers;
69 private final int maxLine;
71 public IntArrayLineLocator(int[] rowStarts) {
73 int lastRow = rowStarts.length-1;
74 this.lineNumbers = new int[rowStarts[lastRow]];
75 this.maxLine = rowStarts.length-1;
79 while(line < maxLine) {
80 int endPosition = rowStarts[line+1];
81 while(position < endPosition)
82 lineNumbers[position++] = line;
88 public int lineNumberFromPosition(int position) {
91 if(position >= lineNumbers.length)
93 return lineNumbers[position];
97 private static class BinarySearchLineLocator extends LineLocator {
98 public BinarySearchLineLocator(int[] rowStarts) {
103 public int lineNumberFromPosition(int position) {
106 if(position >= rowStarts[rowStarts.length-1])
107 return rowStarts.length-1;
109 int high = rowStarts.length-1;
110 // invariant, low <= lineNumber < high
111 while(low < high-1) {
112 int middle = (low+high) / 2;
113 if(position < rowStarts[middle])
122 private static class InterpolationSearchLineLocator extends LineLocator {
123 public InterpolationSearchLineLocator(int[] rowStarts) {
128 public int lineNumberFromPosition(int position) {
131 if(position >= rowStarts[rowStarts.length-1])
132 return rowStarts.length-1;
135 int high = rowStarts.length-1;
136 int highPosition = rowStarts[high];
137 // invariant, low <= lineNumber < high
138 while(low < high-1) {
139 int delta = (int)((long)(high - low) * (position - lowPosition) / (highPosition - lowPosition));
140 int middle = low + delta;
143 if(position < rowStarts[middle]) {
145 highPosition = rowStarts[high];
149 lowPosition = rowStarts[low];
156 public static final LineLocator DUMMY_LOCATOR = new LineLocator(new int[] {0}) {
158 public int lineNumberFromPosition(int position) {
163 private static int[] findRowStarts(String source) {
164 TIntArrayList rowStarts = new TIntArrayList();
167 int length = source.length();
168 for(int i=0;i<length;++i) {
169 char c = source.charAt(i);
173 return rowStarts.toArray();
176 public static LineLocator createLineLocator(String source) {
177 int[] rowStarts = findRowStarts(source);
178 if(rowStarts.length <= Byte.MAX_VALUE)
179 return new ByteArrayLineLocator(rowStarts);
180 else if(rowStarts.length <= Character.MAX_VALUE)
181 return new CharArrayLineLocator(rowStarts);
183 return new InterpolationSearchLineLocator(rowStarts);