189 lines
4.5 KiB
Java
Executable File
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);
|
|
}
|
|
}
|
|
}
|