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
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
303 additions
and
233 deletions
+303
-233
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++
+123
-131
wire-format.h
c++/src/capnproto/wire-format.h
+50
-28
No files found.
c++/src/capnproto/descriptor-test.c++
View file @
648d267d
...
...
@@ -31,28 +31,23 @@ namespace {
const
int
READONLY_SEGMENT_START
=
123
;
const
FieldDescriptor
TEST_FIELDS
[
2
]
=
{
{
1
*
WORDS
,
0
,
0
,
FieldSize
::
FOUR_BYTES
,
1
,
0
,
0
,
0
},
{
1
*
WORDS
,
1
,
0
,
FieldSize
::
REFERENCE
,
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
*
REFERENCES
,
FieldSize
::
REFERENCE
,
0
*
ELEMENTS
,
0
*
BYTES
,
1
,
0
,
0
*
BYTES
,
0
*
BITS
,
nullptr
,
nullptr
}
};
extern
const
StructDescriptor
TEST_STRUCT
;
extern
const
Descriptor
*
const
TEST_STRUCT_DEFAULT_REFS
[
1
]
=
{
&
TEST_STRUCT
.
base
};
const
AlignedData
<
1
>
TEST_STRUCT_DEFAULT_DATA
=
{
const
AlignedData
<
1
>
TEST_STRUCT_DEFAULT_VALUE
=
{
{
0x12
,
0x34
,
0x56
,
0x78
,
0x9a
,
0xbc
,
0xde
,
0xf0
}
};
const
StructDescriptor
TEST_STRUCT
=
{
{
Descriptor
::
Kind
::
STRUCT
},
2
,
WordCount8
(
1
*
WORDS
)
,
1
,
FieldNumber
(
2
)
,
1
*
WORDS
,
1
*
REFERENCES
,
TEST_FIELDS
,
TEST_STRUCT_DEFAULT_DATA
.
bytes
,
TEST_STRUCT_DEFAULT_REFS
TEST_STRUCT_DEFAULT_VALUE
.
words
};
const
int
READONLY_SEGMENT_END
=
321
;
...
...
@@ -66,10 +61,8 @@ TEST(Descriptors, InReadOnlySegment) {
EXPECT_LE
((
const
void
*
)
&
READONLY_SEGMENT_START
,
(
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_GE
((
const
void
*
)
&
READONLY_SEGMENT_END
,
(
const
void
*
)
&
TEST_STRUCT_DEFAULT_DATA
);
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_DEFAULT_VALUE
);
EXPECT_GE
((
const
void
*
)
&
READONLY_SEGMENT_END
,
(
const
void
*
)
&
TEST_STRUCT_DEFAULT_VALUE
);
EXPECT_LE
((
const
void
*
)
&
READONLY_SEGMENT_START
,
(
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:
// 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.
template
<
typename
OtherNumber
>
inline
constexpr
UnitRatio
(
const
UnitRatio
<
OtherNumber
,
Unit1
,
Unit2
>&
other
)
:
unit1PerUnit2
(
other
.
unit1PerUnit2
)
{}
template
<
typename
OtherNumber
,
typename
Unit3
>
inline
constexpr
UnitRatio
<
decltype
(
Number
(
1
)
*
OtherNumber
(
1
)),
Unit3
,
Unit2
>
operator
*
(
UnitRatio
<
OtherNumber
,
Unit3
,
Unit1
>
other
)
{
...
...
@@ -422,72 +426,38 @@ inline constexpr decltype(BYTES / ELEMENTS) bytesPerElement() {
#ifndef __CDT_PARSER__
template
<
typename
T
>
inline
constexpr
byte
*
operator
+
(
byte
*
ptr
,
Quantity
<
T
,
byte
>
offset
)
{
return
ptr
+
offset
/
BYTES
;
}
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
,
typename
U
>
inline
constexpr
U
*
operator
+
(
U
*
ptr
,
Quantity
<
T
,
U
>
offset
)
{
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
,
typename
U
>
inline
constexpr
const
U
*
operator
+
(
const
U
*
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
+
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
template
<
typename
T
>
inline
constexpr
byte
*
operator
-=
(
byte
*&
ptr
,
Quantity
<
T
,
byte
>
offset
)
{
return
ptr
=
ptr
-
offset
/
BYTES
;
template
<
typename
T
,
typename
U
>
inline
constexpr
U
*
operator
+=
(
U
*&
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
=
ptr
+
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
template
<
typename
T
>
inline
constexpr
const
byte
*
operator
-=
(
const
byte
*
ptr
,
Quantity
<
T
,
byte
>
offset
)
{
return
ptr
=
ptr
-
offset
/
BYTES
;
template
<
typename
T
,
typename
U
>
inline
constexpr
const
U
*
operator
+=
(
const
U
*&
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
=
ptr
+
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
template
<
typename
T
>
inline
constexpr
word
*
operator
-
(
word
*
ptr
,
Quantity
<
T
,
word
>
offset
)
{
return
ptr
-
offset
/
WORDS
;
template
<
typename
T
,
typename
U
>
inline
constexpr
U
*
operator
-
(
U
*
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
-
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
template
<
typename
T
>
inline
constexpr
const
word
*
operator
-
(
const
word
*
ptr
,
Quantity
<
T
,
word
>
offset
)
{
return
ptr
-
offset
/
WORDS
;
template
<
typename
T
,
typename
U
>
inline
constexpr
const
U
*
operator
-
(
const
U
*
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
-
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
template
<
typename
T
>
inline
constexpr
word
*
operator
-=
(
word
*&
ptr
,
Quantity
<
T
,
word
>
offset
)
{
return
ptr
=
ptr
-
offset
/
WORDS
;
template
<
typename
T
,
typename
U
>
inline
constexpr
U
*
operator
-=
(
U
*&
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
=
ptr
-
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
template
<
typename
T
>
inline
constexpr
const
word
*
operator
-=
(
const
word
*&
ptr
,
Quantity
<
T
,
word
>
offset
)
{
return
ptr
=
ptr
-
offset
/
WORDS
;
template
<
typename
T
,
typename
U
>
inline
constexpr
const
U
*
operator
-=
(
const
U
*&
ptr
,
Quantity
<
T
,
U
>
offset
)
{
return
ptr
=
ptr
-
offset
/
unit
<
Quantity
<
T
,
U
>>
()
;
}
#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(
// =======================================================================================
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
{
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
(
WireReference
*&
ref
,
SegmentBuilder
*&
segment
,
WordCount
amount
))
{
word
*
ptr
=
segment
->
allocate
(
amount
);
...
...
@@ -208,23 +192,6 @@ struct WireHelpers {
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
(
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
,
WireReference
*
ref
,
SegmentBuilder
*
segment
))
{
...
...
@@ -232,27 +199,25 @@ struct WireHelpers {
// Allocate space for the new struct.
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.
ref
->
setStruct
(
fieldCount
,
dataSize
,
referenceCount
,
segment
->
getOffsetTo
(
ptr
));
// Build the StructBuilder.
return
StructBuilder
(
segment
,
ptr
);
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
dataSize
)
);
}
else
{
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."
);
CAPNPROTO_ASSERT
(
ref
->
structRef
.
fieldCount
.
get
()
==
fieldCount
,
CAPNPROTO_
DEBUG_
ASSERT
(
ref
->
structRef
.
fieldCount
.
get
()
==
fieldCount
,
"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."
);
CAPNPROTO_ASSERT
(
ref
->
structRef
.
refCount
.
get
()
==
referenceCount
,
CAPNPROTO_
DEBUG_
ASSERT
(
ref
->
structRef
.
refCount
.
get
()
==
referenceCount
,
"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 {
CAPNPROTO_DEBUG_ASSERT
(
elementSize
!=
FieldSize
::
STRUCT
,
"Should have called initStructListReference() instead."
);
// Calculate size of the list. Need to cast to uint here because a list can be up to
// 2**32-1 bits, so int would overflow. Plus uint division by a power of 2 is a bit shift.
WordCount
wordCount
=
divRoundingUp
(
elementCount
*
bitsPerElement
(
elementSize
),
BITS_PER_WORD
);
// Calculate size of the list.
WordCount
wordCount
=
roundUpToWords
(
ElementCount64
(
elementCount
)
*
bitsPerElement
(
elementSize
));
// Allocate the list.
word
*
ptr
=
allocate
(
ref
,
segment
,
wordCount
);
...
...
@@ -321,15 +285,14 @@ struct WireHelpers {
}
static
CAPNPROTO_ALWAYS_INLINE
(
StructReader
readStructReference
(
SegmentReader
*
segment
,
const
WireReference
*
ref
,
const
WireReference
*
defaultValue
,
SegmentReader
*
segment
,
const
WireReference
*
ref
,
const
word
*
defaultValue
,
int
recursionLimit
))
{
const
word
*
ptr
;
const
word
*
ptr
=
ref
->
target
()
;
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
useDefault
:
segment
=
nullptr
;
ref
=
defaultValue
;
ptr
=
ref
->
target
();
ref
=
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
);
}
else
if
(
segment
!=
nullptr
)
{
if
(
CAPNPROTO_EXPECT_FALSE
(
recursionLimit
==
0
))
{
segment
->
getMessage
()
->
reportInvalidData
(
...
...
@@ -352,8 +315,6 @@ struct WireHelpers {
WordCount
size
=
ref
->
structRef
.
dataSize
.
get
()
+
ref
->
structRef
.
refCount
.
get
()
*
WORDS_PER_REFERENCE
;
ptr
=
ref
->
target
();
if
(
CAPNPROTO_EXPECT_FALSE
(
!
segment
->
containsInterval
(
ptr
,
ptr
+
size
)))
{
segment
->
getMessage
()
->
reportInvalidData
(
"Message contained out-of-bounds struct reference."
);
...
...
@@ -369,12 +330,12 @@ struct WireHelpers {
}
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
))
{
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
useDefault
:
segment
=
nullptr
;
ref
=
defaultValue
;
ref
=
reinterpret_cast
<
const
WireReference
*>
(
defaultValue
)
;
}
else
if
(
segment
!=
nullptr
)
{
if
(
CAPNPROTO_EXPECT_FALSE
(
recursionLimit
==
0
))
{
segment
->
getMessage
()
->
reportInvalidData
(
...
...
@@ -490,7 +451,7 @@ struct WireHelpers {
if
(
segment
!=
nullptr
)
{
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
(
"Message contained out-of-bounds list reference."
);
goto
useDefault
;
...
...
@@ -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
(
descriptor->defaultReferences[refIndex]->asStruct()
,
re
interpret_cast<WireReference*>(ptr)
+ refIndex, segment);
fieldCount
,
dataSize
,
referenceCount
,
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
(
descriptor->defaultReferences[refIndex]->asList()
,
reinterpret_cast<WireReference*>(ptr) + refIndex, segment, elementCount
);
references
+
refIndex
,
segment
,
elementCount
,
elementSize
);
}
ListBuilder StructBuilder::getListFieldInternal(int refIndex) const {
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
(
WireReferenceCount
refIndex
,
FieldSize
elementSize
)
const
{
return
WireHelpers
::
getWritableListReference
(
descriptor->defaultReferences[refIndex]->asList(),
reinterpret_cast<WireReference*>(ptr) + refIndex, segment);
elementSize
,
references
+
refIndex
,
segment
);
}
StructReader
StructBuilder
::
asReader
()
const
{
return StructReader(descriptor, segment, ptr, descriptor->defaultData,
descriptor->fieldCount, 0 * BITS, std::numeric_limits<int>::max());
// HACK: We just give maxed-out field and reference counts because they are only used for
// 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
::
readRootTrusted
(
const
word
*
location
,
const
word
*
defaultValue
)
{
return
WireHelpers
::
readStructReference
(
nullptr
,
reinterpret_cast
<
const
WireReference
*>
(
location
),
defaultValue
,
std
::
numeric_limits
<
int
>::
max
());
}
StructReader StructReader::getStructFieldInternal(int fieldNumber, unsigned int refIndex) const {
return WireHelpers::readStructReference(
descriptor->defaultReferences[refIndex]->asStruct(),
fieldNumber < fieldCount
? reinterpret_cast<const WireReference*>(ptr) + refIndex
: nullptr,
segment, recursionLimit);
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
);
}
ListReader StructReader::getListFieldInternal(int fieldNumber, unsigned int refIndex) const {
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
(
descriptor->defaultReferences[refIndex]->asList(),
fieldNumber < fieldCount
? reinterpret_cast<const WireReference*>(ptr) + refIndex
: nullptr,
segment, recursionLimit);
segment
,
ref
,
defaultValue
,
expectedElementSize
,
recursionLimit
);
}
StructBuilder ListBuilder::getStructElement
Internal
(
unsigned int index, WordCount element
Size) const {
return StructBuilder(
descriptor->elementDescriptor->asStruct(), segment
,
ptr + elementSize * index
);
StructBuilder
ListBuilder
::
getStructElement
(
ElementCount
index
,
decltype
(
WORDS
/
ELEMENTS
)
elementSize
,
WordCount
structData
Size
)
const
{
word
*
structPtr
=
ptr
+
elementSize
*
index
;
return
StructBuilder
(
segment
,
structPtr
,
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
(
descriptor->elementDescriptor->asList(),
reinterpret_cast<WireReference*>(ptr) + index,
segment, size);
reinterpret_cast
<
WireReference
*>
(
ptr
)
+
index
,
segment
,
elementCount
,
elementSize
);
}
ListBuilder ListBuilder::getListElementInternal(unsigned int index) const {
ListBuilder
ListBuilder
::
initStructListElement
(
WireReferenceCount
index
,
ElementCount
elementCount
,
FieldNumber
fieldCount
,
WordCount
dataSize
,
WireReferenceCount
referenceCount
)
const
{
return
WireHelpers
::
initStructListReference
(
reinterpret_cast
<
WireReference
*>
(
ptr
)
+
index
,
segment
,
elementCount
,
fieldCount
,
dataSize
,
referenceCount
);
}
ListBuilder
ListBuilder
::
getListElement
(
WireReferenceCount
index
,
FieldSize
elementSize
)
const
{
return
WireHelpers
::
getWritableListReference
(
descriptor->elementDescriptor->asList(),
reinterpret_cast<WireReference*>(ptr) + index,
segment);
elementSize
,
reinterpret_cast
<
WireReference
*>
(
ptr
)
+
index
,
segment
);
}
ListReader ListBuilder::asReader() const {
return ListReader(descriptor, segment, ptr, elementCount,
sizeInBits(descriptor->elementSize),
descriptor->elementSize == FieldSize::STRUCT
? descriptor->elementDescriptor->asStruct()->fieldCount : 0,
1 << 30);
ListReader
ListBuilder
::
asReader
(
FieldSize
elementSize
)
const
{
return
ListReader
(
segment
,
ptr
,
elementCount
,
bitsPerElement
(
elementSize
),
std
::
numeric_limits
<
int
>::
max
());
}
StructReader ListReader::getStructElementInternal(unsigned int index) const {
const StructDescriptor* elementDescriptor;
if (ptr == nullptr) {
elementDescriptor = descriptor->defaultReferences()[index]->asStruct();
} else {
elementDescriptor = descriptor->elementDescriptor->asStruct();
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
());
}
if (CAPNPROTO_EXPECT_FALSE(recursionLimit == 0)) {
StructReader
ListReader
::
getStructElement
(
ElementCount
index
,
const
word
*
defaultValue
)
const
{
if
(
CAPNPROTO_EXPECT_FALSE
((
segment
!=
nullptr
)
&
(
recursionLimit
==
0
)))
{
segment
->
getMessage
()
->
reportInvalidData
(
"Message is too deeply-nested or contains cycles."
);
return
WireHelpers
::
readStructReference
(
nullptr
,
nullptr
,
defaultValue
,
recursionLimit
);
}
else
{
BitCount64 indexBit = static_cast<uint64_t>
(index) * stepBits;
BitCount64
indexBit
=
ElementCount64
(
index
)
*
stepBits
;
return
StructReader
(
elementDescriptor, segment,
reinterpret_cast<const byte*>(ptr) + indexBit / BITS_PER_BYTE,
descriptor->defaultData, structFieldCount, indexBit % BITS_PER_BYTE,
segment
,
reinterpret_cast
<
const
byte
*>
(
ptr
)
+
indexBit
/
BITS_PER_BYTE
,
structFieldCount
,
structDataSize
,
structReferenceCount
,
indexBit
%
BITS_PER_BYTE
,
recursionLimit
-
1
);
}
}
return StructReader(elementDescriptor, segment, nullptr, descriptor->defaultData, 0, 0 * BITS, 0);
}
ListReader ListReader::getListElementInternal(unsigned int index) const {
if (ptr == nullptr) {
return WireHelpers::readListReference(
descriptor->defaultReferences()[index]->asList(),
nullptr, segment, recursionLimit);
} else {
ListReader
ListReader
::
getListElement
(
WireReferenceCount
index
,
FieldSize
expectedElementSize
,
const
word
*
defaultValue
)
const
{
return
WireHelpers
::
readListReference
(
descriptor->elementDescriptor->asList(),
reinterpret_cast<const WireReference*>(ptr) +
index * (stepBits / BITS_PER_WORD / WORDS_PER_REFERENCE),
segment, recursionLimit);
}
segment
,
reinterpret_cast
<
const
WireReference
*>
(
ptr
)
+
index
,
defaultValue
,
expectedElementSize
,
recursionLimit
);
}
#endif
}
// namespace internal
}
// namespace capnproto
c++/src/capnproto/wire-format.h
View file @
648d267d
...
...
@@ -81,9 +81,10 @@ private:
class
StructBuilder
{
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
>
CAPNPROTO_ALWAYS_INLINE
(
T
getDataField
(
ElementCount
offset
)
const
);
...
...
@@ -95,16 +96,21 @@ public:
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
value
)
const
);
// 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
// struct if necessary.
inline
ListBuilder
initListField
(
WireReferenceCount
refIndex
,
FieldSize
field
Size
,
ListBuilder
initListField
(
WireReferenceCount
refIndex
,
FieldSize
element
Size
,
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
// 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 --
// NOT necessarily the default value -- if the field is not initialized.
...
...
@@ -113,10 +119,11 @@ public:
private
:
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
)
:
segment
(
segment
),
ptr
(
ptr
)
{}
inline
StructBuilder
(
SegmentBuilder
*
segment
,
word
*
data
,
WireReference
*
references
)
:
segment
(
segment
),
data
(
data
),
references
(
references
)
{}
friend
class
ListBuilder
;
friend
struct
WireHelpers
;
...
...
@@ -128,6 +135,10 @@ public:
:
segment
(
nullptr
),
ptr
(
nullptr
),
fieldCount
(
0
),
dataSize
(
0
),
referenceCount
(
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
>
CAPNPROTO_ALWAYS_INLINE
(
T
getDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
defaultValue
)
const
);
...
...
@@ -143,11 +154,13 @@ public:
// with later numbers, and therefore the offset being in-bounds alone does not prove that the
// 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
// 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
// initialized.
...
...
@@ -208,20 +221,27 @@ public:
ElementCount
index
,
typename
NoInfer
<
T
>::
Type
value
)
const
);
// Set the element at the given index.
CAPNPROTO_ALWAYS_INLINE
(
StructBuilder
getStructElement
(
ElementCount
index
,
decltype
(
WORDS
/
ELEMENTS
)
elementSize
)
const
)
;
StructBuilder
getStructElement
(
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
// each element.
CAPNPROTO_ALWAYS_INLINE
(
ListBuilder
initListElement
(
WireReferenceCount
index
,
ElementCount
size
)
const
);
ListBuilder
initListElement
(
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.
CAPNPROTO_ALWAYS_INLINE
(
ListBuilder
getListElement
(
WireReferenceCount
index
)
const
)
;
ListBuilder
getListElement
(
WireReferenceCount
index
,
FieldSize
elementSize
)
const
;
// Get the existing list element at the given index.
ListReader
asReader
()
const
;
// Get a ListReader pointing at the same memory.
ListReader
asReader
(
FieldSize
elementSize
)
const
;
// 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
:
SegmentBuilder
*
segment
;
// Memory segment in which the list resides.
...
...
@@ -249,11 +269,11 @@ public:
CAPNPROTO_ALWAYS_INLINE
(
T
getDataElement
(
ElementCount
index
)
const
);
// 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.
CAPNPROTO_ALWAYS_INLINE
(
ListReader
getListElement
(
WireReferenceCount
index
,
FieldSize
expectedElementSize
)
const
)
;
ListReader
getListElement
(
WireReferenceCount
index
,
FieldSize
expectedElementSize
,
const
word
*
defaultValue
)
const
;
// Get the list element at the given index.
private
:
...
...
@@ -273,7 +293,9 @@ private:
FieldNumber
structFieldCount
;
WordCount
structDataSize
;
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
;
// Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
...
...
@@ -302,26 +324,26 @@ private:
template
<
typename
T
>
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
<>
inline
bool
StructBuilder
::
getDataField
<
bool
>
(
ElementCount
offset
)
const
{
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
;
}
template
<
typename
T
>
inline
void
StructBuilder
::
setDataField
(
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
<>
inline
void
StructBuilder
::
setDataField
<
bool
>
(
ElementCount
offset
,
bool
value
)
const
{
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
;
*
reinterpret_cast
<
uint8_t
*>
(
b
)
=
(
*
reinterpret_cast
<
uint8_t
*>
(
b
)
&
~
(
1
<<
bitnum
))
|
(
static_cast
<
uint8_t
>
(
value
)
<<
bitnum
);
...
...
@@ -332,7 +354,7 @@ inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) c
template
<
typename
T
>
T
StructReader
::
getDataField
(
ElementCount
offset
,
typename
NoInfer
<
T
>::
Type
defaultValue
)
const
{
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
{
return
defaultValue
;
}
...
...
@@ -359,7 +381,7 @@ T StructReader::getDataFieldCheckingNumber(
// Intentionally use & rather than && to reduce branches.
if
((
fieldNumber
<
fieldCount
)
&
(
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
{
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