blob: 5aa700cca4a738e5a909b00bf1e7e1c7070a678a [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library dart2js.io.line_column;
import 'code_output.dart';
/// Interface for providing line/column information.
abstract class LineColumnProvider {
/// Returns the line number (0-based) for [offset].
int getLine(int offset);
/// Returns the column number (0-based) for [offset] at the given [line].
int getColumn(int line, int offset);
}
/// [CodeOutputListener] that collects line information.
class LineColumnCollector extends CodeOutputListener
implements LineColumnProvider {
int lastLineStart = 0;
List<int> lineStarts = <int>[0];
void _collect(String text) {
int offset = lastLineStart;
int index = 0;
while (index < text.length) {
// Unix uses '\n' and Windows uses '\r\n', so this algorithm works for
// both platforms.
index = text.indexOf('\n', index) + 1;
if (index <= 0) break;
lastLineStart = offset + index;
lineStarts.add(lastLineStart);
}
}
@override
void onText(String text) {
_collect(text);
}
@override
int getLine(int offset) {
List<int> starts = lineStarts;
if (offset < 0 || starts.last <= offset) {
throw 'bad position #$offset in buffer with length ${lineStarts.last}.';
}
int first = 0;
int count = starts.length;
while (count > 1) {
int step = count ~/ 2;
int middle = first + step;
int lineStart = starts[middle];
if (offset < lineStart) {
count = step;
} else {
first = middle;
count -= step;
}
}
return first;
}
@override
int getColumn(int line, int offset) {
return offset - lineStarts[line];
}
@override
void onDone(int length) {
lineStarts.add(length);
}
}