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
648d267d
Commit
648d267d
authored
Mar 03, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Finish rewriting WireFormat.
parent
36a60467
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
311 additions
and
241 deletions
+311
-241
descriptor-test.c++
c++/src/capnproto/descriptor-test.c++
+9
-16
type-safety.h
c++/src/capnproto/type-safety.h
+28
-58
wire-format-test.c++
c++/src/capnproto/wire-format-test.c++
+93
-0
wire-format.c++
c++/src/capnproto/wire-format.c++
+129
-137
wire-format.h
c++/src/capnproto/wire-format.h
+52
-30
No files found.
c++/src/capnproto/descriptor-test.c++
View file @
648d267d
...
@@ -31,28 +31,23 @@ namespace {
...
@@ -31,28 +31,23 @@ namespace {
const
int
READONLY_SEGMENT_START
=
123
;
const
int
READONLY_SEGMENT_START
=
123
;
const
FieldDescriptor
TEST_FIELDS
[
2
]
=
{
const
FieldDescriptor
TEST_FIELDS
[
2
]
=
{
{
1
*
WORDS
,
0
,
0
,
FieldSize
::
FOUR_BYTES
,
1
,
0
,
0
,
0
},
{
1
*
WORDS
,
0
*
REFERENCES
,
FieldSize
::
FOUR_BYTES
,
0
*
ELEMENTS
,
0
*
BYTES
,
1
,
0
,
0
*
BYTES
,
0
*
BITS
,
nullptr
,
nullptr
},
{
1
*
WORDS
,
1
,
0
,
FieldSize
::
REFERENCE
,
1
,
0
,
0
,
0
}
{
1
*
WORDS
,
1
*
REFERENCES
,
FieldSize
::
REFERENCE
,
0
*
ELEMENTS
,
0
*
BYTES
,
1
,
0
,
0
*
BYTES
,
0
*
BITS
,
nullptr
,
nullptr
}
};
};
extern
const
StructDescriptor
TEST_STRUCT
;
extern
const
StructDescriptor
TEST_STRUCT
;
extern
const
Descriptor
*
const
TEST_STRUCT_DEFAULT_REFS
[
1
]
=
{
const
AlignedData
<
1
>
TEST_STRUCT_DEFAULT_VALUE
=
{
&
TEST_STRUCT
.
base
};
const
AlignedData
<
1
>
TEST_STRUCT_DEFAULT_DATA
=
{
{
0x12
,
0x34
,
0x56
,
0x78
,
0x9a
,
0xbc
,
0xde
,
0xf0
}
{
0x12
,
0x34
,
0x56
,
0x78
,
0x9a
,
0xbc
,
0xde
,
0xf0
}
};
};
const
StructDescriptor
TEST_STRUCT
=
{
const
StructDescriptor
TEST_STRUCT
=
{
{
Descriptor
::
Kind
::
STRUCT
},
{
Descriptor
::
Kind
::
STRUCT
},
2
,
FieldNumber
(
2
)
,
WordCount8
(
1
*
WORDS
)
,
1
*
WORDS
,
1
,
1
*
REFERENCES
,
TEST_FIELDS
,
TEST_FIELDS
,
TEST_STRUCT_DEFAULT_DATA
.
bytes
,
TEST_STRUCT_DEFAULT_VALUE
.
words
TEST_STRUCT_DEFAULT_REFS
};
};
const
int
READONLY_SEGMENT_END
=
321
;
const
int
READONLY_SEGMENT_END
=
321
;
...
@@ -66,10 +61,8 @@ TEST(Descriptors, InReadOnlySegment) {
...
@@ -66,10 +61,8 @@ TEST(Descriptors, InReadOnlySegment) {
EXPECT_LE
((
const
void
*
)
&
READONLY_SEGMENT_START
,
(
const
void
*
)
&
TEST_FIELDS
);
EXPECT_LE
((
const
void
*
)
&
READONLY_SEGMENT_START
,
(
const
void
*
)
&
TEST_FIELDS
);
EXPECT_GE
((
const
void
*
)
&
READONLY_SEGMENT_END
,
(
const
void
*
)
&
TEST_FIELDS
);
EXPECT_GE
((
const
void
*
)
&
READONLY_SEGMENT_END
,
(
const
void
*
)
&
TEST_FIELDS
);
EXPECT_LE
((
const
void
*
)
&
READONLY_SEGMENT_START
,
(
const
void
*
)
&
TEST_STRUCT_DEFAULT_DATA
);
EXPECT_LE
((
const
void
*
)
&
READONLY_SEGMENT_START
,
(
const
void
*
)
&
TEST_STRUCT_DEFAULT_VALUE
);
EXPECT_GE
((
const
void
*
)
&
READONLY_SEGMENT_END
,
(
const
void
*
)
&
TEST_STRUCT_DEFAULT_DATA
);
EXPECT_GE
((
const
void
*
)
&
READONLY_SEGMENT_END
,
(
const
void
*
)
&
TEST_STRUCT_DEFAULT_VALUE
);
EXPECT_LE
((
const
void
*
)
&
READONLY_SEGMENT_START
,
(
const
void
*
)
&
TEST_STRUCT_DEFAULT_REFS
);
EXPECT_GE
((
const
void
*
)
&
READONLY_SEGMENT_END
,
(
const
void
*
)
&
TEST_STRUCT_DEFAULT_REFS
);
EXPECT_LE
((
const
void
*
)
&
READONLY_SEGMENT_START
,
(
const
void
*
)
&
TEST_STRUCT
);
EXPECT_LE
((
const
void
*
)
&
READONLY_SEGMENT_START
,
(
const
void
*
)
&
TEST_STRUCT
);
EXPECT_GE
((
const
void
*
)
&
READONLY_SEGMENT_END
,
(
const
void
*
)
&
TEST_STRUCT
);
EXPECT_GE
((
const
void
*
)
&
READONLY_SEGMENT_END
,
(
const
void
*
)
&
TEST_STRUCT
);
}
}
...
...
c++/src/capnproto/type-safety.h
View file @
648d267d
...
@@ -90,6 +90,10 @@ public:
...
@@ -90,6 +90,10 @@ public:
// This constructor was intended to be private, but GCC complains about it being private in a
// This constructor was intended to be private, but GCC complains about it being private in a
// bunch of places that don't appear to even call it, so I made it public. Oh well.
// bunch of places that don't appear to even call it, so I made it public. Oh well.
template
<
typename
OtherNumber
>
inline
constexpr
UnitRatio
(
const
UnitRatio
<
OtherNumber
,
Unit1
,
Unit2
>&
other
)
:
unit1PerUnit2
(
other
.
unit1PerUnit2
)
{}
template
<
typename
OtherNumber
,
typename
Unit3
>
template
<
typename
OtherNumber
,
typename
Unit3
>
inline
constexpr
UnitRatio
<
decltype
(
Number
(
1
)
*
OtherNumber
(
1
)),
Unit3
,
Unit2
>
inline
constexpr
UnitRatio
<
decltype
(
Number
(
1
)
*
OtherNumber
(
1
)),
Unit3
,
Unit2
>
operator
*
(
UnitRatio
<
OtherNumber
,
Unit3
,
Unit1
>
other
)
{
operator
*
(
UnitRatio
<
OtherNumber
,
Unit3
,
Unit1
>
other
)
{
...
@@ -422,72 +426,38 @@ inline constexpr decltype(BYTES / ELEMENTS) bytesPerElement() {
...
@@ -422,72 +426,38 @@ inline constexpr decltype(BYTES / ELEMENTS) bytesPerElement() {
#ifndef __CDT_PARSER__
#ifndef __CDT_PARSER__
template
<
typename
T
>
template
<
typename
T
,
typename
U
>
inline
constexpr
byte
*
operator
+
(
byte
*
ptr
,
Quantity
<
T
,
byte
>
offset
)
{
inline
constexpr
U
*
operator
+
(
U
*
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
+
offset
/
BYTES
;
return
ptr
+
offset
/
unit
<
Quantity
<
T
,
U
>>
();
}
template
<
typename
T
>
inline
constexpr
const
byte
*
operator
+
(
const
byte
*
ptr
,
Quantity
<
T
,
byte
>
offset
)
{
return
ptr
+
offset
/
BYTES
;
}
template
<
typename
T
>
inline
constexpr
byte
*
operator
+=
(
byte
*&
ptr
,
Quantity
<
T
,
byte
>
offset
)
{
return
ptr
=
ptr
+
offset
/
BYTES
;
}
template
<
typename
T
>
inline
constexpr
const
byte
*
operator
+=
(
const
byte
*
ptr
,
Quantity
<
T
,
byte
>
offset
)
{
return
ptr
=
ptr
+
offset
/
BYTES
;
}
template
<
typename
T
>
inline
constexpr
word
*
operator
+
(
word
*
ptr
,
Quantity
<
T
,
word
>
offset
)
{
return
ptr
+
offset
/
WORDS
;
}
template
<
typename
T
>
inline
constexpr
const
word
*
operator
+
(
const
word
*
ptr
,
Quantity
<
T
,
word
>
offset
)
{
return
ptr
+
offset
/
WORDS
;
}
template
<
typename
T
>
inline
constexpr
word
*
operator
+=
(
word
*&
ptr
,
Quantity
<
T
,
word
>
offset
)
{
return
ptr
=
ptr
+
offset
/
WORDS
;
}
template
<
typename
T
>
inline
constexpr
const
word
*
operator
+=
(
const
word
*&
ptr
,
Quantity
<
T
,
word
>
offset
)
{
return
ptr
=
ptr
+
offset
/
WORDS
;
}
template
<
typename
T
>
inline
constexpr
byte
*
operator
-
(
byte
*
ptr
,
Quantity
<
T
,
byte
>
offset
)
{
return
ptr
-
offset
/
BYTES
;
}
}
template
<
typename
T
>
template
<
typename
T
,
typename
U
>
inline
constexpr
const
byte
*
operator
-
(
const
byte
*
ptr
,
Quantity
<
T
,
byte
>
offset
)
{
inline
constexpr
const
U
*
operator
+
(
const
U
*
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
-
offset
/
BYTES
;
return
ptr
+
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
}
template
<
typename
T
>
template
<
typename
T
,
typename
U
>
inline
constexpr
byte
*
operator
-=
(
byte
*&
ptr
,
Quantity
<
T
,
byte
>
offset
)
{
inline
constexpr
U
*
operator
+=
(
U
*&
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
=
ptr
-
offset
/
BYTES
;
return
ptr
=
ptr
+
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
}
template
<
typename
T
>
template
<
typename
T
,
typename
U
>
inline
constexpr
const
byte
*
operator
-=
(
const
byte
*
ptr
,
Quantity
<
T
,
byte
>
offset
)
{
inline
constexpr
const
U
*
operator
+=
(
const
U
*&
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
=
ptr
-
offset
/
BYTES
;
return
ptr
=
ptr
+
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
}
template
<
typename
T
>
template
<
typename
T
,
typename
U
>
inline
constexpr
word
*
operator
-
(
word
*
ptr
,
Quantity
<
T
,
word
>
offset
)
{
inline
constexpr
U
*
operator
-
(
U
*
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
-
offset
/
WORDS
;
return
ptr
-
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
}
template
<
typename
T
>
template
<
typename
T
,
typename
U
>
inline
constexpr
const
word
*
operator
-
(
const
word
*
ptr
,
Quantity
<
T
,
word
>
offset
)
{
inline
constexpr
const
U
*
operator
-
(
const
U
*
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
-
offset
/
WORDS
;
return
ptr
-
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
}
template
<
typename
T
>
template
<
typename
T
,
typename
U
>
inline
constexpr
word
*
operator
-=
(
word
*&
ptr
,
Quantity
<
T
,
word
>
offset
)
{
inline
constexpr
U
*
operator
-=
(
U
*&
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
=
ptr
-
offset
/
WORDS
;
return
ptr
=
ptr
-
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
}
template
<
typename
T
>
template
<
typename
T
,
typename
U
>
inline
constexpr
const
word
*
operator
-=
(
const
word
*&
ptr
,
Quantity
<
T
,
word
>
offset
)
{
inline
constexpr
const
U
*
operator
-=
(
const
U
*&
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
=
ptr
-
offset
/
WORDS
;
return
ptr
=
ptr
-
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
}
#endif
#endif
...
...
c++/src/capnproto/wire-format-test.c++
0 → 100644
View file @
648d267d
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "wire-format.h"
#include "descriptor.h"
#include <gtest/gtest.h>
namespace
capnproto
{
namespace
internal
{
namespace
{
TEST
(
StructReader
,
RawData
)
{
AlignedData
<
2
>
data
=
{
{
// Struct ref, offset = 1, fieldCount = 1, dataSize = 1, referenceCount = 0
0x08
,
0x00
,
0x00
,
0x00
,
0x01
,
0x01
,
0x00
,
0x00
,
// Content for the data segment.
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
));
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
,
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_FALSE
(
reader
.
getDataField
<
bool
>
(
64
*
ELEMENTS
,
false
));
EXPECT_TRUE
(
reader
.
getDataField
<
bool
>
(
64
*
ELEMENTS
,
true
));
// Field number guards.
EXPECT_EQ
(
0xefcdab89u
,
reader
.
getDataFieldCheckingNumber
<
uint32_t
>
(
FieldNumber
(
0
),
1
*
ELEMENTS
,
321u
));
EXPECT_EQ
(
321u
,
reader
.
getDataFieldCheckingNumber
<
uint32_t
>
(
FieldNumber
(
1
),
1
*
ELEMENTS
,
321u
));
EXPECT_TRUE
(
reader
.
getDataFieldCheckingNumber
<
bool
>
(
FieldNumber
(
0
),
0
*
ELEMENTS
,
false
));
EXPECT_TRUE
(
reader
.
getDataFieldCheckingNumber
<
bool
>
(
FieldNumber
(
0
),
0
*
ELEMENTS
,
true
));
EXPECT_FALSE
(
reader
.
getDataFieldCheckingNumber
<
bool
>
(
FieldNumber
(
0
),
1
*
ELEMENTS
,
false
));
EXPECT_FALSE
(
reader
.
getDataFieldCheckingNumber
<
bool
>
(
FieldNumber
(
0
),
1
*
ELEMENTS
,
true
));
EXPECT_FALSE
(
reader
.
getDataFieldCheckingNumber
<
bool
>
(
FieldNumber
(
1
),
0
*
ELEMENTS
,
false
));
EXPECT_TRUE
(
reader
.
getDataFieldCheckingNumber
<
bool
>
(
FieldNumber
(
1
),
0
*
ELEMENTS
,
true
));
}
}
// namespace
}
// namespace internal
}
// namespace capnproto
c++/src/capnproto/wire-format.c++
View file @
648d267d
...
@@ -134,29 +134,13 @@ static_assert(REFERENCES * BITS_PER_REFERENCE / BITS_PER_BYTE / BYTES == sizeof(
...
@@ -134,29 +134,13 @@ static_assert(REFERENCES * BITS_PER_REFERENCE / BITS_PER_BYTE / BYTES == sizeof(
// =======================================================================================
// =======================================================================================
template
<
typename
T
,
typename
U
>
static
inline
decltype
(
T
()
/
U
())
divRoundingUp
(
T
a
,
U
b
)
{
return
(
a
+
b
-
1
)
/
b
;
}
template
<
typename
T
,
typename
U
>
static
CAPNPROTO_ALWAYS_INLINE
(
T
divRoundingUp
(
Quantity
<
T
,
U
>
a
,
Quantity
<
T
,
U
>
b
));
template
<
typename
T
,
typename
U
>
static
inline
T
divRoundingUp
(
Quantity
<
T
,
U
>
a
,
Quantity
<
T
,
U
>
b
)
{
return
(
a
+
b
-
unit
<
Quantity
<
T
,
U
>>
())
/
b
;
}
template
<
typename
T
,
typename
T2
,
typename
U
,
typename
U2
>
static
CAPNPROTO_ALWAYS_INLINE
(
decltype
(
Quantity
<
T
,
U
>
()
/
UnitRatio
<
T2
,
U
,
U2
>
())
divRoundingUp
(
Quantity
<
T
,
U
>
a
,
UnitRatio
<
T2
,
U
,
U2
>
b
));
template
<
typename
T
,
typename
T2
,
typename
U
,
typename
U2
>
static
inline
decltype
(
Quantity
<
T
,
U
>
()
/
UnitRatio
<
T2
,
U
,
U2
>
())
divRoundingUp
(
Quantity
<
T
,
U
>
a
,
UnitRatio
<
T2
,
U
,
U2
>
b
)
{
return
(
a
+
(
unit
<
Quantity
<
T2
,
U2
>>
()
*
b
-
unit
<
Quantity
<
T2
,
U
>>
()))
/
b
;
}
struct
WireHelpers
{
struct
WireHelpers
{
static
CAPNPROTO_ALWAYS_INLINE
(
WordCount
roundUpToWords
(
BitCount64
bits
))
{
static_assert
(
sizeof
(
word
)
==
8
,
"This code assumes 64-bit words."
);
uint64_t
bits2
=
bits
/
BITS
;
return
((
bits2
>>
6
)
+
((
bits2
&
63
)
!=
0
))
*
WORDS
;
}
static
CAPNPROTO_ALWAYS_INLINE
(
word
*
allocate
(
static
CAPNPROTO_ALWAYS_INLINE
(
word
*
allocate
(
WireReference
*&
ref
,
SegmentBuilder
*&
segment
,
WordCount
amount
))
{
WireReference
*&
ref
,
SegmentBuilder
*&
segment
,
WordCount
amount
))
{
word
*
ptr
=
segment
->
allocate
(
amount
);
word
*
ptr
=
segment
->
allocate
(
amount
);
...
@@ -208,23 +192,6 @@ struct WireHelpers {
...
@@ -208,23 +192,6 @@ struct WireHelpers {
return
true
;
return
true
;
}
}
static
CAPNPROTO_ALWAYS_INLINE
(
bool
isStructCompatible
(
const
StructDescriptor
*
descriptor
,
const
WireReference
*
ref
))
{
if
(
ref
->
structRef
.
fieldCount
.
get
()
>=
descriptor
->
fieldCount
)
{
// The incoming struct has all of the fields that we know about.
return
ref
->
structRef
.
dataSize
.
get
()
>=
descriptor
->
dataSize
&&
ref
->
structRef
.
refCount
.
get
()
>=
descriptor
->
referenceCount
;
}
else
if
(
ref
->
structRef
.
fieldCount
.
get
()
>
FieldNumber
(
0
))
{
// We know about more fields than the struct has, and the struct is non-empty.
const
FieldDescriptor
*
field
=
&
descriptor
->
fields
[
ref
->
structRef
.
fieldCount
.
get
().
value
-
1
];
return
ref
->
structRef
.
dataSize
.
get
()
>=
field
->
requiredDataSize
&&
ref
->
structRef
.
refCount
.
get
()
>=
field
->
requiredReferenceCount
;
}
else
{
// The incoming struct has no fields, so is necessarily compatible.
return
true
;
}
}
static
CAPNPROTO_ALWAYS_INLINE
(
StructBuilder
initStructReference
(
static
CAPNPROTO_ALWAYS_INLINE
(
StructBuilder
initStructReference
(
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
,
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
,
WireReference
*
ref
,
SegmentBuilder
*
segment
))
{
WireReference
*
ref
,
SegmentBuilder
*
segment
))
{
...
@@ -232,27 +199,25 @@ struct WireHelpers {
...
@@ -232,27 +199,25 @@ struct WireHelpers {
// Allocate space for the new struct.
// Allocate space for the new struct.
word
*
ptr
=
allocate
(
ref
,
segment
,
dataSize
+
referenceCount
*
WORDS_PER_REFERENCE
);
word
*
ptr
=
allocate
(
ref
,
segment
,
dataSize
+
referenceCount
*
WORDS_PER_REFERENCE
);
// Advance the pointer to point between the data and reference segments.
ptr
+=
dataSize
;
// Initialize the reference.
// Initialize the reference.
ref
->
setStruct
(
fieldCount
,
dataSize
,
referenceCount
,
segment
->
getOffsetTo
(
ptr
));
ref
->
setStruct
(
fieldCount
,
dataSize
,
referenceCount
,
segment
->
getOffsetTo
(
ptr
));
// Build the StructBuilder.
// Build the StructBuilder.
return
StructBuilder
(
segment
,
ptr
);
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
dataSize
)
);
}
else
{
}
else
{
followFars
(
ref
,
segment
);
followFars
(
ref
,
segment
);
CAPNPROTO_ASSERT
(
ref
->
tag
()
==
WireReference
::
STRUCT
,
CAPNPROTO_
DEBUG_
ASSERT
(
ref
->
tag
()
==
WireReference
::
STRUCT
,
"Called getStruct{Field,Element}() but existing reference is not a struct."
);
"Called getStruct{Field,Element}() but existing reference is not a struct."
);
CAPNPROTO_ASSERT
(
ref
->
structRef
.
fieldCount
.
get
()
==
fieldCount
,
CAPNPROTO_
DEBUG_
ASSERT
(
ref
->
structRef
.
fieldCount
.
get
()
==
fieldCount
,
"Trying to update struct with incorrect field count."
);
"Trying to update struct with incorrect field count."
);
CAPNPROTO_ASSERT
(
ref
->
structRef
.
dataSize
.
get
()
==
dataSize
,
CAPNPROTO_
DEBUG_
ASSERT
(
ref
->
structRef
.
dataSize
.
get
()
==
dataSize
,
"Trying to update struct with incorrect data size."
);
"Trying to update struct with incorrect data size."
);
CAPNPROTO_ASSERT
(
ref
->
structRef
.
refCount
.
get
()
==
referenceCount
,
CAPNPROTO_
DEBUG_
ASSERT
(
ref
->
structRef
.
refCount
.
get
()
==
referenceCount
,
"Trying to update struct with incorrect reference count."
);
"Trying to update struct with incorrect reference count."
);
return
StructBuilder
(
segment
,
segment
->
getPtrUnchecked
(
ref
->
offset
()));
word
*
ptr
=
segment
->
getPtrUnchecked
(
ref
->
offset
());
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
dataSize
));
}
}
}
}
...
@@ -262,10 +227,9 @@ struct WireHelpers {
...
@@ -262,10 +227,9 @@ struct WireHelpers {
CAPNPROTO_DEBUG_ASSERT
(
elementSize
!=
FieldSize
::
STRUCT
,
CAPNPROTO_DEBUG_ASSERT
(
elementSize
!=
FieldSize
::
STRUCT
,
"Should have called initStructListReference() instead."
);
"Should have called initStructListReference() instead."
);
// Calculate size of the list. Need to cast to uint here because a list can be up to
// Calculate size of the list.
// 2**32-1 bits, so int would overflow. Plus uint division by a power of 2 is a bit shift.
WordCount
wordCount
=
roundUpToWords
(
WordCount
wordCount
=
divRoundingUp
(
ElementCount64
(
elementCount
)
*
bitsPerElement
(
elementSize
));
elementCount
*
bitsPerElement
(
elementSize
),
BITS_PER_WORD
);
// Allocate the list.
// Allocate the list.
word
*
ptr
=
allocate
(
ref
,
segment
,
wordCount
);
word
*
ptr
=
allocate
(
ref
,
segment
,
wordCount
);
...
@@ -321,15 +285,14 @@ struct WireHelpers {
...
@@ -321,15 +285,14 @@ struct WireHelpers {
}
}
static
CAPNPROTO_ALWAYS_INLINE
(
StructReader
readStructReference
(
static
CAPNPROTO_ALWAYS_INLINE
(
StructReader
readStructReference
(
SegmentReader
*
segment
,
const
WireReference
*
ref
,
const
WireReference
*
defaultValue
,
SegmentReader
*
segment
,
const
WireReference
*
ref
,
const
word
*
defaultValue
,
int
recursionLimit
))
{
int
recursionLimit
))
{
const
word
*
ptr
;
const
word
*
ptr
=
ref
->
target
()
;
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
useDefault
:
useDefault
:
segment
=
nullptr
;
segment
=
nullptr
;
ref
=
defaultValue
;
ref
=
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
);
ptr
=
ref
->
target
();
}
else
if
(
segment
!=
nullptr
)
{
}
else
if
(
segment
!=
nullptr
)
{
if
(
CAPNPROTO_EXPECT_FALSE
(
recursionLimit
==
0
))
{
if
(
CAPNPROTO_EXPECT_FALSE
(
recursionLimit
==
0
))
{
segment
->
getMessage
()
->
reportInvalidData
(
segment
->
getMessage
()
->
reportInvalidData
(
...
@@ -352,8 +315,6 @@ struct WireHelpers {
...
@@ -352,8 +315,6 @@ struct WireHelpers {
WordCount
size
=
ref
->
structRef
.
dataSize
.
get
()
+
WordCount
size
=
ref
->
structRef
.
dataSize
.
get
()
+
ref
->
structRef
.
refCount
.
get
()
*
WORDS_PER_REFERENCE
;
ref
->
structRef
.
refCount
.
get
()
*
WORDS_PER_REFERENCE
;
ptr
=
ref
->
target
();
if
(
CAPNPROTO_EXPECT_FALSE
(
!
segment
->
containsInterval
(
ptr
,
ptr
+
size
)))
{
if
(
CAPNPROTO_EXPECT_FALSE
(
!
segment
->
containsInterval
(
ptr
,
ptr
+
size
)))
{
segment
->
getMessage
()
->
reportInvalidData
(
segment
->
getMessage
()
->
reportInvalidData
(
"Message contained out-of-bounds struct reference."
);
"Message contained out-of-bounds struct reference."
);
...
@@ -369,12 +330,12 @@ struct WireHelpers {
...
@@ -369,12 +330,12 @@ struct WireHelpers {
}
}
static
CAPNPROTO_ALWAYS_INLINE
(
ListReader
readListReference
(
static
CAPNPROTO_ALWAYS_INLINE
(
ListReader
readListReference
(
SegmentReader
*
segment
,
const
WireReference
*
ref
,
const
WireReference
*
defaultValue
,
SegmentReader
*
segment
,
const
WireReference
*
ref
,
const
word
*
defaultValue
,
FieldSize
expectedElementSize
,
int
recursionLimit
))
{
FieldSize
expectedElementSize
,
int
recursionLimit
))
{
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
useDefault
:
useDefault
:
segment
=
nullptr
;
segment
=
nullptr
;
ref
=
defaultValue
;
ref
=
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
)
;
}
else
if
(
segment
!=
nullptr
)
{
}
else
if
(
segment
!=
nullptr
)
{
if
(
CAPNPROTO_EXPECT_FALSE
(
recursionLimit
==
0
))
{
if
(
CAPNPROTO_EXPECT_FALSE
(
recursionLimit
==
0
))
{
segment
->
getMessage
()
->
reportInvalidData
(
segment
->
getMessage
()
->
reportInvalidData
(
...
@@ -490,7 +451,7 @@ struct WireHelpers {
...
@@ -490,7 +451,7 @@ struct WireHelpers {
if
(
segment
!=
nullptr
)
{
if
(
segment
!=
nullptr
)
{
if
(
CAPNPROTO_EXPECT_FALSE
(
!
segment
->
containsInterval
(
ptr
,
ptr
+
if
(
CAPNPROTO_EXPECT_FALSE
(
!
segment
->
containsInterval
(
ptr
,
ptr
+
divRoundingUp
(
ElementCount64
(
ref
->
listRef
.
elementCount
())
*
step
,
BITS_PER_WORD
))))
{
roundUpToWords
(
ElementCount64
(
ref
->
listRef
.
elementCount
())
*
step
))))
{
segment
->
getMessage
()
->
reportInvalidData
(
segment
->
getMessage
()
->
reportInvalidData
(
"Message contained out-of-bounds list reference."
);
"Message contained out-of-bounds list reference."
);
goto
useDefault
;
goto
useDefault
;
...
@@ -547,114 +508,145 @@ struct WireHelpers {
...
@@ -547,114 +508,145 @@ struct WireHelpers {
// =======================================================================================
// =======================================================================================
#if 0
StructBuilder
StructBuilder
::
initRoot
(
SegmentBuilder
*
segment
,
word
*
location
,
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
)
{
return
WireHelpers
::
initStructReference
(
fieldCount
,
dataSize
,
referenceCount
,
reinterpret_cast
<
WireReference
*>
(
location
),
segment
);
}
StructBuilder StructBuilder::getStructFieldInternal(int refIndex) const {
StructBuilder
StructBuilder
::
getStructField
(
WireReferenceCount
refIndex
,
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
)
const
{
return
WireHelpers
::
initStructReference
(
return
WireHelpers
::
initStructReference
(
descriptor->defaultReferences[refIndex]->asStruct()
,
fieldCount
,
dataSize
,
referenceCount
,
re
interpret_cast<WireReference*>(ptr)
+ refIndex, segment);
re
ferences
+
refIndex
,
segment
);
}
}
ListBuilder StructBuilder::initListFieldInternal(int refIndex, uint32_t elementCount) const {
ListBuilder
StructBuilder
::
initListField
(
WireReferenceCount
refIndex
,
FieldSize
elementSize
,
ElementCount
elementCount
)
const
{
return
WireHelpers
::
initListReference
(
return
WireHelpers
::
initListReference
(
descriptor->defaultReferences[refIndex]->asList(),
references
+
refIndex
,
segment
,
reinterpret_cast<WireReference*>(ptr) + refIndex, segment, elementCount);
elementCount
,
elementSize
);
}
ListBuilder
StructBuilder
::
initStructListField
(
WireReferenceCount
refIndex
,
ElementCount
elementCount
,
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
)
const
{
return
WireHelpers
::
initStructListReference
(
references
+
refIndex
,
segment
,
elementCount
,
fieldCount
,
dataSize
,
referenceCount
);
}
}
ListBuilder StructBuilder::getListField
Internal(int refIndex
) const {
ListBuilder
StructBuilder
::
getListField
(
WireReferenceCount
refIndex
,
FieldSize
elementSize
)
const
{
return
WireHelpers
::
getWritableListReference
(
return
WireHelpers
::
getWritableListReference
(
descriptor->defaultReferences[refIndex]->asList(),
elementSize
,
references
+
refIndex
,
segment
);
reinterpret_cast<WireReference*>(ptr) + refIndex, segment);
}
}
StructReader
StructBuilder
::
asReader
()
const
{
StructReader
StructBuilder
::
asReader
()
const
{
return StructReader(descriptor, segment, ptr, descriptor->defaultData,
// HACK: We just give maxed-out field and reference counts because they are only used for
descriptor->fieldCount, 0 * BITS, std::numeric_limits<int>::max());
// checking for field presence.
static_assert
(
sizeof
(
WireReference
::
structRef
.
fieldCount
)
==
1
,
"Has the maximum field count changed?"
);
static_assert
(
sizeof
(
WireReference
::
structRef
.
refCount
)
==
1
,
"Has the maximum reference count changed?"
);
return
StructReader
(
segment
,
data
,
FieldNumber
(
0xff
),
intervalLength
(
data
,
reinterpret_cast
<
word
*>
(
references
)),
0xff
*
REFERENCES
,
0
*
BITS
,
std
::
numeric_limits
<
int
>::
max
());
}
}
StructReader StructReader::getStructFieldInternal(int fieldNumber, unsigned int refIndex) const {
StructReader
StructReader
::
readRootTrusted
(
const
word
*
location
,
const
word
*
defaultValue
)
{
return WireHelpers::readStructReference(
return
WireHelpers
::
readStructReference
(
nullptr
,
reinterpret_cast
<
const
WireReference
*>
(
location
),
descriptor->defaultReferences[refIndex]->asStruct(),
defaultValue
,
std
::
numeric_limits
<
int
>::
max
());
fieldNumber < fieldCount
? reinterpret_cast<const WireReference*>(ptr) + refIndex
: nullptr,
segment, recursionLimit);
}
}
ListReader StructReader::getListFieldInternal(int fieldNumber, unsigned int refIndex) const {
StructReader
StructReader
::
readRoot
(
const
word
*
location
,
const
word
*
defaultValue
,
SegmentReader
*
segment
,
int
recursionLimit
)
{
if
(
segment
->
containsInterval
(
location
,
location
+
1
*
REFERENCES
*
WORDS_PER_REFERENCE
))
{
segment
->
getMessage
()
->
reportInvalidData
(
"Root location out-of-bounds."
);
location
=
nullptr
;
}
return
WireHelpers
::
readStructReference
(
segment
,
reinterpret_cast
<
const
WireReference
*>
(
location
),
defaultValue
,
recursionLimit
);
}
StructReader
StructReader
::
getStructField
(
WireReferenceCount
refIndex
,
const
word
*
defaultValue
)
const
{
const
WireReference
*
ref
=
refIndex
>=
referenceCount
?
nullptr
:
reinterpret_cast
<
const
WireReference
*>
(
reinterpret_cast
<
const
word
*>
(
ptr
)
+
dataSize
)
+
refIndex
;
return
WireHelpers
::
readStructReference
(
segment
,
ref
,
defaultValue
,
recursionLimit
);
}
ListReader
StructReader
::
getListField
(
WireReferenceCount
refIndex
,
FieldSize
expectedElementSize
,
const
word
*
defaultValue
)
const
{
const
WireReference
*
ref
=
refIndex
>=
referenceCount
?
nullptr
:
reinterpret_cast
<
const
WireReference
*>
(
reinterpret_cast
<
const
word
*>
(
ptr
)
+
dataSize
)
+
refIndex
;
return
WireHelpers
::
readListReference
(
return
WireHelpers
::
readListReference
(
descriptor->defaultReferences[refIndex]->asList(),
segment
,
ref
,
defaultValue
,
expectedElementSize
,
recursionLimit
);
fieldNumber < fieldCount
? reinterpret_cast<const WireReference*>(ptr) + refIndex
: nullptr,
segment, recursionLimit);
}
}
StructBuilder ListBuilder::getStructElement
Internal
(
StructBuilder
ListBuilder
::
getStructElement
(
unsigned int index, WordCount element
Size) const {
ElementCount
index
,
decltype
(
WORDS
/
ELEMENTS
)
elementSize
,
WordCount
structData
Size
)
const
{
return StructBuilder(
word
*
structPtr
=
ptr
+
elementSize
*
index
;
descriptor->elementDescriptor->asStruct(), segment
,
return
StructBuilder
(
segment
,
structPtr
,
ptr + elementSize * index
);
reinterpret_cast
<
WireReference
*>
(
structPtr
+
structDataSize
)
);
}
}
ListBuilder ListBuilder::initListElementInternal(unsigned int index, uint32_t size) const {
ListBuilder
ListBuilder
::
initListElement
(
WireReferenceCount
index
,
FieldSize
elementSize
,
ElementCount
elementCount
)
const
{
return
WireHelpers
::
initListReference
(
return
WireHelpers
::
initListReference
(
descriptor->elementDescriptor->asList(),
reinterpret_cast
<
WireReference
*>
(
ptr
)
+
index
,
segment
,
reinterpret_cast<WireReference*>(ptr) + index,
elementCount
,
elementSize
);
segment, size);
}
}
ListBuilder ListBuilder::getListElementInternal(unsigned int index) const {
ListBuilder
ListBuilder
::
initStructListElement
(
return WireHelpers::getWritableListReference(
WireReferenceCount
index
,
ElementCount
elementCount
,
descriptor->elementDescriptor->asList(),
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
)
const
{
reinterpret_cast<WireReference*>(ptr) + index,
return
WireHelpers
::
initStructListReference
(
segment);
reinterpret_cast
<
WireReference
*>
(
ptr
)
+
index
,
segment
,
elementCount
,
fieldCount
,
dataSize
,
referenceCount
);
}
}
ListReader ListBuilder::asReader() const {
ListBuilder
ListBuilder
::
getListElement
(
WireReferenceCount
index
,
FieldSize
elementSize
)
const
{
return ListReader(descriptor, segment, ptr, elementCount,
return
WireHelpers
::
getWritableListReference
(
sizeInBits(descriptor->elementSize),
elementSize
,
reinterpret_cast
<
WireReference
*>
(
ptr
)
+
index
,
segment
);
descriptor->elementSize == FieldSize::STRUCT
? descriptor->elementDescriptor->asStruct()->fieldCount : 0,
1 << 30);
}
}
StructReader ListReader::getStructElementInternal(unsigned int index) const {
ListReader
ListBuilder
::
asReader
(
FieldSize
elementSize
)
const
{
const StructDescriptor* elementDescriptor;
return
ListReader
(
segment
,
ptr
,
elementCount
,
bitsPerElement
(
elementSize
),
if (ptr == nullptr) {
std
::
numeric_limits
<
int
>::
max
());
elementDescriptor = descriptor->defaultReferences()[index]->asStruct();
}
} else {
elementDescriptor = descriptor->elementDescriptor->asStruct();
if (CAPNPROTO_EXPECT_FALSE(recursionLimit == 0)) {
segment->getMessage()->reportInvalidData(
"Message is too deeply-nested or contains cycles.");
} else {
BitCount64 indexBit = static_cast<uint64_t>(index) * stepBits;
return StructReader(
elementDescriptor, segment,
reinterpret_cast<const byte*>(ptr) + indexBit / BITS_PER_BYTE,
descriptor->defaultData, structFieldCount, indexBit % BITS_PER_BYTE,
recursionLimit - 1);
}
}
return StructReader(elementDescriptor, segment, nullptr, descriptor->defaultData, 0, 0 * BITS, 0);
ListReader
ListBuilder
::
asReader
(
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
)
const
{
return
ListReader
(
segment
,
ptr
,
elementCount
,
(
dataSize
+
referenceCount
*
WORDS_PER_REFERENCE
)
*
BITS_PER_WORD
/
ELEMENTS
,
fieldCount
,
dataSize
,
referenceCount
,
std
::
numeric_limits
<
int
>::
max
());
}
}
ListReader ListReader::getListElementInternal(unsigned int index
) const {
StructReader
ListReader
::
getStructElement
(
ElementCount
index
,
const
word
*
defaultValue
)
const
{
if (
ptr == nullptr
) {
if
(
CAPNPROTO_EXPECT_FALSE
((
segment
!=
nullptr
)
&
(
recursionLimit
==
0
))
)
{
return WireHelpers::readListReference
(
segment
->
getMessage
()
->
reportInvalidData
(
descriptor->defaultReferences()[index]->asList(),
"Message is too deeply-nested or contains cycles."
);
nullptr, segment
, recursionLimit);
return
WireHelpers
::
readStructReference
(
nullptr
,
nullptr
,
defaultValue
,
recursionLimit
);
}
else
{
}
else
{
return WireHelpers::readListReference(
BitCount64
indexBit
=
ElementCount64
(
index
)
*
stepBits
;
descriptor->elementDescriptor->asList(),
return
StructReader
(
reinterpret_cast<const WireReference*>(ptr) +
segment
,
reinterpret_cast
<
const
byte
*>
(
ptr
)
+
indexBit
/
BITS_PER_BYTE
,
index * (stepBits / BITS_PER_WORD / WORDS_PER_REFERENCE)
,
structFieldCount
,
structDataSize
,
structReferenceCount
,
indexBit
%
BITS_PER_BYTE
,
segment, recursionLimit
);
recursionLimit
-
1
);
}
}
}
}
#endif
ListReader
ListReader
::
getListElement
(
WireReferenceCount
index
,
FieldSize
expectedElementSize
,
const
word
*
defaultValue
)
const
{
return
WireHelpers
::
readListReference
(
segment
,
reinterpret_cast
<
const
WireReference
*>
(
ptr
)
+
index
,
defaultValue
,
expectedElementSize
,
recursionLimit
);
}
}
// namespace internal
}
// namespace internal
}
// namespace capnproto
}
// namespace capnproto
c++/src/capnproto/wire-format.h
View file @
648d267d
...
@@ -81,9 +81,10 @@ private:
...
@@ -81,9 +81,10 @@ private:
class
StructBuilder
{
class
StructBuilder
{
public
:
public
:
inline
StructBuilder
()
:
segment
(
nullptr
),
ptr
(
nullptr
)
{}
inline
StructBuilder
()
:
segment
(
nullptr
),
data
(
nullptr
),
references
(
nullptr
)
{}
static
StructBuilder
initRoot
(
SegmentBuilder
*
segment
,
word
*
location
);
static
StructBuilder
initRoot
(
SegmentBuilder
*
segment
,
word
*
location
,
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
);
template
<
typename
T
>
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
T
getDataField
(
ElementCount
offset
)
const
);
CAPNPROTO_ALWAYS_INLINE
(
T
getDataField
(
ElementCount
offset
)
const
);
...
@@ -95,16 +96,21 @@ public:
...
@@ -95,16 +96,21 @@ public:
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
value
)
const
);
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
value
)
const
);
// Set the data field value at the given offset.
// Set the data field value at the given offset.
inline
StructBuilder
getStructField
(
WireReferenceCount
refIndex
)
const
;
StructBuilder
getStructField
(
WireReferenceCount
refIndex
,
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
)
const
;
// Get the struct field at the given index in the reference segment. Allocates space for the
// Get the struct field at the given index in the reference segment. Allocates space for the
// struct if necessary.
// struct if necessary.
inline
ListBuilder
initListField
(
WireReferenceCount
refIndex
,
FieldSize
fieldSize
,
ListBuilder
initListField
(
WireReferenceCount
refIndex
,
FieldSize
elementSize
,
ElementCount
elementCount
)
const
;
ElementCount
elementCount
)
const
;
ListBuilder
initStructListField
(
WireReferenceCount
refIndex
,
ElementCount
elementCount
,
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
)
const
;
// Allocate a new list of the given size for the field at the given index in the reference
// Allocate a new list of the given size for the field at the given index in the reference
// segment, and return a pointer to it.
// segment, and return a pointer to it.
inline
ListBuilder
getListField
(
WireReferenceCount
refIndex
)
const
;
ListBuilder
getListField
(
WireReferenceCount
refIndex
,
FieldSize
elementSize
)
const
;
// Get the already-allocated list field for the given reference index. Returns an empty list --
// Get the already-allocated list field for the given reference index. Returns an empty list --
// NOT necessarily the default value -- if the field is not initialized.
// NOT necessarily the default value -- if the field is not initialized.
...
@@ -112,11 +118,12 @@ public:
...
@@ -112,11 +118,12 @@ public:
// Get a StructReader pointing at the same memory.
// Get a StructReader pointing at the same memory.
private
:
private
:
SegmentBuilder
*
segment
;
// Memory segment in which the struct resides.
SegmentBuilder
*
segment
;
// Memory segment in which the struct resides.
word
*
ptr
;
// Pointer to the encoded struct (data followed by references).
word
*
data
;
// Pointer to the encoded data.
WireReference
*
references
;
// Pointer to the encoded references.
inline
StructBuilder
(
SegmentBuilder
*
segment
,
word
*
ptr
)
inline
StructBuilder
(
SegmentBuilder
*
segment
,
word
*
data
,
WireReference
*
references
)
:
segment
(
segment
),
ptr
(
ptr
)
{}
:
segment
(
segment
),
data
(
data
),
references
(
references
)
{}
friend
class
ListBuilder
;
friend
class
ListBuilder
;
friend
struct
WireHelpers
;
friend
struct
WireHelpers
;
...
@@ -128,6 +135,10 @@ public:
...
@@ -128,6 +135,10 @@ public:
:
segment
(
nullptr
),
ptr
(
nullptr
),
fieldCount
(
0
),
dataSize
(
0
),
referenceCount
(
0
),
:
segment
(
nullptr
),
ptr
(
nullptr
),
fieldCount
(
0
),
dataSize
(
0
),
referenceCount
(
0
),
bit0Offset
(
0
*
BITS
),
recursionLimit
(
0
)
{}
bit0Offset
(
0
*
BITS
),
recursionLimit
(
0
)
{}
static
StructReader
readRootTrusted
(
const
word
*
location
,
const
word
*
defaultValue
);
static
StructReader
readRoot
(
const
word
*
location
,
const
word
*
defaultValue
,
SegmentReader
*
segment
,
int
recursionLimit
);
template
<
typename
T
>
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
CAPNPROTO_ALWAYS_INLINE
(
T
getDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
defaultValue
)
const
);
T
getDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
defaultValue
)
const
);
...
@@ -143,11 +154,13 @@ public:
...
@@ -143,11 +154,13 @@ public:
// with later numbers, and therefore the offset being in-bounds alone does not prove that the
// with later numbers, and therefore the offset being in-bounds alone does not prove that the
// struct contains the field.
// struct contains the field.
inline
StructReader
getStructField
(
WireReferenceCount
refIndex
)
const
;
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
// Get the struct field at the given index in the reference segment, or the default value if not
// initialized.
// initialized. defaultValue will be interpreted as a trusted message -- it must point at a
// struct reference, which in turn points at the struct value.
inline
ListReader
getListField
(
WireReferenceCount
refIndex
,
FieldSize
expectedElementSize
)
const
;
ListReader
getListField
(
WireReferenceCount
refIndex
,
FieldSize
expectedElementSize
,
const
word
*
defaultValue
)
const
;
// Get the list field at the given index in the reference segment, or the default value if not
// Get the list field at the given index in the reference segment, or the default value if not
// initialized.
// initialized.
...
@@ -208,20 +221,27 @@ public:
...
@@ -208,20 +221,27 @@ public:
ElementCount
index
,
typename
NoInfer
<
T
>::
Type
value
)
const
);
ElementCount
index
,
typename
NoInfer
<
T
>::
Type
value
)
const
);
// Set the element at the given index.
// Set the element at the given index.
CAPNPROTO_ALWAYS_INLINE
(
StructBuilder
getStructElement
(
StructBuilder
getStructElement
(
ElementCount
index
,
decltype
(
WORDS
/
ELEMENTS
)
elementSize
)
const
)
;
ElementCount
index
,
decltype
(
WORDS
/
ELEMENTS
)
elementSize
,
WordCount
structDataSize
)
const
;
// Get the struct element at the given index. elementSize is the size, in 64-bit words, of
// Get the struct element at the given index. elementSize is the size, in 64-bit words, of
// each element.
// each element.
CAPNPROTO_ALWAYS_INLINE
(
ListBuilder
initListElement
(
ListBuilder
initListElement
(
WireReferenceCount
index
,
ElementCount
size
)
const
);
WireReferenceCount
index
,
FieldSize
elementSize
,
ElementCount
elementCount
)
const
;
ListBuilder
initStructListElement
(
WireReferenceCount
index
,
ElementCount
elementCount
,
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
)
const
;
// Create a new list element of the given size at the given index.
// Create a new list element of the given size at the given index.
CAPNPROTO_ALWAYS_INLINE
(
ListBuilder
getListElement
(
WireReferenceCount
index
)
const
)
;
ListBuilder
getListElement
(
WireReferenceCount
index
,
FieldSize
elementSize
)
const
;
// Get the existing list element at the given index.
// Get the existing list element at the given index.
ListReader
asReader
()
const
;
ListReader
asReader
(
FieldSize
elementSize
)
const
;
// Get a ListReader pointing at the same memory.
// Get a ListReader pointing at the same memory. Use this version only for non-struct lists.
ListReader
asReader
(
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
)
const
;
// Get a ListReader pointing at the same memory. Use this version only for struct lists.
private
:
private
:
SegmentBuilder
*
segment
;
// Memory segment in which the list resides.
SegmentBuilder
*
segment
;
// Memory segment in which the list resides.
...
@@ -249,11 +269,11 @@ public:
...
@@ -249,11 +269,11 @@ public:
CAPNPROTO_ALWAYS_INLINE
(
T
getDataElement
(
ElementCount
index
)
const
);
CAPNPROTO_ALWAYS_INLINE
(
T
getDataElement
(
ElementCount
index
)
const
);
// Get the element of the given type at the given index.
// Get the element of the given type at the given index.
CAPNPROTO_ALWAYS_INLINE
(
StructReader
getStructElement
(
ElementCount
index
)
const
)
;
StructReader
getStructElement
(
ElementCount
index
,
const
word
*
defaultValue
)
const
;
// Get the struct element at the given index.
// Get the struct element at the given index.
CAPNPROTO_ALWAYS_INLINE
(
ListReader
getListElement
(
ListReader
getListElement
(
WireReferenceCount
index
,
FieldSize
expectedElementSize
,
WireReferenceCount
index
,
FieldSize
expectedElementSize
)
const
)
;
const
word
*
defaultValue
)
const
;
// Get the list element at the given index.
// Get the list element at the given index.
private
:
private
:
...
@@ -273,7 +293,9 @@ private:
...
@@ -273,7 +293,9 @@ private:
FieldNumber
structFieldCount
;
FieldNumber
structFieldCount
;
WordCount
structDataSize
;
WordCount
structDataSize
;
WireReferenceCount
structReferenceCount
;
WireReferenceCount
structReferenceCount
;
// If the elements are structs, the properties of the struct.
// If the elements are structs, the properties of the struct. The field and reference counts are
// only used to check for field presence; the data size is also used to compute the reference
// pointer.
int
recursionLimit
;
int
recursionLimit
;
// Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
// Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
...
@@ -302,26 +324,26 @@ private:
...
@@ -302,26 +324,26 @@ private:
template
<
typename
T
>
template
<
typename
T
>
inline
T
StructBuilder
::
getDataField
(
ElementCount
offset
)
const
{
inline
T
StructBuilder
::
getDataField
(
ElementCount
offset
)
const
{
return
reinterpret_cast
<
WireValue
<
T
>*>
(
ptr
)[
offset
/
ELEMENTS
].
get
();
return
reinterpret_cast
<
WireValue
<
T
>*>
(
data
)[
offset
/
ELEMENTS
].
get
();
}
}
template
<>
template
<>
inline
bool
StructBuilder
::
getDataField
<
bool
>
(
ElementCount
offset
)
const
{
inline
bool
StructBuilder
::
getDataField
<
bool
>
(
ElementCount
offset
)
const
{
BitCount
boffset
=
offset
*
(
1
*
BITS
/
ELEMENTS
);
BitCount
boffset
=
offset
*
(
1
*
BITS
/
ELEMENTS
);
byte
*
b
=
reinterpret_cast
<
byte
*>
(
ptr
)
+
boffset
/
BITS_PER_BYTE
;
byte
*
b
=
reinterpret_cast
<
byte
*>
(
data
)
+
boffset
/
BITS_PER_BYTE
;
return
(
*
reinterpret_cast
<
uint8_t
*>
(
b
)
&
(
1
<<
(
boffset
%
BITS_PER_BYTE
/
BITS
)))
!=
0
;
return
(
*
reinterpret_cast
<
uint8_t
*>
(
b
)
&
(
1
<<
(
boffset
%
BITS_PER_BYTE
/
BITS
)))
!=
0
;
}
}
template
<
typename
T
>
template
<
typename
T
>
inline
void
StructBuilder
::
setDataField
(
inline
void
StructBuilder
::
setDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
value
)
const
{
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
value
)
const
{
reinterpret_cast
<
WireValue
<
T
>*>
(
ptr
)[
offset
/
ELEMENTS
].
set
(
value
);
reinterpret_cast
<
WireValue
<
T
>*>
(
data
)[
offset
/
ELEMENTS
].
set
(
value
);
}
}
template
<>
template
<>
inline
void
StructBuilder
::
setDataField
<
bool
>
(
ElementCount
offset
,
bool
value
)
const
{
inline
void
StructBuilder
::
setDataField
<
bool
>
(
ElementCount
offset
,
bool
value
)
const
{
BitCount
boffset
=
offset
*
(
1
*
BITS
/
ELEMENTS
);
BitCount
boffset
=
offset
*
(
1
*
BITS
/
ELEMENTS
);
byte
*
b
=
reinterpret_cast
<
byte
*>
(
ptr
)
+
boffset
/
BITS_PER_BYTE
;
byte
*
b
=
reinterpret_cast
<
byte
*>
(
data
)
+
boffset
/
BITS_PER_BYTE
;
uint
bitnum
=
boffset
%
BITS_PER_BYTE
/
BITS
;
uint
bitnum
=
boffset
%
BITS_PER_BYTE
/
BITS
;
*
reinterpret_cast
<
uint8_t
*>
(
b
)
=
(
*
reinterpret_cast
<
uint8_t
*>
(
b
)
&
~
(
1
<<
bitnum
))
*
reinterpret_cast
<
uint8_t
*>
(
b
)
=
(
*
reinterpret_cast
<
uint8_t
*>
(
b
)
&
~
(
1
<<
bitnum
))
|
(
static_cast
<
uint8_t
>
(
value
)
<<
bitnum
);
|
(
static_cast
<
uint8_t
>
(
value
)
<<
bitnum
);
...
@@ -332,7 +354,7 @@ inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) c
...
@@ -332,7 +354,7 @@ inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) c
template
<
typename
T
>
template
<
typename
T
>
T
StructReader
::
getDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
defaultValue
)
const
{
T
StructReader
::
getDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
defaultValue
)
const
{
if
(
offset
*
bytesPerElement
<
T
>
()
<
dataSize
*
BYTES_PER_WORD
)
{
if
(
offset
*
bytesPerElement
<
T
>
()
<
dataSize
*
BYTES_PER_WORD
)
{
return
reinterpret_cast
<
WireValue
<
T
>*>
(
ptr
)[
offset
/
ELEMENTS
].
get
();
return
reinterpret_cast
<
const
WireValue
<
T
>*>
(
ptr
)[
offset
/
ELEMENTS
].
get
();
}
else
{
}
else
{
return
defaultValue
;
return
defaultValue
;
}
}
...
@@ -359,7 +381,7 @@ T StructReader::getDataFieldCheckingNumber(
...
@@ -359,7 +381,7 @@ T StructReader::getDataFieldCheckingNumber(
// Intentionally use & rather than && to reduce branches.
// Intentionally use & rather than && to reduce branches.
if
((
fieldNumber
<
fieldCount
)
&
if
((
fieldNumber
<
fieldCount
)
&
(
offset
*
bytesPerElement
<
T
>
()
<
dataSize
*
BYTES_PER_WORD
))
{
(
offset
*
bytesPerElement
<
T
>
()
<
dataSize
*
BYTES_PER_WORD
))
{
return
reinterpret_cast
<
WireValue
<
T
>*>
(
ptr
)[
offset
/
ELEMENTS
].
get
();
return
reinterpret_cast
<
const
WireValue
<
T
>*>
(
ptr
)[
offset
/
ELEMENTS
].
get
();
}
else
{
}
else
{
return
defaultValue
;
return
defaultValue
;
}
}
...
...
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