1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.davidmoten.text.utils;
15
16 import java.io.IOException;
17 import java.io.Reader;
18 import java.nio.CharBuffer;
19
20 import com.github.davidmoten.guavamini.Preconditions;
21
22
23
24
25
26
27
28
29 final class CharSequenceReader extends Reader {
30
31 private CharSequence seq;
32 private int pos;
33 private int mark;
34
35 public CharSequenceReader(CharSequence seq) {
36 this.seq = Preconditions.checkNotNull(seq);
37 }
38
39 private void checkOpen() throws IOException {
40 if (seq == null) {
41 throw new IOException("reader closed");
42 }
43 }
44
45 private boolean hasRemaining() {
46 return remaining() > 0;
47 }
48
49 private int remaining() {
50 return seq.length() - pos;
51 }
52
53 @Override
54 public synchronized int read(CharBuffer target) throws IOException {
55 Preconditions.checkNotNull(target);
56 checkOpen();
57 if (!hasRemaining()) {
58 return -1;
59 }
60 int charsToRead = Math.min(target.remaining(), remaining());
61 for (int i = 0; i < charsToRead; i++) {
62 target.put(seq.charAt(pos++));
63 }
64 return charsToRead;
65 }
66
67 @Override
68 public synchronized int read() throws IOException {
69 checkOpen();
70 return hasRemaining() ? seq.charAt(pos++) : -1;
71 }
72
73 @Override
74 public synchronized int read(char[] cbuf, int off, int len) throws IOException {
75 if (len < 0 || off < 0 || off + len > cbuf.length) {
76 throw new IndexOutOfBoundsException();
77 }
78 checkOpen();
79 if (!hasRemaining()) {
80 return -1;
81 }
82 int charsToRead = Math.min(len, remaining());
83 for (int i = 0; i < charsToRead; i++) {
84 cbuf[off + i] = seq.charAt(pos++);
85 }
86 return charsToRead;
87 }
88
89 @Override
90 public synchronized long skip(long n) throws IOException {
91 Preconditions.checkArgument(n >= 0, "n may not be negative");
92 checkOpen();
93 int charsToSkip = (int) Math.min(remaining(), n);
94 pos += charsToSkip;
95 return charsToSkip;
96 }
97
98 @Override
99 public synchronized boolean ready() throws IOException {
100 checkOpen();
101 return true;
102 }
103
104 @Override
105 public boolean markSupported() {
106 return true;
107 }
108
109 @Override
110 public synchronized void mark(int readAheadLimit) throws IOException {
111 Preconditions.checkArgument(readAheadLimit >= 0, "readAheadLimit may not be negative");
112 checkOpen();
113 mark = pos;
114 }
115
116 @Override
117 public synchronized void reset() throws IOException {
118 checkOpen();
119 pos = mark;
120 }
121
122 @Override
123 public synchronized void close() throws IOException {
124 seq = null;
125 }
126 }