Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
20b1ea55
Commit
20b1ea55
authored
Mar 14, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Encoding test. Bug fixes. It works.
parent
b4f80598
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
425 additions
and
64 deletions
+425
-64
blob-test.c++
c++/src/capnproto/blob-test.c++
+5
-4
blob.h
c++/src/capnproto/blob.h
+19
-1
capnpc.ekam-rule
c++/src/capnproto/capnpc.ekam-rule
+2
-2
encoding-test.c++
c++/src/capnproto/encoding-test.c++
+0
-0
list.h
c++/src/capnproto/list.h
+75
-2
message.h
c++/src/capnproto/message.h
+30
-1
test.capnp
c++/src/capnproto/test.capnp
+142
-0
type-safety.h
c++/src/capnproto/type-safety.h
+8
-0
wire-format.c++
c++/src/capnproto/wire-format.c++
+12
-13
wire-format.h
c++/src/capnproto/wire-format.h
+32
-0
capnproto-compiler.cabal
compiler/capnproto-compiler.cabal
+1
-0
CxxGenerator.hs
compiler/src/CxxGenerator.hs
+7
-3
Lexer.hs
compiler/src/Lexer.hs
+11
-5
Parser.hs
compiler/src/Parser.hs
+25
-18
Semantics.hs
compiler/src/Semantics.hs
+4
-2
Token.hs
compiler/src/Token.hs
+7
-4
WireFormat.hs
compiler/src/WireFormat.hs
+19
-9
c++-header.mustache
compiler/src/c++-header.mustache
+26
-0
No files found.
c++/src/capnproto/blob-test.c++
View file @
20b1ea55
...
...
@@ -42,7 +42,7 @@ TEST(Blob, Text) {
std
::
string
str
=
"foo"
;
Text
::
Reader
text
=
str
;
EXPECT_
STR
EQ
(
"foo"
,
text
);
EXPECT_EQ
(
"foo"
,
text
);
EXPECT_STREQ
(
"foo"
,
text
.
c_str
());
EXPECT_STREQ
(
"foo"
,
text
.
data
());
EXPECT_EQ
(
3u
,
text
.
size
());
...
...
@@ -51,14 +51,14 @@ TEST(Blob, Text) {
EXPECT_EQ
(
"foo"
,
str2
);
Text
::
Reader
text2
=
"bar"
;
EXPECT_
STR
EQ
(
"bar"
,
text2
);
EXPECT_EQ
(
"bar"
,
text2
);
char
c
[
4
]
=
"baz"
;
Text
::
Reader
text3
(
c
);
EXPECT_
STR
EQ
(
"baz"
,
text3
);
EXPECT_EQ
(
"baz"
,
text3
);
Text
::
Builder
builder
(
c
,
3
);
EXPECT_
STR
EQ
(
"baz"
,
builder
);
EXPECT_EQ
(
"baz"
,
builder
);
EXPECT_EQ
(
Data
::
Reader
(
"az"
),
builder
.
slice
(
1
,
3
));
}
...
...
@@ -67,6 +67,7 @@ TEST(Blob, Data) {
std
::
string
str
=
"foo"
;
Data
::
Reader
data
=
str
;
EXPECT_EQ
(
"foo"
,
data
);
EXPECT_EQ
(
3u
,
data
.
size
());
std
::
string
str2
=
data
;
...
...
c++/src/capnproto/blob.h
View file @
20b1ea55
...
...
@@ -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
// 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
// well as from any type which has c_str() and size() methods. Many types follow this pattern,
// such as std::string.
...
...
@@ -197,6 +201,20 @@ private:
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
#endif // CAPNPROTO_BLOB_H_
c++/src/capnproto/capnpc.ekam-rule
View file @
20b1ea55
...
...
@@ -44,9 +44,9 @@ echo findProvider file:capnproto-compiler
read
CAPNPC
if
test
"
$CAPNPC
"
=
""
;
then
echo
"error: couldn't find capnproto-compiler."
>
&2
exit
1
CAPNPC
=
capnpc
fi
# When exception stack traces are needed, add: +RTS -xc -RTS
LD_PRELOAD
=
$INTERCEPTOR
DYLD_FORCE_FLAT_NAMESPACE
=
DYLD_INSERT_LIBRARIES
=
$INTERCEPTOR
\
$CAPNPC
"
$INPUT
"
3>&1 4<&0
>
&2
c++/src/capnproto/encoding-test.c++
View file @
20b1ea55
This diff is collapsed.
Click to expand it.
c++/src/capnproto/list.h
View file @
20b1ea55
...
...
@@ -26,6 +26,7 @@
#include "wire-format.h"
#include "descriptor.h" // only for FieldSize; TODO: Eliminate this
#include <initializer_list>
namespace
capnproto
{
...
...
@@ -40,7 +41,7 @@ namespace internal {
template
<
typename
T
>
struct
IsPrimitive
{
static
constexpr
bool
value
=
false
;
};
template
<>
struct
IsPrimitive
<
v
oid
>
{
static
constexpr
bool
value
=
true
;
};
template
<>
struct
IsPrimitive
<
V
oid
>
{
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
<
int16_t
>
{
static
constexpr
bool
value
=
true
;
};
...
...
@@ -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
<>
struct
FieldSizeForType
<
v
oid
>
{
static
constexpr
FieldSize
value
=
FieldSize
::
VOID
;
};
template
<>
struct
FieldSizeForType
<
V
oid
>
{
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
;
};
...
...
@@ -182,6 +183,23 @@ struct List<T, true> {
inline
iterator
begin
()
{
return
iterator
(
this
,
0
);
}
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
:
internal
::
ListBuilder
builder
;
};
...
...
@@ -223,6 +241,11 @@ struct List<T, false> {
inline
iterator
begin
()
{
return
iterator
(
this
,
0
);
}
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
:
internal
::
ListBuilder
builder
;
};
...
...
@@ -267,6 +290,11 @@ struct List<List<T>, true> {
inline
iterator
begin
()
{
return
iterator
(
this
,
0
);
}
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
:
internal
::
ListBuilder
builder
;
};
...
...
@@ -311,6 +339,11 @@ struct List<List<T>, false> {
inline
iterator
begin
()
{
return
iterator
(
this
,
0
);
}
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
:
internal
::
ListBuilder
builder
;
};
...
...
@@ -345,6 +378,9 @@ struct List<Data, false> {
inline
Data
::
Builder
operator
[](
uint
index
)
{
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
)
{
return
builder
.
initDataElement
(
index
*
REFERENCES
,
size
*
BYTES
);
}
...
...
@@ -353,6 +389,23 @@ struct List<Data, false> {
inline
iterator
begin
()
{
return
iterator
(
this
,
0
);
}
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
:
internal
::
ListBuilder
builder
;
};
...
...
@@ -387,6 +440,9 @@ struct List<Text, false> {
inline
Text
::
Builder
operator
[](
uint
index
)
{
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
)
{
return
builder
.
initTextElement
(
index
*
REFERENCES
,
size
*
BYTES
);
}
...
...
@@ -395,6 +451,23 @@ struct List<Text, false> {
inline
iterator
begin
()
{
return
iterator
(
this
,
0
);
}
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
:
internal
::
ListBuilder
builder
;
};
...
...
c++/src/capnproto/message.h
View file @
20b1ea55
...
...
@@ -25,6 +25,8 @@
#include <memory>
#include "macros.h"
#include "type-safety.h"
#include "wire-format.h"
#include "list.h"
#ifndef CAPNPROTO_MESSAGE_H_
#define CAPNPROTO_MESSAGE_H_
...
...
@@ -95,9 +97,24 @@ public:
// 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.
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
{
// 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
...
...
@@ -244,6 +261,18 @@ inline WordCount SegmentBuilder::available() {
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
#endif // CAPNPROTO_MESSAGE_H_
c++/src/capnproto/test.capnp
0 → 100644
View file @
20b1ea55
# 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
}
c++/src/capnproto/type-safety.h
View file @
20b1ea55
...
...
@@ -34,6 +34,14 @@ namespace capnproto {
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
>
struct
NoInfer
{
// Use NoInfer<T>::Type in place of T for a template function parameter to prevent inference of
...
...
c++/src/capnproto/wire-format.c++
View file @
20b1ea55
...
...
@@ -293,8 +293,7 @@ struct WireHelpers {
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
++
)
{
for
(
uint
i
=
0
;
i
<
referenceCount
/
REFERENCES
;
i
++
)
{
SegmentBuilder
*
subSegment
=
segment
;
WireReference
*
dstRef
=
dstRefs
+
i
;
copyMessage
(
subSegment
,
dstRef
,
srcRefs
+
i
);
...
...
@@ -313,11 +312,11 @@ struct WireHelpers {
const
word
*
srcPtr
=
src
->
target
();
word
*
dstPtr
=
allocate
(
dst
,
segment
,
src
->
structRef
.
wordSize
(),
WireReference
::
STRUCT
);
copyStruct
(
segment
,
dstPtr
,
srcPtr
,
dst
->
structRef
.
dataSize
.
get
(),
dst
->
structRef
.
refCount
.
get
());
copyStruct
(
segment
,
dstPtr
,
srcPtr
,
src
->
structRef
.
dataSize
.
get
(),
src
->
structRef
.
refCount
.
get
());
dst
->
structRef
.
set
(
dst
->
structRef
.
fieldCount
.
get
(),
dst
->
structRef
.
dataSize
.
get
(),
dst
->
structRef
.
refCount
.
get
());
dst
->
structRef
.
set
(
src
->
structRef
.
fieldCount
.
get
(),
src
->
structRef
.
dataSize
.
get
(),
src
->
structRef
.
refCount
.
get
());
return
dstPtr
;
}
}
...
...
@@ -418,7 +417,7 @@ struct WireHelpers {
reinterpret_cast
<
WireReference
*>
(
ptr
+
defaultRef
->
structRef
.
dataSize
.
get
()));
}
static
CAPNPROTO_ALWAYS_INLINE
(
StructBuilder
getStructReference
(
static
CAPNPROTO_ALWAYS_INLINE
(
StructBuilder
get
Writable
StructReference
(
WireReference
*
ref
,
SegmentBuilder
*
segment
,
const
word
*
defaultValue
))
{
const
WireReference
*
defaultRef
=
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
);
word
*
ptr
;
...
...
@@ -631,7 +630,7 @@ struct WireHelpers {
ptr
=
followFars
(
ref
,
segment
);
if
(
CAPNPROTO_EXPECT_FALSE
(
ptr
==
nullptr
))
{
segment
->
getMessage
()
->
reportInvalidData
(
"Message contains
out-of-bounds
far reference."
);
"Message contains
invalid
far reference."
);
goto
useDefault
;
}
...
...
@@ -681,7 +680,7 @@ struct WireHelpers {
ptr
=
followFars
(
ref
,
segment
);
if
(
CAPNPROTO_EXPECT_FALSE
(
ptr
==
nullptr
))
{
segment
->
getMessage
()
->
reportInvalidData
(
"Message contains
out-of-bounds
far reference."
);
"Message contains
invalid
far reference."
);
goto
useDefault
;
}
...
...
@@ -861,7 +860,7 @@ struct WireHelpers {
if
(
CAPNPROTO_EXPECT_FALSE
(
ptr
==
nullptr
))
{
segment
->
getMessage
()
->
reportInvalidData
(
"Message contains
out-of-bounds
far reference."
);
"Message contains
invalid
far reference."
);
goto
useDefault
;
}
...
...
@@ -913,7 +912,7 @@ struct WireHelpers {
if
(
CAPNPROTO_EXPECT_FALSE
(
ptr
==
nullptr
))
{
segment
->
getMessage
()
->
reportInvalidData
(
"Message contains
out-of-bounds
far reference."
);
"Message contains
invalid
far reference."
);
goto
useDefault
;
}
...
...
@@ -923,7 +922,7 @@ struct WireHelpers {
goto
useDefault
;
}
if
(
CAPNPROTO_EXPECT_FALSE
(
ref
->
listRef
.
elementSize
()
=
=
FieldSize
::
BYTE
))
{
if
(
CAPNPROTO_EXPECT_FALSE
(
ref
->
listRef
.
elementSize
()
!
=
FieldSize
::
BYTE
))
{
segment
->
getMessage
()
->
reportInvalidData
(
"Message contains list reference of non-bytes where data was expected."
);
goto
useDefault
;
...
...
@@ -956,7 +955,7 @@ StructBuilder StructBuilder::initStructField(
StructBuilder
StructBuilder
::
getStructField
(
WireReferenceCount
refIndex
,
const
word
*
defaultValue
)
const
{
return
WireHelpers
::
getStructReference
(
references
+
refIndex
,
segment
,
defaultValue
);
return
WireHelpers
::
get
Writable
StructReference
(
references
+
refIndex
,
segment
,
defaultValue
);
}
ListBuilder
StructBuilder
::
initListField
(
...
...
c++/src/capnproto/wire-format.h
View file @
20b1ea55
...
...
@@ -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
;
}
template
<>
inline
Void
StructBuilder
::
getDataField
<
Void
>
(
ElementCount
offset
)
const
{
return
Void
::
VOID
;
}
template
<
typename
T
>
inline
void
StructBuilder
::
setDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
value
)
const
{
...
...
@@ -402,6 +407,9 @@ inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) c
|
(
static_cast
<
uint8_t
>
(
value
)
<<
bitnum
);
}
template
<>
inline
void
StructBuilder
::
setDataField
<
Void
>
(
ElementCount
offset
,
Void
value
)
const
{}
// -------------------------------------------------------------------
template
<
typename
T
>
...
...
@@ -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
>
T
StructReader
::
getDataFieldCheckingNumber
(
FieldNumber
fieldNumber
,
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
defaultValue
)
const
{
...
...
@@ -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
;
}
...
...
@@ -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
;
}
template
<>
inline
Void
ListBuilder
::
getDataElement
<
Void
>
(
ElementCount
index
)
const
{
return
Void
::
VOID
;
}
template
<
typename
T
>
inline
void
ListBuilder
::
setDataElement
(
ElementCount
index
,
typename
NoInfer
<
T
>::
Type
value
)
const
{
reinterpret_cast
<
WireValue
<
T
>*>
(
ptr
)[
index
/
ELEMENTS
].
set
(
value
);
...
...
@@ -487,6 +511,9 @@ inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) co
|
(
static_cast
<
uint8_t
>
(
value
)
<<
bitnum
);
}
template
<>
inline
void
ListBuilder
::
setDataElement
<
Void
>
(
ElementCount
index
,
Void
value
)
const
{}
// -------------------------------------------------------------------
inline
ElementCount
ListReader
::
size
()
{
return
elementCount
;
}
...
...
@@ -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
;
}
template
<>
inline
Void
ListReader
::
getDataElement
<
Void
>
(
ElementCount
index
)
const
{
return
Void
::
VOID
;
}
}
// namespace internal
}
// namespace capnproto
...
...
compiler/capnproto-compiler.cabal
View file @
20b1ea55
...
...
@@ -20,6 +20,7 @@ executable capnproto-compiler
array,
data-binary-ieee754,
filepath
-- When profiling is needed, add: -prof -fprof-auto -osuf p_o -hisuf p_hi
ghc-options: -Wall -fno-warn-missing-signatures
other-modules:
Lexer,
...
...
compiler/src/CxxGenerator.hs
View file @
20b1ea55
...
...
@@ -68,6 +68,9 @@ isList _ = False
isNonStructList
(
ListType
t
)
=
not
$
isStruct
t
isNonStructList
_
=
False
isPrimitiveList
(
ListType
t
)
=
isPrimitive
t
isPrimitiveList
_
=
False
isStructList
(
ListType
t
)
=
isStruct
t
isStructList
_
=
False
...
...
@@ -75,7 +78,7 @@ blobTypeString (BuiltinType BuiltinText) = "Text"
blobTypeString
(
BuiltinType
BuiltinData
)
=
"Data"
blobTypeString
_
=
error
"Not a blob."
cxxTypeString
(
BuiltinType
BuiltinVoid
)
=
"
v
oid"
cxxTypeString
(
BuiltinType
BuiltinVoid
)
=
"
::capnproto::V
oid"
cxxTypeString
(
BuiltinType
BuiltinBool
)
=
"bool"
cxxTypeString
(
BuiltinType
BuiltinInt8
)
=
" ::int8_t"
cxxTypeString
(
BuiltinType
BuiltinInt16
)
=
" ::int16_t"
...
...
@@ -103,7 +106,7 @@ cxxFieldSizeString Size64 = "EIGHT_BYTES";
cxxFieldSizeString
SizeReference
=
"REFERENCE"
;
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
(
Int8Desc
i
)
=
show
i
cxxValueString
(
Int16Desc
i
)
=
show
i
...
...
@@ -129,7 +132,7 @@ defaultValueBytes t v@(StructValueDesc _) = Just $ encodeMessage t v
defaultValueBytes
t
v
@
(
ListDesc
_
)
=
Just
$
encodeMessage
t
v
defaultValueBytes
_
_
=
Nothing
cxxDefaultDefault
(
BuiltinType
BuiltinVoid
)
=
error
"Can't stringify void value.
"
cxxDefaultDefault
(
BuiltinType
BuiltinVoid
)
=
" ::capnproto::Void::VOID
"
cxxDefaultDefault
(
BuiltinType
BuiltinBool
)
=
"false"
cxxDefaultDefault
(
BuiltinType
BuiltinInt8
)
=
"0"
cxxDefaultDefault
(
BuiltinType
BuiltinInt16
)
=
"0"
...
...
@@ -175,6 +178,7 @@ fieldContext parent desc = mkStrContext context where
context
"fieldIsStruct"
=
MuBool
$
isStruct
$
fieldType
desc
context
"fieldIsList"
=
MuBool
$
isList
$
fieldType
desc
context
"fieldIsNonStructList"
=
MuBool
$
isNonStructList
$
fieldType
desc
context
"fieldIsPrimitiveList"
=
MuBool
$
isPrimitiveList
$
fieldType
desc
context
"fieldIsStructList"
=
MuBool
$
isStructList
$
fieldType
desc
context
"fieldDefaultBytes"
=
case
fieldDefaultValue
desc
>>=
defaultValueBytes
(
fieldType
desc
)
of
...
...
compiler/src/Lexer.hs
View file @
20b1ea55
...
...
@@ -32,7 +32,8 @@ import Token
import
Data.Char
(
isUpper
,
isLower
)
keywords
=
[
(
TrueKeyword
,
"true"
)
[
(
VoidKeyword
,
"void"
)
,
(
TrueKeyword
,
"true"
)
,
(
FalseKeyword
,
"false"
)
,
(
InKeyword
,
"in"
)
,
(
OfKeyword
,
"of"
)
...
...
@@ -105,11 +106,16 @@ identifier = do
\
names into the target language's preferred style."
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
=
keyword
<|>
identifier
<|>
liftM
ParenthesizedList
(
parens
(
sepBy
(
many
locatedToken
)
(
symbol
","
)))
<|>
liftM
BracketedList
(
brackets
(
sepBy
(
many
locatedToken
)
(
symbol
","
)))
<|>
liftM
ParenthesizedList
(
parens
(
sepBy
tokenSequence
(
symbol
","
)))
<|>
liftM
BracketedList
(
brackets
(
sepBy
tokenSequence
(
symbol
","
)))
<|>
liftM
toLiteral
naturalOrFloat
<|>
liftM
LiteralString
stringLiteral
<|>
liftM
(
const
AtSign
)
(
symbol
"@"
)
...
...
@@ -126,13 +132,13 @@ statementEnd :: Parser (Maybe [Located Statement])
statementEnd
=
(
symbol
";"
>>=
\
_
->
return
Nothing
)
<|>
(
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
(
Just
statements
)
=
Block
tokens
statements
statement
::
Parser
Statement
statement
=
do
tokens
<-
many
locatedToken
tokens
<-
tokenSequence
end
<-
statementEnd
return
(
compileStatement
tokens
end
)
...
...
compiler/src/Parser.hs
View file @
20b1ea55
...
...
@@ -25,6 +25,7 @@ module Parser (parseFile) where
import
Text.Parsec
hiding
(
tokens
)
import
Text.Parsec.Error
(
newErrorMessage
,
Message
(
Message
))
import
Text.Parsec.Pos
(
newPos
)
import
Text.Printf
(
printf
)
import
Token
import
Grammar
...
...
@@ -48,6 +49,7 @@ tokenErrorString Period = "\".\""
tokenErrorString
EqualsSign
=
"
\"
=
\"
"
tokenErrorString
MinusSign
=
"
\"
-
\"
"
tokenErrorString
ExclamationPoint
=
"
\"
!
\"
"
tokenErrorString
VoidKeyword
=
"keyword
\"
void
\"
"
tokenErrorString
TrueKeyword
=
"keyword
\"
true
\"
"
tokenErrorString
FalseKeyword
=
"keyword
\"
false
\"
"
tokenErrorString
InKeyword
=
"keyword
\"
in
\"
"
...
...
@@ -103,6 +105,7 @@ literalInt = tokenParser matchLiteralInt <?> "integer"
literalFloat
=
tokenParser
matchLiteralFloat
<?>
"floating-point number"
literalString
=
tokenParser
matchLiteralString
<?>
"string"
literalBool
=
tokenParser
matchLiteralBool
<?>
"boolean"
literalVoid
=
tokenParser
(
matchSimpleToken
VoidKeyword
)
<?>
"
\"
void
\"
"
atSign
=
tokenParser
(
matchSimpleToken
AtSign
)
<?>
"
\"
@
\"
"
colon
=
tokenParser
(
matchSimpleToken
Colon
)
<?>
"
\"
:
\"
"
...
...
@@ -238,7 +241,8 @@ fieldDecl statements = do
negativeFieldValue
=
liftM
(
IntegerFieldValue
.
negate
)
literalInt
<|>
liftM
(
FloatFieldValue
.
negate
)
literalFloat
fieldValue
=
liftM
BoolFieldValue
literalBool
fieldValue
=
(
literalVoid
>>
return
VoidFieldValue
)
<|>
liftM
BoolFieldValue
literalBool
<|>
liftM
IntegerFieldValue
literalInt
<|>
liftM
FloatFieldValue
literalFloat
<|>
liftM
StringFieldValue
literalString
...
...
@@ -302,30 +306,33 @@ failNonFatal :: SourcePos -> String -> TokenParser ()
failNonFatal
pos
msg
=
modifyState
(
newError
:
)
where
newError
=
newErrorMessage
(
Message
msg
)
pos
parseList
parser
items
=
finish
where
results
=
map
(
parseCollectingErrors
parser
)
items
finish
=
do
modifyState
(
\
old
->
concat
(
old
:
map
extractErrors
results
))
return
[
result
|
Right
(
result
,
_
)
<-
results
]
parseList
parser
items
=
do
let
results
=
map
(
parseCollectingErrors
parser
)
items
modifyState
(
\
old
->
concat
(
old
:
map
extractErrors
results
))
return
[
result
|
Right
(
result
,
_
)
<-
results
]
parseBlock
::
(
Maybe
[
Located
Statement
]
->
TokenParser
Declaration
)
->
[
Located
Statement
]
->
TokenParser
[
Declaration
]
parseBlock
parser
statements
=
finish
where
results
=
map
(
parseStatement
parser
)
statements
finish
=
do
modifyState
(
\
old
->
concat
(
old
:
map
extractErrors
results
))
return
[
result
|
Right
(
result
,
_
)
<-
results
]
parseCollectingErrors
::
TokenParser
a
->
[
Located
Token
]
->
Either
ParseError
(
a
,
[
ParseError
])
parseCollectingErrors
parser
tokens
=
runParser
parser'
[]
""
tokens
where
parseBlock
parser
statements
=
do
let
results
=
map
(
parseStatement
parser
)
statements
modifyState
(
\
old
->
concat
(
old
:
map
extractErrors
results
))
return
[
result
|
Right
(
result
,
_
)
<-
results
]
parseCollectingErrors
::
TokenParser
a
->
TokenSequence
->
Either
ParseError
(
a
,
[
ParseError
])
parseCollectingErrors
parser
tokenSequence
=
runParser
parser'
[]
""
tokens
where
TokenSequence
tokens
endPos
=
tokenSequence
parser'
=
do
-- 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,
-- 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.
case
tokens
of
Located
pos
_
:
_
->
setPosition
pos
[]
->
return
()
--
-- TODO: There's still a problem when a parse error occurs at end-of-input: Parsec will
-- report the error at the location of the previous token.
setPosition
(
case
tokens
of
Located
pos2
_
:
_
->
pos2
[]
->
endPos
)
result
<-
parser
eof
...
...
@@ -349,4 +356,4 @@ parseFileTokens statements = (decls, errors) where
parseFile
::
String
->
String
->
([
Declaration
],
[
ParseError
])
parseFile
filename
text
=
case
parse
lexer
filename
text
of
Left
e
->
(
[]
,
[
e
])
Right
tokens
->
parseFileTokens
token
s
Right
statements
->
parseFileTokens
statement
s
compiler/src/Semantics.hs
View file @
20b1ea55
...
...
@@ -122,7 +122,7 @@ data ValueDesc = VoidDesc
|
ListDesc
[
ValueDesc
]
deriving
(
Show
)
valueString
VoidDesc
=
error
"Can't stringify void value.
"
valueString
VoidDesc
=
"void
"
valueString
(
BoolDesc
b
)
=
if
b
then
"true"
else
"false"
valueString
(
Int8Desc
i
)
=
show
i
valueString
(
Int16Desc
i
)
=
show
i
...
...
@@ -156,6 +156,8 @@ data PackingState = PackingState
,
packingReferenceCount
::
Integer
}
packingSize
PackingState
{
packingDataSize
=
ds
,
packingReferenceCount
=
rc
}
=
ds
+
rc
-- 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 reference allocated to the union.
...
...
@@ -416,7 +418,7 @@ descToCode indent (DescField desc) = printf "%s%s@%d%s: %s%s; # %s\n" indent
SizeReference
->
printf
"ref[%d]"
$
fieldOffset
desc
SizeInlineComposite
_
_
->
"??"
s
->
let
bits
=
(
sizeInBits
s
)
bits
=
sizeInBits
s
offset
=
fieldOffset
desc
in
printf
"bits[%d, %d)"
(
offset
*
bits
)
((
offset
+
1
)
*
bits
))
-- (maybeBlockCode indent $ fieldStatements desc)
...
...
compiler/src/Token.hs
View file @
20b1ea55
...
...
@@ -37,13 +37,16 @@ instance Eq a => Eq (Located a) where
instance
Ord
a
=>
Ord
(
Located
a
)
where
compare
(
Located
_
a
)
(
Located
_
b
)
=
compare
a
b
data
TokenSequence
=
TokenSequence
[
Located
Token
]
SourcePos
deriving
(
Show
,
Eq
)
data
Token
=
Identifier
String
|
TypeIdentifier
String
|
ParenthesizedList
[
[
Located
Token
]
]
|
BracketedList
[
[
Located
Token
]
]
|
ParenthesizedList
[
TokenSequence
]
|
BracketedList
[
TokenSequence
]
|
LiteralInt
Integer
|
LiteralFloat
Double
|
LiteralString
String
|
VoidKeyword
|
TrueKeyword
|
FalseKeyword
|
AtSign
...
...
@@ -68,6 +71,6 @@ data Token = Identifier String
|
OptionKeyword
deriving
(
Show
,
Eq
)
data
Statement
=
Line
[
Located
Token
]
|
Block
[
Located
Token
]
[
Located
Statement
]
data
Statement
=
Line
TokenSequence
|
Block
TokenSequence
[
Located
Statement
]
deriving
(
Show
)
compiler/src/WireFormat.hs
View file @
20b1ea55
...
...
@@ -100,7 +100,7 @@ encodeReferences o size = loop 0 (o + size) where
(
dataBytes
,
refBytes
,
childBytes
)
=
encodeStruct
desc
assignments
0
in
(
encodeStructReference
desc
offset
,
concat
[
dataBytes
,
refBytes
,
childBytes
])
(
ListType
elementType
,
ListDesc
items
)
->
(
encodeListReference
(
field
Size
elementType
)
(
genericLength
items
)
offset
,
(
encodeListReference
(
element
Size
elementType
)
(
genericLength
items
)
offset
,
encodeList
elementType
items
)
(
BuiltinType
BuiltinText
,
TextDesc
text
)
->
let
encoded
=
(
UTF8
.
encode
text
++
[
0
])
...
...
@@ -118,6 +118,20 @@ encodeReferences o size = loop 0 (o + size) where
in
(
genericReplicate
(
padCount
*
8
)
0
++
refs
,
objects
)
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
=
bytes
(
offset
*
4
+
structTag
)
4
++
[
fromIntegral
(
length
(
structFields
desc
)
+
length
(
structUnions
desc
))
...
...
@@ -205,21 +219,17 @@ encodeStruct desc assignments childOffset = (dataBytes, referenceBytes, children
(
packingReferenceCount
$
structPacking
desc
)
sortedReferences
encodeList
elementType
elements
=
case
elementSize
elementType
of
SizeInlineComposite
ds
rc
->
case
elementType
of
SizeInlineComposite
_
_
->
case
elementType
of
StructType
desc
->
let
count
=
genericLength
elements
tag
=
encodeStructReference
desc
count
elemWords
=
ds
+
rc
(
elemBytes
,
childBytes
)
=
unzip
[
(
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
]
(
elemBytes
,
childBytes
)
=
encodeStructList
0
desc
[
v
|
StructValueDesc
v
<-
elements
]
in
concat
[
tag
,
elemBytes
,
childBytes
]
_
->
error
"Only structs can be inline composites."
SizeReference
->
refBytes
++
childBytes
where
(
refBytes
,
childBytes
)
=
encodeReferences
0
(
genericLength
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
encodeMessage
(
StructType
desc
)
(
StructValueDesc
assignments
)
=
let
...
...
compiler/src/c++-header.mustache
View file @
20b1ea55
...
...
@@ -86,6 +86,8 @@ class {{structName}}::Builder {
public:
Builder() = default;
inline explicit Builder(::capnproto::internal::StructBuilder base): _builder(base) {}
inline operator Reader() { return Reader(_builder.asReader()); }
inline Reader asReader() { return *this; }
{{#
structFields
}}
//
{{
fieldDecl
}}
...
...
@@ -105,6 +107,14 @@ public:
{{#
fieldIsNonStructList
}}
inline
{{
fieldType
}}
::Builder init
{{
fieldTitleCase
}}
(unsigned int size);
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
}}
{{#
fieldIsStructList
}}
inline
{{
fieldType
}}
::Builder init
{{
fieldTitleCase
}}
(unsigned int size);
...
...
@@ -210,6 +220,22 @@ inline {{fieldType}}::Builder {{structName}}::Builder::get{{fieldTitleCase}}() {
{{#
fieldDefaultBytes
}}
DEFAULT_
{{
fieldUpperCase
}}
.words
{{/
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
}}
{{#
fieldIsStructList
}}
inline
{{
fieldType
}}
::Builder
{{
structName
}}
::Builder::init
{{
fieldTitleCase
}}
(unsigned int size) {
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment