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.
......
......@@ -24,6 +24,7 @@
#include "wire-format.h"
#include "message.h"
#include "descriptor.h"
#include <string.h>
#include <limits>
namespace capnproto {
......@@ -138,6 +139,11 @@ struct WireReference {
(static_cast<int>(elementSize) << 29) | (elementCount / ELEMENTS));
}
CAPNPROTO_ALWAYS_INLINE(void setEmptyList(FieldSize elementSize)) {
setTagAndOffset(LIST, 0 * WORDS);
listRef.elementSizeAndCount.set(static_cast<int>(elementSize) << 29);
}
CAPNPROTO_ALWAYS_INLINE(void setInlineCompositeList(WordCount wordCount, word* target)) {
setTagAndOffset(LIST, intervalLength(reinterpret_cast<word*>(this), target));
CAPNPROTO_DEBUG_ASSERT(wordCount < (1 << 29) * WORDS,
......@@ -229,33 +235,160 @@ struct WireHelpers {
return true;
}
// -----------------------------------------------------------------
static CAPNPROTO_ALWAYS_INLINE(
void copyStruct(SegmentBuilder* segment, word* dst, const word* src,
WordCount dataSize, WireReferenceCount referenceCount)) {
memcpy(dst, src, dataSize * BYTES_PER_WORD / BYTES);
const WireReference* srcRefs = reinterpret_cast<const WireReference*>(src + dataSize);
WireReference* dstRefs = reinterpret_cast<WireReference*>(dst + dataSize);
uint n = referenceCount / REFERENCES;
for (uint i = 0; i < n; i++) {
copyMessage(segment, dstRefs + i, srcRefs + i);
}
}
// Not always-inline because it's recursive.
static WireReference* copyMessage(
SegmentBuilder* segment, WireReference* dst, const WireReference* src) {
switch (src->tag()) {
case WireReference::STRUCT: {
if (src->isNull()) {
memset(dst, 0, sizeof(WireReference));
} else {
const word* srcPtr = src->target();
word* dstPtr = allocate(dst, segment, src->structRef.wordSize());
copyStruct(segment, dstPtr, srcPtr, dst->structRef.dataSize.get(),
dst->structRef.refCount.get());
dst->setStruct(dst->structRef.fieldCount.get(), dst->structRef.dataSize.get(),
dst->structRef.refCount.get(), dstPtr);
}
break;
}
case WireReference::LIST: {
switch (src->listRef.elementSize()) {
case FieldSize::VOID:
case FieldSize::BIT:
case FieldSize::BYTE:
case FieldSize::TWO_BYTES:
case FieldSize::FOUR_BYTES:
case FieldSize::EIGHT_BYTES: {
WordCount wordCount = roundUpToWords(
ElementCount64(src->listRef.elementCount()) *
bitsPerElement(src->listRef.elementSize()));
const word* srcPtr = src->target();
word* dstPtr = allocate(dst, segment, wordCount);
memcpy(dstPtr, srcPtr, wordCount * BYTES_PER_WORD / BYTES);
dst->setList(src->listRef.elementSize(), src->listRef.elementCount(), dstPtr);
break;
}
case FieldSize::REFERENCE: {
const WireReference* srcRefs = reinterpret_cast<const WireReference*>(src->target());
WireReference* dstRefs = reinterpret_cast<WireReference*>(
allocate(dst, segment, src->listRef.elementCount() *
(1 * REFERENCES / ELEMENTS) * WORDS_PER_REFERENCE));
uint n = src->listRef.elementCount() / ELEMENTS;
for (uint i = 0; i < n; i++) {
copyMessage(segment, dstRefs + i, srcRefs + i);
}
dst->setList(FieldSize::REFERENCE, src->listRef.elementCount(),
reinterpret_cast<word*>(dstRefs));
break;
}
case FieldSize::INLINE_COMPOSITE: {
const word* srcPtr = src->target();
word* dstPtr = allocate(dst, segment,
src->listRef.inlineCompositeWordCount() + REFERENCE_SIZE_IN_WORDS);
dst->setInlineCompositeList(src->listRef.inlineCompositeWordCount(), dstPtr);
const WireReference* srcTag = reinterpret_cast<const WireReference*>(srcPtr);
memcpy(dstPtr, srcTag, sizeof(WireReference));
srcPtr += REFERENCE_SIZE_IN_WORDS;
dstPtr += REFERENCE_SIZE_IN_WORDS;
CAPNPROTO_ASSERT(srcTag->tag() == WireReference::STRUCT,
"INLINE_COMPOSITE of lists is not yet supported.");
uint n = srcTag->tagElementCount() / ELEMENTS;
for (uint i = 0; i < n; i++) {
copyStruct(segment, dstPtr, srcPtr,
srcTag->structRef.dataSize.get(), srcTag->structRef.refCount.get());
srcPtr += srcTag->structRef.wordSize();
dstPtr += srcTag->structRef.wordSize();
}
break;
}
}
break;
}
default:
CAPNPROTO_ASSERT(false, "Copy source message contained unexpected tag.");
break;
}
return dst;
}
// -----------------------------------------------------------------
static CAPNPROTO_ALWAYS_INLINE(StructBuilder initStructReference(
FieldNumber fieldCount, WordCount dataSize, WireReferenceCount referenceCount,
WireReference* ref, SegmentBuilder* segment)) {
if (ref->isNull()) {
// Allocate space for the new struct.
word* ptr = allocate(ref, segment, dataSize + referenceCount * WORDS_PER_REFERENCE);
WireReference* ref, SegmentBuilder* segment, const word* typeDefaultValue)) {
const WireReference* defaultRef = reinterpret_cast<const WireReference*>(typeDefaultValue);
// Allocate space for the new struct.
word* ptr = allocate(ref, segment, defaultRef->structRef.wordSize());
// Copy over the data segment from the default value. We don't have to copy the reference
// segment because it is presumed to be all-null.
memcpy(ptr, defaultRef->target(),
defaultRef->structRef.dataSize.get() * BYTES_PER_WORD / BYTES);
// Initialize the reference.
ref->setStruct(defaultRef->structRef.fieldCount.get(), defaultRef->structRef.dataSize.get(),
defaultRef->structRef.refCount.get(), ptr);
// Build the StructBuilder.
return StructBuilder(segment, ptr,
reinterpret_cast<WireReference*>(ptr + defaultRef->structRef.dataSize.get()));
}
// Initialize the reference.
ref->setStruct(fieldCount, dataSize, referenceCount, ptr);
static CAPNPROTO_ALWAYS_INLINE(StructBuilder getStructReference(
WireReference* ref, SegmentBuilder* segment, const word* defaultValue)) {
const WireReference* defaultRef = reinterpret_cast<const WireReference*>(defaultValue);
// Build the StructBuilder.
return StructBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr + dataSize));
if (ref->isNull()) {
ref = copyMessage(segment, ref, defaultRef);
} else {
followFars(ref, segment);
CAPNPROTO_DEBUG_ASSERT(ref->tag() == WireReference::STRUCT,
"Called getStruct{Field,Element}() but existing reference is not a struct.");
CAPNPROTO_DEBUG_ASSERT(ref->structRef.fieldCount.get() == fieldCount,
CAPNPROTO_DEBUG_ASSERT(
ref->structRef.fieldCount.get() == defaultRef->structRef.fieldCount.get(),
"Trying to update struct with incorrect field count.");
CAPNPROTO_DEBUG_ASSERT(ref->structRef.dataSize.get() == dataSize,
CAPNPROTO_DEBUG_ASSERT(
ref->structRef.dataSize.get() == defaultRef->structRef.dataSize.get(),
"Trying to update struct with incorrect data size.");
CAPNPROTO_DEBUG_ASSERT(ref->structRef.refCount.get() == referenceCount,
CAPNPROTO_DEBUG_ASSERT(
ref->structRef.refCount.get() == defaultRef->structRef.refCount.get(),
"Trying to update struct with incorrect reference count.");
word* ptr = ref->target();
return StructBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr + dataSize));
}
word* ptr = ref->target();
return StructBuilder(segment, ptr,
reinterpret_cast<WireReference*>(ptr + defaultRef->structRef.dataSize.get()));
}
static CAPNPROTO_ALWAYS_INLINE(ListBuilder initListReference(
......@@ -280,8 +413,10 @@ struct WireHelpers {
static CAPNPROTO_ALWAYS_INLINE(ListBuilder initStructListReference(
WireReference* ref, SegmentBuilder* segment, ElementCount elementCount,
FieldNumber fieldCount, WordCount dataSize, WireReferenceCount referenceCount)) {
auto wordsPerElement = (dataSize + referenceCount * WORDS_PER_REFERENCE) / ELEMENTS;
const word* elementDefaultValue)) {
const WireReference* defaultRef = reinterpret_cast<const WireReference*>(elementDefaultValue);
auto wordsPerElement = defaultRef->structRef.wordSize() / ELEMENTS;
// Allocate the list, prefixed by a single WireReference.
WordCount wordCount = elementCount * wordsPerElement;
......@@ -293,24 +428,44 @@ struct WireHelpers {
// Initialize the list tag.
reinterpret_cast<WireReference*>(ptr)->setStructTag(
fieldCount, dataSize, referenceCount, elementCount);
defaultRef->structRef.fieldCount.get(),
defaultRef->structRef.dataSize.get(),
defaultRef->structRef.refCount.get(),
elementCount);
ptr += REFERENCE_SIZE_IN_WORDS;
// Initialize the elements. We only have to copy the data segments, as the reference segment
// in a struct type default value is always all-null.
ByteCount elementDataByteSize = defaultRef->structRef.dataSize.get() * BYTES_PER_WORD;
const word* defaultData = defaultRef->target();
word* elementPtr = ptr;
uint n = elementCount / ELEMENTS;
for (uint i = 0; i < n; i++) {
memcpy(elementPtr, defaultData, elementDataByteSize / BYTES);
elementPtr += 1 * ELEMENTS * wordsPerElement;
}
// Build the ListBuilder.
return ListBuilder(segment, ptr + REFERENCE_SIZE_IN_WORDS, elementCount);
return ListBuilder(segment, ptr, elementCount);
}
static CAPNPROTO_ALWAYS_INLINE(ListBuilder getWritableListReference(
FieldSize elementSize, WireReference* ref, SegmentBuilder* segment)) {
if (ref->isNull()) {
return ListBuilder(segment, nullptr, 0 * ELEMENTS);
}
WireReference* ref, SegmentBuilder* segment, const word* defaultValue)) {
const WireReference* defaultRef = reinterpret_cast<const WireReference*>(defaultValue);
followFars(ref, segment);
if (ref->isNull()) {
if (defaultValue == nullptr) {
return ListBuilder(segment, nullptr, 0 * ELEMENTS);
}
ref = copyMessage(segment, ref, defaultRef);
} else {
followFars(ref, segment);
CAPNPROTO_ASSERT(ref->tag() == WireReference::LIST,
"Called getList{Field,Element}() but existing reference is not a list.");
CAPNPROTO_ASSERT(ref->tag() == WireReference::LIST,
"Called getList{Field,Element}() but existing reference is not a list.");
}
if (elementSize == FieldSize::INLINE_COMPOSITE) {
if (ref->listRef.elementSize() == FieldSize::INLINE_COMPOSITE) {
// Read the tag to get the actual element count.
WireReference* tag = reinterpret_cast<WireReference*>(ref->target());
CAPNPROTO_ASSERT(tag->tag() == WireReference::STRUCT,
......@@ -379,7 +534,11 @@ struct WireHelpers {
if (ref == nullptr || ref->isNull()) {
useDefault:
segment = nullptr;
ref = reinterpret_cast<const WireReference*>(defaultValue);
if (defaultValue == nullptr) {
return ListReader(nullptr, nullptr, 0 * ELEMENTS, 0 * BITS / ELEMENTS, recursionLimit - 1);
} else {
ref = reinterpret_cast<const WireReference*>(defaultValue);
}
} else if (segment != nullptr) {
if (CAPNPROTO_EXPECT_FALSE(recursionLimit == 0)) {
segment->getMessage()->reportInvalidData(
......@@ -553,19 +712,20 @@ struct WireHelpers {
// =======================================================================================
StructBuilder StructBuilder::initRoot(SegmentBuilder* segment, word* location,
FieldNumber fieldCount, WordCount dataSize, WireReferenceCount referenceCount) {
StructBuilder StructBuilder::initRoot(
SegmentBuilder* segment, word* location, const word* defaultValue) {
return WireHelpers::initStructReference(
fieldCount, dataSize, referenceCount,
reinterpret_cast<WireReference*>(location), segment);
reinterpret_cast<WireReference*>(location), segment, defaultValue);
}
StructBuilder StructBuilder::initStructField(
WireReferenceCount refIndex, const word* typeDefaultValue) const {
return WireHelpers::initStructReference(references + refIndex, segment, typeDefaultValue);
}
StructBuilder StructBuilder::getStructField(
WireReferenceCount refIndex, FieldNumber fieldCount,
WordCount dataSize, WireReferenceCount referenceCount) const {
return WireHelpers::initStructReference(
fieldCount, dataSize, referenceCount,
references + refIndex, segment);
WireReferenceCount refIndex, const word* defaultValue) const {
return WireHelpers::getStructReference(references + refIndex, segment, defaultValue);
}
ListBuilder StructBuilder::initListField(
......@@ -577,15 +737,15 @@ ListBuilder StructBuilder::initListField(
ListBuilder StructBuilder::initStructListField(
WireReferenceCount refIndex, ElementCount elementCount,
FieldNumber fieldCount, WordCount dataSize, WireReferenceCount referenceCount) const {
const word* elementDefaultValue) const {
return WireHelpers::initStructListReference(
references + refIndex, segment,
elementCount, fieldCount, dataSize, referenceCount);
references + refIndex, segment, elementCount, elementDefaultValue);
}
ListBuilder StructBuilder::getListField(WireReferenceCount refIndex, FieldSize elementSize) const {
ListBuilder StructBuilder::getListField(
WireReferenceCount refIndex, const word* defaultValue) const {
return WireHelpers::getWritableListReference(
elementSize, references + refIndex, segment);
references + refIndex, segment, defaultValue);
}
StructReader StructBuilder::asReader() const {
......@@ -646,16 +806,15 @@ ListBuilder ListBuilder::initListElement(
}
ListBuilder ListBuilder::initStructListElement(
WireReferenceCount index, ElementCount elementCount,
FieldNumber fieldCount, WordCount dataSize, WireReferenceCount referenceCount) const {
WireReferenceCount index, ElementCount elementCount, const word* elementDefaultValue) const {
return WireHelpers::initStructListReference(
reinterpret_cast<WireReference*>(ptr) + index, segment,
elementCount, fieldCount, dataSize, referenceCount);
elementCount, elementDefaultValue);
}
ListBuilder ListBuilder::getListElement(WireReferenceCount index, FieldSize elementSize) const {
return WireHelpers::getWritableListReference(
elementSize, reinterpret_cast<WireReference*>(ptr) + index, segment);
reinterpret_cast<WireReference*>(ptr) + index, segment, nullptr);
}
ListReader ListBuilder::asReader(FieldSize elementSize) const {
......
......@@ -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