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
de33baaf
Commit
de33baaf
authored
May 06, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Simplify more after removing inline types.
parent
7197456b
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
142 additions
and
167 deletions
+142
-167
layout-test.c++
c++/src/capnproto/layout-test.c++
+12
-8
layout.c++
c++/src/capnproto/layout.c++
+68
-73
layout.h
c++/src/capnproto/layout.h
+40
-82
type-safety.h
c++/src/capnproto/type-safety.h
+9
-0
CxxGenerator.hs
compiler/src/CxxGenerator.hs
+9
-1
c++-header.mustache
compiler/src/c++-header.mustache
+4
-3
No files found.
c++/src/capnproto/layout-test.c++
View file @
de33baaf
...
...
@@ -102,7 +102,8 @@ static const AlignedData<2> SUBSTRUCT_DEFAULT = {{0,0,0,0,1,0,0,0, 0,0,0,0,0,0,
static
const
AlignedData
<
2
>
STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT
=
{{
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
}};
static
constexpr
StructSize
STRUCTLIST_ELEMENT_SIZE
(
1
*
WORDS
,
1
*
REFERENCES
,
8
*
BYTES
);
static
constexpr
StructSize
STRUCTLIST_ELEMENT_SIZE
(
1
*
WORDS
,
1
*
REFERENCES
,
FieldSize
::
INLINE_COMPOSITE
);
static
void
setupStruct
(
StructBuilder
builder
)
{
builder
.
setDataField
<
uint64_t
>
(
0
*
ELEMENTS
,
0x1011121314151617ull
);
...
...
@@ -120,7 +121,7 @@ static void setupStruct(StructBuilder builder) {
{
StructBuilder
subStruct
=
builder
.
initStructField
(
0
*
REFERENCES
,
StructSize
(
1
*
WORDS
,
0
*
REFERENCES
,
8
*
BYTES
));
0
*
REFERENCES
,
StructSize
(
1
*
WORDS
,
0
*
REFERENCES
,
FieldSize
::
EIGHT_
BYTES
));
subStruct
.
setDataField
<
uint32_t
>
(
0
*
ELEMENTS
,
123
);
}
...
...
@@ -139,7 +140,8 @@ static void setupStruct(StructBuilder builder) {
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
StructBuilder
element
=
list
.
getStructElement
(
i
*
ELEMENTS
,
STRUCTLIST_ELEMENT_SIZE
);
element
.
setDataField
<
int32_t
>
(
0
*
ELEMENTS
,
300
+
i
);
element
.
initStructField
(
0
*
REFERENCES
,
StructSize
(
1
*
WORDS
,
0
*
REFERENCES
,
8
*
BYTES
))
element
.
initStructField
(
0
*
REFERENCES
,
StructSize
(
1
*
WORDS
,
0
*
REFERENCES
,
FieldSize
::
EIGHT_BYTES
))
.
setDataField
<
int32_t
>
(
0
*
ELEMENTS
,
400
+
i
);
}
}
...
...
@@ -174,7 +176,8 @@ static void checkStruct(StructBuilder builder) {
{
StructBuilder
subStruct
=
builder
.
getStructField
(
0
*
REFERENCES
,
StructSize
(
1
*
WORDS
,
0
*
REFERENCES
,
8
*
BYTES
),
SUBSTRUCT_DEFAULT
.
words
);
0
*
REFERENCES
,
StructSize
(
1
*
WORDS
,
0
*
REFERENCES
,
FieldSize
::
EIGHT_BYTES
),
SUBSTRUCT_DEFAULT
.
words
);
EXPECT_EQ
(
123u
,
subStruct
.
getDataField
<
uint32_t
>
(
0
*
ELEMENTS
));
}
...
...
@@ -193,7 +196,8 @@ static void checkStruct(StructBuilder builder) {
StructBuilder
element
=
list
.
getStructElement
(
i
*
ELEMENTS
,
STRUCTLIST_ELEMENT_SIZE
);
EXPECT_EQ
(
300
+
i
,
element
.
getDataField
<
int32_t
>
(
0
*
ELEMENTS
));
EXPECT_EQ
(
400
+
i
,
element
.
getStructField
(
0
*
REFERENCES
,
StructSize
(
1
*
WORDS
,
0
*
REFERENCES
,
8
*
BYTES
),
element
.
getStructField
(
0
*
REFERENCES
,
StructSize
(
1
*
WORDS
,
0
*
REFERENCES
,
FieldSize
::
EIGHT_BYTES
),
STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT
.
words
)
.
getDataField
<
int32_t
>
(
0
*
ELEMENTS
));
}
...
...
@@ -272,7 +276,7 @@ TEST(WireFormat, StructRoundTrip_OneSegment) {
word
*
rootLocation
=
segment
->
allocate
(
1
*
WORDS
);
StructBuilder
builder
=
StructBuilder
::
initRoot
(
segment
,
rootLocation
,
StructSize
(
2
*
WORDS
,
4
*
REFERENCES
,
16
*
BYTES
));
segment
,
rootLocation
,
StructSize
(
2
*
WORDS
,
4
*
REFERENCES
,
FieldSize
::
INLINE_COMPOSITE
));
setupStruct
(
builder
);
// word count:
...
...
@@ -308,7 +312,7 @@ TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation) {
word
*
rootLocation
=
segment
->
allocate
(
1
*
WORDS
);
StructBuilder
builder
=
StructBuilder
::
initRoot
(
segment
,
rootLocation
,
StructSize
(
2
*
WORDS
,
4
*
REFERENCES
,
16
*
BYTES
));
segment
,
rootLocation
,
StructSize
(
2
*
WORDS
,
4
*
REFERENCES
,
FieldSize
::
INLINE_COMPOSITE
));
setupStruct
(
builder
);
// Verify that we made 15 segments.
...
...
@@ -345,7 +349,7 @@ TEST(WireFormat, StructRoundTrip_MultipleSegmentsWithMultipleAllocations) {
word
*
rootLocation
=
segment
->
allocate
(
1
*
WORDS
);
StructBuilder
builder
=
StructBuilder
::
initRoot
(
segment
,
rootLocation
,
StructSize
(
2
*
WORDS
,
4
*
REFERENCES
,
16
*
BYTES
));
segment
,
rootLocation
,
StructSize
(
2
*
WORDS
,
4
*
REFERENCES
,
FieldSize
::
INLINE_COMPOSITE
));
setupStruct
(
builder
);
// Verify that we made 6 segments.
...
...
c++/src/capnproto/layout.c++
View file @
de33baaf
...
...
@@ -418,8 +418,7 @@ struct WireHelpers {
ref
->
structRef
.
set
(
size
);
// Build the StructBuilder.
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
size
.
data
),
size
.
pointers
);
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
size
.
data
));
}
static
CAPNPROTO_ALWAYS_INLINE
(
StructBuilder
getWritableStructReference
(
...
...
@@ -446,8 +445,7 @@ struct WireHelpers {
"Trying to update struct with incorrect reference count."
);
}
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
size
.
data
),
size
.
pointers
);
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
size
.
data
));
}
static
CAPNPROTO_ALWAYS_INLINE
(
ListBuilder
initListReference
(
...
...
@@ -456,6 +454,8 @@ struct WireHelpers {
DPRECOND
(
elementSize
!=
FieldSize
::
INLINE_COMPOSITE
,
"Should have called initStructListReference() instead."
);
// Note: Use bitsPerElement(), not bytesPerElement(), to handle bit lists correctly when
// computing wordCount. After that, the step is not used for bit lists.
auto
step
=
bitsPerElement
(
elementSize
);
// Calculate size of the list.
...
...
@@ -468,30 +468,18 @@ struct WireHelpers {
ref
->
listRef
.
set
(
elementSize
,
elementCount
);
// Build the ListBuilder.
return
ListBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
),
step
/
BITS_PER_BYTE
,
step
/
BITS_PER_REFERENCE
,
elementCount
);
return
ListBuilder
(
segment
,
ptr
,
step
/
BITS_PER_BYTE
,
elementCount
);
}
static
CAPNPROTO_ALWAYS_INLINE
(
ListBuilder
initStructListReference
(
WireReference
*
ref
,
SegmentBuilder
*
segment
,
ElementCount
elementCount
,
StructSize
elementSize
))
{
if
((
elementSize
.
pointers
==
0
*
REFERENCES
&&
elementSize
.
data
<=
1
*
WORDS
)
||
(
elementSize
.
pointers
==
1
*
REFERENCES
&&
elementSize
.
data
==
0
*
WORDS
))
{
// Small data-only struct. Allocate a list of primitives instead.
FieldSize
primitiveElementSize
=
FieldSize
::
VOID
;
if
(
elementSize
.
pointers
==
1
*
REFERENCES
)
{
primitiveElementSize
=
FieldSize
::
REFERENCE
;
}
else
{
switch
(
elementSize
.
dataBytes
/
BYTES
)
{
case
0
:
primitiveElementSize
=
FieldSize
::
VOID
;
break
;
case
1
:
primitiveElementSize
=
FieldSize
::
BYTE
;
break
;
case
2
:
primitiveElementSize
=
FieldSize
::
TWO_BYTES
;
break
;
case
4
:
primitiveElementSize
=
FieldSize
::
FOUR_BYTES
;
break
;
case
8
:
primitiveElementSize
=
FieldSize
::
EIGHT_BYTES
;
break
;
default
:
FAIL_PRECOND
(
"Invalid struct size."
);
break
;
}
}
return
initListReference
(
ref
,
segment
,
elementCount
,
primitiveElementSize
);
if
(
elementSize
.
preferredListEncoding
!=
FieldSize
::
INLINE_COMPOSITE
)
{
// Small data-only struct. Allocate a list of primitives instead. Don't ever pack as
// individual bits, though; we don't support that.
return
initListReference
(
ref
,
segment
,
elementCount
,
elementSize
.
preferredListEncoding
==
FieldSize
::
BIT
?
FieldSize
::
BYTE
:
elementSize
.
preferredListEncoding
);
}
auto
wordsPerElement
=
elementSize
.
total
()
/
ELEMENTS
;
...
...
@@ -511,9 +499,7 @@ struct WireHelpers {
ptr
+=
REFERENCE_SIZE_IN_WORDS
;
// Build the ListBuilder.
return
ListBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
elementSize
.
data
),
wordsPerElement
*
BYTES_PER_WORD
,
wordsPerElement
/
WORDS_PER_REFERENCE
,
elementCount
);
return
ListBuilder
(
segment
,
ptr
,
wordsPerElement
*
BYTES_PER_WORD
,
elementCount
);
}
static
CAPNPROTO_ALWAYS_INLINE
(
ListBuilder
getWritableListReference
(
...
...
@@ -523,8 +509,7 @@ struct WireHelpers {
if
(
ref
->
isNull
())
{
if
(
defaultValue
==
nullptr
)
{
return
ListBuilder
(
segment
,
nullptr
,
nullptr
,
0
*
BYTES
/
ELEMENTS
,
0
*
REFERENCES
/
ELEMENTS
,
0
*
ELEMENTS
);
return
ListBuilder
();
}
ptr
=
copyMessage
(
segment
,
ref
,
defaultRef
);
}
else
{
...
...
@@ -541,17 +526,11 @@ struct WireHelpers {
"INLINE_COMPOSITE list with non-STRUCT elements not supported."
);
// First list element is at tag + 1 reference.
word
*
data
=
reinterpret_cast
<
word
*>
(
tag
+
1
);
WireReference
*
pointers
=
reinterpret_cast
<
WireReference
*>
(
data
+
tag
->
structRef
.
dataSize
.
get
());
auto
step
=
tag
->
structRef
.
wordSize
()
/
ELEMENTS
;
return
ListBuilder
(
segment
,
data
,
pointers
,
step
*
BYTES_PER_WORD
,
step
/
WORDS_PER_REFERENCE
,
return
ListBuilder
(
segment
,
tag
+
1
,
tag
->
structRef
.
wordSize
()
*
BYTES_PER_WORD
/
ELEMENTS
,
tag
->
inlineCompositeListElementCount
());
}
else
{
auto
step
=
bytesPerElement
(
ref
->
listRef
.
elementSize
());
return
ListBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
),
step
,
step
/
BYTES_PER_REFERENCE
,
ref
->
listRef
.
elementCount
());
return
ListBuilder
(
segment
,
ptr
,
step
,
ref
->
listRef
.
elementCount
());
}
}
...
...
@@ -685,9 +664,7 @@ struct WireHelpers {
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
useDefault
:
if
(
defaultValue
==
nullptr
)
{
return
ListReader
(
nullptr
,
nullptr
,
nullptr
,
0
*
ELEMENTS
,
0
*
BYTES
/
ELEMENTS
,
0
*
REFERENCES
/
ELEMENTS
,
nestingLimit
-
1
);
return
ListReader
();
}
segment
=
nullptr
;
ref
=
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
);
...
...
@@ -795,9 +772,7 @@ struct WireHelpers {
}
return
ListReader
(
segment
,
ptr
,
reinterpret_cast
<
const
WireReference
*>
(
ptr
+
tag
->
structRef
.
dataSize
.
get
()),
size
,
wordsPerElement
*
BYTES_PER_WORD
,
wordsPerElement
/
WORDS_PER_REFERENCE
,
segment
,
ptr
,
size
,
wordsPerElement
*
BYTES_PER_WORD
,
tag
->
structRef
.
dataSize
.
get
()
*
BYTES_PER_WORD
,
tag
->
structRef
.
refCount
.
get
(),
nestingLimit
-
1
);
...
...
@@ -814,9 +789,8 @@ struct WireHelpers {
}
if
(
ref
->
listRef
.
elementSize
()
==
expectedElementSize
)
{
return
ListReader
(
segment
,
ptr
,
reinterpret_cast
<
const
WireReference
*>
(
ptr
),
ref
->
listRef
.
elementCount
(),
step
/
BITS_PER_BYTE
,
step
/
BITS_PER_REFERENCE
,
nestingLimit
-
1
);
return
ListReader
(
segment
,
ptr
,
ref
->
listRef
.
elementCount
(),
step
/
BITS_PER_BYTE
,
nestingLimit
-
1
);
}
else
if
(
expectedElementSize
==
FieldSize
::
INLINE_COMPOSITE
)
{
// We were expecting a struct list, but we received a list of some other type. Perhaps a
// non-struct list was recently upgraded to a struct list, but the sender is using the
...
...
@@ -845,9 +819,8 @@ struct WireHelpers {
break
;
}
return
ListReader
(
segment
,
ptr
,
reinterpret_cast
<
const
WireReference
*>
(
ptr
),
ref
->
listRef
.
elementCount
(),
step
/
BITS_PER_BYTE
,
step
/
BITS_PER_REFERENCE
,
dataSize
,
referenceCount
,
nestingLimit
-
1
);
return
ListReader
(
segment
,
ptr
,
ref
->
listRef
.
elementCount
(),
step
/
BITS_PER_BYTE
,
dataSize
,
referenceCount
,
nestingLimit
-
1
);
}
else
{
PRECOND
(
segment
!=
nullptr
,
"Trusted message had incompatible list element type."
);
goto
useDefault
;
...
...
@@ -1080,102 +1053,124 @@ Data::Reader StructReader::getDataField(
StructBuilder
ListBuilder
::
getStructElement
(
ElementCount
index
,
StructSize
elementSize
)
const
{
// TODO: Inline this method?
ByteCount
indexByte
=
ElementCount64
(
index
)
*
stepBytes
;
byte
*
structData
=
reinterpret_cast
<
byte
*>
(
data
)
+
indexByte
;
WireReference
*
structPointers
=
pointers
+
index
*
stepPointers
;
return
StructBuilder
(
segment
,
structData
,
structPointers
,
elementSize
.
pointers
);
byte
*
structData
=
ptr
+
index
*
stepBytes
;
return
StructBuilder
(
segment
,
structData
,
reinterpret_cast
<
WireReference
*>
(
structData
)
+
elementSize
.
data
/
WORDS_PER_REFERENCE
);
}
ListBuilder
ListBuilder
::
initListElement
(
ElementCount
index
,
FieldSize
elementSize
,
ElementCount
elementCount
)
const
{
return
WireHelpers
::
initListReference
(
pointers
+
index
*
stepPointers
,
segment
,
elementCount
,
elementSize
);
reinterpret_cast
<
WireReference
*>
(
ptr
+
index
*
stepBytes
)
,
segment
,
elementCount
,
elementSize
);
}
ListBuilder
ListBuilder
::
initStructListElement
(
ElementCount
index
,
ElementCount
elementCount
,
StructSize
elementSize
)
const
{
return
WireHelpers
::
initStructListReference
(
pointers
+
index
*
stepPointers
,
segment
,
elementCount
,
elementSize
);
reinterpret_cast
<
WireReference
*>
(
ptr
+
index
*
stepBytes
)
,
segment
,
elementCount
,
elementSize
);
}
ListBuilder
ListBuilder
::
getListElement
(
ElementCount
index
)
const
{
return
WireHelpers
::
getWritableListReference
(
pointers
+
index
*
stepPointers
,
segment
,
nullptr
);
reinterpret_cast
<
WireReference
*>
(
ptr
+
index
*
stepBytes
)
,
segment
,
nullptr
);
}
Text
::
Builder
ListBuilder
::
initTextElement
(
ElementCount
index
,
ByteCount
size
)
const
{
return
WireHelpers
::
initTextReference
(
pointers
+
index
*
stepPointers
,
segment
,
size
);
reinterpret_cast
<
WireReference
*>
(
ptr
+
index
*
stepBytes
)
,
segment
,
size
);
}
void
ListBuilder
::
setTextElement
(
ElementCount
index
,
Text
::
Reader
value
)
const
{
WireHelpers
::
setTextReference
(
pointers
+
index
*
stepPointers
,
segment
,
value
);
reinterpret_cast
<
WireReference
*>
(
ptr
+
index
*
stepBytes
)
,
segment
,
value
);
}
Text
::
Builder
ListBuilder
::
getTextElement
(
ElementCount
index
)
const
{
return
WireHelpers
::
getWritableTextReference
(
pointers
+
index
*
stepPointers
,
segment
,
""
,
0
*
BYTES
);
reinterpret_cast
<
WireReference
*>
(
ptr
+
index
*
stepBytes
)
,
segment
,
""
,
0
*
BYTES
);
}
Data
::
Builder
ListBuilder
::
initDataElement
(
ElementCount
index
,
ByteCount
size
)
const
{
return
WireHelpers
::
initDataReference
(
pointers
+
index
*
stepPointers
,
segment
,
size
);
reinterpret_cast
<
WireReference
*>
(
ptr
+
index
*
stepBytes
)
,
segment
,
size
);
}
void
ListBuilder
::
setDataElement
(
ElementCount
index
,
Data
::
Reader
value
)
const
{
WireHelpers
::
setDataReference
(
pointers
+
index
*
stepPointers
,
segment
,
value
);
reinterpret_cast
<
WireReference
*>
(
ptr
+
index
*
stepBytes
)
,
segment
,
value
);
}
Data
::
Builder
ListBuilder
::
getDataElement
(
ElementCount
index
)
const
{
return
WireHelpers
::
getWritableDataReference
(
pointers
+
index
*
stepPointers
,
segment
,
nullptr
,
0
*
BYTES
);
reinterpret_cast
<
WireReference
*>
(
ptr
+
index
*
stepBytes
)
,
segment
,
nullptr
,
0
*
BYTES
);
}
ListReader
ListBuilder
::
asReader
(
FieldSize
elementSize
)
const
{
// TODO: For INLINE_COMPOSITE I suppose we could just check the tag?
PRECOND
(
elementSize
!=
FieldSize
::
INLINE_COMPOSITE
,
"Need to call the other asReader() overload for INLINE_COMPOSITE lists."
);
return
ListReader
(
segment
,
data
,
pointers
,
elementCount
,
stepBytes
,
stepPointers
,
std
::
numeric_limits
<
int
>::
max
());
return
ListReader
(
segment
,
ptr
,
elementCount
,
stepBytes
,
std
::
numeric_limits
<
int
>::
max
());
}
ListReader
ListBuilder
::
asReader
(
StructSize
elementSize
)
const
{
return
ListReader
(
segment
,
data
,
pointers
,
elementCount
,
stepBytes
,
stepPointers
,
elementSize
.
dataBytes
,
elementSize
.
pointers
,
std
::
numeric_limits
<
int
>::
max
());
DCHECK
(
stepBytes
*
ELEMENTS
>=
elementSize
.
data
*
BYTES_PER_WORD
||
(
elementSize
.
data
==
1
*
WORDS
&&
elementSize
.
preferredListEncoding
!=
FieldSize
::
INLINE_COMPOSITE
&&
elementSize
.
preferredListEncoding
!=
FieldSize
::
REFERENCE
&&
stepBytes
==
bytesPerElement
(
elementSize
.
preferredListEncoding
)),
"Assumptions used here did not hold."
);
return
ListReader
(
segment
,
ptr
,
elementCount
,
stepBytes
,
std
::
min
(
stepBytes
*
ELEMENTS
,
elementSize
.
data
*
BYTES_PER_WORD
),
elementSize
.
pointers
,
std
::
numeric_limits
<
int
>::
max
());
}
// =======================================================================================
// ListReader
StructReader
ListReader
::
getStructElement
(
ElementCount
index
)
const
{
// TODO: Inline this method?
VALIDATE_INPUT
((
segment
==
nullptr
)
|
(
nestingLimit
>
0
),
"Message is too deeply-nested or contains cycles. See capnproto::ReadOptions."
)
{
return
StructReader
::
readEmpty
();
}
ByteCount
indexByte
=
index
*
stepBytes
;
const
byte
*
structData
=
reinterpret_cast
<
const
byte
*>
(
data
)
+
indexByte
;
const
byte
*
structData
=
ptr
+
indexByte
;
const
WireReference
*
structPointers
=
reinterpret_cast
<
const
WireReference
*>
(
structData
+
structDataSize
);
// This check should pass if there are no bugs in the list pointer validation code.
DCHECK
(
structReferenceCount
==
0
*
REFERENCES
||
(
uintptr_t
)
structPointers
%
sizeof
(
WireReference
)
==
0
,
"Pointer segment of struct list element not aligned."
);
return
StructReader
(
segment
,
structData
,
pointers
+
index
*
step
Pointers
,
segment
,
structData
,
struct
Pointers
,
structDataSize
,
structReferenceCount
,
nestingLimit
-
1
);
}
static
const
WireReference
*
checkAlignment
(
const
void
*
ptr
)
{
DCHECK
((
uintptr_t
)
ptr
%
sizeof
(
WireReference
)
==
0
,
"Pointer segment of struct list element not aligned."
);
return
reinterpret_cast
<
const
WireReference
*>
(
ptr
);
}
ListReader
ListReader
::
getListElement
(
ElementCount
index
,
FieldSize
expectedElementSize
)
const
{
return
WireHelpers
::
readListReference
(
segment
,
pointers
+
index
*
stepPointers
,
segment
,
checkAlignment
(
ptr
+
index
*
stepBytes
)
,
nullptr
,
expectedElementSize
,
nestingLimit
);
}
Text
::
Reader
ListReader
::
getTextElement
(
ElementCount
index
)
const
{
return
WireHelpers
::
readTextReference
(
segment
,
pointers
+
index
*
stepPointers
,
""
,
0
*
BYTES
);
segment
,
checkAlignment
(
ptr
+
index
*
stepBytes
),
""
,
0
*
BYTES
);
}
Data
::
Reader
ListReader
::
getDataElement
(
ElementCount
index
)
const
{
return
WireHelpers
::
readDataReference
(
segment
,
pointers
+
index
*
stepPointers
,
nullptr
,
0
*
BYTES
);
segment
,
checkAlignment
(
ptr
+
index
*
stepBytes
),
nullptr
,
0
*
BYTES
);
}
}
// namespace internal
...
...
c++/src/capnproto/layout.h
View file @
de33baaf
...
...
@@ -28,11 +28,6 @@
// as does other parts of the Cap'n proto library which provide a higher-level interface for
// dynamic introspection.
#ifdef __CDT_PARSER__
// Eclipse keeps thinking this is pre-defined for no apparent reason.
#undef CAPNPROTO_LAYOUT_H_
#endif
#ifndef CAPNPROTO_LAYOUT_H_
#define CAPNPROTO_LAYOUT_H_
...
...
@@ -137,15 +132,17 @@ struct StructSize {
WordCount16
data
;
WireReferenceCount16
pointers
;
ByteCount32
dataBytes
;
// Number of bytes in the data section. Must be data * 8 except when data == 1 in which case
// this can be 1, 2, 4, or 8.
FieldSize
preferredListEncoding
;
// Preferred size to use when encoding a list of this struct. This is INLINE_COMPOSITE if and
// only if the struct is larger than one word; otherwise the struct list can be encoded more
// efficiently by encoding it as if it were some primitive type.
inline
constexpr
WordCount
total
()
const
{
return
data
+
pointers
*
WORDS_PER_REFERENCE
;
}
StructSize
()
=
default
;
inline
constexpr
StructSize
(
WordCount
data
,
WireReferenceCount
pointers
,
ByteCount
dataBytes
)
:
data
(
data
),
pointers
(
pointers
),
dataBytes
(
dataBytes
)
{}
inline
constexpr
StructSize
(
WordCount
data
,
WireReferenceCount
pointers
,
FieldSize
preferredListEncoding
)
:
data
(
data
),
pointers
(
pointers
),
preferredListEncoding
(
preferredListEncoding
)
{}
};
template
<
typename
T
>
...
...
@@ -325,20 +322,13 @@ public:
StructReader
asReader
()
const
;
// Gets a StructReader pointing at the same memory.
WireReferenceCount
getReferenceCount
()
{
return
referenceCount
;
}
private
:
SegmentBuilder
*
segment
;
// Memory segment in which the struct resides.
void
*
data
;
// Pointer to the encoded data.
WireReference
*
references
;
// Pointer to the encoded references.
WireReferenceCount16
referenceCount
;
// Size of the pointer segment, available only for the sake of computing size of List(Inline(T)).
inline
StructBuilder
(
SegmentBuilder
*
segment
,
void
*
data
,
WireReference
*
references
,
WireReferenceCount
referenceCount
)
:
segment
(
segment
),
data
(
data
),
references
(
references
),
referenceCount
(
referenceCount
)
{}
inline
StructBuilder
(
SegmentBuilder
*
segment
,
void
*
data
,
WireReference
*
references
)
:
segment
(
segment
),
data
(
data
),
references
(
references
)
{}
friend
class
ListBuilder
;
friend
struct
WireHelpers
;
...
...
@@ -393,7 +383,10 @@ private:
const
void
*
data
;
const
WireReference
*
references
;
ByteCount32
dataSize
;
// Size of data segment.
ByteCount32
dataSize
;
// Size of data segment. We use a byte count rather than a word count to more easily handle the
// case of struct lists encoded with less than a word per element.
WireReferenceCount16
referenceCount
;
// Size of the reference segment.
int
nestingLimit
;
...
...
@@ -417,8 +410,8 @@ private:
class
ListBuilder
{
public
:
inline
ListBuilder
()
:
segment
(
nullptr
),
data
(
nullptr
),
pointers
(
nullptr
),
elementCount
(
0
*
ELEMENTS
),
stepBytes
(
0
*
BYTES
/
ELEMENTS
)
,
stepPointers
(
0
*
REFERENCES
/
ELEMENTS
)
{}
:
segment
(
nullptr
),
ptr
(
nullptr
),
elementCount
(
0
*
ELEMENTS
),
stepBytes
(
0
*
BYTES
/
ELEMENTS
)
{}
inline
ElementCount
size
();
// The number of elements in the list.
...
...
@@ -449,10 +442,6 @@ public:
// Get the existing list element at the given index. Returns an empty list if the element is
// not initialized.
CAPNPROTO_ALWAYS_INLINE
(
ListBuilder
slice
(
ElementCount
start
,
ElementCount
length
)
const
);
// Get a list pointing at a slice of this list. WARNING: The second parameter is a length, not
// an end index, because this is what is most convenient at the only call site.
Text
::
Builder
initTextElement
(
ElementCount
index
,
ByteCount
size
)
const
;
// Initialize the text element to the given size in bytes (not including NUL terminator) and
// return a Text::Builder which can be used to fill in the content.
...
...
@@ -477,22 +466,18 @@ public:
private
:
SegmentBuilder
*
segment
;
// Memory segment in which the list resides.
void
*
data
;
WireReference
*
pointers
;
// Pointers to list content.
byte
*
ptr
;
// Pointer to list content.
ElementCount
elementCount
;
// Number of elements in the list.
decltype
(
BYTES
/
ELEMENTS
)
stepBytes
;
decltype
(
REFERENCES
/
ELEMENTS
)
stepPointers
;
// The distance between elements. Can be tricky e.g. for inlined struct lists.
// The distance between elements.
// Bit lists ignore stepBytes -- they are always tightly-packed.
inline
ListBuilder
(
SegmentBuilder
*
segment
,
void
*
data
,
WireReference
*
pointers
,
decltype
(
BYTES
/
ELEMENTS
)
stepBytes
,
decltype
(
REFERENCES
/
ELEMENTS
)
stepPointers
,
ElementCount
size
)
:
segment
(
segment
),
data
(
data
),
pointers
(
pointers
),
elementCount
(
size
),
stepBytes
(
stepBytes
),
stepPointers
(
stepPointers
)
{}
inline
ListBuilder
(
SegmentBuilder
*
segment
,
void
*
ptr
,
decltype
(
BYTES
/
ELEMENTS
)
stepBytes
,
ElementCount
size
)
:
segment
(
segment
),
ptr
(
reinterpret_cast
<
byte
*>
(
ptr
)),
elementCount
(
size
),
stepBytes
(
stepBytes
)
{}
friend
class
StructBuilder
;
friend
struct
WireHelpers
;
...
...
@@ -501,8 +486,7 @@ private:
class
ListReader
{
public
:
inline
ListReader
()
:
segment
(
nullptr
),
data
(
nullptr
),
pointers
(
nullptr
),
elementCount
(
0
),
stepBytes
(
0
*
BYTES
/
ELEMENTS
),
stepPointers
(
0
*
REFERENCES
/
ELEMENTS
),
:
segment
(
nullptr
),
ptr
(
nullptr
),
elementCount
(
0
),
stepBytes
(
0
*
BYTES
/
ELEMENTS
),
structDataSize
(
0
),
structReferenceCount
(
0
),
nestingLimit
(
0
)
{}
inline
ElementCount
size
();
...
...
@@ -518,10 +502,6 @@ public:
ListReader
getListElement
(
ElementCount
index
,
FieldSize
expectedElementSize
)
const
;
// Get the list element at the given index.
CAPNPROTO_ALWAYS_INLINE
(
ListReader
slice
(
ElementCount
start
,
ElementCount
length
)
const
);
// Get a list pointing at a slice of this list. WARNING: The second parameter is a length, not
// an end index, because this is what is most convenient at the only call site.
Text
::
Reader
getTextElement
(
ElementCount
index
)
const
;
// Get the text element. If it is not initialized, returns an empty Text::Reader.
...
...
@@ -531,15 +511,12 @@ public:
private
:
SegmentReader
*
segment
;
// Memory segment in which the list resides.
const
void
*
data
;
const
WireReference
*
pointers
;
// Pointers to list content.
const
byte
*
ptr
;
// Pointer to list content.
ElementCount
elementCount
;
// Number of elements in the list.
decltype
(
BYTES
/
ELEMENTS
)
stepBytes
;
decltype
(
REFERENCES
/
ELEMENTS
)
stepPointers
;
// The distance between elements. Can be tricky e.g. for inlined struct lists.
// The distance between elements.
// Bit lists ignore stepBytes -- they are always tightly-packed.
ByteCount
structDataSize
;
...
...
@@ -550,18 +527,18 @@ private:
// Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
// Once this reaches zero, further pointers will be pruned.
inline
ListReader
(
SegmentReader
*
segment
,
const
void
*
data
,
const
WireReference
*
pointers
,
inline
ListReader
(
SegmentReader
*
segment
,
const
void
*
ptr
,
ElementCount
elementCount
,
decltype
(
BYTES
/
ELEMENTS
)
stepBytes
,
decltype
(
REFERENCES
/
ELEMENTS
)
stepPointers
,
int
nestingLimit
)
:
segment
(
segment
),
data
(
data
),
pointers
(
pointers
),
elementCount
(
elementCount
),
stepBytes
(
stepBytes
),
st
epPointers
(
stepPointers
),
structDataSize
(
0
),
structReferenceCount
(
0
),
nestingLimit
(
nestingLimit
)
{}
inline
ListReader
(
SegmentReader
*
segment
,
const
void
*
data
,
const
WireReference
*
pointers
,
int
nestingLimit
)
:
segment
(
segment
),
ptr
(
reinterpret_cast
<
const
byte
*>
(
ptr
)
),
elementCount
(
elementCount
),
stepBytes
(
stepBytes
),
st
ructDataSize
(
0
),
structReferenceCount
(
0
),
nestingLimit
(
nestingLimit
)
{}
inline
ListReader
(
SegmentReader
*
segment
,
const
void
*
ptr
,
ElementCount
elementCount
,
decltype
(
BYTES
/
ELEMENTS
)
stepBytes
,
decltype
(
REFERENCES
/
ELEMENTS
)
stepPointers
,
ByteCount
structDataSize
,
WireReferenceCount
structReferenceCount
,
int
nestingLimit
)
:
segment
(
segment
),
data
(
data
),
pointers
(
pointers
),
elementCount
(
elementCount
),
stepBytes
(
stepBytes
),
st
epPointers
(
stepPointers
),
st
ructDataSize
(
structDataSize
),
ByteCount
structDataSize
,
WireReferenceCount
structReferenceCount
,
int
nestingLimit
)
:
segment
(
segment
),
ptr
(
reinterpret_cast
<
const
byte
*>
(
ptr
)
),
elementCount
(
elementCount
),
stepBytes
(
stepBytes
),
structDataSize
(
structDataSize
),
structReferenceCount
(
structReferenceCount
),
nestingLimit
(
nestingLimit
)
{}
friend
class
StructReader
;
...
...
@@ -656,15 +633,14 @@ inline ElementCount ListBuilder::size() { return elementCount; }
template
<
typename
T
>
inline
T
ListBuilder
::
getDataElement
(
ElementCount
index
)
const
{
return
reinterpret_cast
<
WireValue
<
T
>*>
(
reinterpret_cast
<
byte
*>
(
data
)
+
index
*
stepBytes
)
->
get
();
return
reinterpret_cast
<
WireValue
<
T
>*>
(
ptr
+
index
*
stepBytes
)
->
get
();
}
template
<>
inline
bool
ListBuilder
::
getDataElement
<
bool
>
(
ElementCount
index
)
const
{
// Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
BitCount
bindex
=
index
*
(
1
*
BITS
/
ELEMENTS
);
byte
*
b
=
reinterpret_cast
<
byte
*>
(
data
)
+
bindex
/
BITS_PER_BYTE
;
byte
*
b
=
ptr
+
bindex
/
BITS_PER_BYTE
;
return
(
*
reinterpret_cast
<
uint8_t
*>
(
b
)
&
(
1
<<
(
bindex
%
BITS_PER_BYTE
/
BITS
)))
!=
0
;
}
...
...
@@ -675,15 +651,14 @@ inline Void ListBuilder::getDataElement<Void>(ElementCount index) const {
template
<
typename
T
>
inline
void
ListBuilder
::
setDataElement
(
ElementCount
index
,
typename
NoInfer
<
T
>::
Type
value
)
const
{
reinterpret_cast
<
WireValue
<
T
>*>
(
reinterpret_cast
<
byte
*>
(
data
)
+
index
*
stepBytes
)
->
set
(
value
);
reinterpret_cast
<
WireValue
<
T
>*>
(
ptr
+
index
*
stepBytes
)
->
set
(
value
);
}
template
<>
inline
void
ListBuilder
::
setDataElement
<
bool
>
(
ElementCount
index
,
bool
value
)
const
{
// Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
BitCount
bindex
=
index
*
(
1
*
BITS
/
ELEMENTS
);
byte
*
b
=
reinterpret_cast
<
byte
*>
(
data
)
+
bindex
/
BITS_PER_BYTE
;
byte
*
b
=
ptr
+
bindex
/
BITS_PER_BYTE
;
uint
bitnum
=
bindex
%
BITS_PER_BYTE
/
BITS
;
*
reinterpret_cast
<
uint8_t
*>
(
b
)
=
(
*
reinterpret_cast
<
uint8_t
*>
(
b
)
&
~
(
1
<<
bitnum
))
|
(
static_cast
<
uint8_t
>
(
value
)
<<
bitnum
);
...
...
@@ -692,29 +667,20 @@ inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) co
template
<>
inline
void
ListBuilder
::
setDataElement
<
Void
>
(
ElementCount
index
,
Void
value
)
const
{}
inline
ListBuilder
ListBuilder
::
slice
(
ElementCount
start
,
ElementCount
length
)
const
{
return
ListBuilder
(
segment
,
reinterpret_cast
<
byte
*>
(
data
)
+
start
*
stepBytes
,
reinterpret_cast
<
WireReference
*>
(
reinterpret_cast
<
word
*>
(
pointers
)
+
start
*
stepPointers
*
WORDS_PER_REFERENCE
),
stepBytes
,
stepPointers
,
length
);
}
// -------------------------------------------------------------------
inline
ElementCount
ListReader
::
size
()
{
return
elementCount
;
}
template
<
typename
T
>
inline
T
ListReader
::
getDataElement
(
ElementCount
index
)
const
{
return
reinterpret_cast
<
const
WireValue
<
T
>*>
(
reinterpret_cast
<
const
byte
*>
(
data
)
+
index
*
stepBytes
)
->
get
();
return
reinterpret_cast
<
const
WireValue
<
T
>*>
(
ptr
+
index
*
stepBytes
)
->
get
();
}
template
<>
inline
bool
ListReader
::
getDataElement
<
bool
>
(
ElementCount
index
)
const
{
// Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
BitCount
bindex
=
index
*
(
1
*
BITS
/
ELEMENTS
);
const
byte
*
b
=
reinterpret_cast
<
const
byte
*>
(
data
)
+
bindex
/
BITS_PER_BYTE
;
const
byte
*
b
=
ptr
+
bindex
/
BITS_PER_BYTE
;
return
(
*
reinterpret_cast
<
const
uint8_t
*>
(
b
)
&
(
1
<<
(
bindex
%
BITS_PER_BYTE
/
BITS
)))
!=
0
;
}
...
...
@@ -723,14 +689,6 @@ inline Void ListReader::getDataElement<Void>(ElementCount index) const {
return
Void
::
VOID
;
}
inline
ListReader
ListReader
::
slice
(
ElementCount
start
,
ElementCount
length
)
const
{
return
ListReader
(
segment
,
reinterpret_cast
<
const
byte
*>
(
data
)
+
start
*
stepBytes
,
reinterpret_cast
<
const
WireReference
*>
(
reinterpret_cast
<
const
word
*>
(
pointers
)
+
start
*
stepPointers
*
WORDS_PER_REFERENCE
),
length
,
stepBytes
,
stepPointers
,
structDataSize
,
structReferenceCount
,
nestingLimit
);
}
}
// namespace internal
}
// namespace capnproto
...
...
c++/src/capnproto/type-safety.h
View file @
de33baaf
...
...
@@ -353,6 +353,15 @@ public:
unit1PerUnit2
/
other
.
unit1PerUnit2
);
}
template
<
typename
OtherNumber
>
inline
decltype
(
Number
(
1
)
/
OtherNumber
(
1
))
operator
/
(
UnitRatio
<
OtherNumber
,
Unit1
,
Unit2
>
other
)
const
{
return
unit1PerUnit2
/
other
.
unit1PerUnit2
;
}
inline
bool
operator
==
(
UnitRatio
other
)
const
{
return
unit1PerUnit2
==
other
.
unit1PerUnit2
;
}
inline
bool
operator
!=
(
UnitRatio
other
)
const
{
return
unit1PerUnit2
!=
other
.
unit1PerUnit2
;
}
private
:
Number
unit1PerUnit2
;
...
...
compiler/src/CxxGenerator.hs
View file @
de33baaf
...
...
@@ -379,8 +379,16 @@ structContext parent desc = mkStrContext context where
context
"structFields"
=
MuList
$
map
(
fieldContext
context
)
$
structFields
desc
context
"structUnions"
=
MuList
$
map
(
unionContext
context
)
$
structUnions
desc
context
"structDataSize"
=
MuVariable
$
dataSectionWordSize
$
structDataSize
desc
context
"structDataBytes"
=
MuVariable
(
div
(
dataSectionBits
(
structDataSize
desc
))
8
)
context
"structReferenceCount"
=
MuVariable
$
structPointerCount
desc
context
"structPreferredListEncoding"
=
case
(
structDataSize
desc
,
structPointerCount
desc
)
of
(
DataSectionWords
0
,
0
)
->
MuVariable
"VOID"
(
DataSection1
,
0
)
->
MuVariable
"BYTE"
(
DataSection8
,
0
)
->
MuVariable
"BYTE"
(
DataSection16
,
0
)
->
MuVariable
"TWO_BYTES"
(
DataSection32
,
0
)
->
MuVariable
"FOUR_BYTES"
(
DataSectionWords
1
,
0
)
->
MuVariable
"EIGHT_BYTES"
(
DataSectionWords
0
,
1
)
->
MuVariable
"REFERENCE"
_
->
MuVariable
"INLINE_COMPOSITE"
context
"structNestedEnums"
=
MuList
$
map
(
enumContext
context
)
[
m
|
DescEnum
m
<-
structMembers
desc
]
context
"structNestedStructs"
=
...
...
compiler/src/c++-header.mustache
View file @
de33baaf
...
...
@@ -68,9 +68,10 @@ struct {{typeFullName}} {
{{/
structNestedEnums
}}
static constexpr ::capnproto::internal::StructSize STRUCT_SIZE =
::capnproto::internal::StructSize(
{{
structDataSize
}}
* ::capnproto::WORDS,
{{
structReferenceCount
}}
* ::capnproto::REFERENCES,
{{
structDataBytes
}}
* ::capnproto::BYTES);
::capnproto::internal::StructSize(
{{
structDataSize
}}
* ::capnproto::WORDS,
{{
structReferenceCount
}}
* ::capnproto::REFERENCES,
::capnproto::internal::FieldSize::
{{
structPreferredListEncoding
}}
);
{{/
typeStruct
}}
{{#
typeUnion
}}
...
...
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