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:
|
||||
//Serialize.write((new java.io.FileOutputStream("/Users/dwrensha/Desktop/test.dat")).getChannel(),
|
||||
// message)
|
||||
|
|
|
@ -197,4 +197,63 @@ public class StructBuilder {
|
|||
protected final <Builder, Reader> void _setPointerField(SetPointerBuilder<Builder, Reader> factory, int index, Reader 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 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
|
||||
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) {
|
||||
return new Reader(factory,
|
||||
this.segment, this.ptr, this.elementCount, this.step,
|
||||
|
|
Loading…
Reference in a new issue