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
f017105e
Commit
f017105e
authored
May 09, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Various stuff in support of dynamic API.
parent
5ab5e2a3
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
164 additions
and
29 deletions
+164
-29
generated-header-support.h
c++/src/capnproto/generated-header-support.h
+22
-1
layout.c++
c++/src/capnproto/layout.c++
+71
-0
layout.h
c++/src/capnproto/layout.h
+43
-20
list.h
c++/src/capnproto/list.h
+1
-1
type-safety.h
c++/src/capnproto/type-safety.h
+27
-7
No files found.
c++/src/capnproto/generated-header-support.h
View file @
f017105e
...
...
@@ -30,6 +30,9 @@
#include "list.h"
namespace
capnproto
{
class
DynamicStruct
;
// So that it can be declared a friend.
namespace
internal
{
template
<
typename
T
>
...
...
@@ -91,8 +94,26 @@ struct PointerHelpers<Data> {
}
};
}
// namespace internal
#ifdef CAPNPROTO_PRIVATE
struct
TrustedMessage
{
typedef
const
word
*
Reader
;
};
template
<>
struct
PointerHelpers
<
TrustedMessage
>
{
// Reads an Object field as a trusted message pointer. Requires that the containing message is
// itself trusted. This hack is currently private. It is used to locate default values within
// encoded schemas.
static
inline
const
word
*
get
(
StructReader
reader
,
WireReferenceCount
index
)
{
return
reader
.
getTrustedPointer
(
index
);
}
};
#endif
}
// namespace internal
}
// namespace capnproto
#endif // CAPNPROTO_GENERATED_HEADER_SUPPORT_H_
c++/src/capnproto/layout.c++
View file @
f017105e
...
...
@@ -908,6 +908,10 @@ struct WireHelpers {
goto
useDefault
;
}
VALIDATE_INPUT
(
size
>
0
,
"Message contains text that is not NUL-terminated."
)
{
goto
useDefault
;
}
const
char
*
cptr
=
reinterpret_cast
<
const
char
*>
(
ptr
);
--
size
;
// NUL terminator
...
...
@@ -1144,6 +1148,11 @@ ObjectBuilder StructBuilder::getObjectField(
return
WireHelpers
::
getWritableObjectReference
(
segment
,
references
+
refIndex
,
defaultValue
);
}
const
word
*
StructBuilder
::
getTrustedPointer
(
WireReferenceCount
refIndex
)
const
{
PRECOND
(
segment
==
nullptr
,
"getTrustedPointer() only allowed on trusted messages."
);
return
reinterpret_cast
<
const
word
*>
(
references
+
refIndex
);
}
StructReader
StructBuilder
::
asReader
()
const
{
return
StructReader
(
segment
,
data
,
references
,
dataSize
,
referenceCount
,
bit0Offset
,
std
::
numeric_limits
<
int
>::
max
());
...
...
@@ -1202,6 +1211,37 @@ ObjectReader StructReader::getObjectField(
// =======================================================================================
// ListBuilder
Text
::
Builder
ListBuilder
::
asText
()
{
VALIDATE_INPUT
(
structDataSize
==
8
*
BITS
&&
structReferenceCount
==
0
*
REFERENCES
,
"Expected Text, got list of non-bytes."
)
{
return
Text
::
Builder
();
}
size_t
size
=
elementCount
/
ELEMENTS
;
VALIDATE_INPUT
(
size
>
0
,
"Message contains text that is not NUL-terminated."
)
{
return
Text
::
Builder
();
}
char
*
cptr
=
reinterpret_cast
<
char
*>
(
ptr
);
--
size
;
// NUL terminator
VALIDATE_INPUT
(
cptr
[
size
]
==
'\0'
,
"Message contains text that is not NUL-terminated."
)
{
return
Text
::
Builder
();
}
return
Text
::
Builder
(
cptr
,
size
);
}
Data
::
Builder
ListBuilder
::
asData
()
{
VALIDATE_INPUT
(
structDataSize
==
8
*
BITS
&&
structReferenceCount
==
0
*
REFERENCES
,
"Expected Text, got list of non-bytes."
)
{
return
Data
::
Builder
();
}
return
Data
::
Builder
(
reinterpret_cast
<
char
*>
(
ptr
),
elementCount
/
ELEMENTS
);
}
StructBuilder
ListBuilder
::
getStructElement
(
ElementCount
index
,
StructSize
elementSize
)
const
{
BitCount64
indexBit
=
ElementCount64
(
index
)
*
step
;
byte
*
structData
=
ptr
+
indexBit
/
BITS_PER_BYTE
;
...
...
@@ -1269,6 +1309,37 @@ ListReader ListBuilder::asReader() const {
// =======================================================================================
// ListReader
Text
::
Reader
ListReader
::
asText
()
{
VALIDATE_INPUT
(
structDataSize
==
8
*
BITS
&&
structReferenceCount
==
0
*
REFERENCES
,
"Expected Text, got list of non-bytes."
)
{
return
Text
::
Reader
();
}
size_t
size
=
elementCount
/
ELEMENTS
;
VALIDATE_INPUT
(
size
>
0
,
"Message contains text that is not NUL-terminated."
)
{
return
Text
::
Reader
();
}
const
char
*
cptr
=
reinterpret_cast
<
const
char
*>
(
ptr
);
--
size
;
// NUL terminator
VALIDATE_INPUT
(
cptr
[
size
]
==
'\0'
,
"Message contains text that is not NUL-terminated."
)
{
return
Text
::
Reader
();
}
return
Text
::
Reader
(
cptr
,
size
);
}
Data
::
Reader
ListReader
::
asData
()
{
VALIDATE_INPUT
(
structDataSize
==
8
*
BITS
&&
structReferenceCount
==
0
*
REFERENCES
,
"Expected Text, got list of non-bytes."
)
{
return
Data
::
Reader
();
}
return
Data
::
Reader
(
reinterpret_cast
<
const
char
*>
(
ptr
),
elementCount
/
ELEMENTS
);
}
StructReader
ListReader
::
getStructElement
(
ElementCount
index
)
const
{
VALIDATE_INPUT
((
segment
==
nullptr
)
|
(
nestingLimit
>
0
),
"Message is too deeply-nested or contains cycles. See capnproto::ReadOptions."
)
{
...
...
c++/src/capnproto/layout.h
View file @
f017105e
...
...
@@ -251,6 +251,10 @@ public:
static
StructBuilder
initRoot
(
SegmentBuilder
*
segment
,
word
*
location
,
StructSize
size
);
static
StructBuilder
getRoot
(
SegmentBuilder
*
segment
,
word
*
location
,
StructSize
size
);
inline
BitCount
getDataSectionSize
()
const
{
return
dataSize
;
}
inline
WireReferenceCount
getPointerSectionSize
()
const
{
return
referenceCount
;
}
inline
Data
::
Builder
getDataSectionAsBlob
();
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
T
getDataField
(
ElementCount
offset
)
const
);
// Gets the data field value of the given type at the given offset. The offset is measured in
...
...
@@ -320,6 +324,11 @@ public:
ObjectBuilder
getObjectField
(
WireReferenceCount
refIndex
,
const
word
*
defaultValue
)
const
;
// Read a pointer of arbitrary type.
const
word
*
getTrustedPointer
(
WireReferenceCount
refIndex
)
const
;
// If this is a trusted message, get a word* pointing at the location of the pointer. This
// word* can actually be passed to readTrusted() to read the designated sub-object later. If
// this isn't a trusted message, throws an exception.
StructReader
asReader
()
const
;
// Gets a StructReader pointing at the same memory.
...
...
@@ -357,6 +366,10 @@ public:
static
StructReader
readRootTrusted
(
const
word
*
location
);
static
StructReader
readRoot
(
const
word
*
location
,
SegmentReader
*
segment
,
int
nestingLimit
);
inline
BitCount
getDataSectionSize
()
const
{
return
dataSize
;
}
inline
WireReferenceCount
getPointerSectionSize
()
const
{
return
referenceCount
;
}
inline
Data
::
Reader
getDataSectionAsBlob
();
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
T
getDataField
(
ElementCount
offset
)
const
);
// Get the data field value of the given type at the given offset. The offset is measured in
...
...
@@ -443,6 +456,10 @@ public:
inline
ElementCount
size
();
// The number of elements in the list.
Text
::
Builder
asText
();
Data
::
Builder
asData
();
// Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized.
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
T
getDataElement
(
ElementCount
index
)
const
);
// Get the element of the given type at the given index.
...
...
@@ -525,6 +542,10 @@ public:
inline
ElementCount
size
();
// The number of elements in the list.
Text
::
Reader
asText
();
Data
::
Reader
asData
();
// Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized.
template
<
typename
T
>
CAPNPROTO_ALWAYS_INLINE
(
T
getDataElement
(
ElementCount
index
)
const
);
// Get the element of the given type at the given index.
...
...
@@ -578,55 +599,53 @@ private:
// -------------------------------------------------------------------
enum
class
ObjectKind
{
NULL_POINTER
,
// Object was read from a null pointer.
STRUCT
,
LIST
};
struct
ObjectBuilder
{
// A reader for any kind of object.
enum
Kind
{
NULL_POINTER
,
// Object was read from a null pointer.
STRUCT
,
LIST
};
Kind
kind
;
ObjectKind
kind
;
union
{
StructBuilder
structBuilder
;
ListBuilder
listBuilder
;
};
ObjectBuilder
()
:
kind
(
NULL_POINTER
),
structBuilder
()
{}
ObjectBuilder
()
:
kind
(
ObjectKind
::
NULL_POINTER
),
structBuilder
()
{}
ObjectBuilder
(
StructBuilder
structBuilder
)
:
kind
(
STRUCT
),
structBuilder
(
structBuilder
)
{}
:
kind
(
ObjectKind
::
STRUCT
),
structBuilder
(
structBuilder
)
{}
ObjectBuilder
(
ListBuilder
listBuilderBuilder
)
:
kind
(
LIST
),
listBuilder
(
listBuilder
)
{}
:
kind
(
ObjectKind
::
LIST
),
listBuilder
(
listBuilder
)
{}
};
struct
ObjectReader
{
// A reader for any kind of object.
enum
Kind
{
NULL_POINTER
,
// Object was read from a null pointer.
STRUCT
,
LIST
};
Kind
kind
;
ObjectKind
kind
;
union
{
StructReader
structReader
;
ListReader
listReader
;
};
ObjectReader
()
:
kind
(
NULL_POINTER
),
structReader
()
{}
ObjectReader
()
:
kind
(
ObjectKind
::
NULL_POINTER
),
structReader
()
{}
ObjectReader
(
StructReader
structReader
)
:
kind
(
STRUCT
),
structReader
(
structReader
)
{}
:
kind
(
ObjectKind
::
STRUCT
),
structReader
(
structReader
)
{}
ObjectReader
(
ListReader
listReader
)
:
kind
(
LIST
),
listReader
(
listReader
)
{}
:
kind
(
ObjectKind
::
LIST
),
listReader
(
listReader
)
{}
};
// =======================================================================================
// Internal implementation details...
inline
Data
::
Builder
StructBuilder
::
getDataSectionAsBlob
()
{
return
Data
::
Builder
(
reinterpret_cast
<
char
*>
(
data
),
dataSize
/
BITS_PER_BYTE
/
BYTES
);
}
template
<
typename
T
>
inline
T
StructBuilder
::
getDataField
(
ElementCount
offset
)
const
{
return
reinterpret_cast
<
WireValue
<
T
>*>
(
data
)[
offset
/
ELEMENTS
].
get
();
...
...
@@ -679,6 +698,10 @@ inline void StructBuilder::setDataField(
// -------------------------------------------------------------------
inline
Data
::
Reader
StructReader
::
getDataSectionAsBlob
()
{
return
Data
::
Reader
(
reinterpret_cast
<
const
char
*>
(
data
),
dataSize
/
BITS_PER_BYTE
/
BYTES
);
}
template
<
typename
T
>
T
StructReader
::
getDataField
(
ElementCount
offset
)
const
{
if
((
offset
+
1
*
ELEMENTS
)
*
capnproto
::
bitsPerElement
<
T
>
()
<=
dataSize
)
{
...
...
c++/src/capnproto/list.h
View file @
f017105e
...
...
@@ -72,7 +72,7 @@ using ReaderFor = typename internal::MaybeReaderBuilder<T>::Reader;
// The type returned by List<T>::Reader::operator[].
template
<
typename
T
>
using
BuilderFor
=
typename
internal
::
MaybeReaderBuilder
<
T
>::
Rea
der
;
using
BuilderFor
=
typename
internal
::
MaybeReaderBuilder
<
T
>::
Buil
der
;
// The type returned by List<T>::Builder::operator[].
namespace
internal
{
...
...
c++/src/capnproto/type-safety.h
View file @
f017105e
...
...
@@ -76,6 +76,26 @@ T instance() noexcept;
// Like std::declval, but doesn't transform T into an rvalue reference. If you want that, specify
// instance<T&&>().
// #including <new> pulls in a lot of crap, but we want placement news. But operator new cannot
// be defined in a namespace, and defining it globally conflicts with the standard library
// definition. So...
namespace
internal
{
struct
PlacementNew
{}
placementNew
;
}
// namespace internal;
}
// namespace capnproto
inline
void
*
operator
new
(
std
::
size_t
,
capnproto
::
internal
::
PlacementNew
,
void
*
__p
)
noexcept
{
return
__p
;
}
namespace
capnproto
{
template
<
typename
T
,
typename
...
Params
>
void
constructAt
(
T
*
location
,
Params
&&
...
params
)
{
new
(
internal
::
placementNew
,
location
)
T
(
capnproto
::
forward
<
Params
>
(
params
)...);
}
// =======================================================================================
// Maybe
...
...
@@ -85,22 +105,22 @@ public:
Maybe
()
:
isSet
(
false
)
{}
Maybe
(
T
&&
t
)
:
isSet
(
true
)
{
new
(
&
value
)
T
(
move
(
t
));
constructAt
(
&
value
,
capnproto
::
move
(
t
));
}
Maybe
(
const
T
&
t
)
:
isSet
(
true
)
{
new
(
&
value
)
T
(
t
);
constructAt
(
&
value
,
t
);
}
Maybe
(
Maybe
&&
other
)
noexcept
(
noexcept
(
T
(
capnproto
::
move
(
other
.
value
))))
:
isSet
(
other
.
isSet
)
{
if
(
isSet
)
{
new
(
&
value
)
T
(
move
(
other
.
value
));
constructAt
(
&
value
,
capnproto
::
move
(
other
.
value
));
}
}
Maybe
(
const
Maybe
&
other
)
:
isSet
(
other
.
isSet
)
{
if
(
isSet
)
{
new
(
&
value
)
T
(
other
.
value
);
constructAt
(
&
value
,
other
.
value
);
}
}
Maybe
(
std
::
nullptr_t
)
:
isSet
(
false
)
{}
...
...
@@ -117,7 +137,7 @@ public:
value
.
~
T
();
}
isSet
=
true
;
new
(
&
value
)
T
(
capnproto
::
forward
(
params
)...);
constructAt
(
&
value
,
capnproto
::
forward
(
params
)...);
}
inline
T
&
operator
*
()
{
return
value
;
}
...
...
@@ -132,7 +152,7 @@ public:
}
isSet
=
other
.
isSet
;
if
(
isSet
)
{
new
(
&
value
)
T
(
move
(
other
.
value
));
constructAt
(
&
value
,
capnproto
::
move
(
other
.
value
));
}
}
return
*
this
;
...
...
@@ -145,7 +165,7 @@ public:
}
isSet
=
other
.
isSet
;
if
(
isSet
)
{
new
(
&
value
)
T
(
other
.
value
);
constructAt
(
&
value
,
other
.
value
);
}
}
return
*
this
;
...
...
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