getWritableListPointer

This commit is contained in:
David Renshaw 2014-06-14 14:32:54 -04:00
parent c3142893f7
commit b39b352dc6
7 changed files with 101 additions and 4 deletions

View file

@ -1098,13 +1098,21 @@ private:
spaces(indent), " public final boolean has", titleCase, "() {\n", spaces(indent), " public final boolean has", titleCase, "() {\n",
spaces(indent), " return !_builder.getPointerField(", offset, ").isNull();\n", spaces(indent), " return !_builder.getPointerField(", offset, ").isNull();\n",
spaces(indent), " }\n", spaces(indent), " }\n",
spaces(indent), " public final ", type, ".", builderClass, spaces(indent), " public final ", type, ".", builderClass,
" get", titleCase, "() {\n", " get", titleCase, "() {\n",
spaces(indent), " throw new Error();\n", spaces(indent), " return new ", type, ".", builderClass, " (\n",
spaces(indent), " ", builderFactoryArg, "_builder.getPointerField(", offset, ").get",
(isStructList ?
kj::strTree("StructList(", typeName(typeBody.getList().getElementType()),".STRUCT_SIZE)") :
kj::strTree("List(", fieldSize, ")")),
");\n",
spaces(indent), " }\n", spaces(indent), " }\n",
spaces(indent), " public final void set", titleCase, "(", type, ".Reader value) {\n", spaces(indent), " public final void set", titleCase, "(", type, ".Reader value) {\n",
spaces(indent), " throw new Error();\n", spaces(indent), " throw new Error();\n",
spaces(indent), " }\n", spaces(indent), " }\n",
spaces(indent), " public final ", type, ".", builderClass, spaces(indent), " public final ", type, ".", builderClass,
" init", titleCase, "(int size) {\n", " init", titleCase, "(int size) {\n",
spaces(indent), " return new ", type, ".", builderClass, "(\n", spaces(indent), " return new ", type, ".", builderClass, "(\n",

View file

@ -45,7 +45,7 @@ object TestUtil {
builder.setEnumField(TestEnum.CORGE); builder.setEnumField(TestEnum.CORGE);
//builder.initVoidList(6); builder.initVoidList(6);
} }
@ -85,6 +85,8 @@ object TestUtil {
assert(subSubBuilder.getTextField().toString() == "nested") assert(subSubBuilder.getTextField().toString() == "nested")
} }
} }
assert(builder.getVoidList().size() == 6);
} }
} }

View file

@ -0,0 +1,7 @@
package org.capnproto;
public final class InternalError extends RuntimeException {
public InternalError(String message) {
super(message);
}
}

View file

@ -19,6 +19,10 @@ public final class ListBuilder {
this.structPointerCount = structPointerCount; this.structPointerCount = structPointerCount;
} }
public int size() {
return this.elementCount;
}
public final StructBuilder getStructElement(int index) { public final StructBuilder getStructElement(int index) {
int indexBit = index * this.step; int indexBit = index * this.step;
int structData = this.ptr + indexBit / 8 ; int structData = this.ptr + indexBit / 8 ;

View file

@ -21,6 +21,14 @@ public final class PointerBuilder {
return WireHelpers.getWritableStructPointer(this.pointer, this.segment, size); return WireHelpers.getWritableStructPointer(this.pointer, this.segment, size);
} }
public final ListBuilder getList(byte elementSize) {
return WireHelpers.getWritableListPointer(this.pointer, this.segment, elementSize);
}
public final ListBuilder getStructList(StructSize elementSize) {
throw new Error("unimplemented");
}
public final Text.Builder getText() { public final Text.Builder getText() {
return WireHelpers.getWritableTextPointer( return WireHelpers.getWritableTextPointer(
this.pointer, this.segment); this.pointer, this.segment);
@ -35,7 +43,7 @@ public final class PointerBuilder {
} }
public final ListBuilder initList(byte elementSize, int elementCount) { public final ListBuilder initList(byte elementSize, int elementCount) {
throw new Error("unimplemented"); return WireHelpers.initListPointer(this.pointer, this.segment, elementCount, elementSize);
} }
public final ListBuilder initStructList(int elementCount, StructSize elementSize) { public final ListBuilder initStructList(int elementCount, StructSize elementSize) {

View file

@ -25,6 +25,11 @@ public class PrimitiveList {
this.builder = builder; this.builder = builder;
} }
public int size() {
return this.builder.size();
}
} }
} }
@ -52,6 +57,10 @@ public class PrimitiveList {
this.builder = builder; this.builder = builder;
} }
public int size() {
return this.builder.size();
}
} }
} }

View file

@ -71,7 +71,7 @@ final class WireHelpers {
int elementCount, int elementCount,
byte elementSize) { byte elementSize) {
if (elementSize == FieldSize.INLINE_COMPOSITE) { if (elementSize == FieldSize.INLINE_COMPOSITE) {
throw new DecodeException("Should have called initStructListPointer instead"); throw new InternalError("Should have called initStructListPointer instead");
} }
int dataSize = FieldSize.dataBitsPerElement(elementSize); int dataSize = FieldSize.dataBitsPerElement(elementSize);
@ -115,6 +115,65 @@ final class WireHelpers {
elementSize.data * 64, elementSize.pointers); elementSize.data * 64, elementSize.pointers);
} }
public static ListBuilder getWritableListPointer(int origRefOffset,
SegmentBuilder origSegment,
byte elementSize) {
if (elementSize == FieldSize.INLINE_COMPOSITE) {
throw new InternalError("Use getStructList{Element,Field} for structs");
}
long origRef = WirePointer.get(origSegment.buffer, origRefOffset);
int origRefTarget = WirePointer.target(origRefOffset, origRef);
if (WirePointer.isNull(origRef)) {
throw new Error("unimplemented");
}
//# We must verify that the pointer has the right size. Unlike
//# in getWritableStructListReference(), we never need to
//# "upgrade" the data, because this method is called only for
//# non-struct lists, and there is no allowed upgrade path *to*
//# a non-struct list, only *from* them.
long ref = origRef;
SegmentBuilder segment = origSegment;
int ptr = origRefTarget; // TODO follow fars.
if (WirePointer.kind(ref) != WirePointer.LIST) {
throw new DecodeException("Called getList{Field,Element}() but existing pointer is not a list");
}
byte oldSize = ListPointer.elementSize(WirePointer.listPointer(ref));
if (oldSize == FieldSize.INLINE_COMPOSITE) {
//# The existing element size is InlineComposite, which
//# means that it is at least two words, which makes it
//# bigger than the expected element size. Since fields can
//# only grow when upgraded, the existing data must have
//# been written with a newer version of the protocol. We
//# therefore never need to upgrade the data in this case,
//# but we do need to validate that it is a valid upgrade
//# from what we expected.
throw new Error("unimplemented");
} else {
int dataSize = FieldSize.dataBitsPerElement(oldSize);
int pointerCount = FieldSize.pointersPerElement(oldSize);
if (dataSize < FieldSize.dataBitsPerElement(elementSize)) {
throw new DecodeException("Existing list value is incompatible with expected type.");
}
if (pointerCount < FieldSize.pointersPerElement(elementSize)) {
throw new DecodeException("Existing list value is incompatible with expected type.");
}
int step = dataSize + pointerCount * Constants.BITS_PER_POINTER;
return new ListBuilder(segment, ptr * Constants.BYTES_PER_WORD,
ListPointer.elementCount(WirePointer.listPointer(ref)),
step, dataSize, (short) pointerCount);
}
}
// size is in bytes // size is in bytes
public static Text.Builder initTextPointer(int refOffset, public static Text.Builder initTextPointer(int refOffset,
SegmentBuilder segment, SegmentBuilder segment,