implement StructList.Builder.setWithCaveats()
This commit is contained in:
parent
45fd638c7c
commit
c6762ff0f7
3 changed files with 98 additions and 1 deletions
|
@ -817,6 +817,30 @@ class EncodingSuite extends FunSuite {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("setWithCaveats") {
|
||||||
|
val builder = new MessageBuilder()
|
||||||
|
val root = builder.initRoot(TestAllTypes.factory)
|
||||||
|
val list = root.initStructList(2)
|
||||||
|
|
||||||
|
{
|
||||||
|
val message1 = new MessageBuilder()
|
||||||
|
val root1 = message1.initRoot(TestAllTypes.factory)
|
||||||
|
root1.setInt8Field(11)
|
||||||
|
list.setWithCaveats(TestAllTypes.factory, 0, root1.asReader())
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
val message2 = new MessageBuilder()
|
||||||
|
val root2 = message2.initRoot(TestAllTypes.factory)
|
||||||
|
TestUtil.initTestMessage(root2)
|
||||||
|
list.setWithCaveats(TestAllTypes.factory, 1, root2.asReader())
|
||||||
|
}
|
||||||
|
|
||||||
|
val listReader = list.asReader(TestAllTypes.factory)
|
||||||
|
listReader.get(0).getInt8Field() should equal (11)
|
||||||
|
TestUtil.checkTestMessage(listReader.get(1))
|
||||||
|
}
|
||||||
|
|
||||||
// to debug, do this:
|
// to debug, do this:
|
||||||
//Serialize.write((new java.io.FileOutputStream("/Users/dwrensha/Desktop/test.dat")).getChannel(),
|
//Serialize.write((new java.io.FileOutputStream("/Users/dwrensha/Desktop/test.dat")).getChannel(),
|
||||||
// message)
|
// message)
|
||||||
|
|
|
@ -197,4 +197,63 @@ public class StructBuilder {
|
||||||
protected final <Builder, Reader> void _setPointerField(SetPointerBuilder<Builder, Reader> factory, int index, Reader value) {
|
protected final <Builder, Reader> void _setPointerField(SetPointerBuilder<Builder, Reader> factory, int index, Reader value) {
|
||||||
factory.setPointerBuilder(this.segment, this.pointers + index, value);
|
factory.setPointerBuilder(this.segment, this.pointers + index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected final void _copyContentFrom(StructReader other) {
|
||||||
|
// Determine the amount of data the builders have in common.
|
||||||
|
int sharedDataSize = java.lang.Math.min(this.dataSize, other.dataSize);
|
||||||
|
int sharedPointerCount = java.lang.Math.min(this.pointerCount, other.pointerCount);
|
||||||
|
|
||||||
|
if (other.segment == this.segment &&
|
||||||
|
((sharedDataSize > 0 && other.data == this.data) ||
|
||||||
|
(sharedPointerCount > 0 && other.pointers == this.pointers))) {
|
||||||
|
// At least one of the section pointers is pointing to ourself. Verify that the other is too
|
||||||
|
// (but ignore empty sections).
|
||||||
|
if ((sharedDataSize == 0 || other.data == this.data) &&
|
||||||
|
(sharedPointerCount == 0 || other.pointers == this.pointers)) {
|
||||||
|
throw new Error("Only one of the section pointers is pointing to ourself");
|
||||||
|
}
|
||||||
|
|
||||||
|
// So `other` appears to be a reader for this same struct. No copying is needed.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.dataSize > sharedDataSize) {
|
||||||
|
// Since the target is larger than the source, make sure to zero out the extra bits that the
|
||||||
|
// source doesn't have.
|
||||||
|
if (this.dataSize == 1) {
|
||||||
|
this._setBooleanField(0, false);
|
||||||
|
} else {
|
||||||
|
int unshared = this.data + sharedDataSize / Constants.BITS_PER_BYTE;
|
||||||
|
WireHelpers.memset(this.segment.buffer,
|
||||||
|
unshared,
|
||||||
|
(byte)0,
|
||||||
|
(this.dataSize - sharedDataSize) / Constants.BITS_PER_BYTE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy over the shared part.
|
||||||
|
if (sharedDataSize == 1) {
|
||||||
|
this._setBooleanField(0, other._getBooleanField(0));
|
||||||
|
} else {
|
||||||
|
WireHelpers.memcpy(this.segment.buffer,
|
||||||
|
this.data,
|
||||||
|
other.segment.buffer,
|
||||||
|
other.data,
|
||||||
|
sharedDataSize / Constants.BITS_PER_BYTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zero out all pointers in the target.
|
||||||
|
for (int ii = 0; ii < this.pointerCount; ++ii) {
|
||||||
|
WireHelpers.zeroObject(this.segment, this.pointers + ii);
|
||||||
|
}
|
||||||
|
this.segment.buffer.putLong(this.pointers * Constants.BYTES_PER_WORD, 0);
|
||||||
|
|
||||||
|
for (int ii = 0; ii < sharedPointerCount; ++ii) {
|
||||||
|
WireHelpers.copyPointer(this.segment,
|
||||||
|
this.pointers + ii,
|
||||||
|
other.segment,
|
||||||
|
other.pointers + ii,
|
||||||
|
other.nestingLimit);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ public final class StructList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Builder<T> extends ListBuilder implements Iterable<T> {
|
public static final class Builder<T extends StructBuilder> extends ListBuilder implements Iterable<T> {
|
||||||
public final StructBuilder.Factory<T> factory;
|
public final StructBuilder.Factory<T> factory;
|
||||||
|
|
||||||
public Builder(StructBuilder.Factory<T> factory,
|
public Builder(StructBuilder.Factory<T> factory,
|
||||||
|
@ -134,6 +134,20 @@ public final class StructList {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: rework generics so that we don't need this factory parameter
|
// TODO: rework generics so that we don't need this factory parameter
|
||||||
|
public final <U extends StructReader> void setWithCaveats(StructFactory<T, U> factory,
|
||||||
|
int index,
|
||||||
|
U value) {
|
||||||
|
this._getStructElement(this.factory, index)._copyContentFrom(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the list element, with the following limitation based on the fact that structs in a
|
||||||
|
* struct list are allocated inline: if the source struct is larger than the target struct
|
||||||
|
* (as can happen if it was created with a newer version of the schema), then it will be
|
||||||
|
* truncated, losing fields.
|
||||||
|
*
|
||||||
|
* TODO: rework generics, so that we don't need this factory parameter
|
||||||
|
*/
|
||||||
public final <U extends StructReader> Reader<U> asReader(StructFactory<T, U> factory) {
|
public final <U extends StructReader> Reader<U> asReader(StructFactory<T, U> factory) {
|
||||||
return new Reader(factory,
|
return new Reader(factory,
|
||||||
this.segment, this.ptr, this.elementCount, this.step,
|
this.segment, this.ptr, this.elementCount, this.step,
|
||||||
|
|
Loading…
Reference in a new issue