Commit edad34c4 authored by Kenton Varda's avatar Kenton Varda

Initialize from default values.

parent 90eae25e
......@@ -96,6 +96,14 @@ TEST(WireFormat, SimpleRawDataStruct) {
EXPECT_TRUE (reader.getDataFieldCheckingNumber<bool>(FieldNumber(1), 0 * ELEMENTS, true ));
}
static const AlignedData<2> STRUCT_DEFAULT = {{8,0,0,0,16,2,4,0, 0}};
static const AlignedData<2> SUBSTRUCT_DEFAULT = {{8,0,0,0,1,1,0,0, 0,0,0,0,0,0,0,0}};
static const AlignedData<3> STRUCTLIST_ELEMENT_DEFAULT =
{{8,0,0,0,1,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}};
static const AlignedData<2> STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT =
{{8,0,0,0,1,1,0,0, 0,0,0,0,0,0,0,0}};
static void setupStruct(StructBuilder builder) {
builder.setDataField<uint64_t>(0 * ELEMENTS, 0x1011121314151617ull);
builder.setDataField<uint32_t>(2 * ELEMENTS, 0x20212223u);
......@@ -111,8 +119,7 @@ static void setupStruct(StructBuilder builder) {
builder.setDataField<bool>(127 * ELEMENTS, false);
{
StructBuilder subStruct = builder.getStructField(
0 * REFERENCES, FieldNumber(1), 1 * WORDS, 0 * REFERENCES);
StructBuilder subStruct = builder.initStructField(0 * REFERENCES, SUBSTRUCT_DEFAULT.words);
subStruct.setDataField<uint32_t>(0 * ELEMENTS, 123);
}
......@@ -126,12 +133,12 @@ static void setupStruct(StructBuilder builder) {
{
ListBuilder list = builder.initStructListField(
2 * REFERENCES, 4 * ELEMENTS, FieldNumber(2), 1 * WORDS, 1 * REFERENCES);
2 * REFERENCES, 4 * ELEMENTS, STRUCTLIST_ELEMENT_DEFAULT.words);
EXPECT_EQ(4 * ELEMENTS, list.size());
for (int i = 0; i < 4; i++) {
StructBuilder element = list.getStructElement(i * ELEMENTS, 2 * WORDS / ELEMENTS, 1 * WORDS);
element.setDataField<int32_t>(0 * ELEMENTS, 300 + i);
element.getStructField(0 * REFERENCES, FieldNumber(1), 1 * WORDS, 0 * REFERENCES)
element.initStructField(0 * REFERENCES, STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT.words)
.setDataField<int32_t>(0 * ELEMENTS, 400 + i);
}
}
......@@ -165,13 +172,12 @@ static void checkStruct(StructBuilder builder) {
EXPECT_FALSE(builder.getDataField<bool>(127 * ELEMENTS));
{
StructBuilder subStruct = builder.getStructField(
0 * REFERENCES, FieldNumber(1), 1 * WORDS, 0 * REFERENCES);
StructBuilder subStruct = builder.getStructField(0 * REFERENCES, SUBSTRUCT_DEFAULT.words);
EXPECT_EQ(123u, subStruct.getDataField<uint32_t>(0 * ELEMENTS));
}
{
ListBuilder list = builder.getListField(1 * REFERENCES, FieldSize::FOUR_BYTES);
ListBuilder list = builder.getListField(1 * REFERENCES, nullptr);
ASSERT_EQ(3 * ELEMENTS, list.size());
EXPECT_EQ(200, list.getDataElement<int32_t>(0 * ELEMENTS));
EXPECT_EQ(201, list.getDataElement<int32_t>(1 * ELEMENTS));
......@@ -179,19 +185,19 @@ static void checkStruct(StructBuilder builder) {
}
{
ListBuilder list = builder.getListField(2 * REFERENCES, FieldSize::INLINE_COMPOSITE);
ListBuilder list = builder.getListField(2 * REFERENCES, nullptr);
ASSERT_EQ(4 * ELEMENTS, list.size());
for (int i = 0; i < 4; i++) {
StructBuilder element = list.getStructElement(i * ELEMENTS, 2 * WORDS / ELEMENTS, 1 * WORDS);
EXPECT_EQ(300 + i, element.getDataField<int32_t>(0 * ELEMENTS));
EXPECT_EQ(400 + i,
element.getStructField(0 * REFERENCES, FieldNumber(1), 1 * WORDS, 0 * REFERENCES)
element.getStructField(0 * REFERENCES, STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT.words)
.getDataField<int32_t>(0 * ELEMENTS));
}
}
{
ListBuilder list = builder.getListField(3 * REFERENCES, FieldSize::REFERENCE);
ListBuilder list = builder.getListField(3 * REFERENCES, nullptr);
ASSERT_EQ(5 * ELEMENTS, list.size());
for (uint i = 0; i < 5; i++) {
ListBuilder element = list.getListElement(i * REFERENCES, FieldSize::TWO_BYTES);
......@@ -218,13 +224,11 @@ static void checkStruct(StructReader reader) {
EXPECT_FALSE(reader.getDataField<bool>(127 * ELEMENTS, false));
{
// TODO: Use valid default value.
StructReader subStruct = reader.getStructField(0 * REFERENCES, nullptr);
StructReader subStruct = reader.getStructField(0 * REFERENCES, SUBSTRUCT_DEFAULT.words);
EXPECT_EQ(123u, subStruct.getDataField<uint32_t>(0 * ELEMENTS, 456));
}
{
// TODO: Use valid default value.
ListReader list = reader.getListField(1 * REFERENCES, FieldSize::FOUR_BYTES, nullptr);
ASSERT_EQ(3 * ELEMENTS, list.size());
EXPECT_EQ(200, list.getDataElement<int32_t>(0 * ELEMENTS));
......@@ -233,14 +237,13 @@ static void checkStruct(StructReader reader) {
}
{
// TODO: Use valid default value.
ListReader list = reader.getListField(2 * REFERENCES, FieldSize::INLINE_COMPOSITE, nullptr);
ASSERT_EQ(4 * ELEMENTS, list.size());
for (int i = 0; i < 4; i++) {
StructReader element = list.getStructElement(i * ELEMENTS, nullptr);
StructReader element = list.getStructElement(i * ELEMENTS, STRUCTLIST_ELEMENT_DEFAULT.words);
EXPECT_EQ(300 + i, element.getDataField<int32_t>(0 * ELEMENTS, 1616));
EXPECT_EQ(400 + i,
element.getStructField(0 * REFERENCES, nullptr)
element.getStructField(0 * REFERENCES, STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT.words)
.getDataField<int32_t>(0 * ELEMENTS, 1616));
}
}
......@@ -264,8 +267,7 @@ TEST(WireFormat, StructRoundTrip_OneSegment) {
SegmentBuilder* segment = message->getSegmentWithAvailable(1 * WORDS);
word* rootLocation = segment->allocate(1 * WORDS);
StructBuilder builder =
StructBuilder::initRoot(segment, rootLocation, FieldNumber(16), 2 * WORDS, 4 * REFERENCES);
StructBuilder builder = StructBuilder::initRoot(segment, rootLocation, STRUCT_DEFAULT.words);
setupStruct(builder);
// word count:
......@@ -297,8 +299,7 @@ TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation) {
SegmentBuilder* segment = message->getSegmentWithAvailable(1 * WORDS);
word* rootLocation = segment->allocate(1 * WORDS);
StructBuilder builder =
StructBuilder::initRoot(segment, rootLocation, FieldNumber(16), 2 * WORDS, 4 * REFERENCES);
StructBuilder builder = StructBuilder::initRoot(segment, rootLocation, STRUCT_DEFAULT.words);
setupStruct(builder);
// Verify that we made 15 segments.
......@@ -333,8 +334,7 @@ TEST(WireFormat, StructRoundTrip_MultipleSegmentsWithMultipleAllocations) {
SegmentBuilder* segment = message->getSegmentWithAvailable(1 * WORDS);
word* rootLocation = segment->allocate(1 * WORDS);
StructBuilder builder =
StructBuilder::initRoot(segment, rootLocation, FieldNumber(16), 2 * WORDS, 4 * REFERENCES);
StructBuilder builder = StructBuilder::initRoot(segment, rootLocation, STRUCT_DEFAULT.words);
setupStruct(builder);
// Verify that we made 6 segments.
......
This diff is collapsed.
......@@ -69,7 +69,7 @@ class WireValue {
// allocation and layout of memory, in order to squeeze out every last drop of performance.
public:
CAPNPROTO_ALWAYS_INLINE(WireValue()) {}
WireValue() = default;
CAPNPROTO_ALWAYS_INLINE(WireValue(T value)): value(value) {}
CAPNPROTO_ALWAYS_INLINE(T get() const) { return value; }
......@@ -83,39 +83,49 @@ class StructBuilder {
public:
inline StructBuilder(): segment(nullptr), data(nullptr), references(nullptr) {}
static StructBuilder initRoot(SegmentBuilder* segment, word* location,
FieldNumber fieldCount, WordCount dataSize, WireReferenceCount referenceCount);
static StructBuilder initRoot(SegmentBuilder* segment, word* location, const word* defaultValue);
template <typename T>
CAPNPROTO_ALWAYS_INLINE(T getDataField(ElementCount offset) const);
// Get the data field value of the given type at the given offset. The offset is measured in
// Gets the data field value of the given type at the given offset. The offset is measured in
// multiples of the field size, determined by the type.
template <typename T>
CAPNPROTO_ALWAYS_INLINE(void setDataField(
ElementCount offset, typename NoInfer<T>::Type value) const);
// Set the data field value at the given offset.
// Sets the data field value at the given offset.
StructBuilder initStructField(WireReferenceCount refIndex, const word* typeDefaultValue) const;
// Initializes the struct field at the given index in the reference segment. If it is already
// initialized, the previous value is discarded or overwritten. The struct is initialized to
// match the given default value (a trusted message). This must be the default value for the
// *type*, not the specific field, and in particular its reference segment is expected to be
// all nulls (only the data segment is copied). Use getStructField() if you want the struct
// to be initialized as a copy of the field's default value (which may have non-null references).
StructBuilder getStructField(
WireReferenceCount refIndex, FieldNumber fieldCount,
WordCount dataSize, WireReferenceCount referenceCount) const;
// Get the struct field at the given index in the reference segment. Allocates space for the
// struct if necessary.
StructBuilder getStructField(WireReferenceCount refIndex, const word* defaultValue) const;
// Gets the struct field at the given index in the reference segment. If the field is not already
// initialized, it is initialized as a deep copy of the given default value (a trusted message).
ListBuilder initListField(WireReferenceCount refIndex, FieldSize elementSize,
ElementCount elementCount) const;
ListBuilder initStructListField(
WireReferenceCount refIndex, ElementCount elementCount,
FieldNumber fieldCount, WordCount dataSize, WireReferenceCount referenceCount) const;
// Allocate a new list of the given size for the field at the given index in the reference
// segment, and return a pointer to it.
// Allocates a new list of the given size for the field at the given index in the reference
// segment, and return a pointer to it. All elements are initialized to zero.
ListBuilder getListField(WireReferenceCount refIndex, FieldSize elementSize) const;
// Get the already-allocated list field for the given reference index. Returns an empty list --
// NOT necessarily the default value -- if the field is not initialized.
ListBuilder initStructListField(WireReferenceCount refIndex, ElementCount elementCount,
const word* elementDefaultValue) const;
// Allocates a new list of the given size for the field at the given index in the reference
// segment, and return a pointer to it. Each element is initialized as a copy of
// elementDefaultValue. As with initStructField(), this should be the default value for the
// *type*, with all-null references.
ListBuilder getListField(WireReferenceCount refIndex, const word* defaultValue) const;
// Gets the already-allocated list field for the given reference index. If the list is not
// already allocated, it is allocated as a deep copy of the given default value (a trusted
// message). If the default value is null, an empty list is used.
StructReader asReader() const;
// Get a StructReader pointing at the same memory.
// Gets a StructReader pointing at the same memory.
private:
SegmentBuilder* segment; // Memory segment in which the struct resides.
......@@ -162,7 +172,7 @@ public:
ListReader getListField(WireReferenceCount refIndex, FieldSize expectedElementSize,
const word* defaultValue) const;
// Get the list field at the given index in the reference segment, or the default value if not
// initialized.
// initialized. The default value is allowed to be null, in which case an empty list is used.
private:
SegmentReader* segment; // Memory segment in which the struct resides.
......@@ -220,13 +230,19 @@ public:
ListBuilder initListElement(
WireReferenceCount index, FieldSize elementSize, ElementCount elementCount) const;
ListBuilder initStructListElement(
WireReferenceCount index, ElementCount elementCount,
FieldNumber fieldCount, WordCount dataSize, WireReferenceCount referenceCount) const;
// Create a new list element of the given size at the given index.
// Create a new list element of the given size at the given index. All elements are initialized
// to zero.
ListBuilder initStructListElement(WireReferenceCount index, ElementCount elementCount,
const word* elementDefaultValue) const;
// Allocates a new list of the given size for the field at the given index in the reference
// segment, and return a pointer to it. Each element is initialized as a copy of
// elementDefaultValue. As with StructBuilder::initStructListElement(), this should be the
// default value for the *type*, with all-null references.
ListBuilder getListElement(WireReferenceCount index, FieldSize elementSize) const;
// Get the existing list element at the given index.
// Get the existing list element at the given index. Returns an empty list if the element is
// not initialized.
ListReader asReader(FieldSize elementSize) const;
// Get a ListReader pointing at the same memory. Use this version only for non-struct lists.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment