Moved files, updated readme, added src/main/generated to build.scala for IDE support
This commit is contained in:
parent
570ff3e2c3
commit
07788c83fc
32 changed files with 48 additions and 2537 deletions
52
Makefile
52
Makefile
|
@ -1,51 +1,19 @@
|
|||
CXX=g++ -std=c++11
|
||||
CXX=clang++ -std=c++11 -stdlib=libc++ `pkg-config capnp --cflags --libs`
|
||||
|
||||
CAPNP_SOURCES=\
|
||||
src/capnp/AnyPointer.java\
|
||||
src/capnp/DecodeException.java\
|
||||
src/capnp/FieldSize.java\
|
||||
src/capnp/FromStructBuilder.java\
|
||||
src/capnp/FromStructReader.java\
|
||||
src/capnp/InputStreamMessageReader.java\
|
||||
src/capnp/ListPointer.java\
|
||||
src/capnp/ListBuilder.java\
|
||||
src/capnp/ListReader.java\
|
||||
src/capnp/MessageBuilder.java\
|
||||
src/capnp/MessageReader.java\
|
||||
src/capnp/PointerBuilder.java\
|
||||
src/capnp/PointerReader.java\
|
||||
src/capnp/SegmentBuilder.java\
|
||||
src/capnp/SegmentReader.java\
|
||||
src/capnp/StructBuilder.java\
|
||||
src/capnp/StructList.java\
|
||||
src/capnp/StructPointer.java\
|
||||
src/capnp/StructReader.java\
|
||||
src/capnp/StructSize.java\
|
||||
src/capnp/Text.java\
|
||||
src/capnp/WireHelpers.java\
|
||||
src/capnp/WirePointer.java\
|
||||
src/capnp/WordPointer.java
|
||||
|
||||
CAPNP_COMPILATION_MARKER=org/capnproto/PointerReader.class
|
||||
|
||||
CAPNPC_JAVA_SOURCES=src/compiler/capnpc-java.c++
|
||||
CAPNPC_JAVA_SOURCES=generator/src/main/cpp/compiler/capnpc-java.c++
|
||||
|
||||
.PHONY: all clean addressbook
|
||||
|
||||
all : capnpc-java addressbook capnp
|
||||
all : capnpc-java addressbook
|
||||
|
||||
clean :
|
||||
rm -rf capnpc-java org examples/*.class
|
||||
|
||||
capnp : $(CAPNP_COMPILATION_MARKER)
|
||||
|
||||
$(CAPNP_COMPILATION_MARKER) : $(CAPNP_SOURCES)
|
||||
javac -d . $(CAPNP_SOURCES)
|
||||
rm capnpc-java
|
||||
sbt clean
|
||||
|
||||
capnpc-java : $(CAPNPC_JAVA_SOURCES)
|
||||
$(CXX) -I/usr/local/include -L/usr/local/lib -lkj -lcapnp $(CAPNPC_JAVA_SOURCES) -o capnpc-java
|
||||
$(CXX) -I/usr/local/include -g $(CAPNPC_JAVA_SOURCES) -o capnpc-java
|
||||
|
||||
|
||||
addressbook : capnp capnpc-java examples/AddressbookMain.java
|
||||
capnp compile -o ./capnpc-java examples/addressbook.capnp
|
||||
javac -cp .:examples examples/AddressbookMain.java
|
||||
addressbook : capnpc-java
|
||||
PWD=pwd
|
||||
capnp compile -I$(PWD)/generator/src/main/cpp/compiler --src-prefix=examples/src/main/schema -o./capnpc-java:examples/src/main/generated examples/src/main/schema/addressbook.capnp
|
||||
sbt examples/"run read"
|
||||
|
|
14
README.md
14
README.md
|
@ -2,13 +2,11 @@
|
|||
|
||||
This is an experimental pure Java implementation of Cap'n Proto.
|
||||
|
||||
It doesn't do much yet.
|
||||
It doesn't do much yet. An attempt to use SBT as the build system and integration with `make` is currently underway.
|
||||
|
||||
To get started, try this:
|
||||
To get started with SBT, visit https://github.com/paulp/sbt-extras or to run direct, try `curl -s https://raw.githubusercontent.com/paulp/sbt-extras/master/sbt > ~/bin/sbt && chmod 0755 ~/bin/sbt`
|
||||
|
||||
When you first build the project, try running `sbt update gen-idea`. This will bootstrap SBT and generate IntelliJ project files for those who wish to develop in an IDE.
|
||||
|
||||
When running `make`, the supporting Java code will be built, and the sample schema will be run through the code generator as well to produce the Java binding. You can find the generated code in `/examples/src/main/generated/Addressbook.java`
|
||||
|
||||
```
|
||||
$ make
|
||||
$ cd examples
|
||||
$ echo '(people = [(id = 123, name = "Alice", email = "alice@example.com", employment = (school = "MIT"))])' \
|
||||
| capnp encode addressbook.capnp AddressBook | java -cp .:.. AddressbookMain read
|
||||
```
|
|
@ -4,6 +4,8 @@ import org.capnproto.MessageReader;
|
|||
import org.capnproto.StructList;
|
||||
import org.capnproto.InputStreamMessageReader;
|
||||
|
||||
import org.capnproto.examples.Addressbook.*;
|
||||
|
||||
public class AddressbookMain {
|
||||
|
||||
public static void writeAddressBook() {
|
||||
|
@ -12,16 +14,16 @@ public class AddressbookMain {
|
|||
|
||||
public static void printAddressBook() throws java.io.IOException {
|
||||
MessageReader message = InputStreamMessageReader.create(System.in);
|
||||
Addressbook.AddressBook.Reader addressbook = message.getRoot(Addressbook.AddressBook.Reader.factory);
|
||||
StructList.Reader<Addressbook.Person.Reader> people = addressbook.getPeople();
|
||||
AddressBook.Reader addressbook = message.getRoot(AddressBook.Reader.factory);
|
||||
StructList.Reader<Person.Reader> people = addressbook.getPeople();
|
||||
int size = people.size();
|
||||
for(int ii = 0; ii < size; ++ii) {
|
||||
Addressbook.Person.Reader person = people.get(ii);
|
||||
Person.Reader person = people.get(ii);
|
||||
System.out.println(person.getName() + ": " + person.getEmail());
|
||||
|
||||
StructList.Reader<Addressbook.Person.PhoneNumber.Reader> phones = person.getPhones();
|
||||
StructList.Reader<Person.PhoneNumber.Reader> phones = person.getPhones();
|
||||
for (int jj = 0; jj < phones.size(); ++jj) {
|
||||
Addressbook.Person.PhoneNumber.Reader phone = phones.get(jj);
|
||||
Person.PhoneNumber.Reader phone = phones.get(jj);
|
||||
String typeName = "UNKNOWN";
|
||||
switch (phone.getType()) {
|
||||
case MOBILE :
|
||||
|
@ -37,7 +39,7 @@ public class AddressbookMain {
|
|||
System.out.println(" " + typeName + " phone: " + phone.getNumber());
|
||||
}
|
||||
|
||||
Addressbook.Person.Employment.Reader employment = person.getEmployment();
|
||||
Person.Employment.Reader employment = person.getEmployment();
|
||||
switch (employment.which()) {
|
||||
case UNEMPLOYED :
|
||||
System.out.println(" unemployed");
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
using Cxx = import "/capnp/c++.capnp";
|
||||
$Cxx.namespace("addressbook");
|
||||
|
||||
using Java = import "/java_support/java.capnp";
|
||||
$Java.package("org.capnproto.examples");
|
||||
|
||||
struct Person {
|
||||
id @0 :UInt32;
|
||||
name @1 :Text;
|
||||
|
|
|
@ -27,13 +27,13 @@
|
|||
|
||||
|
||||
#include <capnp/schema.capnp.h>
|
||||
#include "capnp/serialize.h"
|
||||
#include <capnp/serialize.h>
|
||||
#include <kj/debug.h>
|
||||
#include <kj/io.h>
|
||||
#include <kj/string-tree.h>
|
||||
#include <kj/vector.h>
|
||||
#include "capnp/schema-loader.h"
|
||||
#include "capnp/dynamic.h"
|
||||
#include <capnp/schema-loader.h>
|
||||
#include <capnp/dynamic.h>
|
||||
#include <unistd.h>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
@ -57,6 +57,7 @@ namespace capnp {
|
|||
namespace {
|
||||
|
||||
static constexpr uint64_t NAMESPACE_ANNOTATION_ID = 0xb9c6f99ebf805f2cull;
|
||||
static constexpr uint64_t PACKAGE_ANNOTATION_ID = 0x9ee4c8f803b3b596ull;
|
||||
|
||||
static constexpr const char* FIELD_SIZE_NAMES[] = {
|
||||
"VOID", "BIT", "BYTE", "TWO_BYTES", "FOUR_BYTES", "EIGHT_BYTES", "POINTER", "INLINE_COMPOSITE"
|
||||
|
@ -1508,6 +1509,7 @@ private:
|
|||
|
||||
kj::Vector<kj::ArrayPtr<const char>> namespaceParts;
|
||||
kj::String namespacePrefix;
|
||||
kj::StringPtr packageName;
|
||||
|
||||
for (auto annotation: node.getAnnotations()) {
|
||||
if (annotation.getId() == NAMESPACE_ANNOTATION_ID) {
|
||||
|
@ -1532,6 +1534,18 @@ private:
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto annotation: node.getAnnotations()) {
|
||||
if (annotation.getId() == PACKAGE_ANNOTATION_ID) {
|
||||
packageName = annotation.getValue().getText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (packageName.size() == 0) {
|
||||
context.exitError(kj::str(displayName, ": must provide a Java package name."));
|
||||
}
|
||||
|
||||
auto nodeTexts = KJ_MAP(nested, node.getNestedNodes()) {
|
||||
return makeNodeText(namespacePrefix, "", nested.getName(), schemaLoader.get(nested.getId()), 1);
|
||||
};
|
||||
|
@ -1551,8 +1565,8 @@ private:
|
|||
return FileText {
|
||||
kj::strTree(
|
||||
"// Generated by Cap'n Proto compiler, DO NOT EDIT\n"
|
||||
"// source: ", baseName(displayName), "\n",
|
||||
"\n",
|
||||
"// source: ", baseName(displayName), "\n\n",
|
||||
"package ", packageName, ";\n\n",
|
||||
//"import org.capnproto;\n",
|
||||
// KJ_MAP(n, namespaceParts) { return kj::strTree("namespace ", n, " {\n"); }, "\n",
|
||||
"public class ", outerClassName, " {\n",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import sbt.Keys._
|
||||
import sbt._
|
||||
import org.sbtidea.SbtIdeaPlugin._
|
||||
|
||||
object Build extends sbt.Build {
|
||||
|
||||
|
@ -21,6 +22,7 @@ object Build extends sbt.Build {
|
|||
id = "examples",
|
||||
base = file("examples")
|
||||
).dependsOn(generator)
|
||||
.settings(unmanagedSourceDirectories in Compile += sourceDirectory.value / "main" / "generated")
|
||||
.settings(publish := {})
|
||||
.settings(publishLocal := {})
|
||||
.settings(fork in run := true)
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
public class DecodeException extends RuntimeException {
|
||||
public DecodeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
public class FieldSize {
|
||||
public static final byte VOID = 0;
|
||||
public static final byte BIT = 1;
|
||||
public static final byte BYTE = 2;
|
||||
public static final byte TWO_BYTES = 3;
|
||||
public static final byte FOUR_BYTES = 4;
|
||||
public static final byte EIGHT_BYTES = 5;
|
||||
public static final byte POINTER = 6;
|
||||
public static final byte INLINE_COMPOSITE = 7;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
public interface FromStructBuilder<T> {
|
||||
public abstract T fromStructBuilder(StructBuilder builder);
|
||||
public abstract StructSize structSize();
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
public interface FromStructReader<T> {
|
||||
public abstract T fromStructReader(StructReader reader);
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
public class InputStreamMessageReader {
|
||||
|
||||
static byte[] readExact(InputStream is, int length) throws IOException {
|
||||
byte[] bytes = new byte[length];
|
||||
|
||||
int bytesRead = 0;
|
||||
while (bytesRead < length) {
|
||||
int r = is.read(bytes, bytesRead, length - bytesRead);
|
||||
if (r < 0) {
|
||||
throw new IOException("premature EOF");
|
||||
}
|
||||
bytesRead += r;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static ByteBuffer makeByteBuffer(byte[] bytes) {
|
||||
ByteBuffer result = ByteBuffer.wrap(bytes);
|
||||
result.order(ByteOrder.LITTLE_ENDIAN);
|
||||
result.mark();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static MessageReader create(InputStream is) throws IOException {
|
||||
ByteBuffer firstWord = makeByteBuffer(readExact(is, 8));
|
||||
|
||||
int segmentCount = 1 + firstWord.getInt(0);
|
||||
|
||||
int segment0Size = 0;
|
||||
if (segmentCount > 0) {
|
||||
segment0Size = firstWord.getInt(4);
|
||||
}
|
||||
|
||||
int totalWords = segment0Size;
|
||||
|
||||
if (segmentCount > 512) {
|
||||
throw new IOException("too many segments");
|
||||
}
|
||||
|
||||
// in words
|
||||
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 * 4);
|
||||
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 * 8);
|
||||
segmentSlices[0].order(ByteOrder.LITTLE_ENDIAN);
|
||||
segmentSlices[0].mark();
|
||||
|
||||
int offset = segment0Size;
|
||||
|
||||
for (int ii = 1; ii < segmentCount; ++ii) {
|
||||
segmentSlices[ii] = ByteBuffer.wrap(allSegments, offset * 8, moreSizes.get(ii - 1) * 8);
|
||||
segmentSlices[ii].order(ByteOrder.LITTLE_ENDIAN);
|
||||
segmentSlices[ii].mark();
|
||||
offset += moreSizes.get(ii - 1);
|
||||
}
|
||||
|
||||
return new MessageReader(segmentSlices);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
public final class ListBuilder {
|
||||
SegmentBuilder segment;
|
||||
int ptr; // byte offset to front of list
|
||||
int elementCount;
|
||||
int step; // in bits
|
||||
int structDataSize; // in bits
|
||||
short structPointerCount;
|
||||
|
||||
public ListBuilder(SegmentBuilder segment, int ptr,
|
||||
int elementCount, int step,
|
||||
int structDataSize, short structPointerCount) {
|
||||
this.segment = segment;
|
||||
this.ptr = ptr;
|
||||
this.elementCount = elementCount;
|
||||
this.step = step;
|
||||
this.structDataSize = structDataSize;
|
||||
this.structPointerCount = structPointerCount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
final class ListPointer {
|
||||
public static byte elementSize(int elementSizeAndCount) {
|
||||
return (byte) (elementSizeAndCount & 7);
|
||||
}
|
||||
|
||||
public static int elementCount(int elementSizeAndCount) {
|
||||
return elementSizeAndCount >> 3;
|
||||
}
|
||||
|
||||
public static int inlineCompositeWordCount(int elementSizeAndCount) {
|
||||
return elementCount(elementSizeAndCount);
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
public class ListReader {
|
||||
SegmentReader segment;
|
||||
int ptr; // byte offset to front of list
|
||||
int elementCount;
|
||||
int step; // in bits
|
||||
int structDataSize; // in bits
|
||||
short structPointerCount;
|
||||
int nestingLimit;
|
||||
|
||||
|
||||
public ListReader () {
|
||||
this.segment = null;
|
||||
this.ptr = 0;
|
||||
this.elementCount = 0;
|
||||
this.step = 0;
|
||||
this.structDataSize = 0;
|
||||
this.structPointerCount = 0;
|
||||
this.nestingLimit = 0x7fffffff;
|
||||
}
|
||||
|
||||
public ListReader(SegmentReader segment, int ptr,
|
||||
int elementCount, int step,
|
||||
int structDataSize, short structPointerCount,
|
||||
int nestingLimit) {
|
||||
this.segment = segment;
|
||||
this.ptr = ptr;
|
||||
this.elementCount = elementCount;
|
||||
this.step = step;
|
||||
this.structDataSize = structDataSize;
|
||||
this.structPointerCount = structPointerCount;
|
||||
this.nestingLimit = nestingLimit;
|
||||
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return this.elementCount;
|
||||
}
|
||||
|
||||
public StructReader getStructElement(int index) {
|
||||
// TODO check nesting limit
|
||||
|
||||
int indexBit = index * this.step;
|
||||
|
||||
int structData = this.ptr + (indexBit / 8);
|
||||
int structPointers = structData + (this.structDataSize / 8);
|
||||
|
||||
return new StructReader(this.segment, structData, structPointers / 8, this.structDataSize,
|
||||
this.structPointerCount, (byte)(indexBit % 8), this.nestingLimit - 1);
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
public final class MessageBuilder {
|
||||
public <T> T getRoot(FromStructBuilder<T> factory) {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public <T> T initRoot(FromStructBuilder<T> factory) {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
public final class PointerBuilder {
|
||||
public SegmentBuilder segment;
|
||||
public int pointer; // word offset
|
||||
|
||||
public PointerBuilder(SegmentBuilder segment, int pointer) {
|
||||
this.segment = segment;
|
||||
this.pointer = pointer;
|
||||
}
|
||||
|
||||
public final ListBuilder initStructList(int elementCount, StructSize elementSize) {
|
||||
return WireHelpers.initStructListPointer(this.pointer, this.segment, elementCount, elementSize);
|
||||
}
|
||||
|
||||
public final void setText(Text.Reader value) {
|
||||
WireHelpers.setTextPointer(this.pointer, this.segment, value);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
public class PointerReader {
|
||||
public SegmentReader segment;
|
||||
public int pointer; // word offset
|
||||
public int nestingLimit;
|
||||
|
||||
public PointerReader() {
|
||||
this.segment = null;
|
||||
this.pointer = 0; // XXX ?
|
||||
this.nestingLimit = 0x7fffffff;
|
||||
}
|
||||
|
||||
public PointerReader(SegmentReader segment, int pointer, int nestingLimit) {
|
||||
this.segment = segment;
|
||||
this.pointer = pointer;
|
||||
this.nestingLimit = nestingLimit;
|
||||
}
|
||||
|
||||
public static PointerReader getRoot(SegmentReader segment,
|
||||
WordPointer location,
|
||||
int nestingLimit) {
|
||||
// TODO bounds check
|
||||
return new PointerReader(segment, location.offset, nestingLimit);
|
||||
}
|
||||
|
||||
public boolean isNull() {
|
||||
return this.segment.buffer.getLong(this.pointer) == 0;
|
||||
}
|
||||
|
||||
public StructReader getStruct() {
|
||||
return WireHelpers.readStructPointer(this.segment,
|
||||
this.pointer,
|
||||
this.nestingLimit);
|
||||
}
|
||||
|
||||
public ListReader getList(byte expectedElementSize) {
|
||||
// TODO check nullness
|
||||
return WireHelpers.readListPointer(this.segment,
|
||||
this.pointer,
|
||||
expectedElementSize,
|
||||
this.nestingLimit);
|
||||
}
|
||||
|
||||
public Text.Reader getText() {
|
||||
return WireHelpers.readTextPointer(this.segment,
|
||||
this.pointer);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class SegmentBuilder extends SegmentReader {
|
||||
public int pos = 0; // in words
|
||||
|
||||
public static final int FAILED_ALLOCATION = -1;
|
||||
|
||||
public SegmentBuilder(ByteBuffer buf) {
|
||||
super(buf);
|
||||
}
|
||||
|
||||
// the total number of words the buffer can hold
|
||||
private final int capacity() {
|
||||
this.buffer.reset();
|
||||
return this.buffer.remaining() / 8;
|
||||
}
|
||||
|
||||
// return how many words have already been allocated
|
||||
private final int currentSize() {
|
||||
return this.pos;
|
||||
}
|
||||
|
||||
public final int allocate(int amount) {
|
||||
if (amount > this.capacity() - this.currentSize()) {
|
||||
return FAILED_ALLOCATION; // no space left;
|
||||
} else {
|
||||
int result = this.pos;
|
||||
this.pos += amount;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class SegmentReader {
|
||||
ByteBuffer buffer;
|
||||
|
||||
public SegmentReader(ByteBuffer buffer) {
|
||||
this.buffer = buffer;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
public final class StructBuilder {
|
||||
public SegmentBuilder segment;
|
||||
public int data; //byte offset to data section
|
||||
public int pointers; // word offset of pointer section
|
||||
public int dataSize; // in bits
|
||||
public short pointerCount;
|
||||
public byte bit0Offset;
|
||||
|
||||
public StructBuilder(SegmentBuilder segment, int data,
|
||||
int pointers, int dataSize, short pointerCount,
|
||||
byte bit0Offset) {
|
||||
this.segment = segment;
|
||||
this.data = data;
|
||||
this.pointers = pointers;
|
||||
this.dataSize = dataSize;
|
||||
this.pointerCount = pointerCount;
|
||||
this.bit0Offset = bit0Offset;
|
||||
}
|
||||
|
||||
public final int getShortField(int offset) {
|
||||
return this.segment.buffer.getShort(this.data + offset * 2);
|
||||
}
|
||||
|
||||
public final void setShortField(int offset, short value) {
|
||||
this.segment.buffer.putShort(this.data + offset * 2, value);
|
||||
}
|
||||
|
||||
public final int getIntField(int offset) {
|
||||
return this.segment.buffer.getInt(this.data + offset * 4);
|
||||
}
|
||||
|
||||
public final void setIntField(int offset, int value) {
|
||||
this.segment.buffer.putInt(this.data + offset * 4, value);
|
||||
}
|
||||
|
||||
public final PointerBuilder getPointerField(int index) {
|
||||
return new PointerBuilder(this.segment, this.pointers + index);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
|
||||
public final class StructList {
|
||||
public static final class Reader<T> {
|
||||
public ListReader reader;
|
||||
public final FromStructReader<T> factory;
|
||||
|
||||
public Reader(ListReader reader, FromStructReader<T> factory) {
|
||||
this.reader = reader;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return this.reader.size();
|
||||
}
|
||||
|
||||
public T get(int index) {
|
||||
return this.factory.fromStructReader(this.reader.getStructElement(index));
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Builder<T> {
|
||||
public ListBuilder builder;
|
||||
public final FromStructBuilder<T> factory;
|
||||
|
||||
public Builder(ListBuilder builder, FromStructBuilder<T> factory) {
|
||||
this.builder = builder;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
final class StructPointer{
|
||||
public static short dataSize(int structRef) {
|
||||
return (short)(structRef & 0xffff);
|
||||
}
|
||||
|
||||
public static short ptrCount(int structRef) {
|
||||
return (short)(structRef >> 16);
|
||||
}
|
||||
|
||||
public static int wordSize(int structRef) {
|
||||
return (int)dataSize(structRef) + (int)ptrCount(structRef);
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
public final class StructReader {
|
||||
public SegmentReader segment;
|
||||
public int data; //byte offset to data section
|
||||
public int pointers; // word offset of pointer section
|
||||
public int dataSize; // in bits
|
||||
public short pointerCount;
|
||||
public byte bit0Offset;
|
||||
public int nestingLimit;
|
||||
|
||||
|
||||
public StructReader(SegmentReader segment, int data,
|
||||
int pointers, int dataSize, short pointerCount,
|
||||
byte bit0Offset, int nestingLimit) {
|
||||
this.segment = segment;
|
||||
this.data = data;
|
||||
this.pointers = pointers;
|
||||
this.dataSize = dataSize;
|
||||
this.pointerCount = pointerCount;
|
||||
this.bit0Offset = bit0Offset;
|
||||
this.nestingLimit = nestingLimit;
|
||||
}
|
||||
|
||||
public final boolean getBoolField(int offset) {
|
||||
// XXX should use unsigned operations
|
||||
if (offset < this.dataSize) {
|
||||
if (offset == 0) {
|
||||
offset = this.bit0Offset;
|
||||
}
|
||||
byte b = this.segment.buffer.get(offset / 8);
|
||||
return (b & (1 << (offset % 8))) != 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public final byte getByteField(int offset) {
|
||||
if ((offset + 1) * 8 <= this.dataSize) {
|
||||
return this.segment.buffer.get(this.data + offset);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public final byte getShortField(int offset) {
|
||||
if ((offset + 1) * 16 <= this.dataSize) {
|
||||
return this.segment.buffer.get(this.data + offset * 2);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public final int getIntField(int offset) {
|
||||
if ((offset + 1) * 32 <= this.dataSize) {
|
||||
return this.segment.buffer.getInt(this.data + offset * 4);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public final PointerReader getPointerField(int ptrIndex) {
|
||||
if (ptrIndex < this.pointerCount) {
|
||||
return new PointerReader(this.segment,
|
||||
this.pointers + ptrIndex,
|
||||
this.nestingLimit);
|
||||
} else {
|
||||
return new PointerReader();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
public final class StructSize {
|
||||
public final short data; // number of words in data section
|
||||
public final short pointers; // number of words in pointer section
|
||||
public final byte preferredListEncoding; // a FieldSize
|
||||
|
||||
public StructSize(short data, short pointers, byte preferredListEncoding) {
|
||||
this.data = data;
|
||||
this.pointers = pointers;
|
||||
this.preferredListEncoding = preferredListEncoding;
|
||||
}
|
||||
|
||||
public final int total() {
|
||||
return (int)this.data + (int)this.pointers;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class Text {
|
||||
|
||||
public static class Reader {
|
||||
public final ByteBuffer buffer;
|
||||
public final int offset; // in bytes
|
||||
public final int size; // in bytes
|
||||
|
||||
public Reader(ByteBuffer buffer, int offset, int size) {
|
||||
this.buffer = buffer;
|
||||
this.offset = offset * 8;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public Reader(String value) {
|
||||
try {
|
||||
byte[] bytes = value.getBytes("UTF-8");
|
||||
this.buffer = ByteBuffer.wrap(bytes);
|
||||
this.offset = 0;
|
||||
this.size = bytes.length;
|
||||
} catch (java.io.UnsupportedEncodingException e) {
|
||||
throw new Error("UTF-8 is unsupported");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
byte[] bytes = new byte[this.size];
|
||||
|
||||
this.buffer.position(this.offset);
|
||||
this.buffer.get(bytes, 0, this.size);
|
||||
|
||||
try {
|
||||
return new String(bytes, "UTF-8");
|
||||
} catch(java.io.UnsupportedEncodingException e) {
|
||||
return "unsupported encoding"; // XXX
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
final class WireHelpers {
|
||||
|
||||
public static int roundBytesUpToWords(int bytes) {
|
||||
return (bytes + 7) / 8;
|
||||
}
|
||||
|
||||
public static int allocate(int refOffset,
|
||||
SegmentBuilder segment,
|
||||
int amount,
|
||||
byte kind) {
|
||||
|
||||
// TODO check for nullness, amount == 0 case.
|
||||
|
||||
int allocation = segment.allocate(amount);
|
||||
if (allocation == SegmentBuilder.FAILED_ALLOCATION) {
|
||||
//# Need to allocate in a new segment. We'll need to
|
||||
//# allocate an extra pointer worth of space to act as
|
||||
//# the landing pad for a far pointer.
|
||||
throw new Error("unimplemented");
|
||||
} else {
|
||||
WirePointer.setKindAndTarget(segment.buffer, refOffset, kind, allocation);
|
||||
return allocation;
|
||||
}
|
||||
}
|
||||
|
||||
public static ListBuilder initListPointer(int refOffset,
|
||||
SegmentBuilder segment,
|
||||
int elementCount,
|
||||
byte elementSize) {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public static ListBuilder initStructListPointer(int refOffset,
|
||||
SegmentBuilder segment,
|
||||
int elementCount,
|
||||
StructSize elementSize) {
|
||||
if (elementSize.preferredListEncoding != FieldSize.INLINE_COMPOSITE) {
|
||||
//# Small data-only struct. Allocate a list of primitives instead.
|
||||
return initListPointer(refOffset, segment, elementCount,
|
||||
elementSize.preferredListEncoding);
|
||||
}
|
||||
|
||||
int wordsPerElement = elementSize.total();
|
||||
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
// size is in bytes
|
||||
public static void initTextPointer(int refOffset,
|
||||
SegmentBuilder segment,
|
||||
int size) {
|
||||
//# The byte list must include a NUL terminator.
|
||||
int byteSize = size + 1;
|
||||
|
||||
int ptrOffset = allocate(refOffset, segment, roundBytesUpToWords(byteSize), WirePointer.LIST);
|
||||
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public static void setTextPointer(int refOffset,
|
||||
SegmentBuilder segment,
|
||||
Text.Reader value) {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public static StructReader readStructPointer(SegmentReader segment,
|
||||
int refOffset,
|
||||
int nestingLimit) {
|
||||
|
||||
// TODO error handling
|
||||
|
||||
if (nestingLimit < 0) {
|
||||
throw new DecodeException("Message is too deeply nested or contains cycles.");
|
||||
}
|
||||
|
||||
long ref = WirePointer.get(segment.buffer, refOffset);
|
||||
int ptrOffset = WirePointer.target(refOffset, ref);
|
||||
int structPtr = WirePointer.structPointer(ref);
|
||||
int dataSizeWords = StructPointer.dataSize(structPtr);
|
||||
|
||||
return new StructReader(segment,
|
||||
ptrOffset * 8,
|
||||
(ptrOffset + dataSizeWords),
|
||||
dataSizeWords * 64,
|
||||
StructPointer.ptrCount(structPtr),
|
||||
(byte)0,
|
||||
nestingLimit - 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static ListReader readListPointer(SegmentReader segment,
|
||||
int refOffset,
|
||||
byte expectedElementSize,
|
||||
int nestingLimit) {
|
||||
|
||||
long ref = WirePointer.get(segment.buffer, refOffset);
|
||||
|
||||
// TODO check for null, follow fars, nestingLimit
|
||||
if (WirePointer.isNull(ref)) {
|
||||
return new ListReader();
|
||||
}
|
||||
|
||||
int listPtr = WirePointer.listPointer(ref);
|
||||
|
||||
int ptrOffset = WirePointer.target(refOffset, ref);
|
||||
long ptr = WirePointer.get(segment.buffer, ptrOffset);
|
||||
|
||||
switch (ListPointer.elementSize(listPtr)) {
|
||||
case FieldSize.INLINE_COMPOSITE : {
|
||||
int wordCount = ListPointer.inlineCompositeWordCount(listPtr);
|
||||
|
||||
long tag = ptr;
|
||||
ptrOffset += 1;
|
||||
|
||||
// TODO bounds check
|
||||
|
||||
int size = WirePointer.inlineCompositeListElementCount(tag);
|
||||
|
||||
int structPtr = WirePointer.structPointer(tag);
|
||||
int wordsPerElement = StructPointer.wordSize(structPtr);
|
||||
|
||||
// TODO check that elemements do not overrun word count
|
||||
|
||||
// TODO check whether the size is compatible
|
||||
|
||||
return new ListReader(segment, // TODO follow fars
|
||||
ptrOffset * 8, //
|
||||
size,
|
||||
wordsPerElement * 64,
|
||||
StructPointer.dataSize(structPtr) * 64,
|
||||
StructPointer.ptrCount(structPtr),
|
||||
nestingLimit - 1);
|
||||
}
|
||||
case FieldSize.VOID : break;
|
||||
default :
|
||||
throw new Error("unrecognized element size");
|
||||
}
|
||||
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
public static Text.Reader readTextPointer(SegmentReader segment,
|
||||
int refOffset) {
|
||||
long ref = WirePointer.get(segment.buffer, refOffset);
|
||||
|
||||
if (WirePointer.isNull(ref)) {
|
||||
// XXX should use the default value
|
||||
return new Text.Reader(java.nio.ByteBuffer.wrap(new byte[0]), 0, 0);
|
||||
}
|
||||
|
||||
int ptrOffset = WirePointer.target(refOffset, ref);
|
||||
int listPtr = WirePointer.listPointer(ref);
|
||||
int size = ListPointer.elementCount(listPtr);
|
||||
|
||||
if (WirePointer.kind(ref) != WirePointer.LIST) {
|
||||
throw new DecodeException("Message contains non-list pointer where text was expected.");
|
||||
}
|
||||
|
||||
if (ListPointer.elementSize(listPtr) != FieldSize.BYTE) {
|
||||
throw new DecodeException("Message contains list pointer of non-bytes where text was expected.");
|
||||
}
|
||||
|
||||
// TODO bounds check?
|
||||
|
||||
if (size == 0 || segment.buffer.get(8 * ptrOffset + size - 1) != 0) {
|
||||
throw new DecodeException("Message contains text that is not NUL-terminated.");
|
||||
}
|
||||
|
||||
return new Text.Reader(segment.buffer, ptrOffset, size - 1);
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
final class WirePointer {
|
||||
public static final byte STRUCT = 0;
|
||||
public static final byte LIST = 1;
|
||||
public static final byte FAR = 2;
|
||||
public static final byte OTHER = 3;
|
||||
|
||||
public static boolean isNull(long wirePointer) {
|
||||
return wirePointer == 0;
|
||||
}
|
||||
|
||||
public static int offsetAndKind(long wirePointer) {
|
||||
return (int)(wirePointer & 0xffffffff);
|
||||
}
|
||||
|
||||
public static byte kind(long wirePointer) {
|
||||
return (byte)(offsetAndKind(wirePointer) & 3);
|
||||
}
|
||||
|
||||
public static int target(int offset, long wirePointer) {
|
||||
return offset + 1 + (offsetAndKind(wirePointer) >> 2);
|
||||
}
|
||||
|
||||
public static void setKindAndTarget(ByteBuffer buffer, int offset, byte kind, int targetOffset) {
|
||||
buffer.putInt(offset * 8,
|
||||
(((targetOffset - offset) - 1) << 2) | kind);
|
||||
}
|
||||
|
||||
public static int inlineCompositeListElementCount(long wirePointer) {
|
||||
return offsetAndKind(wirePointer) >> 2;
|
||||
}
|
||||
|
||||
public static int upper32Bits(long wirePointer) {
|
||||
return (int)(wirePointer >> 32);
|
||||
}
|
||||
|
||||
public static int listPointer(long wirePointer) {
|
||||
return upper32Bits(wirePointer);
|
||||
}
|
||||
|
||||
public static int structPointer(long wirePointer) {
|
||||
return upper32Bits(wirePointer);
|
||||
}
|
||||
|
||||
public static long get(ByteBuffer buffer, int offset) {
|
||||
return buffer.getLong(offset * 8);
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
class WordPointer {
|
||||
public final ByteBuffer buffer;
|
||||
public int offset; // in words
|
||||
|
||||
public WordPointer(ByteBuffer buffer, int offset) {
|
||||
this.buffer = buffer;
|
||||
this.offset = offset;
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
package org.capnproto;
|
||||
|
||||
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue