This commit is contained in:
David Renshaw 2014-05-10 15:29:29 -04:00
parent 600d3c134b
commit 787559680c
7 changed files with 136 additions and 11 deletions

View file

@ -1,6 +1,7 @@
CXX=g++ -std=c++11
CAPNP_SOURCES=\
src/capnp/AnyPointer.java\
src/capnp/FieldSize.java\
src/capnp/FromStructReader.java\
src/capnp/InputStreamMessageReader.java\

17
src/capnp/AnyPointer.java Normal file
View file

@ -0,0 +1,17 @@
package capnp;
public class AnyPointer {
public static class Reader {
public PointerReader reader;
public Reader(PointerReader reader) {
this.reader = reader;
}
public <T> T getAsStruct(FromStructReader<T> factory) {
return factory.fromStructReader(this.reader.getStruct());
}
}
}

View file

@ -3,24 +3,75 @@ package capnp;
import java.io.InputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Vector;
public class InputStreamMessageReader {
static MessageReader create(InputStream is) throws IOException {
byte[] firstWord = new byte[8];
static byte[] readExact(InputStream is, int length) throws IOException {
byte[] bytes = new byte[length];
int bytesRead = 0;
while (bytesRead < 8) {
int n = is.read(firstWord, bytesRead, 8 - bytesRead);
if (n < 0) {
while (bytesRead < length) {
int r = is.read(bytes, bytesRead, length - bytesRead);
if (r < 0) {
throw new IOException("premature EOF");
}
bytesRead += n;
bytesRead += r;
}
ByteBuffer.wrap(firstWord);
return bytes;
}
static ByteBuffer makeByteBuffer(byte[] bytes) {
ByteBuffer result = ByteBuffer.wrap(bytes);
result.order(ByteOrder.LITTLE_ENDIAN);
return result;
}
throw new Error();
public static MessageReader create(InputStream is) throws IOException {
ByteBuffer firstWord = makeByteBuffer(readExact(is, 8));
int segmentCount = 1 + firstWord.getInt();
int segment0Size = 0;
if (segmentCount > 0) {
segment0Size = firstWord.getInt(1);
}
int totalWords = segment0Size;
if (segmentCount > 512) {
throw new IOException("too many segments");
}
Vector<Integer> moreSizes = new Vector<Integer>();
if (segmentCount > 1) {
ByteBuffer moreSizesRaw = makeByteBuffer(readExact(is, 4 * (segmentCount & ~1)));
for(int ii = 0; ii < segmentCount - 1; ++ii) {
int size = moreSizesRaw.getInt(ii);
moreSizes.add(size);
totalWords += size;
}
}
// TODO check that totalWords is reasonable
byte[] allSegments = readExact(is, totalWords * 8);
ByteBuffer[] segmentSlices = new ByteBuffer[segmentCount];
segmentSlices[0] = ByteBuffer.wrap(allSegments, 0, segment0Size);
int offset = segment0Size;
for (int ii = 1; ii < segmentCount; ++ii) {
segmentSlices[ii] = ByteBuffer.wrap(allSegments, offset, moreSizes.get(ii - 1));
offset += moreSizes.get(ii - 1);
}
return new MessageReader(segmentSlices);
}
}

View file

@ -1,5 +1,20 @@
package capnp;
public class MessageReader {
import java.nio.ByteBuffer;
public class MessageReader {
ByteBuffer[] segmentSlices;
public MessageReader(ByteBuffer[] segmentSlices) {
this.segmentSlices = segmentSlices;
}
public <T> T getRoot(FromStructReader<T> factory) {
SegmentReader segment = new SegmentReader(this.segmentSlices[0]);
PointerReader pointerReader = PointerReader.getRoot(segment,
new WordPointer(this.segmentSlices[0], 0),
0x7fffffff /* XXX */);
AnyPointer.Reader any = new AnyPointer.Reader(pointerReader);
return any.getAsStruct(factory);
}
}

View file

@ -17,12 +17,27 @@ public class PointerReader {
this.nestingLimit = nestingLimit;
}
public static PointerReader getRoot(SegmentReader segment,
WordPointer location,
int nestingLimit) {
// TODO bounds check
return new PointerReader(segment, location.offset, nestingLimit);
}
public StructReader getStruct() {
WirePointer ref = new WirePointer(this.segment.ptr, this.pointer);
return WireHelpers.readStructPointer(this.segment,
ref,
this.nestingLimit);
}
public ListReader getList(byte expectedElementSize) {
// TODO check nullness
WirePointer ref = new WirePointer(this.segment.ptr, this.pointer);
return WireHelpers.readListPointer(this.segment,
ref,
expectedElementSize);
expectedElementSize,
this.nestingLimit);
}
public Text.Reader getText() {

View file

@ -4,4 +4,8 @@ import java.nio.ByteBuffer;
public class SegmentReader {
ByteBuffer ptr;
public SegmentReader(ByteBuffer ptr) {
this.ptr = ptr;
}
}

View file

@ -2,8 +2,30 @@ package capnp;
class WireHelpers {
public static StructReader readStructPointer(SegmentReader segment,
WirePointer ref,
int nestingLimit) {
// TODO error handling
WordPointer ptr = ref.target();
StructPointer structPtr = (StructPointer)ref;
int dataSizeWords = structPtr.dataSize();
return new StructReader(segment,
ptr.offset * 8,
(ptr.offset + dataSizeWords) * 8,
dataSizeWords * 64,
structPtr.ptrCount(),
(byte)0,
nestingLimit - 1);
}
public static ListReader readListPointer(SegmentReader segment,
WirePointer ref,
byte expectedElementSize,
int nestingLimit) {
// TODO check for null, follow fars, nestingLimit
@ -30,7 +52,7 @@ class WireHelpers {
// TODO check whether the size is compatible
return new ListReader(segment, // TODO follow fars
ptr.offset, //
ptr.offset * 8, //
size,
wordsPerElement * 64,
structPtr.dataSize() * 64,