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
f966fc41
Commit
f966fc41
authored
Apr 09, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Store primitive fields XOR'd with their defaults.
parent
f3c4121b
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
371 additions
and
283 deletions
+371
-283
layout-test.c++
c++/src/capnproto/layout-test.c++
+75
-57
layout.c++
c++/src/capnproto/layout.c++
+51
-58
layout.h
c++/src/capnproto/layout.h
+146
-31
list.h
c++/src/capnproto/list.h
+2
-3
message.c++
c++/src/capnproto/message.c++
+7
-8
message.h
c++/src/capnproto/message.h
+7
-8
test.capnp
c++/src/capnproto/test.capnp
+1
-1
CxxGenerator.hs
compiler/src/CxxGenerator.hs
+39
-43
WireFormat.hs
compiler/src/WireFormat.hs
+30
-53
c++-header.mustache
compiler/src/c++-header.mustache
+12
-14
c++-source.mustache
compiler/src/c++-source.mustache
+1
-7
No files found.
c++/src/capnproto/layout-test.c++
View file @
f966fc41
...
...
@@ -45,46 +45,58 @@ TEST(WireFormat, SimpleRawDataStruct) {
0x01
,
0x23
,
0x45
,
0x67
,
0x89
,
0xab
,
0xcd
,
0xef
}};
StructReader
reader
=
StructReader
::
readRootTrusted
(
data
.
words
,
data
.
words
);
EXPECT_EQ
(
0xefcdab8967452301ull
,
reader
.
getDataField
<
uint64_t
>
(
0
*
ELEMENTS
,
321u
));
StructReader
reader
=
StructReader
::
readRootTrusted
(
data
.
words
);
EXPECT_EQ
(
0xefcdab8967452301ull
,
reader
.
getDataField
<
uint64_t
>
(
0
*
ELEMENTS
));
EXPECT_EQ
(
0u
,
reader
.
getDataField
<
uint64_t
>
(
1
*
ELEMENTS
));
EXPECT_EQ
(
0x67452301u
,
reader
.
getDataField
<
uint32_t
>
(
0
*
ELEMENTS
));
EXPECT_EQ
(
0xefcdab89u
,
reader
.
getDataField
<
uint32_t
>
(
1
*
ELEMENTS
));
EXPECT_EQ
(
0u
,
reader
.
getDataField
<
uint32_t
>
(
2
*
ELEMENTS
));
EXPECT_EQ
(
0x2301u
,
reader
.
getDataField
<
uint16_t
>
(
0
*
ELEMENTS
));
EXPECT_EQ
(
0x6745u
,
reader
.
getDataField
<
uint16_t
>
(
1
*
ELEMENTS
));
EXPECT_EQ
(
0xab89u
,
reader
.
getDataField
<
uint16_t
>
(
2
*
ELEMENTS
));
EXPECT_EQ
(
0xefcdu
,
reader
.
getDataField
<
uint16_t
>
(
3
*
ELEMENTS
));
EXPECT_EQ
(
0u
,
reader
.
getDataField
<
uint16_t
>
(
4
*
ELEMENTS
));
EXPECT_EQ
(
321u
^
0xefcdab8967452301ull
,
reader
.
getDataField
<
uint64_t
>
(
0
*
ELEMENTS
,
321u
));
EXPECT_EQ
(
321u
^
0x67452301u
,
reader
.
getDataField
<
uint32_t
>
(
0
*
ELEMENTS
,
321u
));
EXPECT_EQ
(
321u
^
0x2301u
,
reader
.
getDataField
<
uint16_t
>
(
0
*
ELEMENTS
,
321u
));
EXPECT_EQ
(
321u
,
reader
.
getDataField
<
uint64_t
>
(
1
*
ELEMENTS
,
321u
));
EXPECT_EQ
(
0x67452301u
,
reader
.
getDataField
<
uint32_t
>
(
0
*
ELEMENTS
,
321u
));
EXPECT_EQ
(
0xefcdab89u
,
reader
.
getDataField
<
uint32_t
>
(
1
*
ELEMENTS
,
321u
));
EXPECT_EQ
(
321u
,
reader
.
getDataField
<
uint32_t
>
(
2
*
ELEMENTS
,
321u
));
EXPECT_EQ
(
0x2301u
,
reader
.
getDataField
<
uint16_t
>
(
0
*
ELEMENTS
,
321u
));
EXPECT_EQ
(
0x6745u
,
reader
.
getDataField
<
uint16_t
>
(
1
*
ELEMENTS
,
321u
));
EXPECT_EQ
(
0xab89u
,
reader
.
getDataField
<
uint16_t
>
(
2
*
ELEMENTS
,
321u
));
EXPECT_EQ
(
0xefcdu
,
reader
.
getDataField
<
uint16_t
>
(
3
*
ELEMENTS
,
321u
));
EXPECT_EQ
(
321u
,
reader
.
getDataField
<
uint16_t
>
(
4
*
ELEMENTS
,
321u
));
// Bits
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
0
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
1
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
2
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
3
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
4
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
5
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
6
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
7
*
ELEMENTS
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
8
*
ELEMENTS
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
9
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
10
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
11
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
12
*
ELEMENTS
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
13
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
14
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
15
*
ELEMENTS
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
63
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
64
*
ELEMENTS
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
0
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
1
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
2
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
3
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
4
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
5
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
6
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
7
*
ELEMENTS
,
false
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
8
*
ELEMENTS
,
false
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
9
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
10
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
11
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
12
*
ELEMENTS
,
false
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
13
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
14
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
15
*
ELEMENTS
,
false
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
63
*
ELEMENTS
,
false
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
63
*
ELEMENTS
,
true
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
64
*
ELEMENTS
,
false
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
64
*
ELEMENTS
,
true
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
0
*
ELEMENTS
,
true
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
1
*
ELEMENTS
,
true
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
63
*
ELEMENTS
,
true
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
64
*
ELEMENTS
,
true
));
}
static
const
AlignedData
<
6
>
STRUCT_DEFAULT
=
{{
0
,
0
,
0
,
0
,
2
,
0
,
4
,
0
,
0
}};
static
const
AlignedData
<
2
>
SUBSTRUCT_DEFAULT
=
{{
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
}};
static
const
AlignedData
<
3
>
STRUCTLIST_ELEMENT_DEFAULT
=
{{
0
,
0
,
0
,
0
,
1
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
}};
...
...
@@ -106,7 +118,8 @@ static void setupStruct(StructBuilder builder) {
builder
.
setDataField
<
bool
>
(
127
*
ELEMENTS
,
false
);
{
StructBuilder
subStruct
=
builder
.
initStructField
(
0
*
REFERENCES
,
SUBSTRUCT_DEFAULT
.
words
);
StructBuilder
subStruct
=
builder
.
initStructField
(
0
*
REFERENCES
,
StructSize
(
1
*
WORDS
,
0
*
REFERENCES
));
subStruct
.
setDataField
<
uint32_t
>
(
0
*
ELEMENTS
,
123
);
}
...
...
@@ -120,12 +133,12 @@ static void setupStruct(StructBuilder builder) {
{
ListBuilder
list
=
builder
.
initStructListField
(
2
*
REFERENCES
,
4
*
ELEMENTS
,
S
TRUCTLIST_ELEMENT_DEFAULT
.
words
);
2
*
REFERENCES
,
4
*
ELEMENTS
,
S
tructSize
(
1
*
WORDS
,
1
*
REFERENCES
)
);
EXPECT_EQ
(
4
*
ELEMENTS
,
list
.
size
());
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
StructBuilder
element
=
list
.
getStructElement
(
i
*
ELEMENTS
,
2
*
WORDS
/
ELEMENTS
,
1
*
WORDS
);
element
.
setDataField
<
int32_t
>
(
0
*
ELEMENTS
,
300
+
i
);
element
.
initStructField
(
0
*
REFERENCES
,
S
TRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT
.
words
)
element
.
initStructField
(
0
*
REFERENCES
,
S
tructSize
(
1
*
WORDS
,
0
*
REFERENCES
)
)
.
setDataField
<
int32_t
>
(
0
*
ELEMENTS
,
400
+
i
);
}
}
...
...
@@ -159,7 +172,8 @@ static void checkStruct(StructBuilder builder) {
EXPECT_FALSE
(
builder
.
getDataField
<
bool
>
(
127
*
ELEMENTS
));
{
StructBuilder
subStruct
=
builder
.
getStructField
(
0
*
REFERENCES
,
SUBSTRUCT_DEFAULT
.
words
);
StructBuilder
subStruct
=
builder
.
getStructField
(
0
*
REFERENCES
,
StructSize
(
1
*
WORDS
,
0
*
REFERENCES
),
SUBSTRUCT_DEFAULT
.
words
);
EXPECT_EQ
(
123u
,
subStruct
.
getDataField
<
uint32_t
>
(
0
*
ELEMENTS
));
}
...
...
@@ -178,7 +192,8 @@ static void checkStruct(StructBuilder builder) {
StructBuilder
element
=
list
.
getStructElement
(
i
*
ELEMENTS
,
2
*
WORDS
/
ELEMENTS
,
1
*
WORDS
);
EXPECT_EQ
(
300
+
i
,
element
.
getDataField
<
int32_t
>
(
0
*
ELEMENTS
));
EXPECT_EQ
(
400
+
i
,
element
.
getStructField
(
0
*
REFERENCES
,
STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT
.
words
)
element
.
getStructField
(
0
*
REFERENCES
,
StructSize
(
1
*
WORDS
,
0
*
REFERENCES
),
STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT
.
words
)
.
getDataField
<
int32_t
>
(
0
*
ELEMENTS
));
}
}
...
...
@@ -197,22 +212,22 @@ static void checkStruct(StructBuilder builder) {
}
static
void
checkStruct
(
StructReader
reader
)
{
EXPECT_EQ
(
0x1011121314151617ull
,
reader
.
getDataField
<
uint64_t
>
(
0
*
ELEMENTS
,
1616
));
EXPECT_EQ
(
0x20212223u
,
reader
.
getDataField
<
uint32_t
>
(
2
*
ELEMENTS
,
1616
));
EXPECT_EQ
(
0x3031u
,
reader
.
getDataField
<
uint16_t
>
(
6
*
ELEMENTS
,
1616
));
EXPECT_EQ
(
0x40u
,
reader
.
getDataField
<
uint8_t
>
(
14
*
ELEMENTS
,
16
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
120
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
121
*
ELEMENTS
,
false
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
122
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
123
*
ELEMENTS
,
false
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
124
*
ELEMENTS
,
false
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
125
*
ELEMENTS
,
false
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
126
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
127
*
ELEMENTS
,
false
));
EXPECT_EQ
(
0x1011121314151617ull
,
reader
.
getDataField
<
uint64_t
>
(
0
*
ELEMENTS
));
EXPECT_EQ
(
0x20212223u
,
reader
.
getDataField
<
uint32_t
>
(
2
*
ELEMENTS
));
EXPECT_EQ
(
0x3031u
,
reader
.
getDataField
<
uint16_t
>
(
6
*
ELEMENTS
));
EXPECT_EQ
(
0x40u
,
reader
.
getDataField
<
uint8_t
>
(
14
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
120
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
121
*
ELEMENTS
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
122
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
123
*
ELEMENTS
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
124
*
ELEMENTS
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
125
*
ELEMENTS
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
126
*
ELEMENTS
));
EXPECT_FALSE
(
reader
.
getDataField
<
bool
>
(
127
*
ELEMENTS
));
{
StructReader
subStruct
=
reader
.
getStructField
(
0
*
REFERENCES
,
SUBSTRUCT_DEFAULT
.
words
);
EXPECT_EQ
(
123u
,
subStruct
.
getDataField
<
uint32_t
>
(
0
*
ELEMENTS
,
456
));
EXPECT_EQ
(
123u
,
subStruct
.
getDataField
<
uint32_t
>
(
0
*
ELEMENTS
));
}
{
...
...
@@ -227,11 +242,11 @@ static void checkStruct(StructReader reader) {
ListReader
list
=
reader
.
getListField
(
2
*
REFERENCES
,
FieldSize
::
INLINE_COMPOSITE
,
nullptr
);
ASSERT_EQ
(
4
*
ELEMENTS
,
list
.
size
());
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
StructReader
element
=
list
.
getStructElement
(
i
*
ELEMENTS
,
STRUCTLIST_ELEMENT_DEFAULT
.
words
);
EXPECT_EQ
(
300
+
i
,
element
.
getDataField
<
int32_t
>
(
0
*
ELEMENTS
,
1616
));
StructReader
element
=
list
.
getStructElement
(
i
*
ELEMENTS
);
EXPECT_EQ
(
300
+
i
,
element
.
getDataField
<
int32_t
>
(
0
*
ELEMENTS
));
EXPECT_EQ
(
400
+
i
,
element
.
getStructField
(
0
*
REFERENCES
,
STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT
.
words
)
.
getDataField
<
int32_t
>
(
0
*
ELEMENTS
,
1616
));
.
getDataField
<
int32_t
>
(
0
*
ELEMENTS
));
}
}
...
...
@@ -255,7 +270,8 @@ TEST(WireFormat, StructRoundTrip_OneSegment) {
SegmentBuilder
*
segment
=
arena
.
getSegmentWithAvailable
(
1
*
WORDS
);
word
*
rootLocation
=
segment
->
allocate
(
1
*
WORDS
);
StructBuilder
builder
=
StructBuilder
::
initRoot
(
segment
,
rootLocation
,
STRUCT_DEFAULT
.
words
);
StructBuilder
builder
=
StructBuilder
::
initRoot
(
segment
,
rootLocation
,
StructSize
(
2
*
WORDS
,
4
*
REFERENCES
));
setupStruct
(
builder
);
// word count:
...
...
@@ -280,8 +296,8 @@ TEST(WireFormat, StructRoundTrip_OneSegment) {
checkStruct
(
builder
);
checkStruct
(
builder
.
asReader
());
checkStruct
(
StructReader
::
readRootTrusted
(
segment
->
getStartPtr
()
,
nullptr
));
checkStruct
(
StructReader
::
readRoot
(
segment
->
getStartPtr
(),
nullptr
,
segment
,
4
));
checkStruct
(
StructReader
::
readRootTrusted
(
segment
->
getStartPtr
()));
checkStruct
(
StructReader
::
readRoot
(
segment
->
getStartPtr
(),
segment
,
4
));
}
TEST
(
WireFormat
,
StructRoundTrip_OneSegmentPerAllocation
)
{
...
...
@@ -290,7 +306,8 @@ TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation) {
SegmentBuilder
*
segment
=
arena
.
getSegmentWithAvailable
(
1
*
WORDS
);
word
*
rootLocation
=
segment
->
allocate
(
1
*
WORDS
);
StructBuilder
builder
=
StructBuilder
::
initRoot
(
segment
,
rootLocation
,
STRUCT_DEFAULT
.
words
);
StructBuilder
builder
=
StructBuilder
::
initRoot
(
segment
,
rootLocation
,
StructSize
(
2
*
WORDS
,
4
*
REFERENCES
));
setupStruct
(
builder
);
// Verify that we made 15 segments.
...
...
@@ -317,7 +334,7 @@ TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation) {
checkStruct
(
builder
);
checkStruct
(
builder
.
asReader
());
checkStruct
(
StructReader
::
readRoot
(
segment
->
getStartPtr
(),
nullptr
,
segment
,
4
));
checkStruct
(
StructReader
::
readRoot
(
segment
->
getStartPtr
(),
segment
,
4
));
}
TEST
(
WireFormat
,
StructRoundTrip_MultipleSegmentsWithMultipleAllocations
)
{
...
...
@@ -326,7 +343,8 @@ TEST(WireFormat, StructRoundTrip_MultipleSegmentsWithMultipleAllocations) {
SegmentBuilder
*
segment
=
arena
.
getSegmentWithAvailable
(
1
*
WORDS
);
word
*
rootLocation
=
segment
->
allocate
(
1
*
WORDS
);
StructBuilder
builder
=
StructBuilder
::
initRoot
(
segment
,
rootLocation
,
STRUCT_DEFAULT
.
words
);
StructBuilder
builder
=
StructBuilder
::
initRoot
(
segment
,
rootLocation
,
StructSize
(
2
*
WORDS
,
4
*
REFERENCES
));
setupStruct
(
builder
);
// Verify that we made 6 segments.
...
...
@@ -344,7 +362,7 @@ TEST(WireFormat, StructRoundTrip_MultipleSegmentsWithMultipleAllocations) {
checkStruct
(
builder
);
checkStruct
(
builder
.
asReader
());
checkStruct
(
StructReader
::
readRoot
(
segment
->
getStartPtr
(),
nullptr
,
segment
,
4
));
checkStruct
(
StructReader
::
readRoot
(
segment
->
getStartPtr
(),
segment
,
4
));
}
}
// namespace
...
...
c++/src/capnproto/layout.c++
View file @
f966fc41
...
...
@@ -129,6 +129,10 @@ struct WireReference {
dataSize
.
set
(
ds
);
refCount
.
set
(
rc
);
}
CAPNPROTO_ALWAYS_INLINE
(
void
set
(
StructSize
size
))
{
dataSize
.
set
(
size
.
data
);
refCount
.
set
(
size
.
pointers
);
}
}
structRef
;
// Also covers capabilities.
...
...
@@ -403,47 +407,42 @@ struct WireHelpers {
// -----------------------------------------------------------------
static
CAPNPROTO_ALWAYS_INLINE
(
StructBuilder
initStructReference
(
WireReference
*
ref
,
SegmentBuilder
*
segment
,
const
word
*
typeDefaultValue
))
{
const
WireReference
*
defaultRef
=
reinterpret_cast
<
const
WireReference
*>
(
typeDefaultValue
);
// Allocate space for the new struct.
word
*
ptr
=
allocate
(
ref
,
segment
,
defaultRef
->
structRef
.
wordSize
(),
WireReference
::
STRUCT
);
// Copy over the data segment from the default value. We don't have to copy the reference
// segment because it is presumed to be all-null.
memcpy
(
ptr
,
defaultRef
->
target
(),
defaultRef
->
structRef
.
dataSize
.
get
()
*
BYTES_PER_WORD
/
BYTES
);
WireReference
*
ref
,
SegmentBuilder
*
segment
,
StructSize
size
))
{
// Allocate space for the new struct. Newly-allocated space is automatically zeroed.
word
*
ptr
=
allocate
(
ref
,
segment
,
size
.
total
(),
WireReference
::
STRUCT
);
// Initialize the reference.
ref
->
structRef
.
set
(
defaultRef
->
structRef
.
dataSize
.
get
(),
defaultRef
->
structRef
.
refCount
.
get
()
);
ref
->
structRef
.
set
(
size
);
// Build the StructBuilder.
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
defaultRef
->
structRef
.
dataSize
.
get
()));
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
size
.
data
));
}
static
CAPNPROTO_ALWAYS_INLINE
(
StructBuilder
getWritableStructReference
(
WireReference
*
ref
,
SegmentBuilder
*
segment
,
const
word
*
defaultValue
))
{
const
WireReference
*
defaultRef
=
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
);
WireReference
*
ref
,
SegmentBuilder
*
segment
,
StructSize
size
,
const
word
*
defaultValue
))
{
word
*
ptr
;
if
(
ref
->
isNull
())
{
ptr
=
copyMessage
(
segment
,
ref
,
defaultRef
);
if
(
defaultValue
==
nullptr
)
{
ptr
=
allocate
(
ref
,
segment
,
size
.
total
(),
WireReference
::
STRUCT
);
ref
->
structRef
.
set
(
size
);
}
else
{
ptr
=
copyMessage
(
segment
,
ref
,
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
));
}
}
else
{
ptr
=
followFars
(
ref
,
segment
);
CAPNPROTO_DEBUG_ASSERT
(
ref
->
kind
()
==
WireReference
::
STRUCT
,
"Called getStruct{Field,Element}() but existing reference is not a struct."
);
CAPNPROTO_DEBUG_ASSERT
(
ref
->
structRef
.
dataSize
.
get
()
==
defaultRef
->
structRef
.
dataSize
.
get
()
,
ref
->
structRef
.
dataSize
.
get
()
==
size
.
data
,
"Trying to update struct with incorrect data size."
);
CAPNPROTO_DEBUG_ASSERT
(
ref
->
structRef
.
refCount
.
get
()
==
defaultRef
->
structRef
.
refCount
.
get
()
,
ref
->
structRef
.
refCount
.
get
()
==
size
.
pointers
,
"Trying to update struct with incorrect reference count."
);
}
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
defaultRef
->
structRef
.
dataSize
.
get
()));
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
size
.
data
));
}
static
CAPNPROTO_ALWAYS_INLINE
(
ListBuilder
initListReference
(
...
...
@@ -468,10 +467,8 @@ struct WireHelpers {
static
CAPNPROTO_ALWAYS_INLINE
(
ListBuilder
initStructListReference
(
WireReference
*
ref
,
SegmentBuilder
*
segment
,
ElementCount
elementCount
,
const
word
*
elementDefaultValue
))
{
const
WireReference
*
defaultRef
=
reinterpret_cast
<
const
WireReference
*>
(
elementDefaultValue
);
auto
wordsPerElement
=
defaultRef
->
structRef
.
wordSize
()
/
ELEMENTS
;
StructSize
elementSize
))
{
auto
wordsPerElement
=
elementSize
.
total
()
/
ELEMENTS
;
// Allocate the list, prefixed by a single WireReference.
WordCount
wordCount
=
elementCount
*
wordsPerElement
;
...
...
@@ -484,22 +481,9 @@ struct WireHelpers {
// Initialize the list tag.
reinterpret_cast
<
WireReference
*>
(
ptr
)
->
setKindAndInlineCompositeListElementCount
(
WireReference
::
STRUCT
,
elementCount
);
reinterpret_cast
<
WireReference
*>
(
ptr
)
->
structRef
.
set
(
defaultRef
->
structRef
.
dataSize
.
get
(),
defaultRef
->
structRef
.
refCount
.
get
());
reinterpret_cast
<
WireReference
*>
(
ptr
)
->
structRef
.
set
(
elementSize
);
ptr
+=
REFERENCE_SIZE_IN_WORDS
;
// Initialize the elements. We only have to copy the data segments, as the reference segment
// in a struct type default value is always all-null.
ByteCount
elementDataByteSize
=
defaultRef
->
structRef
.
dataSize
.
get
()
*
BYTES_PER_WORD
;
const
word
*
defaultData
=
defaultRef
->
target
();
word
*
elementPtr
=
ptr
;
uint
n
=
elementCount
/
ELEMENTS
;
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
{
memcpy
(
elementPtr
,
defaultData
,
elementDataByteSize
/
BYTES
);
elementPtr
+=
1
*
ELEMENTS
*
wordsPerElement
;
}
// Build the ListBuilder.
return
ListBuilder
(
segment
,
ptr
,
elementCount
);
}
...
...
@@ -618,6 +602,10 @@ struct WireHelpers {
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
useDefault
:
if
(
defaultValue
==
nullptr
)
{
return
StructReader
(
nullptr
,
nullptr
,
nullptr
,
0
*
WORDS
,
0
*
REFERENCES
,
0
*
BITS
,
std
::
numeric_limits
<
int
>::
max
());
}
segment
=
nullptr
;
ref
=
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
);
ptr
=
ref
->
target
();
...
...
@@ -940,25 +928,26 @@ struct WireHelpers {
// =======================================================================================
StructBuilder
StructBuilder
::
initRoot
(
SegmentBuilder
*
segment
,
word
*
location
,
const
word
*
defaultValu
e
)
{
SegmentBuilder
*
segment
,
word
*
location
,
StructSize
siz
e
)
{
return
WireHelpers
::
initStructReference
(
reinterpret_cast
<
WireReference
*>
(
location
),
segment
,
defaultValu
e
);
reinterpret_cast
<
WireReference
*>
(
location
),
segment
,
siz
e
);
}
StructBuilder
StructBuilder
::
getRoot
(
SegmentBuilder
*
segment
,
word
*
location
,
const
word
*
defaultValu
e
)
{
SegmentBuilder
*
segment
,
word
*
location
,
StructSize
siz
e
)
{
return
WireHelpers
::
getWritableStructReference
(
reinterpret_cast
<
WireReference
*>
(
location
),
segment
,
defaultValue
);
reinterpret_cast
<
WireReference
*>
(
location
),
segment
,
size
,
nullptr
);
}
StructBuilder
StructBuilder
::
initStructField
(
WireReferenceCount
refIndex
,
const
word
*
typeDefaultValu
e
)
const
{
return
WireHelpers
::
initStructReference
(
references
+
refIndex
,
segment
,
typeDefaultValu
e
);
WireReferenceCount
refIndex
,
StructSize
siz
e
)
const
{
return
WireHelpers
::
initStructReference
(
references
+
refIndex
,
segment
,
siz
e
);
}
StructBuilder
StructBuilder
::
getStructField
(
WireReferenceCount
refIndex
,
const
word
*
defaultValue
)
const
{
return
WireHelpers
::
getWritableStructReference
(
references
+
refIndex
,
segment
,
defaultValue
);
WireReferenceCount
refIndex
,
StructSize
size
,
const
word
*
defaultValue
)
const
{
return
WireHelpers
::
getWritableStructReference
(
references
+
refIndex
,
segment
,
size
,
defaultValue
);
}
ListBuilder
StructBuilder
::
initListField
(
...
...
@@ -969,10 +958,9 @@ ListBuilder StructBuilder::initListField(
}
ListBuilder
StructBuilder
::
initStructListField
(
WireReferenceCount
refIndex
,
ElementCount
elementCount
,
const
word
*
elementDefaultValue
)
const
{
WireReferenceCount
refIndex
,
ElementCount
elementCount
,
StructSize
elementSize
)
const
{
return
WireHelpers
::
initStructListReference
(
references
+
refIndex
,
segment
,
elementCount
,
element
DefaultValu
e
);
references
+
refIndex
,
segment
,
elementCount
,
element
Siz
e
);
}
ListBuilder
StructBuilder
::
getListField
(
...
...
@@ -1016,20 +1004,25 @@ StructReader StructBuilder::asReader() const {
0xffff
*
WORDS
,
0xffff
*
REFERENCES
,
0
*
BITS
,
std
::
numeric_limits
<
int
>::
max
());
}
StructReader
StructReader
::
readRootTrusted
(
const
word
*
location
,
const
word
*
defaultValue
)
{
StructReader
StructReader
::
readRootTrusted
(
const
word
*
location
)
{
return
WireHelpers
::
readStructReference
(
nullptr
,
reinterpret_cast
<
const
WireReference
*>
(
location
),
defaultValue
,
std
::
numeric_limits
<
int
>::
max
());
nullptr
,
std
::
numeric_limits
<
int
>::
max
());
}
StructReader
StructReader
::
readRoot
(
const
word
*
location
,
const
word
*
defaultValue
,
SegmentReader
*
segment
,
int
nestingLimit
)
{
StructReader
StructReader
::
readRoot
(
const
word
*
location
,
SegmentReader
*
segment
,
int
nestingLimit
)
{
if
(
!
segment
->
containsInterval
(
location
,
location
+
REFERENCE_SIZE_IN_WORDS
))
{
segment
->
getArena
()
->
reportInvalidData
(
"Root location out-of-bounds."
);
location
=
nullptr
;
}
return
WireHelpers
::
readStructReference
(
segment
,
reinterpret_cast
<
const
WireReference
*>
(
location
),
defaultValue
,
nestingLimit
);
nullptr
,
nestingLimit
);
}
StructReader
StructReader
::
readEmpty
()
{
return
StructReader
(
nullptr
,
nullptr
,
nullptr
,
0
*
WORDS
,
0
*
REFERENCES
,
0
*
BITS
,
std
::
numeric_limits
<
int
>::
max
());
}
StructReader
StructReader
::
getStructField
(
...
...
@@ -1072,10 +1065,10 @@ ListBuilder ListBuilder::initListElement(
}
ListBuilder
ListBuilder
::
initStructListElement
(
WireReferenceCount
index
,
ElementCount
elementCount
,
const
word
*
elementDefaultValu
e
)
const
{
WireReferenceCount
index
,
ElementCount
elementCount
,
StructSize
elementSiz
e
)
const
{
return
WireHelpers
::
initStructListReference
(
reinterpret_cast
<
WireReference
*>
(
ptr
)
+
index
,
segment
,
elementCount
,
element
DefaultValu
e
);
elementCount
,
element
Siz
e
);
}
ListBuilder
ListBuilder
::
getListElement
(
WireReferenceCount
index
)
const
{
...
...
@@ -1123,11 +1116,11 @@ ListReader ListBuilder::asReader(WordCount dataSize, WireReferenceCount referenc
dataSize
,
referenceCount
,
std
::
numeric_limits
<
int
>::
max
());
}
StructReader
ListReader
::
getStructElement
(
ElementCount
index
,
const
word
*
defaultValue
)
const
{
StructReader
ListReader
::
getStructElement
(
ElementCount
index
)
const
{
if
(
CAPNPROTO_EXPECT_FALSE
((
segment
!=
nullptr
)
&
(
nestingLimit
==
0
)))
{
segment
->
getArena
()
->
reportInvalidData
(
"Message is too deeply-nested or contains cycles. See capnproto::ReadOptions."
);
return
WireHelpers
::
readStructReference
(
nullptr
,
nullptr
,
defaultValue
,
nestingLimit
);
return
StructReader
::
readEmpty
(
);
}
else
{
BitCount64
indexBit
=
ElementCount64
(
index
)
*
stepBits
;
const
byte
*
structPtr
=
reinterpret_cast
<
const
byte
*>
(
ptr
)
+
indexBit
/
BITS_PER_BYTE
;
...
...
c++/src/capnproto/layout.h
View file @
f966fc41
...
...
@@ -123,6 +123,91 @@ union AlignedData {
word
words
[
wordCount
];
};
struct
StructSize
{
WordCount16
data
;
WireReferenceCount16
pointers
;
inline
constexpr
WordCount
total
()
const
{
return
data
+
pointers
*
WORDS_PER_REFERENCE
;
}
StructSize
()
=
default
;
inline
constexpr
StructSize
(
WordCount
data
,
WireReferenceCount
pointers
)
:
data
(
data
),
pointers
(
pointers
)
{}
};
template
<
typename
T
>
class
IsEnum
{
// Detects whether a primitive value is an enum.
typedef
char
no
;
typedef
long
yes
;
static
no
test
(
int
i
);
static
yes
test
(...);
public
:
static
constexpr
bool
value
=
sizeof
(
test
(
T
()))
==
sizeof
(
yes
);
};
// -------------------------------------------------------------------
// Masking of default values
template
<
typename
T
,
bool
isEnum
=
IsEnum
<
T
>::
value
>
struct
MaskType
{
typedef
T
Type
;
};
template
<
typename
T
>
struct
MaskType
<
T
,
false
>
{
typedef
T
Type
;
};
template
<
typename
T
>
struct
MaskType
<
T
,
true
>
{
typedef
uint16_t
Type
;
};
template
<>
struct
MaskType
<
float
,
false
>
{
typedef
uint32_t
Type
;
};
template
<>
struct
MaskType
<
double
,
false
>
{
typedef
uint64_t
Type
;
};
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
typename
MaskType
<
T
>::
Type
mask
(
T
value
,
typename
MaskType
<
T
>::
Type
mask
));
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
T
unmask
(
typename
MaskType
<
T
>::
Type
value
,
typename
MaskType
<
T
>::
Type
mask
));
template
<
typename
T
>
inline
typename
MaskType
<
T
>::
Type
mask
(
T
value
,
typename
MaskType
<
T
>::
Type
mask
)
{
return
static_cast
<
typename
MaskType
<
T
>::
Type
>
(
value
)
^
mask
;
}
template
<>
inline
uint32_t
mask
<
float
>
(
float
value
,
uint32_t
mask
)
{
uint32_t
i
;
static_assert
(
sizeof
(
i
)
==
sizeof
(
value
),
"float is not 32 bits?"
);
memcpy
(
&
i
,
&
value
,
sizeof
(
value
));
return
i
^
mask
;
}
template
<>
inline
uint64_t
mask
<
double
>
(
double
value
,
uint64_t
mask
)
{
uint64_t
i
;
static_assert
(
sizeof
(
i
)
==
sizeof
(
value
),
"double is not 64 bits?"
);
memcpy
(
&
i
,
&
value
,
sizeof
(
value
));
return
i
^
mask
;
}
template
<
typename
T
>
inline
T
unmask
(
typename
MaskType
<
T
>::
Type
value
,
typename
MaskType
<
T
>::
Type
mask
)
{
return
static_cast
<
T
>
(
value
^
mask
);
}
template
<>
inline
float
unmask
<
float
>
(
uint32_t
value
,
uint32_t
mask
)
{
value
^=
mask
;
float
result
;
static_assert
(
sizeof
(
result
)
==
sizeof
(
value
),
"float is not 32 bits?"
);
memcpy
(
&
result
,
&
value
,
sizeof
(
value
));
return
result
;
}
template
<>
inline
double
unmask
<
double
>
(
uint64_t
value
,
uint64_t
mask
)
{
value
^=
mask
;
double
result
;
static_assert
(
sizeof
(
result
)
==
sizeof
(
value
),
"double is not 64 bits?"
);
memcpy
(
&
result
,
&
value
,
sizeof
(
value
));
return
result
;
}
// -------------------------------------------------------------------
template
<
typename
T
>
...
...
@@ -154,30 +239,42 @@ class StructBuilder {
public
:
inline
StructBuilder
()
:
segment
(
nullptr
),
data
(
nullptr
),
references
(
nullptr
)
{}
static
StructBuilder
initRoot
(
SegmentBuilder
*
segment
,
word
*
location
,
const
word
*
defaultValu
e
);
static
StructBuilder
getRoot
(
SegmentBuilder
*
segment
,
word
*
location
,
const
word
*
defaultValu
e
);
static
StructBuilder
initRoot
(
SegmentBuilder
*
segment
,
word
*
location
,
StructSize
siz
e
);
static
StructBuilder
getRoot
(
SegmentBuilder
*
segment
,
word
*
location
,
StructSize
siz
e
);
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
T
getDataField
(
ElementCount
offset
)
const
);
// Gets the data field value of the given type at the given offset. The offset is measured in
// multiples of the field size, determined by the type.
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
T
getDataField
(
ElementCount
offset
,
typename
MaskType
<
T
>::
Type
mask
)
const
);
// Like getDataField() but applies the given XOR mask to the data on load. Used for reading
// fields with non-zero default values.
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
void
setDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
value
)
const
);
// Sets the data field value at the given offset.
StructBuilder
initStructField
(
WireReferenceCount
refIndex
,
const
word
*
typeDefaultValue
)
const
;
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
void
setDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
value
,
typename
MaskType
<
T
>::
Type
mask
)
const
);
// Like setDataField() but applies the given XOR mask before storing. Used for writing fields
// with non-zero default values.
StructBuilder
initStructField
(
WireReferenceCount
refIndex
,
StructSize
size
)
const
;
// Initializes the struct field at the given index in the reference segment. If it is already
// initialized, the previous value is discarded or overwritten. The struct is initialized to
// match the given default value (a trusted message). This must be the default value for the
// *type*, not the specific field, and in particular its reference segment is expected to be
// all nulls (only the data segment is copied). Use getStructField() if you want the struct
// to be initialized as a copy of the field's default value (which may have non-null references).
// the type's default state (all-zero). Use getStructField() if you want the struct to be
// initialized as a copy of the field's default value (which may have non-null references).
StructBuilder
getStructField
(
WireReferenceCount
refIndex
,
const
word
*
defaultValue
)
const
;
StructBuilder
getStructField
(
WireReferenceCount
refIndex
,
StructSize
size
,
const
word
*
defaultValue
)
const
;
// Gets the struct field at the given index in the reference segment. If the field is not already
// initialized, it is initialized as a deep copy of the given default value (a trusted message).
// initialized, it is initialized as a deep copy of the given default value (a trusted message),
// or to the empty state if defaultValue is nullptr.
ListBuilder
initListField
(
WireReferenceCount
refIndex
,
FieldSize
elementSize
,
ElementCount
elementCount
)
const
;
...
...
@@ -185,11 +282,9 @@ public:
// segment, and return a pointer to it. All elements are initialized to zero.
ListBuilder
initStructListField
(
WireReferenceCount
refIndex
,
ElementCount
elementCount
,
const
word
*
elementDefaultValu
e
)
const
;
StructSize
siz
e
)
const
;
// Allocates a new list of the given size for the field at the given index in the reference
// segment, and return a pointer to it. Each element is initialized as a copy of
// elementDefaultValue. As with initStructField(), this should be the default value for the
// *type*, with all-null references.
// segment, and return a pointer to it. Each element is initialized to its empty state.
ListBuilder
getListField
(
WireReferenceCount
refIndex
,
const
word
*
defaultValue
)
const
;
// Gets the already-allocated list field for the given reference index. If the list is not
...
...
@@ -234,21 +329,27 @@ public:
:
segment
(
nullptr
),
data
(
nullptr
),
references
(
nullptr
),
dataSize
(
0
),
referenceCount
(
0
),
bit0Offset
(
0
*
BITS
),
nestingLimit
(
0
)
{}
static
StructReader
readRootTrusted
(
const
word
*
location
,
const
word
*
defaultValue
);
static
StructReader
readRoot
(
const
word
*
location
,
const
word
*
defaultValue
,
SegmentReader
*
segment
,
int
nestingLimit
);
static
StructReader
readRootTrusted
(
const
word
*
location
);
static
StructReader
readRoot
(
const
word
*
location
,
SegmentReader
*
segment
,
int
nestingLimit
);
static
StructReader
readEmpty
(
);
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
T
getDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
defaultValue
)
const
);
CAPNPROTO_ALWAYS_INLINE
(
T
getDataField
(
ElementCount
offset
)
const
);
// Get the data field value of the given type at the given offset. The offset is measured in
// multiples of the field size, determined by the type. Returns the default value if the offset
// is past the end of the struct's data segment.
// multiples of the field size, determined by the type. Returns zero if the offset is past the
// end of the struct's data segment.
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
T
getDataField
(
ElementCount
offset
,
typename
MaskType
<
T
>::
Type
mask
)
const
);
// Like getDataField(offset), but applies the given XOR mask to the result. Used for reading
// fields with non-zero default values.
StructReader
getStructField
(
WireReferenceCount
refIndex
,
const
word
*
defaultValue
)
const
;
// Get the struct field at the given index in the reference segment, or the default value if not
// initialized. defaultValue will be interpreted as a trusted message -- it must point at a
// struct reference, which in turn points at the struct value.
// struct reference, which in turn points at the struct value. The default value is allowed to
// be null, in which case an empty struct is used.
ListReader
getListField
(
WireReferenceCount
refIndex
,
FieldSize
expectedElementSize
,
const
word
*
defaultValue
)
const
;
...
...
@@ -322,11 +423,9 @@ public:
// to zero.
ListBuilder
initStructListElement
(
WireReferenceCount
index
,
ElementCount
elementCount
,
const
word
*
elementDefaultValu
e
)
const
;
StructSize
siz
e
)
const
;
// Allocates a new list of the given size for the field at the given index in the reference
// segment, and return a pointer to it. Each element is initialized as a copy of
// elementDefaultValue. As with StructBuilder::initStructListElement(), this should be the
// default value for the *type*, with all-null references.
// segment, and return a pointer to it. Each element is initialized to its empty state.
ListBuilder
getListElement
(
WireReferenceCount
index
)
const
;
// Get the existing list element at the given index. Returns an empty list if the element is
...
...
@@ -378,7 +477,7 @@ public:
CAPNPROTO_ALWAYS_INLINE
(
T
getDataElement
(
ElementCount
index
)
const
);
// Get the element of the given type at the given index.
StructReader
getStructElement
(
ElementCount
index
,
const
word
*
defaultValue
)
const
;
StructReader
getStructElement
(
ElementCount
index
)
const
;
// Get the struct element at the given index.
ListReader
getListElement
(
WireReferenceCount
index
,
FieldSize
expectedElementSize
)
const
;
...
...
@@ -451,6 +550,11 @@ inline Void StructBuilder::getDataField<Void>(ElementCount offset) const {
return
Void
::
VOID
;
}
template
<
typename
T
>
inline
T
StructBuilder
::
getDataField
(
ElementCount
offset
,
typename
MaskType
<
T
>::
Type
mask
)
const
{
return
unmask
<
T
>
(
getDataField
<
typename
MaskType
<
T
>::
Type
>
(
offset
),
mask
);
}
template
<
typename
T
>
inline
void
StructBuilder
::
setDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
value
)
const
{
...
...
@@ -469,19 +573,25 @@ inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) c
template
<>
inline
void
StructBuilder
::
setDataField
<
Void
>
(
ElementCount
offset
,
Void
value
)
const
{}
template
<
typename
T
>
inline
void
StructBuilder
::
setDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
value
,
typename
MaskType
<
T
>::
Type
m
)
const
{
setDataField
<
typename
MaskType
<
T
>::
Type
>
(
offset
,
mask
<
T
>
(
value
,
m
));
}
// -------------------------------------------------------------------
template
<
typename
T
>
T
StructReader
::
getDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
defaultValue
)
const
{
T
StructReader
::
getDataField
(
ElementCount
offset
)
const
{
if
(
offset
*
bytesPerElement
<
T
>
()
<
dataSize
*
BYTES_PER_WORD
)
{
return
reinterpret_cast
<
const
WireValue
<
T
>*>
(
data
)[
offset
/
ELEMENTS
].
get
();
}
else
{
return
defaultValue
;
return
static_cast
<
T
>
(
0
)
;
}
}
template
<>
inline
bool
StructReader
::
getDataField
<
bool
>
(
ElementCount
offset
,
bool
defaultValue
)
const
{
inline
bool
StructReader
::
getDataField
<
bool
>
(
ElementCount
offset
)
const
{
BitCount
boffset
=
offset
*
(
1
*
BITS
/
ELEMENTS
);
// This branch should always be optimized away when inlining.
...
...
@@ -491,15 +601,20 @@ inline bool StructReader::getDataField<bool>(ElementCount offset, bool defaultVa
const
byte
*
b
=
reinterpret_cast
<
const
byte
*>
(
data
)
+
boffset
/
BITS_PER_BYTE
;
return
(
*
reinterpret_cast
<
const
uint8_t
*>
(
b
)
&
(
1
<<
(
boffset
%
BITS_PER_BYTE
/
BITS
)))
!=
0
;
}
else
{
return
defaultValu
e
;
return
fals
e
;
}
}
template
<>
inline
Void
StructReader
::
getDataField
<
Void
>
(
ElementCount
offset
,
Void
defaultValue
)
const
{
inline
Void
StructReader
::
getDataField
<
Void
>
(
ElementCount
offset
)
const
{
return
Void
::
VOID
;
}
template
<
typename
T
>
T
StructReader
::
getDataField
(
ElementCount
offset
,
typename
MaskType
<
T
>::
Type
mask
)
const
{
return
unmask
<
T
>
(
getDataField
<
typename
MaskType
<
T
>::
Type
>
(
offset
),
mask
);
}
// -------------------------------------------------------------------
inline
ElementCount
ListBuilder
::
size
()
{
return
elementCount
;
}
...
...
c++/src/capnproto/list.h
View file @
f966fc41
...
...
@@ -216,7 +216,7 @@ struct List<T, false> {
inline
uint
size
()
{
return
reader
.
size
()
/
ELEMENTS
;
}
inline
typename
T
::
Reader
operator
[](
uint
index
)
{
return
typename
T
::
Reader
(
reader
.
getStructElement
(
index
*
ELEMENTS
,
T
::
DEFAULT
.
words
));
return
typename
T
::
Reader
(
reader
.
getStructElement
(
index
*
ELEMENTS
));
}
typedef
internal
::
IndexingIterator
<
Reader
,
typename
T
::
Reader
>
iterator
;
...
...
@@ -235,8 +235,7 @@ struct List<T, false> {
inline
uint
size
()
{
return
builder
.
size
()
/
ELEMENTS
;
}
inline
typename
T
::
Builder
operator
[](
uint
index
)
{
return
typename
T
::
Builder
(
builder
.
getStructElement
(
index
*
ELEMENTS
,
(
T
::
DATA_SIZE
+
T
::
REFERENCE_COUNT
*
WORDS_PER_REFERENCE
)
/
ELEMENTS
,
T
::
DATA_SIZE
));
T
::
STRUCT_SIZE
.
total
()
/
ELEMENTS
,
T
::
STRUCT_SIZE
.
data
));
}
typedef
internal
::
IndexingIterator
<
Builder
,
typename
T
::
Builder
>
iterator
;
...
...
c++/src/capnproto/message.c++
View file @
f966fc41
...
...
@@ -38,7 +38,7 @@ MessageReader::~MessageReader() {
}
}
internal
::
StructReader
MessageReader
::
getRoot
(
const
word
*
defaultValue
)
{
internal
::
StructReader
MessageReader
::
getRoot
Internal
(
)
{
if
(
!
allocatedArena
)
{
static_assert
(
sizeof
(
internal
::
ReaderArena
)
<=
sizeof
(
arenaSpace
),
"arenaSpace is too small to hold a ReaderArena. Please increase it. This will break "
...
...
@@ -51,10 +51,9 @@ internal::StructReader MessageReader::getRoot(const word* defaultValue) {
if
(
segment
==
nullptr
||
!
segment
->
containsInterval
(
segment
->
getStartPtr
(),
segment
->
getStartPtr
()
+
1
))
{
arena
()
->
reportInvalidData
(
"Message did not contain a root pointer."
);
return
internal
::
StructReader
::
read
RootTrusted
(
defaultValue
,
defaultValue
);
return
internal
::
StructReader
::
read
Empty
(
);
}
else
{
return
internal
::
StructReader
::
readRoot
(
segment
->
getStartPtr
(),
defaultValue
,
segment
,
options
.
nestingLimit
);
return
internal
::
StructReader
::
readRoot
(
segment
->
getStartPtr
(),
segment
,
options
.
nestingLimit
);
}
}
...
...
@@ -88,16 +87,16 @@ internal::SegmentBuilder* MessageBuilder::getRootSegment() {
}
}
internal
::
StructBuilder
MessageBuilder
::
initRoot
(
const
word
*
defaultValu
e
)
{
internal
::
StructBuilder
MessageBuilder
::
initRoot
(
internal
::
StructSize
siz
e
)
{
internal
::
SegmentBuilder
*
rootSegment
=
getRootSegment
();
return
internal
::
StructBuilder
::
initRoot
(
rootSegment
,
rootSegment
->
getPtrUnchecked
(
0
*
WORDS
),
defaultValu
e
);
rootSegment
,
rootSegment
->
getPtrUnchecked
(
0
*
WORDS
),
siz
e
);
}
internal
::
StructBuilder
MessageBuilder
::
getRoot
(
const
word
*
defaultValu
e
)
{
internal
::
StructBuilder
MessageBuilder
::
getRoot
(
internal
::
StructSize
siz
e
)
{
internal
::
SegmentBuilder
*
rootSegment
=
getRootSegment
();
return
internal
::
StructBuilder
::
getRoot
(
rootSegment
,
rootSegment
->
getPtrUnchecked
(
0
*
WORDS
),
defaultValu
e
);
rootSegment
,
rootSegment
->
getPtrUnchecked
(
0
*
WORDS
),
siz
e
);
}
ArrayPtr
<
const
ArrayPtr
<
const
word
>>
MessageBuilder
::
getSegmentsForOutput
()
{
...
...
c++/src/capnproto/message.h
View file @
f966fc41
...
...
@@ -144,7 +144,7 @@ private:
bool
allocatedArena
;
internal
::
ReaderArena
*
arena
()
{
return
reinterpret_cast
<
internal
::
ReaderArena
*>
(
arenaSpace
);
}
internal
::
StructReader
getRoot
(
const
word
*
defaultValue
);
internal
::
StructReader
getRoot
Internal
(
);
};
class
MessageBuilder
{
...
...
@@ -175,8 +175,8 @@ private:
internal
::
BuilderArena
*
arena
()
{
return
reinterpret_cast
<
internal
::
BuilderArena
*>
(
arenaSpace
);
}
internal
::
SegmentBuilder
*
getRootSegment
();
internal
::
StructBuilder
initRoot
(
const
word
*
defaultValu
e
);
internal
::
StructBuilder
getRoot
(
const
word
*
defaultValu
e
);
internal
::
StructBuilder
initRoot
(
internal
::
StructSize
siz
e
);
internal
::
StructBuilder
getRoot
(
internal
::
StructSize
siz
e
);
};
template
<
typename
RootType
>
...
...
@@ -297,23 +297,22 @@ inline const ReaderOptions& MessageReader::getOptions() {
template
<
typename
RootType
>
inline
typename
RootType
::
Reader
MessageReader
::
getRoot
()
{
return
typename
RootType
::
Reader
(
getRoot
(
RootType
::
DEFAULT
.
words
));
return
typename
RootType
::
Reader
(
getRoot
Internal
(
));
}
template
<
typename
RootType
>
inline
typename
RootType
::
Builder
MessageBuilder
::
initRoot
()
{
return
typename
RootType
::
Builder
(
initRoot
(
RootType
::
DEFAULT
.
words
));
return
typename
RootType
::
Builder
(
initRoot
(
RootType
::
STRUCT_SIZE
));
}
template
<
typename
RootType
>
inline
typename
RootType
::
Builder
MessageBuilder
::
getRoot
()
{
return
typename
RootType
::
Builder
(
getRoot
(
RootType
::
DEFAULT
.
words
));
return
typename
RootType
::
Builder
(
getRoot
(
RootType
::
STRUCT_SIZE
));
}
template
<
typename
RootType
>
typename
RootType
::
Reader
readMessageTrusted
(
const
word
*
data
)
{
return
typename
RootType
::
Reader
(
internal
::
StructReader
::
readRootTrusted
(
data
,
RootType
::
DEFAULT
.
words
));
return
typename
RootType
::
Reader
(
internal
::
StructReader
::
readRootTrusted
(
data
));
}
}
// namespace capnproto
...
...
c++/src/capnproto/test.capnp
View file @
f966fc41
...
...
@@ -67,7 +67,7 @@ struct TestAllTypes {
dataList @30 : List(Data);
structList @31 : List(TestAllTypes);
enumList @32 : List(TestEnum);
interfaceList @33 :
Void
; # TODO
interfaceList @33 :
List(Void)
; # TODO
}
struct TestDefaults {
...
...
compiler/src/CxxGenerator.hs
View file @
f966fc41
...
...
@@ -29,6 +29,7 @@ import qualified Data.ByteString.UTF8 as ByteStringUTF8
import
Data.FileEmbed
(
embedFile
)
import
Data.Word
(
Word8
)
import
qualified
Data.Digest.MD5
as
MD5
import
Data.Binary.IEEE754
(
floatToWord
,
doubleToWord
)
import
Text.Printf
(
printf
)
import
Text.Hastache
import
Text.Hastache.Context
...
...
@@ -106,25 +107,41 @@ cxxFieldSizeString Size64 = "EIGHT_BYTES";
cxxFieldSizeString
SizeReference
=
"REFERENCE"
;
cxxFieldSizeString
(
SizeInlineComposite
_
_
)
=
"INLINE_COMPOSITE"
;
cxxValueString
VoidDesc
=
" ::capnproto::Void::VOID"
cxxValueString
(
BoolDesc
b
)
=
if
b
then
"true"
else
"false"
cxxValueString
(
Int8Desc
i
)
=
show
i
cxxValueString
(
Int16Desc
i
)
=
show
i
cxxValueString
(
Int32Desc
i
)
=
show
i
cxxValueString
(
Int64Desc
i
)
=
show
i
++
"ll"
cxxValueString
(
UInt8Desc
i
)
=
show
i
cxxValueString
(
UInt16Desc
i
)
=
show
i
cxxValueString
(
UInt32Desc
i
)
=
show
i
++
"u"
cxxValueString
(
UInt64Desc
i
)
=
show
i
++
"llu"
cxxValueString
(
Float32Desc
x
)
=
show
x
++
"f"
cxxValueString
(
Float64Desc
x
)
=
show
x
cxxValueString
(
EnumValueValueDesc
v
)
=
cxxTypeString
(
EnumType
$
enumValueParent
v
)
++
"::"
++
toUpperCaseWithUnderscores
(
enumValueName
v
)
cxxValueString
(
TextDesc
_
)
=
error
"No default value literal for aggregate type."
cxxValueString
(
DataDesc
_
)
=
error
"No default value literal for aggregate type."
cxxValueString
(
StructValueDesc
_
)
=
error
"No default value literal for aggregate type."
cxxValueString
(
ListDesc
_
)
=
error
"No default value literal for aggregate type."
isDefaultZero
VoidDesc
=
True
isDefaultZero
(
BoolDesc
b
)
=
not
b
isDefaultZero
(
Int8Desc
i
)
=
i
==
0
isDefaultZero
(
Int16Desc
i
)
=
i
==
0
isDefaultZero
(
Int32Desc
i
)
=
i
==
0
isDefaultZero
(
Int64Desc
i
)
=
i
==
0
isDefaultZero
(
UInt8Desc
i
)
=
i
==
0
isDefaultZero
(
UInt16Desc
i
)
=
i
==
0
isDefaultZero
(
UInt32Desc
i
)
=
i
==
0
isDefaultZero
(
UInt64Desc
i
)
=
i
==
0
isDefaultZero
(
Float32Desc
x
)
=
x
==
0
isDefaultZero
(
Float64Desc
x
)
=
x
==
0
isDefaultZero
(
EnumValueValueDesc
v
)
=
enumValueNumber
v
==
0
isDefaultZero
(
TextDesc
_
)
=
error
"Can't call isDefaultZero on aggregate types."
isDefaultZero
(
DataDesc
_
)
=
error
"Can't call isDefaultZero on aggregate types."
isDefaultZero
(
StructValueDesc
_
)
=
error
"Can't call isDefaultZero on aggregate types."
isDefaultZero
(
ListDesc
_
)
=
error
"Can't call isDefaultZero on aggregate types."
defaultMask
VoidDesc
=
"0"
defaultMask
(
BoolDesc
b
)
=
if
b
then
"true"
else
"false"
defaultMask
(
Int8Desc
i
)
=
show
i
defaultMask
(
Int16Desc
i
)
=
show
i
defaultMask
(
Int32Desc
i
)
=
show
i
defaultMask
(
Int64Desc
i
)
=
show
i
++
"ll"
defaultMask
(
UInt8Desc
i
)
=
show
i
defaultMask
(
UInt16Desc
i
)
=
show
i
defaultMask
(
UInt32Desc
i
)
=
show
i
++
"u"
defaultMask
(
UInt64Desc
i
)
=
show
i
++
"llu"
defaultMask
(
Float32Desc
x
)
=
show
(
floatToWord
x
)
++
"u"
defaultMask
(
Float64Desc
x
)
=
show
(
doubleToWord
x
)
++
"ul"
defaultMask
(
EnumValueValueDesc
v
)
=
show
(
enumValueNumber
v
)
defaultMask
(
TextDesc
_
)
=
error
"Can't call defaultMask on aggregate types."
defaultMask
(
DataDesc
_
)
=
error
"Can't call defaultMask on aggregate types."
defaultMask
(
StructValueDesc
_
)
=
error
"Can't call defaultMask on aggregate types."
defaultMask
(
ListDesc
_
)
=
error
"Can't call defaultMask on aggregate types."
defaultValueBytes
_
(
TextDesc
s
)
=
Just
(
UTF8
.
encode
s
++
[
0
])
defaultValueBytes
_
(
DataDesc
d
)
=
Just
d
...
...
@@ -132,25 +149,6 @@ defaultValueBytes t v@(StructValueDesc _) = Just $ encodeMessage t v
defaultValueBytes
t
v
@
(
ListDesc
_
)
=
Just
$
encodeMessage
t
v
defaultValueBytes
_
_
=
Nothing
cxxDefaultDefault
(
BuiltinType
BuiltinVoid
)
=
" ::capnproto::Void::VOID"
cxxDefaultDefault
(
BuiltinType
BuiltinBool
)
=
"false"
cxxDefaultDefault
(
BuiltinType
BuiltinInt8
)
=
"0"
cxxDefaultDefault
(
BuiltinType
BuiltinInt16
)
=
"0"
cxxDefaultDefault
(
BuiltinType
BuiltinInt32
)
=
"0"
cxxDefaultDefault
(
BuiltinType
BuiltinInt64
)
=
"0"
cxxDefaultDefault
(
BuiltinType
BuiltinUInt8
)
=
"0"
cxxDefaultDefault
(
BuiltinType
BuiltinUInt16
)
=
"0"
cxxDefaultDefault
(
BuiltinType
BuiltinUInt32
)
=
"0"
cxxDefaultDefault
(
BuiltinType
BuiltinUInt64
)
=
"0"
cxxDefaultDefault
(
BuiltinType
BuiltinFloat32
)
=
"0"
cxxDefaultDefault
(
BuiltinType
BuiltinFloat64
)
=
"0"
cxxDefaultDefault
(
BuiltinType
BuiltinText
)
=
"
\"\"
"
cxxDefaultDefault
(
EnumType
desc
)
=
cxxValueString
$
EnumValueValueDesc
$
head
$
enumValues
desc
cxxDefaultDefault
(
BuiltinType
BuiltinData
)
=
error
"No default value literal for aggregate type."
cxxDefaultDefault
(
StructType
_
)
=
error
"No default value literal for aggregate type."
cxxDefaultDefault
(
InterfaceType
_
)
=
error
"No default value literal for aggregate type."
cxxDefaultDefault
(
ListType
_
)
=
error
"No default value literal for aggregate type."
elementType
(
ListType
t
)
=
t
elementType
_
=
error
"Called elementType on non-list."
...
...
@@ -197,9 +195,9 @@ fieldContext parent desc = mkStrContext context where
context
"fieldType"
=
MuVariable
$
cxxTypeString
$
fieldType
desc
context
"fieldBlobType"
=
MuVariable
$
blobTypeString
$
fieldType
desc
context
"fieldOffset"
=
MuVariable
$
fieldOffset
desc
context
"fieldDefault
Value
"
=
case
fieldDefaultValue
desc
of
Just
v
->
MuVariable
$
cxxValueString
v
Nothing
->
MuVariable
$
cxxDefaultDefault
$
fieldType
desc
context
"fieldDefault
Mask
"
=
case
fieldDefaultValue
desc
of
Nothing
->
MuVariable
""
Just
v
->
MuVariable
(
if
isDefaultZero
v
then
""
else
", "
++
defaultMask
v
)
context
"fieldElementSize"
=
MuVariable
$
cxxFieldSizeString
$
elementSize
$
elementType
$
fieldType
desc
context
"fieldElementType"
=
...
...
@@ -212,8 +210,6 @@ structContext parent desc = mkStrContext context where
context
"structDataSize"
=
MuVariable
$
packingDataSize
$
structPacking
desc
context
"structReferenceCount"
=
MuVariable
$
packingReferenceCount
$
structPacking
desc
context
"structChildren"
=
MuList
[]
-- TODO
context
"structDefault"
=
MuList
[
defaultBytesContext
context
(
StructType
desc
)
(
encodeMessage
(
StructType
desc
)
(
StructValueDesc
[]
))]
context
s
=
parent
s
fileContext
desc
=
mkStrContext
context
where
...
...
compiler/src/WireFormat.hs
View file @
f966fc41
...
...
@@ -25,8 +25,7 @@ module WireFormat(encodeMessage) where
import
Data.List
(
sortBy
,
genericLength
,
genericReplicate
)
import
Data.Word
import
Data.Bits
(
shiftL
,
shiftR
,
Bits
,
setBit
)
import
qualified
Data.Set
as
Set
import
Data.Bits
(
shiftL
,
shiftR
,
Bits
,
setBit
,
xor
)
import
Semantics
import
Data.Binary.IEEE754
(
floatToWord
,
doubleToWord
)
import
qualified
Codec.Binary.UTF8.String
as
UTF8
...
...
@@ -69,27 +68,34 @@ encodeDataValue (EnumValueValueDesc v) = bytes (enumValueNumber v) 2
encodeDataValue
(
StructValueDesc
_
)
=
error
"Not fixed-width data."
encodeDataValue
(
ListDesc
_
)
=
error
"Not fixed-width data."
packBits
::
Bits
a
=>
Int
->
[
Bool
]
->
a
encodeMaskedDataValue
v
Nothing
=
encodeDataValue
v
encodeMaskedDataValue
v
(
Just
d
)
=
zipWith
xor
(
encodeDataValue
v
)
(
encodeDataValue
d
)
packBits
::
Bits
a
=>
Int
->
[(
Bool
,
Maybe
Bool
)]
->
a
packBits
_
[]
=
0
packBits
offset
(
True
:
bits
)
=
setBit
(
packBits
(
offset
+
1
)
bits
)
offset
packBits
offset
(
False
:
bits
)
=
packBits
(
offset
+
1
)
bits
packBits
offset
((
True
,
Nothing
)
:
bits
)
=
setBit
(
packBits
(
offset
+
1
)
bits
)
offset
packBits
offset
((
False
,
Nothing
)
:
bits
)
=
packBits
(
offset
+
1
)
bits
packBits
offset
((
b
,
Just
d
)
:
bits
)
=
packBits
offset
((
b
/=
d
,
Nothing
)
:
bits
)
encodeData
::
Integer
->
[(
Integer
,
TypeDesc
,
ValueDesc
)]
->
[
Word8
]
-- The tuples are (offsetInBits, type, value, defaultValue) for each field to encode.
encodeData
::
Integer
->
[(
Integer
,
TypeDesc
,
ValueDesc
,
Maybe
ValueDesc
)]
->
[
Word8
]
encodeData
size
=
loop
0
where
loop
bit
[]
|
bit
==
size
=
[]
loop
bit
[]
|
bit
>
size
=
error
"Data values overran size."
loop
bit
[]
=
0
:
loop
(
bit
+
8
)
[]
loop
bit
rest
@
((
valuePos
,
_
,
BoolDesc
_
)
:
_
)
|
valuePos
==
bit
=
let
loop
bit
rest
@
((
valuePos
,
_
,
BoolDesc
_
,
_
)
:
_
)
|
valuePos
==
bit
=
let
(
bits
,
rest2
)
=
popBits
(
bit
+
8
)
rest
in
packBits
0
bits
:
loop
(
bit
+
8
)
rest2
loop
bit
((
valuePos
,
_
,
value
)
:
rest
)
|
valuePos
==
bit
=
encodeDataValue
value
++
loop
(
bit
+
sizeInBits
(
fieldValueSize
value
))
rest
loop
bit
rest
@
((
valuePos
,
_
,
_
)
:
_
)
|
valuePos
>
bit
=
0
:
loop
(
bit
+
8
)
rest
loop
bit
((
valuePos
,
_
,
value
,
defaultValue
)
:
rest
)
|
valuePos
==
bit
=
encodeMaskedDataValue
value
defaultValue
++
loop
(
bit
+
sizeInBits
(
fieldValueSize
value
))
rest
loop
bit
rest
@
((
valuePos
,
_
,
_
,
_
)
:
_
)
|
valuePos
>
bit
=
0
:
loop
(
bit
+
8
)
rest
loop
_
_
=
error
"Data values were out-of-order."
popBits
limit
((
valuePos
,
_
,
BoolDesc
b
)
:
rest
)
|
valuePos
<
limit
=
let
popBits
limit
((
valuePos
,
_
,
BoolDesc
b
,
d
)
:
rest
)
|
valuePos
<
limit
=
let
(
restBits
,
rest2
)
=
popBits
limit
rest
in
(
b
:
restBits
,
rest2
)
defaultB
=
fmap
(
\
(
BoolDesc
b2
)
->
b2
)
d
in
((
b
,
defaultB
)
:
restBits
,
rest2
)
popBits
_
rest
=
(
[]
,
rest
)
encodeReferences
::
Integer
->
Integer
->
[(
Integer
,
TypeDesc
,
ValueDesc
)]
->
([
Word8
],
[
Word8
])
...
...
@@ -156,10 +162,6 @@ fieldSizeEnum (SizeInlineComposite _ _) = 7
structTag
=
0
listTag
=
1
-- Is this field a non-retroactive member of a union? If so, its default value is not written.
isNonRetroUnionMember
(
FieldDesc
{
fieldNumber
=
n
,
fieldUnion
=
Just
u
})
=
n
>
unionNumber
u
isNonRetroUnionMember
_
=
False
-- What is this union's default tag value? If there is a retroactive field, it is that field's
-- number, otherwise it is the union's number (meaning no field set).
unionDefault
desc
=
UInt8Desc
$
fromIntegral
$
...
...
@@ -168,49 +170,24 @@ unionDefault desc = UInt8Desc $ fromIntegral $
-- childOffset = number of words between the last reference and the location where children will
-- be allocated.
encodeStruct
desc
assignments
childOffset
=
(
dataBytes
,
referenceBytes
,
children
)
where
explicitlyAssignedNums
=
Set
.
fromList
[
fieldNumber
f
|
(
f
,
_
)
<-
assignments
]
explicitlyAssignedUnions
=
Set
.
fromList
[
unionNumber
u
|
(
FieldDesc
{
fieldUnion
=
Just
u
},
_
)
<-
assignments
]
-- Was this field explicitly assigned, or was another member of the same union explicitly
-- assigned? If so, its default value is not written.
isExplicitlyAssigned
(
FieldDesc
{
fieldNumber
=
n
,
fieldUnion
=
u
})
=
Set
.
member
n
explicitlyAssignedNums
||
maybe
False
(
flip
Set
.
member
explicitlyAssignedUnions
.
unionNumber
)
u
-- Values explicitly assigned.
explicitValues
=
[(
fieldOffset
f
,
fieldType
f
,
v
)
|
(
f
,
v
)
<-
assignments
]
-- Values from defaults.
defaultValues
=
[(
o
,
fieldType
field
,
v
)
|
field
@
(
FieldDesc
{
fieldOffset
=
o
,
fieldDefaultValue
=
Just
v
})
<-
structFields
desc
-- Don't include default values for fields that were explicitly assigned.
,
not
$
isExplicitlyAssigned
field
-- Don't encode defaults for union members since they'd overwrite each other, and anyway
-- they wouldn't be valid unless the union tag specified them, which by default it doesn't,
-- except of course in the case of retroactively-added fields. So do include retro fields.
,
not
$
isNonRetroUnionMember
field
-- Don't encode defaults for references. Setting them to null has the same effect.
,
isDataFieldSize
$
fieldValueSize
v
]
explicitValues
=
[(
fieldOffset
f
,
fieldType
f
,
v
,
fieldDefaultValue
f
)
|
(
f
,
v
)
<-
assignments
]
-- Values of union tags.
unionValues
=
[(
unionTagOffset
u
,
BuiltinType
BuiltinUInt8
,
UInt8Desc
$
fromIntegral
n
)
unionValues
=
[(
unionTagOffset
u
,
BuiltinType
BuiltinUInt8
,
UInt8Desc
$
fromIntegral
n
,
Just
$
unionDefault
u
)
|
(
FieldDesc
{
fieldUnion
=
Just
u
,
fieldNumber
=
n
},
_
)
<-
assignments
]
-- Default values of union tags.
unionDefaultValues
=
[(
unionTagOffset
u
,
BuiltinType
BuiltinUInt8
,
unionDefault
u
)
|
u
<-
structUnions
desc
,
not
$
Set
.
member
(
unionNumber
u
)
explicitlyAssignedUnions
]
allValues
=
explicitValues
++
defaultValues
++
unionValues
++
unionDefaultValues
allData
=
[
(
o
*
sizeInBits
(
fieldValueSize
v
),
t
,
v
)
|
(
o
,
t
,
v
)
<-
allValues
,
isDataFieldSize
$
fieldValueSize
v
]
allReferences
=
[
(
o
,
t
,
v
)
|
(
o
,
t
,
v
)
<-
allValues
allValues
=
explicitValues
++
unionValues
allData
=
[
(
o
*
sizeInBits
(
fieldValueSize
v
),
t
,
v
,
d
)
|
(
o
,
t
,
v
,
d
)
<-
allValues
,
isDataFieldSize
$
fieldValueSize
v
]
allReferences
=
[
(
o
,
t
,
v
)
|
(
o
,
t
,
v
,
_
)
<-
allValues
,
not
$
isDataFieldSize
$
fieldValueSize
v
]
sortedData
=
sortBy
compareValues
allData
sortedReferences
=
sortBy
compareValues
allReferences
compareValues
(
o1
,
_
,
_
)
(
o2
,
_
,
_
)
=
compare
o1
o2
sortedData
=
sortBy
compareDataValues
allData
compareDataValues
(
o1
,
_
,
_
,
_
)
(
o2
,
_
,
_
,
_
)
=
compare
o1
o2
sortedReferences
=
sortBy
compareReferenceValues
allReferences
compareReferenceValues
(
o1
,
_
,
_
)
(
o2
,
_
,
_
)
=
compare
o1
o2
dataBytes
=
encodeData
(
packingDataSize
(
structPacking
desc
)
*
64
)
sortedData
(
referenceBytes
,
children
)
=
encodeReferences
childOffset
...
...
@@ -228,7 +205,7 @@ encodeList elementType elements = case elementSize elementType of
(
refBytes
,
childBytes
)
=
encodeReferences
0
(
genericLength
elements
)
$
zipWith
(
\
i
v
->
(
i
,
elementType
,
v
))
[
0
..
]
elements
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
,
Nothing
))
[
0
..
]
elements
encodeMessage
(
StructType
desc
)
(
StructValueDesc
assignments
)
=
let
(
dataBytes
,
refBytes
,
childBytes
)
=
encodeStruct
desc
assignments
0
...
...
compiler/src/c++-header.mustache
View file @
f966fc41
...
...
@@ -41,12 +41,9 @@ struct {{structName}} {
struct
{{
structChildName
}}
;
{{/
structChildren
}}
static constexpr ::capnproto::WordCount DATA_SIZE =
{{
structDataSize
}}
* ::capnproto::WORDS;
static constexpr ::capnproto::WireReferenceCount REFERENCE_COUNT =
{{
structReferenceCount
}}
* ::capnproto::REFERENCES;
{{#
structDefault
}}
static const ::capnproto::internal::AlignedData
<
{{
defaultWordCount
}}
>
DEFAULT;
{{/
structDefault
}}
static constexpr ::capnproto::internal::StructSize STRUCT_SIZE =
::capnproto::internal::StructSize(
{{
structDataSize
}}
* ::capnproto::WORDS,
{{
structReferenceCount
}}
* ::capnproto::REFERENCES);
{{#
structFields
}}
{{#
fieldDefaultBytes
}}
static const ::capnproto::internal::AlignedData
<
{{
defaultWordCount
}}
>
DEFAULT_
{{
fieldUpperCase
}}
;
...
...
@@ -140,7 +137,7 @@ private:
{{#
fieldIsPrimitive
}}
inline
{{
fieldType
}}
{{
structName
}}
::Reader::get
{{
fieldTitleCase
}}
() {
return _reader.getDataField
<
{{
fieldType
}}
>
(
{{
fieldOffset
}}
* ::capnproto::ELEMENTS
,
{{
fieldDefaultValue
}}
);
{{
fieldOffset
}}
* ::capnproto::ELEMENTS
{{
fieldDefaultMask
}}
);
}
{{/
fieldIsPrimitive
}}
{{#
fieldIsBlob
}}
...
...
@@ -159,7 +156,7 @@ inline {{fieldType}}::Reader {{structName}}::Reader::get{{fieldTitleCase}}() {
return
{{
fieldType
}}
::Reader(_reader.getStructField(
{{
fieldOffset
}}
* ::capnproto::REFERENCES,
{{#
fieldDefaultBytes
}}
DEFAULT_
{{
fieldUpperCase
}}
.words
{{/
fieldDefaultBytes
}}
{{^
fieldDefaultBytes
}}
{{
fieldType
}}
::DEFAULT.words
{{/
fieldDefaultBytes
}}
));
{{^
fieldDefaultBytes
}}
nullptr
{{/
fieldDefaultBytes
}}
));
}
{{/
fieldIsStruct
}}
{{#
fieldIsList
}}
...
...
@@ -179,11 +176,12 @@ inline {{fieldType}}::Reader {{structName}}::Reader::get{{fieldTitleCase}}() {
//
{{
structName
}}
.
{{
fieldDecl
}}
{{#
fieldIsPrimitive
}}
inline
{{
fieldType
}}
{{
structName
}}
::Builder::get
{{
fieldTitleCase
}}
() {
return _builder.getDataField
<
{{
fieldType
}}
>
(
{{
fieldOffset
}}
* ::capnproto::ELEMENTS);
return _builder.getDataField
<
{{
fieldType
}}
>
(
{{
fieldOffset
}}
* ::capnproto::ELEMENTS
{{
fieldDefaultMask
}}
);
}
inline void
{{
structName
}}
::Builder::set
{{
fieldTitleCase
}}
(
{{
fieldType
}}
value) {
return _builder.setDataField
<
{{
fieldType
}}
>
(
{{
fieldOffset
}}
* ::capnproto::ELEMENTS, value);
{{
fieldOffset
}}
* ::capnproto::ELEMENTS, value
{{
fieldDefaultMask
}}
);
}
{{/
fieldIsPrimitive
}}
{{#
fieldIsBlob
}}
...
...
@@ -205,14 +203,14 @@ inline {{fieldType}}::Builder {{structName}}::Builder::init{{fieldTitleCase}}(un
{{#
fieldIsStruct
}}
inline
{{
fieldType
}}
::Builder
{{
structName
}}
::Builder::init
{{
fieldTitleCase
}}
() {
return
{{
fieldType
}}
::Builder(_builder.initStructField(
{{
fieldOffset
}}
* ::capnproto::REFERENCES,
{{
fieldType
}}
::
DEFAULT.words
));
{{
fieldOffset
}}
* ::capnproto::REFERENCES,
{{
fieldType
}}
::
STRUCT_SIZE
));
}
inline
{{
fieldType
}}
::Builder
{{
structName
}}
::Builder::get
{{
fieldTitleCase
}}
() {
{{! TODO: Support per-field default values. }}
return
{{
fieldType
}}
::Builder(_builder.getStructField(
{{
fieldOffset
}}
* ::capnproto::REFERENCES,
{{
fieldOffset
}}
* ::capnproto::REFERENCES,
{{
fieldType
}}
::STRUCT_SIZE,
{{#
fieldDefaultBytes
}}
DEFAULT_
{{
fieldUpperCase
}}
.words
{{/
fieldDefaultBytes
}}
{{^
fieldDefaultBytes
}}
{{
fieldType
}}
::DEFAULT.words
{{/
fieldDefaultBytes
}}
));
{{^
fieldDefaultBytes
}}
nullptr
{{/
fieldDefaultBytes
}}
));
}
{{/
fieldIsStruct
}}
{{#
fieldIsNonStructList
}}
...
...
@@ -249,7 +247,7 @@ inline void {{structName}}::Builder::set{{fieldTitleCase}}(
inline
{{
fieldType
}}
::Builder
{{
structName
}}
::Builder::init
{{
fieldTitleCase
}}
(unsigned int size) {
return
{{
fieldType
}}
::Builder(_builder.initStructListField(
{{
fieldOffset
}}
* ::capnproto::REFERENCES, size * ::capnproto::ELEMENTS,
{{
fieldElementType
}}
::
DEFAULT.words
));
{{
fieldElementType
}}
::
STRUCT_SIZE
));
}
inline
{{
fieldType
}}
::Builder
{{
structName
}}
::Builder::get
{{
fieldTitleCase
}}
() {
return
{{
fieldType
}}
::Builder(_builder.getListField(
...
...
compiler/src/c++-source.mustache
View file @
f966fc41
...
...
@@ -32,13 +32,7 @@ namespace {{namespaceName}} {
{{/
fileNamespaces
}}
{{#
fileStructs
}}
constexpr ::capnproto::WordCount
{{
structName
}}
::DATA_SIZE;
constexpr ::capnproto::WireReferenceCount
{{
structName
}}
::REFERENCE_COUNT;
{{#
structDefault
}}
const ::capnproto::internal::AlignedData
<
{{
defaultWordCount
}}
>
{{
structName
}}
::DEFAULT = {
{
{{
defaultByteList
}}
}
};
{{/
structDefault
}}
constexpr ::capnproto::internal::StructSize
{{
structName
}}
::STRUCT_SIZE;
{{#
structFields
}}
{{#
fieldDefaultBytes
}}
...
...
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