Commit edad34c4 authored by Kenton Varda's avatar Kenton Varda

Initialize from default values.

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