--- /dev/null
+package org.simantics.scl.compiler.completions.parsing;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * Based on java.io.StringReader.
+ */
+
+public class SubstringReader extends Reader {
+
+ private String str;
+ private int end;
+ private int pos;
+ private int mark;
+
+ public SubstringReader(String str, int begin, int end) {
+ this.str = str;
+ this.pos = begin;
+ this.mark = begin;
+ this.end = end;
+ }
+
+ public int read() throws IOException {
+ if (pos >= end)
+ return -1;
+ return str.charAt(pos++);
+ }
+
+ public int read(char cbuf[], int off, int len) throws IOException {
+ if ((off < 0) || (off > cbuf.length) || (len < 0) ||
+ ((off + len) > cbuf.length) || ((off + len) < 0))
+ throw new IndexOutOfBoundsException();
+ else if (len == 0)
+ return 0;
+ if (pos >= end)
+ return -1;
+ int n = Math.min(end - pos, len);
+ str.getChars(pos, pos + n, cbuf, off);
+ pos += n;
+ return n;
+ }
+
+ public long skip(long ns) throws IOException {
+ if (pos >= end)
+ return 0;
+ // Bound skip by beginning and end of the source
+ long n = Math.min(end - pos, ns);
+ n = Math.max(-pos, n);
+ pos += n;
+ return n;
+ }
+
+ public boolean ready() throws IOException {
+ return true;
+ }
+
+ public boolean markSupported() {
+ return true;
+ }
+
+ public void mark(int readAheadLimit) throws IOException {
+ if (readAheadLimit < 0)
+ throw new IllegalArgumentException("Read-ahead limit < 0");
+ mark = pos;
+ }
+
+ public void reset() throws IOException {
+ pos = mark;
+ }
+
+ public void close() {
+ }
+}