Commit 20b1ea55 authored by Kenton Varda's avatar Kenton Varda

Encoding test. Bug fixes. It works.

parent b4f80598
...@@ -42,7 +42,7 @@ TEST(Blob, Text) { ...@@ -42,7 +42,7 @@ TEST(Blob, Text) {
std::string str = "foo"; std::string str = "foo";
Text::Reader text = str; Text::Reader text = str;
EXPECT_STREQ("foo", text); EXPECT_EQ("foo", text);
EXPECT_STREQ("foo", text.c_str()); EXPECT_STREQ("foo", text.c_str());
EXPECT_STREQ("foo", text.data()); EXPECT_STREQ("foo", text.data());
EXPECT_EQ(3u, text.size()); EXPECT_EQ(3u, text.size());
...@@ -51,14 +51,14 @@ TEST(Blob, Text) { ...@@ -51,14 +51,14 @@ TEST(Blob, Text) {
EXPECT_EQ("foo", str2); EXPECT_EQ("foo", str2);
Text::Reader text2 = "bar"; Text::Reader text2 = "bar";
EXPECT_STREQ("bar", text2); EXPECT_EQ("bar", text2);
char c[4] = "baz"; char c[4] = "baz";
Text::Reader text3(c); Text::Reader text3(c);
EXPECT_STREQ("baz", text3); EXPECT_EQ("baz", text3);
Text::Builder builder(c, 3); Text::Builder builder(c, 3);
EXPECT_STREQ("baz", builder); EXPECT_EQ("baz", builder);
EXPECT_EQ(Data::Reader("az"), builder.slice(1, 3)); EXPECT_EQ(Data::Reader("az"), builder.slice(1, 3));
} }
...@@ -67,6 +67,7 @@ TEST(Blob, Data) { ...@@ -67,6 +67,7 @@ TEST(Blob, Data) {
std::string str = "foo"; std::string str = "foo";
Data::Reader data = str; Data::Reader data = str;
EXPECT_EQ("foo", data);
EXPECT_EQ(3u, data.size()); EXPECT_EQ(3u, data.size());
std::string str2 = data; std::string str2 = data;
......
...@@ -98,7 +98,11 @@ class Text::Reader: public Data::Reader { ...@@ -98,7 +98,11 @@ class Text::Reader: public Data::Reader {
// Like Data::Reader, but points at NUL-terminated UTF-8 text. The NUL terminator is not counted // Like Data::Reader, but points at NUL-terminated UTF-8 text. The NUL terminator is not counted
// in the size but must be present immediately after the last byte. // in the size but must be present immediately after the last byte.
// //
// TextReader can be implicitly converted to and from const char*. Additionally, it can be // Text::Reader's interface contract is that its data MUST be NUL-terminated. The producer of
// the Text::Reader must guarantee this, so that the consumer need not check. The data SHOULD
// also be valid UTF-8, but this is NOT guaranteed -- the consumer must verify if it cares.
//
// Text::Reader can be implicitly converted to and from const char*. Additionally, it can be
// implicitly converted to any type that can be constructed from a (const char*, size) pair, as // implicitly converted to any type that can be constructed from a (const char*, size) pair, as
// well as from any type which has c_str() and size() methods. Many types follow this pattern, // well as from any type which has c_str() and size() methods. Many types follow this pattern,
// such as std::string. // such as std::string.
...@@ -197,6 +201,20 @@ private: ...@@ -197,6 +201,20 @@ private:
static char nulstr[1]; static char nulstr[1];
}; };
inline bool operator==(const char* a, Data::Reader b) { return Data::Reader(a) == b; }
inline bool operator==(const char* a, Data::Builder b) { return Data::Reader(a) == (Data::Reader)b; }
inline bool operator==(Data::Reader a, Data::Builder b) { return a == (Data::Reader)b; }
inline bool operator==(Data::Builder a, Data::Reader b) { return (Data::Reader)a == b; }
template <typename T>
T& operator<<(T& os, Data::Reader value) { return os.write(value.data(), value.size()); }
template <typename T>
T& operator<<(T& os, Data::Builder value) { return os.write(value.data(), value.size()); }
template <typename T>
T& operator<<(T& os, Text::Reader value) { return os.write(value.data(), value.size()); }
template <typename T>
T& operator<<(T& os, Text::Builder value) { return os.write(value.data(), value.size()); }
} // namespace capnproto } // namespace capnproto
#endif // CAPNPROTO_BLOB_H_ #endif // CAPNPROTO_BLOB_H_
...@@ -44,9 +44,9 @@ echo findProvider file:capnproto-compiler ...@@ -44,9 +44,9 @@ echo findProvider file:capnproto-compiler
read CAPNPC read CAPNPC
if test "$CAPNPC" = ""; then if test "$CAPNPC" = ""; then
echo "error: couldn't find capnproto-compiler." >&2 CAPNPC=capnpc
exit 1
fi fi
# When exception stack traces are needed, add: +RTS -xc -RTS
LD_PRELOAD=$INTERCEPTOR DYLD_FORCE_FLAT_NAMESPACE= DYLD_INSERT_LIBRARIES=$INTERCEPTOR \ LD_PRELOAD=$INTERCEPTOR DYLD_FORCE_FLAT_NAMESPACE= DYLD_INSERT_LIBRARIES=$INTERCEPTOR \
$CAPNPC "$INPUT" 3>&1 4<&0 >&2 $CAPNPC "$INPUT" 3>&1 4<&0 >&2
This diff is collapsed.
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "wire-format.h" #include "wire-format.h"
#include "descriptor.h" // only for FieldSize; TODO: Eliminate this #include "descriptor.h" // only for FieldSize; TODO: Eliminate this
#include <initializer_list>
namespace capnproto { namespace capnproto {
...@@ -40,7 +41,7 @@ namespace internal { ...@@ -40,7 +41,7 @@ namespace internal {
template <typename T> struct IsPrimitive { static constexpr bool value = false; }; template <typename T> struct IsPrimitive { static constexpr bool value = false; };
template <> struct IsPrimitive<void> { static constexpr bool value = true; }; template <> struct IsPrimitive<Void> { static constexpr bool value = true; };
template <> struct IsPrimitive<bool> { static constexpr bool value = true; }; template <> struct IsPrimitive<bool> { static constexpr bool value = true; };
template <> struct IsPrimitive<int8_t> { static constexpr bool value = true; }; template <> struct IsPrimitive<int8_t> { static constexpr bool value = true; };
template <> struct IsPrimitive<int16_t> { static constexpr bool value = true; }; template <> struct IsPrimitive<int16_t> { static constexpr bool value = true; };
...@@ -58,7 +59,7 @@ template <typename T, bool b> struct IsPrimitive<List<T, b>> { ...@@ -58,7 +59,7 @@ template <typename T, bool b> struct IsPrimitive<List<T, b>> {
template <typename T> struct FieldSizeForType { static constexpr FieldSize value = FieldSize::INLINE_COMPOSITE; }; 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<Void> { static constexpr FieldSize value = FieldSize::VOID; };
template <> struct FieldSizeForType<bool> { static constexpr FieldSize value = FieldSize::BIT; }; template <> struct FieldSizeForType<bool> { static constexpr FieldSize value = FieldSize::BIT; };
template <> struct FieldSizeForType<int8_t> { static constexpr FieldSize value = FieldSize::BYTE; }; 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<int16_t> { static constexpr FieldSize value = FieldSize::TWO_BYTES; };
...@@ -182,6 +183,23 @@ struct List<T, true> { ...@@ -182,6 +183,23 @@ struct List<T, true> {
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()); }
template <typename Other>
void copyFrom(const Other& other) {
auto i = other.begin();
auto end = other.end();
uint pos = 0;
for (; i != end && pos < size(); ++i) {
set(pos, *i);
}
CAPNPROTO_DEBUG_ASSERT(pos == size() && i == end, "copyFrom() argument had different size.");
}
void copyFrom(std::initializer_list<T> other) {
CAPNPROTO_DEBUG_ASSERT(other.size() == size(), "copyFrom() argument had different size.");
for (uint i = 0; i < other.size(); i++) {
set(i, other.begin()[i]);
}
}
private: private:
internal::ListBuilder builder; internal::ListBuilder builder;
}; };
...@@ -223,6 +241,11 @@ struct List<T, false> { ...@@ -223,6 +241,11 @@ struct List<T, false> {
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()); }
template <typename Other>
void copyFrom(const Other& other);
void copyFrom(std::initializer_list<typename T::Reader> other);
// TODO
private: private:
internal::ListBuilder builder; internal::ListBuilder builder;
}; };
...@@ -267,6 +290,11 @@ struct List<List<T>, true> { ...@@ -267,6 +290,11 @@ struct List<List<T>, true> {
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()); }
template <typename Other>
void copyFrom(const Other& other);
void copyFrom(std::initializer_list<typename List<T>::Reader> other);
// TODO
private: private:
internal::ListBuilder builder; internal::ListBuilder builder;
}; };
...@@ -311,6 +339,11 @@ struct List<List<T>, false> { ...@@ -311,6 +339,11 @@ struct List<List<T>, false> {
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()); }
template <typename Other>
void copyFrom(const Other& other);
void copyFrom(std::initializer_list<typename List<T>::Reader> other);
// TODO
private: private:
internal::ListBuilder builder; internal::ListBuilder builder;
}; };
...@@ -345,6 +378,9 @@ struct List<Data, false> { ...@@ -345,6 +378,9 @@ struct List<Data, false> {
inline Data::Builder operator[](uint index) { inline Data::Builder operator[](uint index) {
return builder.getDataElement(index * REFERENCES); return builder.getDataElement(index * REFERENCES);
} }
inline void set(uint index, Data::Reader value) {
builder.setDataElement(index * REFERENCES, value);
}
inline Data::Builder init(uint index, uint size) { inline Data::Builder init(uint index, uint size) {
return builder.initDataElement(index * REFERENCES, size * BYTES); return builder.initDataElement(index * REFERENCES, size * BYTES);
} }
...@@ -353,6 +389,23 @@ struct List<Data, false> { ...@@ -353,6 +389,23 @@ struct List<Data, false> {
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()); }
template <typename Other>
void copyFrom(const Other& other) {
auto i = other.begin();
auto end = other.end();
uint pos = 0;
for (; i != end && pos < size(); ++i) {
set(pos, *i);
}
CAPNPROTO_DEBUG_ASSERT(pos == size() && i == end, "copyFrom() argument had different size.");
}
void copyFrom(std::initializer_list<Data::Reader> other) {
CAPNPROTO_DEBUG_ASSERT(other.size() == size(), "copyFrom() argument had different size.");
for (uint i = 0; i < other.size(); i++) {
set(i, other.begin()[i]);
}
}
private: private:
internal::ListBuilder builder; internal::ListBuilder builder;
}; };
...@@ -387,6 +440,9 @@ struct List<Text, false> { ...@@ -387,6 +440,9 @@ struct List<Text, false> {
inline Text::Builder operator[](uint index) { inline Text::Builder operator[](uint index) {
return builder.getTextElement(index * REFERENCES); return builder.getTextElement(index * REFERENCES);
} }
inline void set(uint index, Text::Reader value) {
builder.setTextElement(index * REFERENCES, value);
}
inline Text::Builder init(uint index, uint size) { inline Text::Builder init(uint index, uint size) {
return builder.initTextElement(index * REFERENCES, size * BYTES); return builder.initTextElement(index * REFERENCES, size * BYTES);
} }
...@@ -395,6 +451,23 @@ struct List<Text, false> { ...@@ -395,6 +451,23 @@ struct List<Text, false> {
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()); }
template <typename Other>
void copyFrom(const Other& other) {
auto i = other.begin();
auto end = other.end();
uint pos = 0;
for (; i != end && pos < size(); ++i) {
set(pos, *i);
}
CAPNPROTO_DEBUG_ASSERT(pos == size() && i == end, "copyFrom() argument had different size.");
}
void copyFrom(std::initializer_list<Text::Reader> other) {
CAPNPROTO_DEBUG_ASSERT(other.size() == size(), "copyFrom() argument had different size.");
for (uint i = 0; i < other.size(); i++) {
set(i, other.begin()[i]);
}
}
private: private:
internal::ListBuilder builder; internal::ListBuilder builder;
}; };
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include <memory> #include <memory>
#include "macros.h" #include "macros.h"
#include "type-safety.h" #include "type-safety.h"
#include "wire-format.h"
#include "list.h"
#ifndef CAPNPROTO_MESSAGE_H_ #ifndef CAPNPROTO_MESSAGE_H_
#define CAPNPROTO_MESSAGE_H_ #define CAPNPROTO_MESSAGE_H_
...@@ -95,9 +97,24 @@ public: ...@@ -95,9 +97,24 @@ public:
// TODO: Methods to deal with bundled capabilities. // TODO: Methods to deal with bundled capabilities.
}; };
std::unique_ptr<MessageBuilder> newMallocMessage(WordCount preferredSegmentSize); std::unique_ptr<MessageBuilder> newMallocMessage(WordCount preferredSegmentSize = 512 * WORDS);
// Returns a simple MessageBuilder implementation that uses standard allocation. // Returns a simple MessageBuilder implementation that uses standard allocation.
template <typename T>
struct MessageRoot {
std::unique_ptr<MessageBuilder> message;
typename T::Builder builder;
MessageRoot() = default;
MessageRoot(std::unique_ptr<MessageBuilder> message, typename T::Builder builder)
: message(move(message)), builder(builder) {}
};
template <typename T>
MessageRoot<T> newMallocMessageRoot(WordCount preferredSegmentSize = 512 * WORDS);
// Starts a new message with the given root type backed by a MallocMessage.
// T must be a Cap'n Proto struct type.
class ReadLimiter { class ReadLimiter {
// Used to keep track of how much data has been processed from a message, and cut off further // Used to keep track of how much data has been processed from a message, and cut off further
// processing if and when a particular limit is reached. This is primarily intended to guard // processing if and when a particular limit is reached. This is primarily intended to guard
...@@ -244,6 +261,18 @@ inline WordCount SegmentBuilder::available() { ...@@ -244,6 +261,18 @@ inline WordCount SegmentBuilder::available() {
return intervalLength(pos, end); return intervalLength(pos, end);
} }
// -------------------------------------------------------------------
template <typename T>
MessageRoot<T> newMallocMessageRoot(WordCount preferredSegmentSize) {
std::unique_ptr<MessageBuilder> message = newMallocMessage(preferredSegmentSize);
SegmentBuilder* segment = message->getSegmentWithAvailable(1 * WORDS);
word* rootLocation = segment->allocate(1 * WORDS);
return MessageRoot<T>(move(message),
typename T::Builder(internal::StructBuilder::initRoot(
segment, rootLocation, T::DEFAULT.words)));
}
} // namespace capnproto } // namespace capnproto
#endif // CAPNPROTO_MESSAGE_H_ #endif // CAPNPROTO_MESSAGE_H_
# Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct TestAllTypes {
voidField @0 : Void;
boolField @1 : Bool;
int8Field @2 : Int8;
int16Field @3 : Int16;
int32Field @4 : Int32;
int64Field @5 : Int64;
uInt8Field @6 : UInt8;
uInt16Field @7 : UInt16;
uInt32Field @8 : UInt32;
uInt64Field @9 : UInt64;
float32Field @10 : Float32;
float64Field @11 : Float64;
textField @12 : Text;
dataField @13 : Data;
structField @14 : TestAllTypes;
enumField @15 : Void; # TODO
interfaceField @16 : Void; # TODO
voidList @17 : List(Void);
boolList @18 : List(Bool);
int8List @19 : List(Int8);
int16List @20 : List(Int16);
int32List @21 : List(Int32);
int64List @22 : List(Int64);
uInt8List @23 : List(UInt8);
uInt16List @24 : List(UInt16);
uInt32List @25 : List(UInt32);
uInt64List @26 : List(UInt64);
float32List @27 : List(Float32);
float64List @28 : List(Float64);
textList @29 : List(Text);
dataList @30 : List(Data);
structList @31 : List(TestAllTypes);
enumList @32 : Void; # TODO
interfaceList @33 : Void; # TODO
}
struct TestDefaults {
voidField @0 : Void = void;
boolField @1 : Bool = true;
int8Field @2 : Int8 = -123;
int16Field @3 : Int16 = -12345;
int32Field @4 : Int32 = -12345678;
int64Field @5 : Int64 = -123456789012345;
uInt8Field @6 : UInt8 = 234;
uInt16Field @7 : UInt16 = 45678;
uInt32Field @8 : UInt32 = 3456789012;
uInt64Field @9 : UInt64 = 12345678901234567890;
float32Field @10 : Float32 = 1234.5;
float64Field @11 : Float64 = -123e45;
textField @12 : Text = "foo";
dataField @13 : Data = "bar";
structField @14 : TestAllTypes = (
voidField = void,
boolField = true,
int8Field = -12,
int16Field = 3456,
int32Field = -78901234,
int64Field = 56789012345678,
uInt8Field = 90,
uInt16Field = 1234,
uInt32Field = 56789012,
uInt64Field = 345678901234567890,
float32Field = -1.25e-10,
float64Field = 345,
textField = "baz",
dataField = "qux",
structField = (
textField = "nested",
structField = (textField = "really nested")),
# enumField = TODO
# interfaceField can't have a default
voidList = [void, void, void],
boolList = [false, true, false, true, true],
int8List = [12, -34, -0x80, 0x7f],
int16List = [1234, -5678, -0x8000, 0x7fff],
int32List = [12345678, -90123456, -0x8000000, 0x7ffffff],
int64List = [123456789012345, -678901234567890, -0x8000000000000000, 0x7fffffffffffffff],
uInt8List = [12, 34, 0, 0xff],
uInt16List = [1234, 5678, 0, 0xffff],
uInt32List = [12345678, 90123456, 0, 0xffffffff],
uInt64List = [123456789012345, 678901234567890, 0, 0xffffffffffffffff],
float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37],
float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306],
textList = ["quux", "corge", "grault"],
dataList = ["garply", "waldo", "fred"],
structList = [
(textField = "x structlist 1"),
(textField = "x structlist 2"),
(textField = "x structlist 3")]
# enumList = TODO
# interfaceList can't have a default
);
enumField @15 : Void; # TODO
interfaceField @16 : Void; # TODO
voidList @17 : List(Void) = [void, void, void, void, void, void];
boolList @18 : List(Bool) = [true, false, false, true];
int8List @19 : List(Int8) = [111, -111];
int16List @20 : List(Int16) = [11111, -11111];
int32List @21 : List(Int32) = [111111111, -111111111];
int64List @22 : List(Int64) = [1111111111111111111, -1111111111111111111];
uInt8List @23 : List(UInt8) = [111, 222] ;
uInt16List @24 : List(UInt16) = [33333, 44444];
uInt32List @25 : List(UInt32) = [3333333333];
uInt64List @26 : List(UInt64) = [11111111111111111111];
float32List @27 : List(Float32) = [5555.5, 2222.25];
float64List @28 : List(Float64) = [7777.75, 1111.125];
textList @29 : List(Text) = ["plugh", "xyzzy", "thud"];
dataList @30 : List(Data) = ["oops", "exhausted", "rfc3092"];
structList @31 : List(TestAllTypes) = [
(textField = "structlist 1"),
(textField = "structlist 2"),
(textField = "structlist 3")];
enumList @32 : List(Void); # TODO
interfaceList @33 : List(Void); # TODO
}
...@@ -34,6 +34,14 @@ namespace capnproto { ...@@ -34,6 +34,14 @@ namespace capnproto {
typedef unsigned int uint; typedef unsigned int uint;
enum class Void {
// Type used for Void fields. There is only one value. Using C++'s "void" type creates a bunch
// of issues since it behaves differently from other types.
VOID
};
template <typename T>
inline T& operator<<(T& os, Void) { return os << "void"; }
template <typename T> template <typename T>
struct NoInfer { struct NoInfer {
// Use NoInfer<T>::Type in place of T for a template function parameter to prevent inference of // Use NoInfer<T>::Type in place of T for a template function parameter to prevent inference of
......
...@@ -293,8 +293,7 @@ struct WireHelpers { ...@@ -293,8 +293,7 @@ struct WireHelpers {
const WireReference* srcRefs = reinterpret_cast<const WireReference*>(src + dataSize); const WireReference* srcRefs = reinterpret_cast<const WireReference*>(src + dataSize);
WireReference* dstRefs = reinterpret_cast<WireReference*>(dst + dataSize); WireReference* dstRefs = reinterpret_cast<WireReference*>(dst + dataSize);
uint n = referenceCount / REFERENCES; for (uint i = 0; i < referenceCount / REFERENCES; i++) {
for (uint i = 0; i < n; i++) {
SegmentBuilder* subSegment = segment; SegmentBuilder* subSegment = segment;
WireReference* dstRef = dstRefs + i; WireReference* dstRef = dstRefs + i;
copyMessage(subSegment, dstRef, srcRefs + i); copyMessage(subSegment, dstRef, srcRefs + i);
...@@ -313,11 +312,11 @@ struct WireHelpers { ...@@ -313,11 +312,11 @@ struct WireHelpers {
const word* srcPtr = src->target(); const word* srcPtr = src->target();
word* dstPtr = allocate(dst, segment, src->structRef.wordSize(), WireReference::STRUCT); word* dstPtr = allocate(dst, segment, src->structRef.wordSize(), WireReference::STRUCT);
copyStruct(segment, dstPtr, srcPtr, dst->structRef.dataSize.get(), copyStruct(segment, dstPtr, srcPtr, src->structRef.dataSize.get(),
dst->structRef.refCount.get()); src->structRef.refCount.get());
dst->structRef.set(dst->structRef.fieldCount.get(), dst->structRef.dataSize.get(), dst->structRef.set(src->structRef.fieldCount.get(), src->structRef.dataSize.get(),
dst->structRef.refCount.get()); src->structRef.refCount.get());
return dstPtr; return dstPtr;
} }
} }
...@@ -418,7 +417,7 @@ struct WireHelpers { ...@@ -418,7 +417,7 @@ struct WireHelpers {
reinterpret_cast<WireReference*>(ptr + defaultRef->structRef.dataSize.get())); reinterpret_cast<WireReference*>(ptr + defaultRef->structRef.dataSize.get()));
} }
static CAPNPROTO_ALWAYS_INLINE(StructBuilder getStructReference( static CAPNPROTO_ALWAYS_INLINE(StructBuilder getWritableStructReference(
WireReference* ref, SegmentBuilder* segment, const word* defaultValue)) { WireReference* ref, SegmentBuilder* segment, const word* defaultValue)) {
const WireReference* defaultRef = reinterpret_cast<const WireReference*>(defaultValue); const WireReference* defaultRef = reinterpret_cast<const WireReference*>(defaultValue);
word* ptr; word* ptr;
...@@ -631,7 +630,7 @@ struct WireHelpers { ...@@ -631,7 +630,7 @@ struct WireHelpers {
ptr = followFars(ref, segment); ptr = followFars(ref, segment);
if (CAPNPROTO_EXPECT_FALSE(ptr == nullptr)) { if (CAPNPROTO_EXPECT_FALSE(ptr == nullptr)) {
segment->getMessage()->reportInvalidData( segment->getMessage()->reportInvalidData(
"Message contains out-of-bounds far reference."); "Message contains invalid far reference.");
goto useDefault; goto useDefault;
} }
...@@ -681,7 +680,7 @@ struct WireHelpers { ...@@ -681,7 +680,7 @@ struct WireHelpers {
ptr = followFars(ref, segment); ptr = followFars(ref, segment);
if (CAPNPROTO_EXPECT_FALSE(ptr == nullptr)) { if (CAPNPROTO_EXPECT_FALSE(ptr == nullptr)) {
segment->getMessage()->reportInvalidData( segment->getMessage()->reportInvalidData(
"Message contains out-of-bounds far reference."); "Message contains invalid far reference.");
goto useDefault; goto useDefault;
} }
...@@ -861,7 +860,7 @@ struct WireHelpers { ...@@ -861,7 +860,7 @@ struct WireHelpers {
if (CAPNPROTO_EXPECT_FALSE(ptr == nullptr)) { if (CAPNPROTO_EXPECT_FALSE(ptr == nullptr)) {
segment->getMessage()->reportInvalidData( segment->getMessage()->reportInvalidData(
"Message contains out-of-bounds far reference."); "Message contains invalid far reference.");
goto useDefault; goto useDefault;
} }
...@@ -913,7 +912,7 @@ struct WireHelpers { ...@@ -913,7 +912,7 @@ struct WireHelpers {
if (CAPNPROTO_EXPECT_FALSE(ptr == nullptr)) { if (CAPNPROTO_EXPECT_FALSE(ptr == nullptr)) {
segment->getMessage()->reportInvalidData( segment->getMessage()->reportInvalidData(
"Message contains out-of-bounds far reference."); "Message contains invalid far reference.");
goto useDefault; goto useDefault;
} }
...@@ -923,7 +922,7 @@ struct WireHelpers { ...@@ -923,7 +922,7 @@ struct WireHelpers {
goto useDefault; goto useDefault;
} }
if (CAPNPROTO_EXPECT_FALSE(ref->listRef.elementSize() == FieldSize::BYTE)) { if (CAPNPROTO_EXPECT_FALSE(ref->listRef.elementSize() != FieldSize::BYTE)) {
segment->getMessage()->reportInvalidData( segment->getMessage()->reportInvalidData(
"Message contains list reference of non-bytes where data was expected."); "Message contains list reference of non-bytes where data was expected.");
goto useDefault; goto useDefault;
...@@ -956,7 +955,7 @@ StructBuilder StructBuilder::initStructField( ...@@ -956,7 +955,7 @@ StructBuilder StructBuilder::initStructField(
StructBuilder StructBuilder::getStructField( StructBuilder StructBuilder::getStructField(
WireReferenceCount refIndex, const word* defaultValue) const { WireReferenceCount refIndex, const word* defaultValue) const {
return WireHelpers::getStructReference(references + refIndex, segment, defaultValue); return WireHelpers::getWritableStructReference(references + refIndex, segment, defaultValue);
} }
ListBuilder StructBuilder::initListField( ListBuilder StructBuilder::initListField(
......
...@@ -387,6 +387,11 @@ inline bool StructBuilder::getDataField<bool>(ElementCount offset) const { ...@@ -387,6 +387,11 @@ inline bool StructBuilder::getDataField<bool>(ElementCount offset) const {
return (*reinterpret_cast<uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0; return (*reinterpret_cast<uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0;
} }
template <>
inline Void StructBuilder::getDataField<Void>(ElementCount offset) const {
return Void::VOID;
}
template <typename T> template <typename T>
inline void StructBuilder::setDataField( inline void StructBuilder::setDataField(
ElementCount offset, typename NoInfer<T>::Type value) const { ElementCount offset, typename NoInfer<T>::Type value) const {
...@@ -402,6 +407,9 @@ inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) c ...@@ -402,6 +407,9 @@ inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) c
| (static_cast<uint8_t>(value) << bitnum); | (static_cast<uint8_t>(value) << bitnum);
} }
template <>
inline void StructBuilder::setDataField<Void>(ElementCount offset, Void value) const {}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
template <typename T> template <typename T>
...@@ -428,6 +436,11 @@ inline bool StructReader::getDataField<bool>(ElementCount offset, bool defaultVa ...@@ -428,6 +436,11 @@ inline bool StructReader::getDataField<bool>(ElementCount offset, bool defaultVa
} }
} }
template <>
inline Void StructReader::getDataField<Void>(ElementCount offset, Void defaultValue) const {
return Void::VOID;
}
template <typename T> template <typename T>
T StructReader::getDataFieldCheckingNumber( T StructReader::getDataFieldCheckingNumber(
FieldNumber fieldNumber, ElementCount offset, typename NoInfer<T>::Type defaultValue) const { FieldNumber fieldNumber, ElementCount offset, typename NoInfer<T>::Type defaultValue) const {
...@@ -457,6 +470,12 @@ inline bool StructReader::getDataFieldCheckingNumber<bool>( ...@@ -457,6 +470,12 @@ inline bool StructReader::getDataFieldCheckingNumber<bool>(
} }
} }
template <>
inline Void StructReader::getDataFieldCheckingNumber<Void>(
FieldNumber fieldNumber, ElementCount offset, Void defaultValue) const {
return Void::VOID;
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
inline ElementCount ListBuilder::size() { return elementCount; } inline ElementCount ListBuilder::size() { return elementCount; }
...@@ -473,6 +492,11 @@ inline bool ListBuilder::getDataElement<bool>(ElementCount index) const { ...@@ -473,6 +492,11 @@ inline bool ListBuilder::getDataElement<bool>(ElementCount index) const {
return (*reinterpret_cast<uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0; return (*reinterpret_cast<uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0;
} }
template <>
inline Void ListBuilder::getDataElement<Void>(ElementCount index) const {
return Void::VOID;
}
template <typename T> template <typename T>
inline void ListBuilder::setDataElement(ElementCount index, typename NoInfer<T>::Type value) const { inline void ListBuilder::setDataElement(ElementCount index, typename NoInfer<T>::Type value) const {
reinterpret_cast<WireValue<T>*>(ptr)[index / ELEMENTS].set(value); reinterpret_cast<WireValue<T>*>(ptr)[index / ELEMENTS].set(value);
...@@ -487,6 +511,9 @@ inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) co ...@@ -487,6 +511,9 @@ inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) co
| (static_cast<uint8_t>(value) << bitnum); | (static_cast<uint8_t>(value) << bitnum);
} }
template <>
inline void ListBuilder::setDataElement<Void>(ElementCount index, Void value) const {}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
inline ElementCount ListReader::size() { return elementCount; } inline ElementCount ListReader::size() { return elementCount; }
...@@ -504,6 +531,11 @@ inline bool ListReader::getDataElement<bool>(ElementCount index) const { ...@@ -504,6 +531,11 @@ inline bool ListReader::getDataElement<bool>(ElementCount index) const {
return (*reinterpret_cast<const uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0; return (*reinterpret_cast<const uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0;
} }
template <>
inline Void ListReader::getDataElement<Void>(ElementCount index) const {
return Void::VOID;
}
} // namespace internal } // namespace internal
} // namespace capnproto } // namespace capnproto
......
...@@ -20,6 +20,7 @@ executable capnproto-compiler ...@@ -20,6 +20,7 @@ executable capnproto-compiler
array, array,
data-binary-ieee754, data-binary-ieee754,
filepath filepath
-- When profiling is needed, add: -prof -fprof-auto -osuf p_o -hisuf p_hi
ghc-options: -Wall -fno-warn-missing-signatures ghc-options: -Wall -fno-warn-missing-signatures
other-modules: other-modules:
Lexer, Lexer,
......
...@@ -68,6 +68,9 @@ isList _ = False ...@@ -68,6 +68,9 @@ isList _ = False
isNonStructList (ListType t) = not $ isStruct t isNonStructList (ListType t) = not $ isStruct t
isNonStructList _ = False isNonStructList _ = False
isPrimitiveList (ListType t) = isPrimitive t
isPrimitiveList _ = False
isStructList (ListType t) = isStruct t isStructList (ListType t) = isStruct t
isStructList _ = False isStructList _ = False
...@@ -75,7 +78,7 @@ blobTypeString (BuiltinType BuiltinText) = "Text" ...@@ -75,7 +78,7 @@ blobTypeString (BuiltinType BuiltinText) = "Text"
blobTypeString (BuiltinType BuiltinData) = "Data" blobTypeString (BuiltinType BuiltinData) = "Data"
blobTypeString _ = error "Not a blob." blobTypeString _ = error "Not a blob."
cxxTypeString (BuiltinType BuiltinVoid) = "void" cxxTypeString (BuiltinType BuiltinVoid) = " ::capnproto::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"
...@@ -103,7 +106,7 @@ cxxFieldSizeString Size64 = "EIGHT_BYTES"; ...@@ -103,7 +106,7 @@ cxxFieldSizeString Size64 = "EIGHT_BYTES";
cxxFieldSizeString SizeReference = "REFERENCE"; cxxFieldSizeString SizeReference = "REFERENCE";
cxxFieldSizeString (SizeInlineComposite _ _) = "INLINE_COMPOSITE"; cxxFieldSizeString (SizeInlineComposite _ _) = "INLINE_COMPOSITE";
cxxValueString VoidDesc = error "Can't stringify void value." cxxValueString VoidDesc = " ::capnproto::Void::VOID"
cxxValueString (BoolDesc b) = if b then "true" else "false" cxxValueString (BoolDesc b) = if b then "true" else "false"
cxxValueString (Int8Desc i) = show i cxxValueString (Int8Desc i) = show i
cxxValueString (Int16Desc i) = show i cxxValueString (Int16Desc i) = show i
...@@ -129,7 +132,7 @@ defaultValueBytes t v@(StructValueDesc _) = Just $ encodeMessage t v ...@@ -129,7 +132,7 @@ defaultValueBytes t v@(StructValueDesc _) = Just $ encodeMessage t v
defaultValueBytes t v@(ListDesc _) = Just $ encodeMessage t v defaultValueBytes t v@(ListDesc _) = Just $ encodeMessage t v
defaultValueBytes _ _ = Nothing defaultValueBytes _ _ = Nothing
cxxDefaultDefault (BuiltinType BuiltinVoid) = error "Can't stringify void value." cxxDefaultDefault (BuiltinType BuiltinVoid) = " ::capnproto::Void::VOID"
cxxDefaultDefault (BuiltinType BuiltinBool) = "false" cxxDefaultDefault (BuiltinType BuiltinBool) = "false"
cxxDefaultDefault (BuiltinType BuiltinInt8) = "0" cxxDefaultDefault (BuiltinType BuiltinInt8) = "0"
cxxDefaultDefault (BuiltinType BuiltinInt16) = "0" cxxDefaultDefault (BuiltinType BuiltinInt16) = "0"
...@@ -175,6 +178,7 @@ fieldContext parent desc = mkStrContext context where ...@@ -175,6 +178,7 @@ fieldContext parent desc = mkStrContext context where
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 "fieldIsNonStructList" = MuBool $ isNonStructList $ fieldType desc context "fieldIsNonStructList" = MuBool $ isNonStructList $ fieldType desc
context "fieldIsPrimitiveList" = MuBool $ isPrimitiveList $ 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
......
...@@ -32,7 +32,8 @@ import Token ...@@ -32,7 +32,8 @@ import Token
import Data.Char (isUpper, isLower) import Data.Char (isUpper, isLower)
keywords = keywords =
[ (TrueKeyword, "true") [ (VoidKeyword, "void")
, (TrueKeyword, "true")
, (FalseKeyword, "false") , (FalseKeyword, "false")
, (InKeyword, "in") , (InKeyword, "in")
, (OfKeyword, "of") , (OfKeyword, "of")
...@@ -105,11 +106,16 @@ identifier = do ...@@ -105,11 +106,16 @@ identifier = do
\names into the target language's preferred style." \names into the target language's preferred style."
return (if isTypeName text then TypeIdentifier text else Identifier text) return (if isTypeName text then TypeIdentifier text else Identifier text)
tokenSequence = do
tokens <- many1 locatedToken
endPos <- getPosition
return (TokenSequence tokens endPos)
token :: Parser Token token :: Parser Token
token = keyword token = keyword
<|> identifier <|> identifier
<|> liftM ParenthesizedList (parens (sepBy (many locatedToken) (symbol ","))) <|> liftM ParenthesizedList (parens (sepBy tokenSequence (symbol ",")))
<|> liftM BracketedList (brackets (sepBy (many locatedToken) (symbol ","))) <|> liftM BracketedList (brackets (sepBy tokenSequence (symbol ",")))
<|> liftM toLiteral naturalOrFloat <|> liftM toLiteral naturalOrFloat
<|> liftM LiteralString stringLiteral <|> liftM LiteralString stringLiteral
<|> liftM (const AtSign) (symbol "@") <|> liftM (const AtSign) (symbol "@")
...@@ -126,13 +132,13 @@ statementEnd :: Parser (Maybe [Located Statement]) ...@@ -126,13 +132,13 @@ statementEnd :: Parser (Maybe [Located Statement])
statementEnd = (symbol ";" >>= \_ -> return Nothing) statementEnd = (symbol ";" >>= \_ -> return Nothing)
<|> (braces (many locatedStatement) >>= \statements -> return (Just statements)) <|> (braces (many locatedStatement) >>= \statements -> return (Just statements))
compileStatement :: [Located Token] -> Maybe [Located Statement] -> Statement compileStatement :: TokenSequence -> Maybe [Located Statement] -> Statement
compileStatement tokens Nothing = Line tokens compileStatement tokens Nothing = Line tokens
compileStatement tokens (Just statements) = Block tokens statements compileStatement tokens (Just statements) = Block tokens statements
statement :: Parser Statement statement :: Parser Statement
statement = do statement = do
tokens <- many locatedToken tokens <- tokenSequence
end <- statementEnd end <- statementEnd
return (compileStatement tokens end) return (compileStatement tokens end)
......
...@@ -25,6 +25,7 @@ module Parser (parseFile) where ...@@ -25,6 +25,7 @@ module Parser (parseFile) where
import Text.Parsec hiding (tokens) import Text.Parsec hiding (tokens)
import Text.Parsec.Error(newErrorMessage, Message(Message)) import Text.Parsec.Error(newErrorMessage, Message(Message))
import Text.Parsec.Pos(newPos)
import Text.Printf(printf) import Text.Printf(printf)
import Token import Token
import Grammar import Grammar
...@@ -48,6 +49,7 @@ tokenErrorString Period = "\".\"" ...@@ -48,6 +49,7 @@ tokenErrorString Period = "\".\""
tokenErrorString EqualsSign = "\"=\"" tokenErrorString EqualsSign = "\"=\""
tokenErrorString MinusSign = "\"-\"" tokenErrorString MinusSign = "\"-\""
tokenErrorString ExclamationPoint = "\"!\"" tokenErrorString ExclamationPoint = "\"!\""
tokenErrorString VoidKeyword = "keyword \"void\""
tokenErrorString TrueKeyword = "keyword \"true\"" tokenErrorString TrueKeyword = "keyword \"true\""
tokenErrorString FalseKeyword = "keyword \"false\"" tokenErrorString FalseKeyword = "keyword \"false\""
tokenErrorString InKeyword = "keyword \"in\"" tokenErrorString InKeyword = "keyword \"in\""
...@@ -103,6 +105,7 @@ literalInt = tokenParser matchLiteralInt <?> "integer" ...@@ -103,6 +105,7 @@ literalInt = tokenParser matchLiteralInt <?> "integer"
literalFloat = tokenParser matchLiteralFloat <?> "floating-point number" literalFloat = tokenParser matchLiteralFloat <?> "floating-point number"
literalString = tokenParser matchLiteralString <?> "string" literalString = tokenParser matchLiteralString <?> "string"
literalBool = tokenParser matchLiteralBool <?> "boolean" literalBool = tokenParser matchLiteralBool <?> "boolean"
literalVoid = tokenParser (matchSimpleToken VoidKeyword) <?> "\"void\""
atSign = tokenParser (matchSimpleToken AtSign) <?> "\"@\"" atSign = tokenParser (matchSimpleToken AtSign) <?> "\"@\""
colon = tokenParser (matchSimpleToken Colon) <?> "\":\"" colon = tokenParser (matchSimpleToken Colon) <?> "\":\""
...@@ -238,7 +241,8 @@ fieldDecl statements = do ...@@ -238,7 +241,8 @@ fieldDecl statements = do
negativeFieldValue = liftM (IntegerFieldValue . negate) literalInt negativeFieldValue = liftM (IntegerFieldValue . negate) literalInt
<|> liftM (FloatFieldValue . negate) literalFloat <|> liftM (FloatFieldValue . negate) literalFloat
fieldValue = liftM BoolFieldValue literalBool fieldValue = (literalVoid >> return VoidFieldValue)
<|> liftM BoolFieldValue literalBool
<|> liftM IntegerFieldValue literalInt <|> liftM IntegerFieldValue literalInt
<|> liftM FloatFieldValue literalFloat <|> liftM FloatFieldValue literalFloat
<|> liftM StringFieldValue literalString <|> liftM StringFieldValue literalString
...@@ -302,30 +306,33 @@ failNonFatal :: SourcePos -> String -> TokenParser () ...@@ -302,30 +306,33 @@ failNonFatal :: SourcePos -> String -> TokenParser ()
failNonFatal pos msg = modifyState (newError:) where failNonFatal pos msg = modifyState (newError:) where
newError = newErrorMessage (Message msg) pos newError = newErrorMessage (Message msg) pos
parseList parser items = finish where parseList parser items = do
results = map (parseCollectingErrors parser) items let results = map (parseCollectingErrors parser) items
finish = do modifyState (\old -> concat (old:map extractErrors results))
modifyState (\old -> concat (old:map extractErrors results)) return [ result | Right (result, _) <- results ]
return [ result | Right (result, _) <- results ]
parseBlock :: (Maybe [Located Statement] -> TokenParser Declaration) parseBlock :: (Maybe [Located Statement] -> TokenParser Declaration)
-> [Located Statement] -> TokenParser [Declaration] -> [Located Statement] -> TokenParser [Declaration]
parseBlock parser statements = finish where parseBlock parser statements = do
results = map (parseStatement parser) statements let results = map (parseStatement parser) statements
finish = do modifyState (\old -> concat (old:map extractErrors results))
modifyState (\old -> concat (old:map extractErrors results)) return [ result | Right (result, _) <- results ]
return [ result | Right (result, _) <- results ]
parseCollectingErrors :: TokenParser a -> TokenSequence
parseCollectingErrors :: TokenParser a -> [Located Token] -> Either ParseError (a, [ParseError]) -> Either ParseError (a, [ParseError])
parseCollectingErrors parser tokens = runParser parser' [] "" tokens where parseCollectingErrors parser tokenSequence = runParser parser' [] "" tokens where
TokenSequence tokens endPos = tokenSequence
parser' = do parser' = do
-- Work around Parsec bug: Text.Parsec.Print.token is supposed to produce a parser that -- Work around Parsec bug: Text.Parsec.Print.token is supposed to produce a parser that
-- sets the position by using the provided function to extract it from each token. However, -- sets the position by using the provided function to extract it from each token. However,
-- it doesn't bother to call this function for the *first* token, only subsequent tokens. -- it doesn't bother to call this function for the *first* token, only subsequent tokens.
-- The first token is always assumed to be at 1:1. To fix this, set it manually. -- The first token is always assumed to be at 1:1. To fix this, set it manually.
case tokens of --
Located pos _:_ -> setPosition pos -- TODO: There's still a problem when a parse error occurs at end-of-input: Parsec will
[] -> return () -- report the error at the location of the previous token.
setPosition (case tokens of
Located pos2 _:_ -> pos2
[] -> endPos)
result <- parser result <- parser
eof eof
...@@ -349,4 +356,4 @@ parseFileTokens statements = (decls, errors) where ...@@ -349,4 +356,4 @@ parseFileTokens statements = (decls, errors) where
parseFile :: String -> String -> ([Declaration], [ParseError]) parseFile :: String -> String -> ([Declaration], [ParseError])
parseFile filename text = case parse lexer filename text of parseFile filename text = case parse lexer filename text of
Left e -> ([], [e]) Left e -> ([], [e])
Right tokens -> parseFileTokens tokens Right statements -> parseFileTokens statements
...@@ -122,7 +122,7 @@ data ValueDesc = VoidDesc ...@@ -122,7 +122,7 @@ data ValueDesc = VoidDesc
| ListDesc [ValueDesc] | ListDesc [ValueDesc]
deriving (Show) deriving (Show)
valueString VoidDesc = error "Can't stringify void value." valueString VoidDesc = "void"
valueString (BoolDesc b) = if b then "true" else "false" valueString (BoolDesc b) = if b then "true" else "false"
valueString (Int8Desc i) = show i valueString (Int8Desc i) = show i
valueString (Int16Desc i) = show i valueString (Int16Desc i) = show i
...@@ -156,6 +156,8 @@ data PackingState = PackingState ...@@ -156,6 +156,8 @@ data PackingState = PackingState
, packingReferenceCount :: Integer , packingReferenceCount :: Integer
} }
packingSize PackingState { packingDataSize = ds, packingReferenceCount = rc } = ds + rc
-- Represents the current packing state of a union. The parameters are: -- Represents the current packing state of a union. The parameters are:
-- - The offset of a 64-bit word in the data segment allocated to the union. -- - The offset of a 64-bit word in the data segment allocated to the union.
-- - The offset of a reference allocated to the union. -- - The offset of a reference allocated to the union.
...@@ -416,7 +418,7 @@ descToCode indent (DescField desc) = printf "%s%s@%d%s: %s%s; # %s\n" indent ...@@ -416,7 +418,7 @@ descToCode indent (DescField desc) = printf "%s%s@%d%s: %s%s; # %s\n" indent
SizeReference -> printf "ref[%d]" $ fieldOffset desc SizeReference -> printf "ref[%d]" $ fieldOffset desc
SizeInlineComposite _ _ -> "??" SizeInlineComposite _ _ -> "??"
s -> let s -> let
bits = (sizeInBits s) bits = sizeInBits s
offset = fieldOffset desc offset = fieldOffset desc
in printf "bits[%d, %d)" (offset * bits) ((offset + 1) * bits)) in printf "bits[%d, %d)" (offset * bits) ((offset + 1) * bits))
-- (maybeBlockCode indent $ fieldStatements desc) -- (maybeBlockCode indent $ fieldStatements desc)
......
...@@ -37,13 +37,16 @@ instance Eq a => Eq (Located a) where ...@@ -37,13 +37,16 @@ instance Eq a => Eq (Located a) where
instance Ord a => Ord (Located a) where instance Ord a => Ord (Located a) where
compare (Located _ a) (Located _ b) = compare a b compare (Located _ a) (Located _ b) = compare a b
data TokenSequence = TokenSequence [Located Token] SourcePos deriving(Show, Eq)
data Token = Identifier String data Token = Identifier String
| TypeIdentifier String | TypeIdentifier String
| ParenthesizedList [[Located Token]] | ParenthesizedList [TokenSequence]
| BracketedList [[Located Token]] | BracketedList [TokenSequence]
| LiteralInt Integer | LiteralInt Integer
| LiteralFloat Double | LiteralFloat Double
| LiteralString String | LiteralString String
| VoidKeyword
| TrueKeyword | TrueKeyword
| FalseKeyword | FalseKeyword
| AtSign | AtSign
...@@ -68,6 +71,6 @@ data Token = Identifier String ...@@ -68,6 +71,6 @@ data Token = Identifier String
| OptionKeyword | OptionKeyword
deriving (Show, Eq) deriving (Show, Eq)
data Statement = Line [Located Token] data Statement = Line TokenSequence
| Block [Located Token] [Located Statement] | Block TokenSequence [Located Statement]
deriving (Show) deriving (Show)
...@@ -100,7 +100,7 @@ encodeReferences o size = loop 0 (o + size) where ...@@ -100,7 +100,7 @@ encodeReferences o size = loop 0 (o + size) where
(dataBytes, refBytes, childBytes) = encodeStruct desc assignments 0 (dataBytes, refBytes, childBytes) = encodeStruct desc assignments 0
in (encodeStructReference desc offset, concat [dataBytes, refBytes, childBytes]) in (encodeStructReference desc offset, concat [dataBytes, refBytes, childBytes])
(ListType elementType, ListDesc items) -> (ListType elementType, ListDesc items) ->
(encodeListReference (fieldSize elementType) (genericLength items) offset, (encodeListReference (elementSize elementType) (genericLength items) offset,
encodeList elementType items) encodeList elementType items)
(BuiltinType BuiltinText, TextDesc text) -> let (BuiltinType BuiltinText, TextDesc text) -> let
encoded = (UTF8.encode text ++ [0]) encoded = (UTF8.encode text ++ [0])
...@@ -118,6 +118,20 @@ encodeReferences o size = loop 0 (o + size) where ...@@ -118,6 +118,20 @@ encodeReferences o size = loop 0 (o + size) where
in (genericReplicate (padCount * 8) 0 ++ refs, objects) in (genericReplicate (padCount * 8) 0 ++ refs, objects)
loop idx _ [] = (genericReplicate ((size - idx) * 8) 0, []) loop idx _ [] = (genericReplicate ((size - idx) * 8) 0, [])
encodeStructList :: Integer -> StructDesc -> [[(FieldDesc, ValueDesc)]] -> ([Word8], [Word8])
encodeStructList o desc elements = loop (o + eSize * genericLength elements) elements where
eSize = packingSize $ structPacking desc
loop _ [] = ([], [])
loop offset (element:rest) = let
offsetFromElementEnd = offset - eSize
(dataBytes, refBytes, childBytes) = encodeStruct desc element offsetFromElementEnd
childLen = genericLength childBytes
childWordLen = if mod childLen 8 == 0
then div childLen 8
else error "Child not word-aligned."
(restBytes, restChildren) = loop (offsetFromElementEnd + childWordLen) rest
in (dataBytes ++ refBytes ++ restBytes, childBytes ++ restChildren)
encodeStructReference desc offset = encodeStructReference desc offset =
bytes (offset * 4 + structTag) 4 ++ bytes (offset * 4 + structTag) 4 ++
[ fromIntegral (length (structFields desc) + length (structUnions desc)) [ fromIntegral (length (structFields desc) + length (structUnions desc))
...@@ -205,21 +219,17 @@ encodeStruct desc assignments childOffset = (dataBytes, referenceBytes, children ...@@ -205,21 +219,17 @@ encodeStruct desc assignments childOffset = (dataBytes, referenceBytes, children
(packingReferenceCount $ structPacking desc) sortedReferences (packingReferenceCount $ structPacking desc) sortedReferences
encodeList elementType elements = case elementSize elementType of encodeList elementType elements = case elementSize elementType of
SizeInlineComposite ds rc -> case elementType of SizeInlineComposite _ _ -> case elementType of
StructType desc -> let StructType desc -> let
count = genericLength elements count = genericLength elements
tag = encodeStructReference desc count tag = encodeStructReference desc count
elemWords = ds + rc (elemBytes, childBytes) = encodeStructList 0 desc [v | StructValueDesc v <- elements]
(elemBytes, childBytes) = unzip in concat [tag, elemBytes, childBytes]
[ (d ++ r, c)
| (i, StructValueDesc assignments) <- zip [1..] elements
, let (d, r, c) = encodeStruct desc assignments ((count - i) * elemWords)]
in concat $ concat [[tag], elemBytes, childBytes]
_ -> error "Only structs can be inline composites." _ -> error "Only structs can be inline composites."
SizeReference -> refBytes ++ childBytes where SizeReference -> refBytes ++ childBytes where
(refBytes, childBytes) = encodeReferences 0 (genericLength elements) (refBytes, childBytes) = encodeReferences 0 (genericLength elements)
$ zipWith (\i v -> (i, elementType, v)) [0..] elements $ zipWith (\i v -> (i, elementType, v)) [0..] elements
size -> encodeData (roundUpToMultiple (genericLength elements * sizeInBits size) 64) size -> encodeData (roundUpToMultiple 64 (genericLength elements * sizeInBits size))
$ zipWith (\i v -> (i * sizeInBits size, elementType, v)) [0..] elements $ zipWith (\i v -> (i * sizeInBits size, elementType, v)) [0..] elements
encodeMessage (StructType desc) (StructValueDesc assignments) = let encodeMessage (StructType desc) (StructValueDesc assignments) = let
......
...@@ -86,6 +86,8 @@ class {{structName}}::Builder { ...@@ -86,6 +86,8 @@ class {{structName}}::Builder {
public: public:
Builder() = default; Builder() = default;
inline explicit Builder(::capnproto::internal::StructBuilder base): _builder(base) {} inline explicit Builder(::capnproto::internal::StructBuilder base): _builder(base) {}
inline operator Reader() { return Reader(_builder.asReader()); }
inline Reader asReader() { return *this; }
{{#structFields}} {{#structFields}}
// {{fieldDecl}} // {{fieldDecl}}
...@@ -105,6 +107,14 @@ public: ...@@ -105,6 +107,14 @@ public:
{{#fieldIsNonStructList}} {{#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}}();
template <typename _t>
inline void set{{fieldTitleCase}}(const _t& other);
{{#fieldIsPrimitiveList}}
inline void set{{fieldTitleCase}}(std::initializer_list<{{fieldElementType}}> other);
{{/fieldIsPrimitiveList}}
{{^fieldIsPrimitiveList}}
inline void set{{fieldTitleCase}}(std::initializer_list<{{fieldElementType}}::Reader> other);
{{/fieldIsPrimitiveList}}
{{/fieldIsNonStructList}} {{/fieldIsNonStructList}}
{{#fieldIsStructList}} {{#fieldIsStructList}}
inline {{fieldType}}::Builder init{{fieldTitleCase}}(unsigned int size); inline {{fieldType}}::Builder init{{fieldTitleCase}}(unsigned int size);
...@@ -210,6 +220,22 @@ inline {{fieldType}}::Builder {{structName}}::Builder::get{{fieldTitleCase}}() { ...@@ -210,6 +220,22 @@ inline {{fieldType}}::Builder {{structName}}::Builder::get{{fieldTitleCase}}() {
{{#fieldDefaultBytes}}DEFAULT_{{fieldUpperCase}}.words{{/fieldDefaultBytes}} {{#fieldDefaultBytes}}DEFAULT_{{fieldUpperCase}}.words{{/fieldDefaultBytes}}
{{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}})); {{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}}));
} }
template <typename _t>
inline void {{structName}}::Builder::set{{fieldTitleCase}}(const _t& other) {
init{{fieldTitleCase}}(other.size()).copyFrom(other);
}
{{#fieldIsPrimitiveList}}
inline void {{structName}}::Builder::set{{fieldTitleCase}}(
std::initializer_list<{{fieldElementType}}> other) {
init{{fieldTitleCase}}(other.size()).copyFrom(other);
}
{{/fieldIsPrimitiveList}}
{{^fieldIsPrimitiveList}}
inline void {{structName}}::Builder::set{{fieldTitleCase}}(
std::initializer_list<{{fieldElementType}}::Reader> other) {
init{{fieldTitleCase}}(other.size()).copyFrom(other);
}
{{/fieldIsPrimitiveList}}
{{/fieldIsNonStructList}} {{/fieldIsNonStructList}}
{{#fieldIsStructList}} {{#fieldIsStructList}}
inline {{fieldType}}::Builder {{structName}}::Builder::init{{fieldTitleCase}}(unsigned int size) { inline {{fieldType}}::Builder {{structName}}::Builder::init{{fieldTitleCase}}(unsigned int size) {
......
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