NetworkDNS/src-wip/org/handwerkszeug/dns/conf/masterfile/Partitioner.java

189 lines
4.5 KiB
Java
Executable File

package org.handwerkszeug.dns.conf.masterfile;
import java.io.IOException;
import java.io.InputStream;
import org.handwerkszeug.dns.conf.masterfile.Partition.PartitionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
public class Partitioner {
static final Logger LOG = LoggerFactory.getLogger(Partitioner.class);
final InputStream source;
static final int DEFAULT_BUFFER_SIZE = 2000;
protected ByteBuf working;
protected Partition next;
public Partitioner(InputStream in) {
this(in, DEFAULT_BUFFER_SIZE);
}
public Partitioner(InputStream in, int size) {
this.source = in;
this.working = Unpooled.buffer(size);
}
public Partition partition() {
Partition result = this.next;
if (result != null) {
this.next = null;
return result;
}
while (true) {
byte ch = readByte();
if (ch == -1) {
if (0 < this.working.readerIndex()) {
result = makePartition(PartitionType.Default, 0);
discardBefore(0);
} else {
break;
}
}
if (ch == '\r') {
byte n = readByte();
if (n == '\n') {
if (this.working.readerIndex() < 3) {
this.working.discardReadBytes();
return Partition.EOL;
}
this.next = Partition.EOL;
result = makePartition(PartitionType.Default, 2);
discardBefore(0);
} else {
this.working.readerIndex(this.working.readerIndex() - 1);
}
}
if (ch == '\n') {
if (this.working.readerIndex() < 2) {
this.working.discardReadBytes();
return Partition.EOL;
}
this.next = Partition.EOL;
result = makePartition(PartitionType.Default, 1);
discardBefore(0);
}
if (ch == ';') {
result = readTo(partitionBefore(), PartitionType.Comment, '\n');
}
if (ch == '(') {
result = currentOrNext(partitionBefore(), Partition.LP);
}
if (ch == ')') {
result = currentOrNext(partitionBefore(), Partition.RP);
}
if ((ch == '"')) {
result = readTo(partitionBefore(), PartitionType.Quoted, '"');
}
if (((ch == ' ') || (ch == '\t'))) {
result = partitionBefore();
int begin = this.working.readerIndex() - 1;
while (true) {
byte c = readByte();
if ((c != ' ') && (c != '\t')) {
int end = this.working.readerIndex() - 1;
Partition ws = makePartition(PartitionType.Whitespace,
begin, end);
result = currentOrNext(result, ws, 1);
break;
}
}
}
if (result != null) {
return result;
}
}
return Partition.EOF;
}
protected Partition currentOrNext(Partition before, Partition p) {
return currentOrNext(before, p, 0);
}
protected Partition currentOrNext(Partition before, Partition p, int discard) {
Partition result = before;
if (before == null) {
result = p;
} else {
this.next = p;
}
discardBefore(discard);
return result;
}
protected Partition readTo(Partition back, PartitionType type, char stop) {
Partition result = back;
int begin = this.working.readerIndex() - 1;
while (true) {
byte c = readByte();
if ((c == stop) || (c == -1)) {
int end = this.working.readerIndex();
Partition p = makePartition(type, begin, end);
result = currentOrNext(back, p);
break;
}
}
return result;
}
protected byte readByte() {
try {
if (this.working.isReadable() == false) {
if (0 < this.source.available()) {
this.working.writeBytes(this.source, DEFAULT_BUFFER_SIZE);
}
}
if (this.working.isReadable()) {
return this.working.readByte();
}
return -1;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
protected Partition makePartition(PartitionType type, int begin, int end) {
byte[] newone = new byte[end - begin];
this.working.getBytes(begin, newone);
return new Partition(type, newone);
}
protected Partition makePartition(PartitionType type, int stripSize) {
int newsize = this.working.readerIndex() - stripSize;
byte[] newone = new byte[newsize];
this.working.getBytes(0, newone);
return new Partition(type, newone);
}
protected Partition partitionBefore() {
if (1 < this.working.readerIndex()) {
return makePartition(PartitionType.Default, 1);
}
return null;
}
protected void discardBefore(int backSize) {
this.working.readerIndex(this.working.readerIndex() - backSize);
this.working.discardReadBytes();
}
public void close() {
try {
this.source.close();
this.working.release();
} catch (IOException e) {
LOG.error(e.getLocalizedMessage(), e);
}
}
}