import java.io.*; import java.nio.charset.StandardCharsets; import java.util.function.Predicate; public class CastScanner implements AutoCloseable { private final Reader reader; private final char[] buffer; private int pose = -2; private int bufferLength; private final char lineSep = System.lineSeparator().charAt(System.lineSeparator().length() - 1); private final Predicate filter; public CastScanner(InputStream in, Predicate filter) { this (new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)), filter); } public CastScanner(File in, Predicate filter) throws FileNotFoundException { this(new BufferedReader(new InputStreamReader(new FileInputStream(in), StandardCharsets.UTF_8)), filter); } public CastScanner(Reader in, Predicate filter) { this.reader = in; this.filter = filter; this.buffer = new char[8192]; } private boolean hasNextChar() throws IOException { if (newBuffer() && bufferLength != -1) { if ((pose != bufferLength && (isCorrectChar(buffer[pose]) || buffer[pose] == lineSep || buffer[pose] == '\r')) || !filter.test(buffer[pose])) { nextChar(); return false; } return true; } return false; } private void nextChar() throws IOException { while (newBuffer()) { while ((bufferLength != -1) && (pose != bufferLength) && ((isCorrectChar(buffer[pose]) || buffer[pose] == lineSep || buffer[pose] == '\r') || !filter.test(buffer[pose]))) { if (buffer[pose] == lineSep || buffer[pose] == '\r') { break; } pose++; } if (pose != bufferLength) { break; } } } private boolean newBuffer() throws IOException { if (pose == -2 || pose == bufferLength) { bufferLength = reader.read(buffer); pose = 0; } else return bufferLength != -1; return true; } public boolean hasNext() throws IOException { newBuffer(); return bufferLength != -1; } public boolean hasNextInLine() throws IOException { if (!(newBuffer() && buffer[pose] != lineSep && buffer[pose] != '\r')) { pose += 1; return false; } return true; } public String next() throws IOException { StringBuilder word = new StringBuilder(); while (true) { if (hasNextChar()) { word.append(buffer[pose]); pose++; } else { break; } } return word.toString(); } private static boolean isDash(char ch) { return Character.getType(ch) == Character.DASH_PUNCTUATION; } private static boolean isCorrectChar(char ch) { return (!Character.isLetter(ch) && ch != '\'' && !isDash(ch) && !Character.isDigit(ch) && ch != '$' && ch != '_' && !Character.isDigit(ch)); } public void close() throws IOException { reader.close(); } }