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
98e6519e
Commit
98e6519e
authored
Aug 26, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor value expression compilation code using new Orphan<DynamicValue>.
parent
c1f3e3ff
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
269 additions
and
50 deletions
+269
-50
node-translator.c++
c++/src/capnp/compiler/node-translator.c++
+0
-0
node-translator.h
c++/src/capnp/compiler/node-translator.h
+15
-6
dynamic.c++
c++/src/capnp/dynamic.c++
+157
-10
dynamic.h
c++/src/capnp/dynamic.h
+44
-12
layout.c++
c++/src/capnp/layout.c++
+37
-14
layout.h
c++/src/capnp/layout.h
+3
-0
orphan-test.c++
c++/src/capnp/orphan-test.c++
+7
-7
exception.c++
c++/src/kj/exception.c++
+6
-1
No files found.
c++/src/capnp/compiler/node-translator.c++
View file @
98e6519e
This diff is collapsed.
Click to expand it.
c++/src/capnp/compiler/node-translator.h
View file @
98e6519e
...
...
@@ -109,6 +109,7 @@ public:
private
:
const
Resolver
&
resolver
;
const
ErrorReporter
&
errorReporter
;
Orphanage
orphanage
;
bool
compileAnnotations
;
Orphan
<
schema
::
Node
>
wipNode
;
...
...
@@ -168,15 +169,23 @@ private:
schema
::
Value
::
Builder
target
,
bool
isBootstrap
);
// Interprets the value expression and initializes `target` with the result.
class
DynamicSlot
;
kj
::
Maybe
<
Orphan
<
DynamicValue
>>
compileValue
(
ValueExpression
::
Reader
src
,
schema
::
Type
::
Reader
type
,
bool
isBootstrap
);
// Compile the given value as the given type. Returns null if there was an error, including
// if the value doesn't match the type.
void
compileValue
(
ValueExpression
::
Reader
src
,
DynamicSlot
&
dst
,
bool
isBootstrap
);
// Fill in `dst` (which effectively points to a struct field or list element) with the given
// value.
void
compileValueInner
(
ValueExpression
::
Reader
src
,
DynamicSlot
&
dst
,
bool
isBootstrap
);
Orphan
<
DynamicValue
>
compileValueInner
(
ValueExpression
::
Reader
src
,
schema
::
Type
::
Reader
type
,
bool
isBootstrap
);
// Helper for compileValue().
void
fillStructValue
(
DynamicStruct
::
Builder
builder
,
List
<
ValueExpression
::
FieldAssignment
>::
Reader
assignments
,
bool
isBootstrap
);
// Interprets the given assignments and uses them to fill in the given struct builder.
kj
::
String
makeNodeName
(
uint64_t
id
);
kj
::
String
makeTypeName
(
schema
::
Type
::
Reader
type
);
kj
::
Maybe
<
DynamicValue
::
Reader
>
readConstant
(
DeclName
::
Reader
name
,
bool
isBootstrap
,
ValueExpression
::
Reader
errorLocation
);
// Get the value of the given constant. May return null if some error occurs, which will already
...
...
c++/src/capnp/dynamic.c++
View file @
98e6519e
...
...
@@ -558,10 +558,12 @@ void DynamicStruct::Builder::set(StructSchema::Field field, const DynamicValue::
return
;
case
schema
:
:
Type
::
LIST
:
// TODO(soon): Type check.
builder
.
setListField
(
nonGroup
.
getOffset
()
*
POINTERS
,
value
.
as
<
DynamicList
>
().
reader
);
return
;
case
schema
:
:
Type
::
STRUCT
:
// TODO(soon): Type check.
builder
.
setStructField
(
nonGroup
.
getOffset
()
*
POINTERS
,
value
.
as
<
DynamicStruct
>
().
reader
);
return
;
...
...
@@ -697,11 +699,11 @@ void DynamicStruct::Builder::adopt(StructSchema::Field field, Orphan<DynamicValu
return
;
case
schema
:
:
Type
::
TEXT
:
orphan
.
getReader
().
as
<
Text
>
();
// type check
KJ_REQUIRE
(
orphan
.
getType
()
==
DynamicValue
::
TEXT
,
"Value type mismatch."
);
break
;
case
schema
:
:
Type
::
DATA
:
orphan
.
getReader
().
as
<
Data
>
();
// type check
KJ_REQUIRE
(
orphan
.
getType
()
==
DynamicValue
::
DATA
,
"Value type mismatch."
);
break
;
case
schema
:
:
Type
::
LIST
:
{
...
...
@@ -869,7 +871,7 @@ void DynamicStruct::Builder::clear(StructSchema::Field field) {
case
schema
:
:
Type
::
LIST
:
case
schema
:
:
Type
::
STRUCT
:
case
schema
:
:
Type
::
OBJECT
:
builder
.
disown
(
nonGroup
.
getOffset
()
*
POINTERS
);
builder
.
clearPointer
(
nonGroup
.
getOffset
()
*
POINTERS
);
return
;
case
schema
:
:
Type
::
INTERFACE
:
...
...
@@ -1199,17 +1201,16 @@ void DynamicList::Builder::set(uint index, const DynamicValue::Reader& value) {
return
;
case
schema
:
:
Type
::
LIST
:
{
// TODO(soon): Type check.
builder
.
setListElement
(
index
*
ELEMENTS
,
value
.
as
<
DynamicList
>
().
reader
);
return
;
}
case
schema
:
:
Type
::
STRUCT
:
// Not supported for the same reason List<struct> doesn't support it -- the space for the
// element is already allocated, and if it's smaller than the input value the copy would
// have to be lossy.
KJ_FAIL_ASSERT
(
"DynamicList of structs does not support set()."
)
{
return
;
}
case
schema
:
:
Type
::
STRUCT
:
{
// TODO(soon): Type check.
builder
.
getStructElement
(
index
*
ELEMENTS
).
copyContentFrom
(
value
.
as
<
DynamicStruct
>
().
reader
);
return
;
}
case
schema
:
:
Type
::
ENUM
:
{
uint16_t
rawValue
;
...
...
@@ -1297,6 +1298,114 @@ DynamicValue::Builder DynamicList::Builder::init(uint index, uint size) {
return
nullptr
;
}
void
DynamicList
::
Builder
::
adopt
(
uint
index
,
Orphan
<
DynamicValue
>&&
orphan
)
{
switch
(
schema
.
whichElementType
())
{
case
schema
:
:
Type
::
VOID
:
case
schema
:
:
Type
::
BOOL
:
case
schema
:
:
Type
::
INT8
:
case
schema
:
:
Type
::
INT16
:
case
schema
:
:
Type
::
INT32
:
case
schema
:
:
Type
::
INT64
:
case
schema
:
:
Type
::
UINT8
:
case
schema
:
:
Type
::
UINT16
:
case
schema
:
:
Type
::
UINT32
:
case
schema
:
:
Type
::
UINT64
:
case
schema
:
:
Type
::
FLOAT32
:
case
schema
:
:
Type
::
FLOAT64
:
case
schema
:
:
Type
::
ENUM
:
set
(
index
,
orphan
.
getReader
());
return
;
case
schema
:
:
Type
::
TEXT
:
KJ_REQUIRE
(
orphan
.
getType
()
==
DynamicValue
::
TEXT
,
"Value type mismatch."
);
builder
.
adopt
(
index
*
ELEMENTS
,
kj
::
mv
(
orphan
.
builder
));
return
;
case
schema
:
:
Type
::
DATA
:
KJ_REQUIRE
(
orphan
.
getType
()
==
DynamicValue
::
DATA
,
"Value type mismatch."
);
builder
.
adopt
(
index
*
ELEMENTS
,
kj
::
mv
(
orphan
.
builder
));
return
;
case
schema
:
:
Type
::
LIST
:
{
ListSchema
elementType
=
schema
.
getListElementType
();
KJ_REQUIRE
(
orphan
.
getType
()
==
DynamicValue
::
LIST
&&
orphan
.
listSchema
==
elementType
,
"Value type mismatch."
);
builder
.
adopt
(
index
*
ELEMENTS
,
kj
::
mv
(
orphan
.
builder
));
return
;
}
case
schema
:
:
Type
::
STRUCT
:
{
auto
elementType
=
schema
.
getStructElementType
();
KJ_REQUIRE
(
orphan
.
getType
()
==
DynamicValue
::
STRUCT
&&
orphan
.
structSchema
==
elementType
,
"Value type mismatch."
);
builder
.
getStructElement
(
index
*
ELEMENTS
).
transferContentFrom
(
orphan
.
builder
.
asStruct
(
structSizeFromSchema
(
elementType
)));
return
;
}
case
schema
:
:
Type
::
OBJECT
:
KJ_FAIL_ASSERT
(
"List(Object) not supported."
);
case
schema
:
:
Type
::
INTERFACE
:
KJ_FAIL_ASSERT
(
"Interfaces not yet implemented."
);
}
KJ_UNREACHABLE
;
}
Orphan
<
DynamicValue
>
DynamicList
::
Builder
::
disown
(
uint
index
)
{
switch
(
schema
.
whichElementType
())
{
case
schema
:
:
Type
::
VOID
:
case
schema
:
:
Type
::
BOOL
:
case
schema
:
:
Type
::
INT8
:
case
schema
:
:
Type
::
INT16
:
case
schema
:
:
Type
::
INT32
:
case
schema
:
:
Type
::
INT64
:
case
schema
:
:
Type
::
UINT8
:
case
schema
:
:
Type
::
UINT16
:
case
schema
:
:
Type
::
UINT32
:
case
schema
:
:
Type
::
UINT64
:
case
schema
:
:
Type
::
FLOAT32
:
case
schema
:
:
Type
::
FLOAT64
:
case
schema
:
:
Type
::
ENUM
:
{
auto
result
=
Orphan
<
DynamicValue
>
(
operator
[](
index
),
_
::
OrphanBuilder
());
switch
(
elementSizeFor
(
schema
.
whichElementType
()))
{
case
_
:
:
FieldSize
::
VOID
:
break
;
case
_
:
:
FieldSize
::
BIT
:
builder
.
setDataElement
<
bool
>
(
index
*
ELEMENTS
,
false
);
break
;
case
_
:
:
FieldSize
::
BYTE
:
builder
.
setDataElement
<
uint8_t
>
(
index
*
ELEMENTS
,
0
);
break
;
case
_
:
:
FieldSize
::
TWO_BYTES
:
builder
.
setDataElement
<
uint16_t
>
(
index
*
ELEMENTS
,
0
);
break
;
case
_
:
:
FieldSize
::
FOUR_BYTES
:
builder
.
setDataElement
<
uint32_t
>
(
index
*
ELEMENTS
,
0
);
break
;
case
_
:
:
FieldSize
::
EIGHT_BYTES
:
builder
.
setDataElement
<
uint64_t
>
(
index
*
ELEMENTS
,
0
);
break
;
case
_
:
:
FieldSize
::
POINTER
:
case
_
:
:
FieldSize
::
INLINE_COMPOSITE
:
KJ_UNREACHABLE
;
}
return
kj
::
mv
(
result
);
}
case
schema
:
:
Type
::
TEXT
:
case
schema
:
:
Type
::
DATA
:
case
schema
:
:
Type
::
LIST
:
case
schema
:
:
Type
::
OBJECT
:
case
schema
:
:
Type
::
INTERFACE
:
{
auto
value
=
operator
[](
index
);
return
Orphan
<
DynamicValue
>
(
value
,
builder
.
disown
(
index
*
ELEMENTS
));
}
case
schema
:
:
Type
::
STRUCT
:
{
// We have to make a copy.
Orphan
<
DynamicStruct
>
result
=
Orphanage
::
getForMessageContaining
(
*
this
).
newOrphan
(
schema
.
getStructElementType
());
auto
element
=
builder
.
getStructElement
(
index
*
ELEMENTS
);
result
.
get
().
builder
.
transferContentFrom
(
element
);
element
.
clearAll
();
return
kj
::
mv
(
result
);
}
}
KJ_UNREACHABLE
;
}
void
DynamicList
::
Builder
::
copyFrom
(
std
::
initializer_list
<
DynamicValue
::
Reader
>
value
)
{
KJ_REQUIRE
(
value
.
size
()
==
size
(),
"DynamicList::copyFrom() argument had different size."
);
uint
i
=
0
;
...
...
@@ -1793,12 +1902,50 @@ DynamicValue::Reader Orphan<DynamicValue>::getReader() const {
template
<>
Orphan
<
DynamicStruct
>
Orphan
<
DynamicValue
>::
releaseAs
<
DynamicStruct
>
()
{
KJ_REQUIRE
(
type
==
DynamicValue
::
STRUCT
,
"Value type mismatch."
);
type
=
DynamicValue
::
UNKNOWN
;
return
Orphan
<
DynamicStruct
>
(
structSchema
,
kj
::
mv
(
builder
));
}
template
<>
Orphan
<
DynamicList
>
Orphan
<
DynamicValue
>::
releaseAs
<
DynamicList
>
()
{
KJ_REQUIRE
(
type
==
DynamicValue
::
LIST
,
"Value type mismatch."
);
type
=
DynamicValue
::
UNKNOWN
;
return
Orphan
<
DynamicList
>
(
listSchema
,
kj
::
mv
(
builder
));
}
template
<>
Orphan
<
DynamicObject
>
Orphanage
::
newOrphanCopy
<
DynamicObject
::
Reader
>
(
const
DynamicObject
::
Reader
&
copyFrom
)
const
{
switch
(
copyFrom
.
reader
.
kind
)
{
case
_
:
:
ObjectKind
::
NULL_POINTER
:
return
Orphan
<
DynamicObject
>
();
case
_
:
:
ObjectKind
::
STRUCT
:
return
Orphan
<
DynamicObject
>
(
_
::
OrphanBuilder
::
copy
(
arena
,
copyFrom
.
reader
.
structReader
));
case
_
:
:
ObjectKind
::
LIST
:
return
Orphan
<
DynamicObject
>
(
_
::
OrphanBuilder
::
copy
(
arena
,
copyFrom
.
reader
.
listReader
));
}
KJ_UNREACHABLE
;
}
template
<>
Orphan
<
DynamicValue
>
Orphanage
::
newOrphanCopy
<
DynamicValue
::
Reader
>
(
const
DynamicValue
::
Reader
&
copyFrom
)
const
{
switch
(
copyFrom
.
getType
())
{
case
DynamicValue
:
:
UNKNOWN
:
return
nullptr
;
case
DynamicValue
:
:
VOID
:
return
copyFrom
.
voidValue
;
case
DynamicValue
:
:
BOOL
:
return
copyFrom
.
boolValue
;
case
DynamicValue
:
:
INT
:
return
copyFrom
.
intValue
;
case
DynamicValue
:
:
UINT
:
return
copyFrom
.
uintValue
;
case
DynamicValue
:
:
FLOAT
:
return
copyFrom
.
floatValue
;
case
DynamicValue
:
:
ENUM
:
return
copyFrom
.
enumValue
;
case
DynamicValue
:
:
TEXT
:
return
newOrphanCopy
(
copyFrom
.
textValue
);
case
DynamicValue
:
:
DATA
:
return
newOrphanCopy
(
copyFrom
.
dataValue
);
case
DynamicValue
:
:
LIST
:
return
newOrphanCopy
(
copyFrom
.
listValue
);
case
DynamicValue
:
:
STRUCT
:
return
newOrphanCopy
(
copyFrom
.
structValue
);
case
DynamicValue
:
:
INTERFACE
:
KJ_FAIL_ASSERT
(
"Interfaces not implemented."
);
case
DynamicValue
:
:
OBJECT
:
return
newOrphanCopy
(
copyFrom
.
objectValue
);
}
KJ_UNREACHABLE
;
}
}
// namespace capnp
c++/src/capnp/dynamic.h
View file @
98e6519e
...
...
@@ -150,6 +150,8 @@ class DynamicObject::Reader {
// Represents an "Object" field of unknown type.
public
:
typedef
DynamicObject
Reads
;
Reader
()
=
default
;
template
<
typename
T
>
...
...
@@ -171,6 +173,7 @@ private:
friend
class
DynamicObject
::
Builder
;
friend
class
Orphan
<
DynamicObject
>
;
friend
class
Orphan
<
DynamicValue
>
;
friend
class
Orphanage
;
};
class
DynamicObject
::
Builder
:
public
kj
::
DisallowConstCopy
{
...
...
@@ -182,6 +185,8 @@ class DynamicObject::Builder: public kj::DisallowConstCopy {
// DynamicStruct::Builder::{get,set,init}Object() and pass a type schema to build object fields.
public
:
typedef
DynamicObject
Builds
;
Builder
()
=
default
;
Builder
(
Builder
&
)
=
default
;
Builder
(
Builder
&&
)
=
default
;
...
...
@@ -313,8 +318,6 @@ public:
// Clear a field, setting it to its default value. For pointer fields, this actually makes the
// field null.
// TODO(someday): Implement adopt() and disown().
DynamicStruct
::
Builder
getObject
(
StructSchema
::
Field
field
,
StructSchema
type
);
DynamicList
::
Builder
getObject
(
StructSchema
::
Field
field
,
ListSchema
type
);
Text
::
Builder
getObjectAsText
(
StructSchema
::
Field
field
);
...
...
@@ -437,7 +440,8 @@ public:
DynamicValue
::
Builder
operator
[](
uint
index
);
void
set
(
uint
index
,
const
DynamicValue
::
Reader
&
value
);
DynamicValue
::
Builder
init
(
uint
index
,
uint
size
);
// TODO(someday): Implement adopt() and disown().
void
adopt
(
uint
index
,
Orphan
<
DynamicValue
>&&
orphan
);
Orphan
<
DynamicValue
>
disown
(
uint
index
);
typedef
_
::
IndexingIterator
<
Builder
,
DynamicStruct
::
Builder
>
Iterator
;
inline
Iterator
begin
()
{
return
Iterator
(
this
,
0
);
}
...
...
@@ -484,7 +488,7 @@ class DynamicValue::Reader {
public
:
typedef
DynamicValue
Reads
;
inline
Reader
(
std
::
nullptr_t
n
=
nullptr
);
// UNKNOWN
inline
Reader
(
decltype
(
nullptr
)
n
=
nullptr
);
// UNKNOWN
inline
Reader
(
Void
value
);
inline
Reader
(
bool
value
);
inline
Reader
(
char
value
);
...
...
@@ -557,13 +561,15 @@ private:
template
<
typename
T
,
Kind
kind
=
kind
<
T
>
()
>
struct
AsImpl
;
// Implementation backing the as() method. Needs to be a struct to allow partial
// specialization. Has a method apply() which does the work.
friend
class
Orphanage
;
// to speed up newOrphanCopy(DynamicValue::Reader)
};
class
DynamicValue
::
Builder
{
public
:
typedef
DynamicValue
Builds
;
inline
Builder
(
std
::
nullptr_t
n
=
nullptr
);
// UNKNOWN
inline
Builder
(
decltype
(
nullptr
)
n
=
nullptr
);
// UNKNOWN
inline
Builder
(
Void
value
);
inline
Builder
(
bool
value
);
inline
Builder
(
char
value
);
...
...
@@ -757,16 +763,34 @@ private:
template
<
typename
,
Kind
>
friend
struct
_
::
PointerHelpers
;
friend
class
Orphan
<
DynamicValue
>
;
friend
class
Orphanage
;
};
template
<>
class
Orphan
<
DynamicValue
>
{
public
:
Orphan
()
=
default
;
KJ_DISALLOW_COPY
(
Orphan
);
inline
Orphan
(
decltype
(
nullptr
)
n
=
nullptr
)
:
type
(
DynamicValue
::
UNKNOWN
)
{}
inline
Orphan
(
Void
value
);
inline
Orphan
(
bool
value
);
inline
Orphan
(
char
value
);
inline
Orphan
(
signed
char
value
);
inline
Orphan
(
short
value
);
inline
Orphan
(
int
value
);
inline
Orphan
(
long
value
);
inline
Orphan
(
long
long
value
);
inline
Orphan
(
unsigned
char
value
);
inline
Orphan
(
unsigned
short
value
);
inline
Orphan
(
unsigned
int
value
);
inline
Orphan
(
unsigned
long
value
);
inline
Orphan
(
unsigned
long
long
value
);
inline
Orphan
(
float
value
);
inline
Orphan
(
double
value
);
inline
Orphan
(
DynamicEnum
value
);
Orphan
(
Orphan
&&
)
=
default
;
template
<
typename
T
>
Orphan
(
Orphan
<
T
>&&
);
KJ_DISALLOW_COPY
(
Orphan
);
Orphan
&
operator
=
(
Orphan
&&
)
=
default
;
inline
DynamicValue
::
Type
getType
()
{
return
type
;
}
...
...
@@ -780,9 +804,6 @@ public:
// the original Orphan<DynamicStruct> is no longer valid after this call; ownership is
// transferred to the returned Orphan<T>.
inline
bool
operator
==
(
decltype
(
nullptr
))
const
{
return
builder
==
nullptr
;
}
inline
bool
operator
!=
(
decltype
(
nullptr
))
const
{
return
builder
!=
nullptr
;
}
private
:
DynamicValue
::
Type
type
;
union
{
...
...
@@ -851,6 +872,7 @@ Orphan<T> Orphan<DynamicList>::releaseAs() {
template
<
typename
T
>
Orphan
<
T
>
Orphan
<
DynamicValue
>::
releaseAs
()
{
get
().
as
<
T
>
();
// type check
type
=
DynamicValue
::
UNKNOWN
;
return
Orphan
<
T
>
(
kj
::
mv
(
builder
));
}
...
...
@@ -886,6 +908,14 @@ inline Orphan<DynamicList> Orphanage::newOrphanCopy<DynamicList::Reader>(
return
Orphan
<
DynamicList
>
(
copyFrom
.
getSchema
(),
_
::
OrphanBuilder
::
copy
(
arena
,
copyFrom
.
reader
));
}
template
<>
Orphan
<
DynamicObject
>
Orphanage
::
newOrphanCopy
<
DynamicObject
::
Reader
>
(
const
DynamicObject
::
Reader
&
copyFrom
)
const
;
template
<>
Orphan
<
DynamicValue
>
Orphanage
::
newOrphanCopy
<
DynamicValue
::
Reader
>
(
const
DynamicValue
::
Reader
&
copyFrom
)
const
;
// -------------------------------------------------------------------
// Inject the ability to use DynamicStruct for message roots and Dynamic{Struct,List} for
// generated Object accessors.
...
...
@@ -1001,11 +1031,13 @@ DynamicTypeFor<TypeIfEnum<T>> toDynamic(T&& value) {
inline
DynamicValue
::
Reader
::
Reader
(
std
::
nullptr_t
n
)
:
type
(
UNKNOWN
)
{}
inline
DynamicValue
::
Builder
::
Builder
(
std
::
nullptr_t
n
)
:
type
(
UNKNOWN
)
{}
#define CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \
#define CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \
inline DynamicValue::Reader::Reader(cppType value) \
: type(typeTag), fieldName##Value(value) {} \
inline DynamicValue::Builder::Builder(cppType value) \
: type(typeTag), fieldName##Value(value) {}
: type(typeTag), fieldName##Value(value) {} \
inline Orphan<DynamicValue>::Orphan(cppType value) \
: type(DynamicValue::typeTag), fieldName##Value(value) {}
CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
(
Void
,
VOID
,
void
);
CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
(
bool
,
BOOL
,
bool
);
...
...
c++/src/capnp/layout.c++
View file @
98e6519e
...
...
@@ -1558,19 +1558,19 @@ struct WireHelpers {
WirePointer
*
tag
=
reinterpret_cast
<
WirePointer
*>
(
ptr
);
tag
->
setKindAndInlineCompositeListElementCount
(
WirePointer
::
STRUCT
,
value
.
elementCount
);
tag
->
structRef
.
set
(
dataSize
,
pointerCount
);
ptr
+=
POINTER_SIZE_IN_WORDS
;
word
*
dst
=
ptr
+
POINTER_SIZE_IN_WORDS
;
const
word
*
src
=
reinterpret_cast
<
const
word
*>
(
value
.
ptr
);
for
(
uint
i
=
0
;
i
<
value
.
elementCount
/
ELEMENTS
;
i
++
)
{
memcpy
(
ptr
,
src
,
value
.
structDataSize
/
BITS_PER_BYTE
/
BYTES
);
ptr
+=
dataSize
;
memcpy
(
dst
,
src
,
value
.
structDataSize
/
BITS_PER_BYTE
/
BYTES
);
dst
+=
dataSize
;
src
+=
dataSize
;
for
(
uint
j
=
0
;
j
<
pointerCount
/
POINTERS
;
j
++
)
{
setObjectPointer
(
segment
,
reinterpret_cast
<
WirePointer
*>
(
ptr
),
readObjectPointer
(
setObjectPointer
(
segment
,
reinterpret_cast
<
WirePointer
*>
(
dst
),
readObjectPointer
(
value
.
segment
,
reinterpret_cast
<
const
WirePointer
*>
(
src
),
nullptr
,
value
.
nestingLimit
));
ptr
+=
POINTER_SIZE_IN_WORDS
;
dst
+=
POINTER_SIZE_IN_WORDS
;
src
+=
POINTER_SIZE_IN_WORDS
;
}
}
...
...
@@ -2152,6 +2152,19 @@ void StructBuilder::clearPointer(WirePointerCount ptrIndex) {
memset
(
pointers
+
ptrIndex
,
0
,
sizeof
(
WirePointer
));
}
void
StructBuilder
::
clearAll
()
{
if
(
dataSize
==
1
*
BITS
)
{
setDataField
<
bool
>
(
1
*
ELEMENTS
,
false
);
}
else
{
memset
(
data
,
0
,
dataSize
/
BITS_PER_BYTE
/
BYTES
);
}
for
(
uint
i
=
0
;
i
<
pointerCount
/
POINTERS
;
i
++
)
{
WireHelpers
::
zeroObject
(
segment
,
pointers
+
i
);
}
memset
(
pointers
,
0
,
pointerCount
*
BYTES_PER_POINTER
/
BYTES
);
}
void
StructBuilder
::
transferContentFrom
(
StructBuilder
other
)
{
// Determine the amount of data the builders have in common.
BitCount
sharedDataSize
=
kj
::
min
(
dataSize
,
other
.
dataSize
);
...
...
@@ -2679,6 +2692,8 @@ ListBuilder OrphanBuilder::asStructList(StructSize elementSize) {
// Watch out, the pointer could have been updated if the object had to be relocated.
if
(
tagAsPtr
()
->
kind
()
==
WirePointer
::
FAR
)
{
location
=
nullptr
;
}
else
if
(
result
.
step
*
ELEMENTS
<=
BITS_PER_WORD
*
WORDS
)
{
location
=
reinterpret_cast
<
word
*>
(
result
.
ptr
);
}
else
{
location
=
reinterpret_cast
<
word
*>
(
result
.
ptr
)
-
POINTER_SIZE_IN_WORDS
;
}
...
...
@@ -2748,16 +2763,24 @@ ObjectReader OrphanBuilder::asObjectReader() const {
}
void
OrphanBuilder
::
euthanize
()
{
auto
ref
=
reinterpret_cast
<
WirePointer
*>
(
&
tag
);
if
(
ref
->
kind
()
==
WirePointer
::
FAR
)
{
WireHelpers
::
zeroObject
(
segment
,
ref
);
}
else
{
WireHelpers
::
zeroObject
(
segment
,
reinterpret_cast
<
WirePointer
*>
(
&
tag
),
location
);
}
// Carefully catch any exceptions and rethrow them as recoverable exceptions since we may be in
// a destructor.
auto
exception
=
kj
::
runCatchingExceptions
([
&
]()
{
auto
ref
=
reinterpret_cast
<
WirePointer
*>
(
&
tag
);
if
(
ref
->
kind
()
==
WirePointer
::
FAR
)
{
WireHelpers
::
zeroObject
(
segment
,
ref
);
}
else
{
WireHelpers
::
zeroObject
(
segment
,
reinterpret_cast
<
WirePointer
*>
(
&
tag
),
location
);
}
memset
(
ref
,
0
,
sizeof
(
*
ref
));
segment
=
nullptr
;
location
=
nullptr
;
memset
(
ref
,
0
,
sizeof
(
*
ref
));
segment
=
nullptr
;
location
=
nullptr
;
});
KJ_IF_MAYBE
(
e
,
exception
)
{
kj
::
getExceptionCallback
().
onRecoverableException
(
kj
::
mv
(
*
e
));
}
}
}
// namespace _ (private)
...
...
c++/src/capnp/layout.h
View file @
98e6519e
...
...
@@ -376,6 +376,9 @@ public:
void
clearPointer
(
WirePointerCount
ptrIndex
);
// Equivalent to calling disown() and letting the result simply be destroyed.
void
clearAll
();
// Clear all pointers and data.
void
transferContentFrom
(
StructBuilder
other
);
// Adopt all pointers from `other`, and also copy all data. If `other`'s sections are larger
// than this, the extra data is not transferred, meaning there is a risk of data loss when
...
...
c++/src/capnp/orphan-test.c++
View file @
98e6519e
...
...
@@ -446,14 +446,14 @@ TEST(Orphans, DynamicStructAs) {
Orphan
<
DynamicValue
>
orphan
=
root
.
disownObjectField
<
DynamicStruct
>
(
Schema
::
from
<
TestAllTypes
>
());
EXPECT_
FALSE
(
orphan
==
nullptr
);
EXPECT_
EQ
(
DynamicValue
::
STRUCT
,
orphan
.
getType
()
);
checkTestMessage
(
orphan
.
getReader
().
as
<
TestAllTypes
>
());
checkTestMessage
(
orphan
.
get
().
as
<
TestAllTypes
>
());
{
Orphan
<
DynamicStruct
>
structOrphan
=
orphan
.
releaseAs
<
DynamicStruct
>
();
EXPECT_
TRUE
(
orphan
==
nullptr
);
EXPECT_
EQ
(
DynamicValue
::
UNKNOWN
,
orphan
.
getType
()
);
EXPECT_FALSE
(
structOrphan
==
nullptr
);
checkDynamicTestMessage
(
structOrphan
.
getReader
());
checkDynamicTestMessage
(
structOrphan
.
get
());
...
...
@@ -467,7 +467,7 @@ TEST(Orphans, DynamicStructAs) {
checkTestMessage
(
typedOrphan
.
getReader
());
checkTestMessage
(
typedOrphan
.
get
());
orphan
=
kj
::
mv
(
typedOrphan
);
EXPECT_
FALSE
(
orphan
==
nullptr
);
EXPECT_
EQ
(
DynamicValue
::
STRUCT
,
orphan
.
getType
()
);
EXPECT_TRUE
(
typedOrphan
==
nullptr
);
}
}
...
...
@@ -487,14 +487,14 @@ TEST(Orphans, DynamicListAs) {
EXPECT_TRUE
(
root
.
hasObjectField
());
Orphan
<
DynamicValue
>
orphan
=
root
.
disownObjectField
<
DynamicList
>
(
Schema
::
from
<
List
<
uint32_t
>>
());
EXPECT_
FALSE
(
orphan
==
nullptr
);
EXPECT_
EQ
(
DynamicValue
::
LIST
,
orphan
.
getType
()
);
checkList
(
orphan
.
getReader
().
as
<
List
<
uint32_t
>>
(),
{
12
,
34
,
56
});
checkList
(
orphan
.
get
().
as
<
List
<
uint32_t
>>
(),
{
12
,
34
,
56
});
{
Orphan
<
DynamicList
>
listOrphan
=
orphan
.
releaseAs
<
DynamicList
>
();
EXPECT_
TRUE
(
orphan
==
nullptr
);
EXPECT_
EQ
(
DynamicValue
::
UNKNOWN
,
orphan
.
getType
()
);
EXPECT_FALSE
(
listOrphan
==
nullptr
);
checkList
<
uint32_t
>
(
listOrphan
.
getReader
(),
{
12
,
34
,
56
});
checkList
<
uint32_t
>
(
listOrphan
.
get
(),
{
12
,
34
,
56
});
...
...
@@ -508,7 +508,7 @@ TEST(Orphans, DynamicListAs) {
checkList
(
typedOrphan
.
getReader
(),
{
12
,
34
,
56
});
checkList
(
typedOrphan
.
get
(),
{
12
,
34
,
56
});
orphan
=
kj
::
mv
(
typedOrphan
);
EXPECT_
FALSE
(
orphan
==
nullptr
);
EXPECT_
EQ
(
DynamicValue
::
LIST
,
orphan
.
getType
()
);
EXPECT_TRUE
(
typedOrphan
==
nullptr
);
}
}
...
...
@@ -528,7 +528,7 @@ TEST(Orphans, DynamicObject) {
EXPECT_TRUE
(
root
.
hasObjectField
());
Orphan
<
DynamicValue
>
orphan
=
root
.
disownObjectField
<
DynamicObject
>
();
EXPECT_
FALSE
(
orphan
==
nullptr
);
EXPECT_
EQ
(
DynamicValue
::
OBJECT
,
orphan
.
getType
()
);
checkTestMessage
(
orphan
.
getReader
().
as
<
DynamicObject
>
().
as
<
TestAllTypes
>
());
...
...
c++/src/kj/exception.c++
View file @
98e6519e
...
...
@@ -326,7 +326,12 @@ public:
#if KJ_NO_EXCEPTIONS
logException
(
mv
(
exception
));
#else
throw
ExceptionImpl
(
mv
(
exception
));
if
(
std
::
uncaught_exception
())
{
// Bad time to throw an exception. Just log instead.
logException
(
mv
(
exception
));
}
else
{
throw
ExceptionImpl
(
mv
(
exception
));
}
#endif
}
...
...
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