1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
package bjc.utils.ioutils.blocks;
import java.io.IOException;
import java.io.Reader;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.regex.Pattern;
import bjc.utils.funcutils.StringUtils;
/**
* Simple implementation of {@link BlockReader}.
*
* NOTE: The EOF marker is always treated as a delimiter. You are expected to
* handle blocks that may be shorter than you expect.
*
* @author EVE
*
*/
public class SimpleBlockReader implements BlockReader {
/*
* I/O source for blocks.
*/
private final Scanner blockReader;
/*
* The current block.
*/
private Block currBlock;
/*
* Info about the current block.
*/
private int blockNo;
private int lineNo;
/**
* Create a new block reader.
*
* @param blockDelim
* The pattern that separates blocks. Note that the end of file
* is always considered to end a block.
*
* @param source
* The source to read blocks from.
*/
public SimpleBlockReader(final String blockDelim, final Reader source) {
blockReader = new Scanner(source);
final String pattern = String.format("(?:%s)|\\Z", blockDelim);
final Pattern pt = Pattern.compile(pattern, Pattern.MULTILINE);
blockReader.useDelimiter(pt);
lineNo = 1;
}
/**
* Create a new block reader.
*
* @param blockDelim
* The pattern that separates blocks. Note that the end of file
* is always considered to end a block.
*
* @param source
* The source to read blocks from.
* NOTE: This does modify the provided scanner.
*/
public SimpleBlockReader(final String blockDelim, final Scanner source) {
blockReader = source;
final String pattern = String.format("(?:%s)|\\Z", blockDelim);
final Pattern pt = Pattern.compile(pattern, Pattern.MULTILINE);
blockReader.useDelimiter(pt);
lineNo = 1;
}
@Override
public boolean hasNextBlock() {
return blockReader.hasNext();
}
@Override
public Block getBlock() {
return currBlock;
}
@Override
public boolean nextBlock() {
try {
/*
* Read in a new block, and keep the line numbers sane.
*/
final String blockContents = blockReader.next();
final int blockStartLine = lineNo;
final int blockEndLine = lineNo + StringUtils.countMatches(blockContents, "\\R");
lineNo = blockEndLine;
blockNo += 1;
currBlock = new Block(blockNo, blockContents, blockStartLine, blockEndLine);
return true;
} catch(final NoSuchElementException nseex) {
currBlock = null;
return false;
}
}
@Override
public int getBlockCount() {
return blockNo;
}
@Override
public void close() throws IOException {
blockReader.close();
}
/**
* Set the delimiter used to separate blocks.
*
* @param delim
* The delimiter used to separate blocks.
*/
public void setDelimiter(final String delim) {
blockReader.useDelimiter(delim);
}
@Override
public String toString() {
return String.format("SimpleBlockReader [currBlock=%s, blockNo=%s]", currBlock, blockNo);
}
}
|