Commit 8b7e9096 authored by Kenton Varda's avatar Kenton Varda

Lists working.

parent 271c4728
...@@ -39,27 +39,107 @@ TEST(Encoding, Simple) { ...@@ -39,27 +39,107 @@ TEST(Encoding, Simple) {
EXPECT_EQ(1234, builder.getA()); EXPECT_EQ(1234, builder.getA());
EXPECT_EQ(-1, builder.getB()); EXPECT_EQ(-1, builder.getB());
EXPECT_EQ(200, builder.getC()); EXPECT_EQ(200, builder.getC());
ASSERT_EQ(0, builder.getNums().size()); ASSERT_EQ(0u, builder.getNums().size());
builder.setA(321); builder.setA(321);
builder.setB(45); builder.setB(45);
builder.setC(67); builder.setC(67);
builder.initD().setX(55.25); builder.initD().setX(55.25);
List<int32_t>::Builder listBuilder = builder.initNums(5); {
ASSERT_EQ(5, listBuilder.size()); List<int32_t>::Builder listBuilder = builder.initNums(5);
listBuilder[0] = 12; ASSERT_EQ(5u, listBuilder.size());
listBuilder[1] = 34; listBuilder.set(0, 12);
listBuilder[2] = 56; listBuilder.set(1, 34);
listBuilder[3] = 78; listBuilder.set(2, 56);
listBuilder[4] = 90; listBuilder.set(3, 78);
listBuilder.set(4, 90);
EXPECT_EQ(12, listBuilder[0]);
EXPECT_EQ(34, listBuilder[1]);
EXPECT_EQ(56, listBuilder[2]);
EXPECT_EQ(78, listBuilder[3]);
EXPECT_EQ(90, listBuilder[4]);
{
int sum = 0;
for (int32_t i: listBuilder) {
sum += i;
}
EXPECT_EQ(12 + 34 + 56 + 78 + 90, sum);
}
}
{
List<Bar>::Builder structListBuilder = builder.initBars(3);
ASSERT_EQ(3u, structListBuilder.size());
structListBuilder[0].setX(123);
structListBuilder[1].setX(456);
structListBuilder[2].setX(789);
EXPECT_EQ(123, structListBuilder[0].getX());
EXPECT_EQ(456, structListBuilder[1].getX());
EXPECT_EQ(789, structListBuilder[2].getX());
{
double sum = 0;
for (auto bar: structListBuilder) {
sum += bar.getX();
}
EXPECT_EQ(123 + 456 + 789, sum);
}
}
{ {
int sum = 0; List<Bar>::Builder structListBuilder = builder.getBars();
for (int32_t i: listBuilder) { ASSERT_EQ(3u, structListBuilder.size());
sum += i;
EXPECT_EQ(123, structListBuilder[0].getX());
EXPECT_EQ(456, structListBuilder[1].getX());
EXPECT_EQ(789, structListBuilder[2].getX());
{
double sum = 0;
for (auto bar: structListBuilder) {
sum += bar.getX();
}
EXPECT_EQ(123 + 456 + 789, sum);
} }
EXPECT_EQ(12 + 34 + 56 + 78 + 90, sum); }
{
List<List<int32_t>>::Builder listListBuilder = builder.initPrimListList(2);
ASSERT_EQ(2u, listListBuilder.size());
List<int32_t>::Builder sublist = listListBuilder.init(0, 2);
ASSERT_EQ(2u, sublist.size());
sublist.set(0, 1234);
sublist.set(1, 5678);
sublist = listListBuilder.init(1, 4);
ASSERT_EQ(4u, sublist.size());
sublist.set(0, 21);
sublist.set(1, 43);
sublist.set(2, 65);
sublist.set(3, 87);
}
{
List<List<Bar>>::Builder listListBuilder = builder.initStructListList(2);
ASSERT_EQ(2u, listListBuilder.size());
List<Bar>::Builder sublist = listListBuilder.init(0, 2);
ASSERT_EQ(2u, sublist.size());
sublist[0].setX(1234);
sublist[1].setX(5678);
sublist = listListBuilder.init(1, 4);
ASSERT_EQ(4u, sublist.size());
sublist[0].setX(21);
sublist[1].setX(43);
sublist[2].setX(65);
sublist[3].setX(87);
} }
EXPECT_EQ(321, builder.getA()); EXPECT_EQ(321, builder.getA());
...@@ -75,20 +155,73 @@ TEST(Encoding, Simple) { ...@@ -75,20 +155,73 @@ TEST(Encoding, Simple) {
EXPECT_EQ(67, reader.getC()); EXPECT_EQ(67, reader.getC());
EXPECT_EQ(55.25, reader.getD().getX()); EXPECT_EQ(55.25, reader.getD().getX());
List<int32_t>::Reader listReader = reader.getNums(); {
ASSERT_EQ(5, listReader.size()); List<int32_t>::Reader listReader = reader.getNums();
EXPECT_EQ(12, listReader[0]); ASSERT_EQ(5u, listReader.size());
EXPECT_EQ(34, listReader[1]); EXPECT_EQ(12, listReader[0]);
EXPECT_EQ(56, listReader[2]); EXPECT_EQ(34, listReader[1]);
EXPECT_EQ(78, listReader[3]); EXPECT_EQ(56, listReader[2]);
EXPECT_EQ(90, listReader[4]); EXPECT_EQ(78, listReader[3]);
EXPECT_EQ(90, listReader[4]);
{
int sum = 0;
for (int32_t i: listReader) {
sum += i;
}
EXPECT_EQ(12 + 34 + 56 + 78 + 90, sum);
}
}
{ {
int sum = 0; List<Bar>::Reader structListReader = reader.getBars();
for (int32_t i: listReader) { ASSERT_EQ(3u, structListReader.size());
sum += i;
EXPECT_EQ(123, structListReader[0].getX());
EXPECT_EQ(456, structListReader[1].getX());
EXPECT_EQ(789, structListReader[2].getX());
{
double sum = 0;
for (auto bar: structListReader) {
sum += bar.getX();
}
EXPECT_EQ(123 + 456 + 789, sum);
} }
EXPECT_EQ(12 + 34 + 56 + 78 + 90, sum); }
{
List<List<int32_t>>::Reader listListReader = reader.getPrimListList();
ASSERT_EQ(2u, listListReader.size());
List<int32_t>::Reader sublist = listListReader[0];
ASSERT_EQ(2u, sublist.size());
EXPECT_EQ(1234, sublist[0]);
EXPECT_EQ(5678, sublist[1]);
sublist = listListReader[1];
ASSERT_EQ(4u, sublist.size());
EXPECT_EQ(21, sublist[0]);
EXPECT_EQ(43, sublist[1]);
EXPECT_EQ(65, sublist[2]);
EXPECT_EQ(87, sublist[3]);
}
{
List<List<Bar>>::Reader listListReader = reader.getStructListList();
ASSERT_EQ(2u, listListReader.size());
List<Bar>::Reader sublist = listListReader[0];
ASSERT_EQ(2u, sublist.size());
EXPECT_EQ(1234, sublist[0].getX());
EXPECT_EQ(5678, sublist[1].getX());
sublist = listListReader[1];
ASSERT_EQ(4u, sublist.size());
EXPECT_EQ(21, sublist[0].getX());
EXPECT_EQ(43, sublist[1].getX());
EXPECT_EQ(65, sublist[2].getX());
EXPECT_EQ(87, sublist[3].getX());
} }
} }
......
...@@ -25,9 +25,17 @@ ...@@ -25,9 +25,17 @@
#define CAPNPROTO_LIST_H_ #define CAPNPROTO_LIST_H_
#include "wire-format.h" #include "wire-format.h"
#include "descriptor.h" // only for FieldSize; TODO: Eliminate this
namespace capnproto { namespace capnproto {
namespace internal {
template <typename T> struct IsPrimitive;
} // namespace internal
template <typename T, bool isPrimitive = internal::IsPrimitive<T>::value>
struct List;
namespace internal { namespace internal {
template <typename T> struct IsPrimitive { static constexpr bool value = false; }; template <typename T> struct IsPrimitive { static constexpr bool value = false; };
...@@ -44,6 +52,27 @@ template <> struct IsPrimitive<uint32_t> { static constexpr bool value = true; } ...@@ -44,6 +52,27 @@ template <> struct IsPrimitive<uint32_t> { static constexpr bool value = true; }
template <> struct IsPrimitive<uint64_t> { static constexpr bool value = true; }; template <> struct IsPrimitive<uint64_t> { static constexpr bool value = true; };
template <> struct IsPrimitive<float> { static constexpr bool value = true; }; template <> struct IsPrimitive<float> { static constexpr bool value = true; };
template <> struct IsPrimitive<double> { static constexpr bool value = true; }; template <> struct IsPrimitive<double> { static constexpr bool value = true; };
template <typename T, bool b> struct IsPrimitive<List<T, b>> {
static constexpr bool value = IsPrimitive<T>::value;
};
template <typename T> struct FieldSizeForType { static constexpr FieldSize value = FieldSize::INLINE_COMPOSITE; };
template <> struct FieldSizeForType<void> { static constexpr FieldSize value = FieldSize::VOID; };
template <> struct FieldSizeForType<bool> { static constexpr FieldSize value = FieldSize::BIT; };
template <> struct FieldSizeForType<int8_t> { static constexpr FieldSize value = FieldSize::BYTE; };
template <> struct FieldSizeForType<int16_t> { static constexpr FieldSize value = FieldSize::TWO_BYTES; };
template <> struct FieldSizeForType<int32_t> { static constexpr FieldSize value = FieldSize::FOUR_BYTES; };
template <> struct FieldSizeForType<int64_t> { static constexpr FieldSize value = FieldSize::EIGHT_BYTES; };
template <> struct FieldSizeForType<uint8_t> { static constexpr FieldSize value = FieldSize::BYTE; };
template <> struct FieldSizeForType<uint16_t> { static constexpr FieldSize value = FieldSize::TWO_BYTES; };
template <> struct FieldSizeForType<uint32_t> { static constexpr FieldSize value = FieldSize::FOUR_BYTES; };
template <> struct FieldSizeForType<uint64_t> { static constexpr FieldSize value = FieldSize::EIGHT_BYTES; };
template <> struct FieldSizeForType<float> { static constexpr FieldSize value = FieldSize::FOUR_BYTES; };
template <> struct FieldSizeForType<double> { static constexpr FieldSize value = FieldSize::EIGHT_BYTES; };
template <typename T, bool b> struct FieldSizeForType<List<T, b>> {
static constexpr FieldSize value = FieldSize::REFERENCE;
};
template<typename T> constexpr T&& move(T& t) noexcept { return static_cast<T&&>(t); } template<typename T> constexpr T&& move(T& t) noexcept { return static_cast<T&&>(t); }
// Like std::move. Unfortunately, #including <utility> brings in tons of unnecessary stuff. // Like std::move. Unfortunately, #including <utility> brings in tons of unnecessary stuff.
...@@ -64,15 +93,17 @@ private: ...@@ -64,15 +93,17 @@ private:
T value; T value;
}; };
template <typename Container, typename Element, typename Reference> template <typename Container, typename Element>
class IndexingIterator { class IndexingIterator {
public: public:
IndexingIterator() = default; IndexingIterator() = default;
inline Reference operator*() { return (*container)[index]; } inline Element operator*() { return (*container)[index]; }
inline Reference operator->() { return TemporaryPointer<Element>((*container)[index]); } inline TemporaryPointer<Element> operator->() {
inline Reference operator[]( int off) { return (*container)[index]; } return TemporaryPointer<Element>((*container)[index]);
inline Reference operator[](uint off) { return (*container)[index]; } }
inline Element operator[]( int off) { return (*container)[index]; }
inline Element operator[](uint off) { return (*container)[index]; }
inline IndexingIterator& operator++() { ++index; return *this; } inline IndexingIterator& operator++() { ++index; return *this; }
inline IndexingIterator operator++(int) { IndexingIterator other = *this; ++index; return other; } inline IndexingIterator operator++(int) { IndexingIterator other = *this; ++index; return other; }
...@@ -105,14 +136,11 @@ private: ...@@ -105,14 +136,11 @@ private:
uint index; uint index;
friend Container; friend Container;
IndexingIterator(Container* builder, uint index): container(container), index(index) {} inline IndexingIterator(Container* container, uint index): container(container), index(index) {}
}; };
} // namespace internal } // namespace internal
template <typename T, bool isPrimitive = internal::IsPrimitive<T>::value>
struct List;
template <typename T> template <typename T>
struct List<T, true> { struct List<T, true> {
class Reader { class Reader {
...@@ -120,11 +148,10 @@ struct List<T, true> { ...@@ -120,11 +148,10 @@ struct List<T, true> {
Reader() = default; Reader() = default;
inline explicit Reader(internal::ListReader reader): reader(reader) {} inline explicit Reader(internal::ListReader reader): reader(reader) {}
typedef internal::IndexingIterator<Reader, T, T> iterator;
inline T operator[](uint index) { return reader.template getDataElement<T>(index * ELEMENTS); }
inline uint size() { return reader.size() / ELEMENTS; } inline uint size() { return reader.size() / ELEMENTS; }
inline T operator[](uint index) { return reader.template getDataElement<T>(index * ELEMENTS); }
typedef internal::IndexingIterator<Reader, T> iterator;
inline iterator begin() { return iterator(this, 0); } inline iterator begin() { return iterator(this, 0); }
inline iterator end() { return iterator(this, size()); } inline iterator end() { return iterator(this, size()); }
...@@ -137,36 +164,62 @@ struct List<T, true> { ...@@ -137,36 +164,62 @@ struct List<T, true> {
Builder() = default; Builder() = default;
inline explicit Builder(internal::ListBuilder builder): builder(builder) {} inline explicit Builder(internal::ListBuilder builder): builder(builder) {}
class reference { inline uint size() { return builder.size() / ELEMENTS; }
public: inline T operator[](uint index) {
reference() = default; return builder.template getDataElement<T>(index * ELEMENTS);
}
inline void set(uint index, T value) {
// Alas, it is not possible to make operator[] return a reference to which you can assign,
// since the encoded representation does not necessarily match the compiler's representation
// of the type. We can't even return a clever class that implements operator T() and
// operator=() because it will lead to surprising behavior when using type inference (e.g.
// calling a template function with inferred argument types, or using "auto" or "decltype").
builder.template setDataElement<T>(index * ELEMENTS, value);
}
inline operator T() { return (*builder)[index]; } typedef internal::IndexingIterator<Builder, T> iterator;
inline reference& operator=(T value) { inline iterator begin() { return iterator(this, 0); }
builder->builder.template setDataElement<T>(index * ELEMENTS, value); inline iterator end() { return iterator(this, size()); }
return *this;
}
T* operator&() { private:
static_assert(sizeof(T) < 0, internal::ListBuilder builder;
"You can't take the address of a list member because they are not stored in memory " };
"in a directly-usable format."); };
return nullptr;
} template <typename T>
struct List<T, false> {
class Reader {
public:
Reader() = default;
inline explicit Reader(internal::ListReader reader): reader(reader) {}
inline uint size() { return reader.size() / ELEMENTS; }
inline typename T::Reader operator[](uint index) {
return typename T::Reader(reader.getStructElement(index * ELEMENTS, T::DEFAULT.words));
}
private: typedef internal::IndexingIterator<Reader, typename T::Reader> iterator;
Builder* builder; inline iterator begin() { return iterator(this, 0); }
uint index; inline iterator end() { return iterator(this, size()); }
friend class Builder; private:
reference(Builder* builder, uint index): builder(builder), index(index) {} internal::ListReader reader;
}; };
typedef internal::IndexingIterator<Builder, T, reference> iterator; class Builder {
public:
Builder() = default;
inline explicit Builder(internal::ListBuilder builder): builder(builder) {}
inline reference operator[](uint index) { return reference(this, index); }
inline uint size() { return builder.size() / ELEMENTS; } inline uint size() { return builder.size() / ELEMENTS; }
inline typename T::Builder operator[](uint index) {
return typename T::Builder(builder.getStructElement(index * ELEMENTS,
(T::DATA_SIZE + T::REFERENCE_COUNT * WORDS_PER_REFERENCE) / ELEMENTS,
T::DATA_SIZE));
}
typedef internal::IndexingIterator<Builder, typename T::Builder> iterator;
inline iterator begin() { return iterator(this, 0); } inline iterator begin() { return iterator(this, 0); }
inline iterator end() { return iterator(this, size()); } inline iterator end() { return iterator(this, size()); }
...@@ -176,19 +229,19 @@ struct List<T, true> { ...@@ -176,19 +229,19 @@ struct List<T, true> {
}; };
template <typename T> template <typename T>
struct List<T, false> { struct List<List<T>, true> {
class Reader { class Reader {
public: public:
Reader() = default; Reader() = default;
inline explicit Reader(internal::ListReader reader): reader(reader) {} inline explicit Reader(internal::ListReader reader): reader(reader) {}
typedef internal::IndexingIterator<Reader, typename T::Reader, typename T::Reader> iterator;
inline typename T::Reader operator[](uint index) {
return typename T::Reader(reader.getStructElement(index * ELEMENTS, T::DEFAULT.words));
}
inline uint size() { return reader.size() / ELEMENTS; } inline uint size() { return reader.size() / ELEMENTS; }
inline typename List<T>::Reader operator[](uint index) {
return typename List<T>::Reader(reader.getListElement(index * REFERENCES,
internal::FieldSizeForType<T>::value));
}
typedef internal::IndexingIterator<Reader, typename List<T>::Reader> iterator;
inline iterator begin() { return iterator(this, 0); } inline iterator begin() { return iterator(this, 0); }
inline iterator end() { return iterator(this, size()); } inline iterator end() { return iterator(this, size()); }
...@@ -201,38 +254,60 @@ struct List<T, false> { ...@@ -201,38 +254,60 @@ struct List<T, false> {
Builder() = default; Builder() = default;
inline explicit Builder(internal::ListBuilder builder): builder(builder) {} inline explicit Builder(internal::ListBuilder builder): builder(builder) {}
class reference { inline uint size() { return builder.size() / ELEMENTS; }
public: inline typename List<T>::Builder operator[](uint index) {
reference() = default; return typename List<T>::Builder(builder.getListElement(index * REFERENCES));
}
inline typename List<T>::Builder init(uint index, uint size) {
return typename List<T>::Builder(builder.initListElement(
index * REFERENCES, internal::FieldSizeForType<T>::value, size * ELEMENTS));
}
inline operator typename T::Builder() { return (*builder)[index]; } typedef internal::IndexingIterator<Builder, typename List<T>::Builder> iterator;
inline iterator begin() { return iterator(this, 0); }
inline iterator end() { return iterator(this, size()); }
// TODO: operator= to accept ownership transfer. private:
internal::ListBuilder builder;
};
};
template <typename T>
struct List<List<T>, false> {
class Reader {
public:
Reader() = default;
inline explicit Reader(internal::ListReader reader): reader(reader) {}
T* operator&() { inline uint size() { return reader.size() / ELEMENTS; }
static_assert(sizeof(T) < 0, inline typename List<T>::Reader operator[](uint index) {
"You can't take the address of a list member because they are not stored in memory " return typename List<T>::Reader(reader.getListElement(index * REFERENCES,
"in a directly-usable format."); internal::FieldSizeForType<T>::value));
return nullptr; }
}
private: typedef internal::IndexingIterator<Reader, typename List<T>::Reader> iterator;
Builder* builder; inline iterator begin() { return iterator(this, 0); }
uint index; inline iterator end() { return iterator(this, size()); }
friend class Builder; private:
reference(Builder* builder, uint index): builder(builder), index(index) {} internal::ListReader reader;
}; };
typedef internal::IndexingIterator<Builder, typename T::Builder, reference> iterator; class Builder {
public:
Builder() = default;
inline explicit Builder(internal::ListBuilder builder): builder(builder) {}
inline typename T::Builder operator[](uint index) {
return typename T::Builder(builder.getStructElement(index * ELEMENTS,
(T::DATA_SIZE + T::REFERENCE_COUNT * WORDS_PER_REFERENCE) / ELEMENTS,
T::DATA_SIZE));
}
inline uint size() { return builder.size() / ELEMENTS; } inline uint size() { return builder.size() / ELEMENTS; }
inline typename List<T>::Builder operator[](uint index) {
return typename List<T>::Builder(builder.getListElement(index * REFERENCES));
}
inline typename List<T>::Builder init(uint index, uint size) {
return typename List<T>::Builder(builder.initStructListElement(
index * REFERENCES, size * ELEMENTS, T::DEFAULT.words));
}
typedef internal::IndexingIterator<Builder, typename List<T>::Builder> iterator;
inline iterator begin() { return iterator(this, 0); } inline iterator begin() { return iterator(this, 0); }
inline iterator end() { return iterator(this, size()); } inline iterator end() { return iterator(this, size()); }
......
...@@ -200,7 +200,7 @@ static void checkStruct(StructBuilder builder) { ...@@ -200,7 +200,7 @@ static void checkStruct(StructBuilder builder) {
ListBuilder list = builder.getListField(3 * REFERENCES, nullptr); 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);
ASSERT_EQ((i + 1) * ELEMENTS, element.size()); ASSERT_EQ((i + 1) * ELEMENTS, element.size());
for (uint j = 0; j <= i; j++) { for (uint j = 0; j <= i; j++) {
EXPECT_EQ(500u + j, element.getDataElement<uint16_t>(j * ELEMENTS)); EXPECT_EQ(500u + j, element.getDataElement<uint16_t>(j * ELEMENTS));
...@@ -253,7 +253,7 @@ static void checkStruct(StructReader reader) { ...@@ -253,7 +253,7 @@ static void checkStruct(StructReader reader) {
ListReader list = reader.getListField(3 * REFERENCES, FieldSize::REFERENCE, nullptr); ListReader list = reader.getListField(3 * REFERENCES, FieldSize::REFERENCE, 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++) {
ListReader element = list.getListElement(i * REFERENCES, FieldSize::TWO_BYTES, nullptr); ListReader element = list.getListElement(i * REFERENCES, FieldSize::TWO_BYTES);
ASSERT_EQ((i + 1) * ELEMENTS, element.size()); ASSERT_EQ((i + 1) * ELEMENTS, element.size());
for (uint j = 0; j <= i; j++) { for (uint j = 0; j <= i; j++) {
EXPECT_EQ(500u + j, element.getDataElement<uint16_t>(j * ELEMENTS)); EXPECT_EQ(500u + j, element.getDataElement<uint16_t>(j * ELEMENTS));
......
...@@ -863,7 +863,7 @@ ListBuilder ListBuilder::initStructListElement( ...@@ -863,7 +863,7 @@ ListBuilder ListBuilder::initStructListElement(
elementCount, elementDefaultValue); elementCount, elementDefaultValue);
} }
ListBuilder ListBuilder::getListElement(WireReferenceCount index, FieldSize elementSize) const { ListBuilder ListBuilder::getListElement(WireReferenceCount index) const {
return WireHelpers::getWritableListReference( return WireHelpers::getWritableListReference(
reinterpret_cast<WireReference*>(ptr) + index, segment, nullptr); reinterpret_cast<WireReference*>(ptr) + index, segment, nullptr);
} }
...@@ -900,10 +900,10 @@ StructReader ListReader::getStructElement(ElementCount index, const word* defaul ...@@ -900,10 +900,10 @@ StructReader ListReader::getStructElement(ElementCount index, const word* defaul
} }
ListReader ListReader::getListElement( ListReader ListReader::getListElement(
WireReferenceCount index, FieldSize expectedElementSize, const word* defaultValue) const { WireReferenceCount index, FieldSize expectedElementSize) const {
return WireHelpers::readListReference( return WireHelpers::readListReference(
segment, reinterpret_cast<const WireReference*>(ptr) + index, segment, reinterpret_cast<const WireReference*>(ptr) + index,
defaultValue, expectedElementSize, recursionLimit); nullptr, expectedElementSize, recursionLimit);
} }
} // namespace internal } // namespace internal
......
...@@ -240,7 +240,7 @@ public: ...@@ -240,7 +240,7 @@ public:
// elementDefaultValue. As with StructBuilder::initStructListElement(), this should be the // elementDefaultValue. As with StructBuilder::initStructListElement(), this should be the
// default value for the *type*, with all-null references. // default value for the *type*, with all-null references.
ListBuilder getListElement(WireReferenceCount index, FieldSize elementSize) const; ListBuilder getListElement(WireReferenceCount index) const;
// Get the existing list element at the given index. Returns an empty list if the element is // Get the existing list element at the given index. Returns an empty list if the element is
// not initialized. // not initialized.
...@@ -280,8 +280,7 @@ public: ...@@ -280,8 +280,7 @@ public:
StructReader getStructElement(ElementCount index, const word* defaultValue) const; StructReader getStructElement(ElementCount index, const word* defaultValue) const;
// Get the struct element at the given index. // Get the struct element at the given index.
ListReader getListElement(WireReferenceCount index, FieldSize expectedElementSize, ListReader getListElement(WireReferenceCount index, FieldSize expectedElementSize) const;
const word* defaultValue) const;
// Get the list element at the given index. // Get the list element at the given index.
private: private:
......
...@@ -61,30 +61,30 @@ isStruct _ = False ...@@ -61,30 +61,30 @@ isStruct _ = False
isList (ListType _) = True isList (ListType _) = True
isList _ = False isList _ = False
isPrimitiveList (ListType t) = isPrimitive t isNonStructList (ListType t) = not $ isStruct t
isPrimitiveList _ = False isNonStructList _ = False
isStructList (ListType t) = isStruct t isStructList (ListType t) = isStruct t
isStructList _ = False isStructList _ = False
cxxTypeString (BuiltinType BuiltinVoid) = "void" cxxTypeString (BuiltinType BuiltinVoid) = "void"
cxxTypeString (BuiltinType BuiltinBool) = "bool" cxxTypeString (BuiltinType BuiltinBool) = "bool"
cxxTypeString (BuiltinType BuiltinInt8) = "int8_t" cxxTypeString (BuiltinType BuiltinInt8) = " ::int8_t"
cxxTypeString (BuiltinType BuiltinInt16) = "int16_t" cxxTypeString (BuiltinType BuiltinInt16) = " ::int16_t"
cxxTypeString (BuiltinType BuiltinInt32) = "int32_t" cxxTypeString (BuiltinType BuiltinInt32) = " ::int32_t"
cxxTypeString (BuiltinType BuiltinInt64) = "int64_t" cxxTypeString (BuiltinType BuiltinInt64) = " ::int64_t"
cxxTypeString (BuiltinType BuiltinUInt8) = "uint8_t" cxxTypeString (BuiltinType BuiltinUInt8) = " ::uint8_t"
cxxTypeString (BuiltinType BuiltinUInt16) = "uint16_t" cxxTypeString (BuiltinType BuiltinUInt16) = " ::uint16_t"
cxxTypeString (BuiltinType BuiltinUInt32) = "uint32_t" cxxTypeString (BuiltinType BuiltinUInt32) = " ::uint32_t"
cxxTypeString (BuiltinType BuiltinUInt64) = "uint64_t" cxxTypeString (BuiltinType BuiltinUInt64) = " ::uint64_t"
cxxTypeString (BuiltinType BuiltinFloat32) = "float" cxxTypeString (BuiltinType BuiltinFloat32) = "float"
cxxTypeString (BuiltinType BuiltinFloat64) = "double" cxxTypeString (BuiltinType BuiltinFloat64) = "double"
cxxTypeString (BuiltinType BuiltinText) = "TODO" cxxTypeString (BuiltinType BuiltinText) = "TODO"
cxxTypeString (BuiltinType BuiltinData) = "TODO" cxxTypeString (BuiltinType BuiltinData) = "TODO"
cxxTypeString (EnumType desc) = enumName desc cxxTypeString (EnumType desc) = enumName desc -- TODO: full name
cxxTypeString (StructType desc) = structName desc cxxTypeString (StructType desc) = structName desc -- TODO: full name
cxxTypeString (InterfaceType desc) = interfaceName desc cxxTypeString (InterfaceType desc) = interfaceName desc -- TODO: full name
cxxTypeString (ListType t) = concat ["::capnproto::List<", cxxTypeString t, ">"] cxxTypeString (ListType t) = concat [" ::capnproto::List<", cxxTypeString t, ">"]
cxxFieldSizeString Size0 = "VOID"; cxxFieldSizeString Size0 = "VOID";
cxxFieldSizeString Size1 = "BIT"; cxxFieldSizeString Size1 = "BIT";
...@@ -161,7 +161,7 @@ fieldContext parent desc = mkStrContext context where ...@@ -161,7 +161,7 @@ fieldContext parent desc = mkStrContext context where
context "fieldIsPrimitive" = MuBool $ isPrimitive $ fieldType desc context "fieldIsPrimitive" = MuBool $ isPrimitive $ fieldType desc
context "fieldIsStruct" = MuBool $ isStruct $ fieldType desc context "fieldIsStruct" = MuBool $ isStruct $ fieldType desc
context "fieldIsList" = MuBool $ isList $ fieldType desc context "fieldIsList" = MuBool $ isList $ fieldType desc
context "fieldIsPrimitiveList" = MuBool $ isPrimitiveList $ fieldType desc context "fieldIsNonStructList" = MuBool $ isNonStructList $ fieldType desc
context "fieldIsStructList" = MuBool $ isStructList $ fieldType desc context "fieldIsStructList" = MuBool $ isStructList $ fieldType desc
context "fieldDefaultBytes" = context "fieldDefaultBytes" =
case fieldDefaultValue desc >>= defaultValueBytes (fieldType desc) of case fieldDefaultValue desc >>= defaultValueBytes (fieldType desc) of
...@@ -173,12 +173,16 @@ fieldContext parent desc = mkStrContext context where ...@@ -173,12 +173,16 @@ fieldContext parent desc = mkStrContext context where
Just v -> MuVariable $ cxxValueString v Just v -> MuVariable $ cxxValueString v
Nothing -> MuVariable $ cxxDefaultDefault $ fieldType desc Nothing -> MuVariable $ cxxDefaultDefault $ fieldType desc
context "fieldElementSize" = context "fieldElementSize" =
MuVariable $ cxxFieldSizeString $ fieldSize $ elementType $ fieldType desc MuVariable $ cxxFieldSizeString $ elementSize $ elementType $ fieldType desc
context "fieldElementType" =
MuVariable $ cxxTypeString $ elementType $ fieldType desc
context s = parent s context s = parent s
structContext parent desc = mkStrContext context where structContext parent desc = mkStrContext context where
context "structName" = MuVariable $ structName desc context "structName" = MuVariable $ structName desc
context "structFields" = MuList $ map (fieldContext context) $ structFields desc context "structFields" = MuList $ map (fieldContext context) $ structFields desc
context "structDataSize" = MuVariable $ packingDataSize $ structPacking desc
context "structReferenceCount" = MuVariable $ packingReferenceCount $ structPacking desc
context "structChildren" = MuList [] -- TODO context "structChildren" = MuList [] -- TODO
context "structDefault" = MuList [defaultBytesContext context context "structDefault" = MuList [defaultBytesContext context
(encodeMessage (StructType desc) (StructValueDesc []))] (encodeMessage (StructType desc) (StructValueDesc []))]
...@@ -191,7 +195,7 @@ fileContext desc = mkStrContext context where ...@@ -191,7 +195,7 @@ fileContext desc = mkStrContext context where
"CAPNPROTO_INCLUDED_" ++ hashString (fileName desc) "CAPNPROTO_INCLUDED_" ++ hashString (fileName desc)
context "fileNamespaces" = MuList [] -- TODO context "fileNamespaces" = MuList [] -- TODO
context "fileStructs" = MuList $ map (structContext context) $ fileStructs desc context "fileStructs" = MuList $ map (structContext context) $ fileStructs desc
context s = MuVariable $ concat ["@@@", s, "@@@"] context s = error ("Template variable not defined: " ++ s)
headerTemplate :: String headerTemplate :: String
headerTemplate = ByteStringUTF8.toString $(embedFile "src/c++-header.mustache") headerTemplate = ByteStringUTF8.toString $(embedFile "src/c++-header.mustache")
......
...@@ -41,6 +41,9 @@ struct {{structName}} { ...@@ -41,6 +41,9 @@ struct {{structName}} {
struct {{structChildName}}; struct {{structChildName}};
{{/structChildren}} {{/structChildren}}
static constexpr ::capnproto::WordCount DATA_SIZE = {{structDataSize}} * ::capnproto::WORDS;
static constexpr ::capnproto::WireReferenceCount REFERENCE_COUNT =
{{structReferenceCount}} * ::capnproto::REFERENCES;
{{#structDefault}} {{#structDefault}}
static const ::capnproto::internal::AlignedData<{{defaultWordCount}}> DEFAULT; static const ::capnproto::internal::AlignedData<{{defaultWordCount}}> DEFAULT;
{{/structDefault}} {{/structDefault}}
...@@ -91,10 +94,10 @@ public: ...@@ -91,10 +94,10 @@ public:
inline {{fieldType}}::Builder init{{fieldTitleCase}}(); inline {{fieldType}}::Builder init{{fieldTitleCase}}();
inline {{fieldType}}::Builder get{{fieldTitleCase}}(); inline {{fieldType}}::Builder get{{fieldTitleCase}}();
{{/fieldIsStruct}} {{/fieldIsStruct}}
{{#fieldIsPrimitiveList}} {{#fieldIsNonStructList}}
inline {{fieldType}}::Builder init{{fieldTitleCase}}(unsigned int size); inline {{fieldType}}::Builder init{{fieldTitleCase}}(unsigned int size);
inline {{fieldType}}::Builder get{{fieldTitleCase}}(); inline {{fieldType}}::Builder get{{fieldTitleCase}}();
{{/fieldIsPrimitiveList}} {{/fieldIsNonStructList}}
{{#fieldIsStructList}} {{#fieldIsStructList}}
inline {{fieldType}}::Builder init{{fieldTitleCase}}(unsigned int size); inline {{fieldType}}::Builder init{{fieldTitleCase}}(unsigned int size);
inline {{fieldType}}::Builder get{{fieldTitleCase}}(); inline {{fieldType}}::Builder get{{fieldTitleCase}}();
...@@ -160,7 +163,7 @@ inline {{fieldType}}::Builder {{structName}}::Builder::get{{fieldTitleCase}}() { ...@@ -160,7 +163,7 @@ inline {{fieldType}}::Builder {{structName}}::Builder::get{{fieldTitleCase}}() {
{{^fieldDefaultBytes}}{{fieldType}}::DEFAULT.words{{/fieldDefaultBytes}})); {{^fieldDefaultBytes}}{{fieldType}}::DEFAULT.words{{/fieldDefaultBytes}}));
} }
{{/fieldIsStruct}} {{/fieldIsStruct}}
{{#fieldIsPrimitiveList}} {{#fieldIsNonStructList}}
inline {{fieldType}}::Builder {{structName}}::Builder::init{{fieldTitleCase}}(unsigned int size) { inline {{fieldType}}::Builder {{structName}}::Builder::init{{fieldTitleCase}}(unsigned int size) {
return {{fieldType}}::Builder(_builder.initListField( return {{fieldType}}::Builder(_builder.initListField(
{{fieldOffset}} * ::capnproto::REFERENCES, {{fieldOffset}} * ::capnproto::REFERENCES,
...@@ -173,12 +176,12 @@ inline {{fieldType}}::Builder {{structName}}::Builder::get{{fieldTitleCase}}() { ...@@ -173,12 +176,12 @@ inline {{fieldType}}::Builder {{structName}}::Builder::get{{fieldTitleCase}}() {
{{#fieldDefaultBytes}}DEFAULT_{{fieldUpperCase}}.words{{/fieldDefaultBytes}} {{#fieldDefaultBytes}}DEFAULT_{{fieldUpperCase}}.words{{/fieldDefaultBytes}}
{{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}})); {{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}}));
} }
{{/fieldIsPrimitiveList}} {{/fieldIsNonStructList}}
{{#fieldIsStructList}} {{#fieldIsStructList}}
inline {{fieldType}}::Builder {{structName}}::Builder::init{{fieldTitleCase}}(unsigned int size) { inline {{fieldType}}::Builder {{structName}}::Builder::init{{fieldTitleCase}}(unsigned int size) {
return {{fieldType}}::Builder(_builder.initStructListField( return {{fieldType}}::Builder(_builder.initStructListField(
{{fieldOffset}} * ::capnproto::REFERENCES, size * ::capnproto::ELEMENTS, {{fieldOffset}} * ::capnproto::REFERENCES, size * ::capnproto::ELEMENTS,
{{fieldType}}::DEFAULT.words)); {{fieldElementType}}::DEFAULT.words));
} }
inline {{fieldType}}::Builder {{structName}}::Builder::get{{fieldTitleCase}}() { inline {{fieldType}}::Builder {{structName}}::Builder::get{{fieldTitleCase}}() {
return {{fieldType}}::Builder(_builder.getListField( return {{fieldType}}::Builder(_builder.getListField(
......
...@@ -32,6 +32,8 @@ namespace {{namespaceName}} { ...@@ -32,6 +32,8 @@ namespace {{namespaceName}} {
{{/fileNamespaces}} {{/fileNamespaces}}
{{#fileStructs}} {{#fileStructs}}
constexpr ::capnproto::WordCount {{structName}}::DATA_SIZE;
constexpr ::capnproto::WireReferenceCount {{structName}}::REFERENCE_COUNT;
{{#structDefault}} {{#structDefault}}
const ::capnproto::internal::AlignedData<{{defaultWordCount}}> {{structName}}::DEFAULT = { const ::capnproto::internal::AlignedData<{{defaultWordCount}}> {{structName}}::DEFAULT = {
{ {{defaultByteList}} } { {{defaultByteList}} }
......
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