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
bdb86c21
Commit
bdb86c21
authored
May 30, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move Maybe into common.h and improve its interface.
parent
328c9a83
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
602 additions
and
330 deletions
+602
-330
dynamic-test.c++
c++/src/capnproto/dynamic-test.c++
+15
-16
dynamic.c++
c++/src/capnproto/dynamic.c++
+32
-29
schema-test.c++
c++/src/capnproto/schema-test.c++
+23
-29
schema.c++
c++/src/capnproto/schema.c++
+20
-12
stringify.c++
c++/src/capnproto/stringify.c++
+8
-11
test-util.c++
c++/src/capnproto/test-util.c++
+11
-6
common-test.c++
c++/src/kj/common-test.c++
+193
-0
common.h
c++/src/kj/common.h
+277
-4
exception.c++
c++/src/kj/exception.c++
+20
-12
exception.h
c++/src/kj/exception.h
+3
-3
type-safety.h
c++/src/kj/type-safety.h
+0
-208
No files found.
c++/src/capnproto/dynamic-test.c++
View file @
bdb86c21
...
@@ -228,6 +228,13 @@ TEST(DynamicApi, DynamicGenericObjects) {
...
@@ -228,6 +228,13 @@ TEST(DynamicApi, DynamicGenericObjects) {
}
}
}
}
#define EXPECT_MAYBE_EQ(name, exp, expected, actual) \
KJ_IF_MAYBE(name, exp) { \
EXPECT_EQ(expected, actual); \
} else { \
FAIL() << "Maybe was empty."; \
}
TEST
(
DynamicApi
,
UnionsRead
)
{
TEST
(
DynamicApi
,
UnionsRead
)
{
MallocMessageBuilder
builder
;
MallocMessageBuilder
builder
;
auto
root
=
builder
.
initRoot
<
TestUnion
>
();
auto
root
=
builder
.
initRoot
<
TestUnion
>
();
...
@@ -241,26 +248,22 @@ TEST(DynamicApi, UnionsRead) {
...
@@ -241,26 +248,22 @@ TEST(DynamicApi, UnionsRead) {
auto
dynamic
=
toDynamic
(
root
.
asReader
());
auto
dynamic
=
toDynamic
(
root
.
asReader
());
{
{
auto
u
=
dynamic
.
get
(
"union0"
).
as
<
DynamicUnion
>
();
auto
u
=
dynamic
.
get
(
"union0"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_MAYBE_EQ
(
w
,
u
.
which
(),
"u0f1s32"
,
w
->
getProto
().
getName
());
EXPECT_EQ
(
"u0f1s32"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_EQ
(
1234567
,
u
.
get
().
as
<
int32_t
>
());
EXPECT_EQ
(
1234567
,
u
.
get
().
as
<
int32_t
>
());
}
}
{
{
auto
u
=
dynamic
.
get
(
"union1"
).
as
<
DynamicUnion
>
();
auto
u
=
dynamic
.
get
(
"union1"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_MAYBE_EQ
(
w
,
u
.
which
(),
"u1f1sp"
,
w
->
getProto
().
getName
());
EXPECT_EQ
(
"u1f1sp"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_EQ
(
"foo"
,
u
.
get
().
as
<
Text
>
());
EXPECT_EQ
(
"foo"
,
u
.
get
().
as
<
Text
>
());
}
}
{
{
auto
u
=
dynamic
.
get
(
"union2"
).
as
<
DynamicUnion
>
();
auto
u
=
dynamic
.
get
(
"union2"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_MAYBE_EQ
(
w
,
u
.
which
(),
"u2f0s1"
,
w
->
getProto
().
getName
());
EXPECT_EQ
(
"u2f0s1"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_TRUE
(
u
.
get
().
as
<
bool
>
());
EXPECT_TRUE
(
u
.
get
().
as
<
bool
>
());
}
}
{
{
auto
u
=
dynamic
.
get
(
"union3"
).
as
<
DynamicUnion
>
();
auto
u
=
dynamic
.
get
(
"union3"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_MAYBE_EQ
(
w
,
u
.
which
(),
"u3f0s64"
,
w
->
getProto
().
getName
());
EXPECT_EQ
(
"u3f0s64"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_EQ
(
1234567890123456789ll
,
u
.
get
().
as
<
int64_t
>
());
EXPECT_EQ
(
1234567890123456789ll
,
u
.
get
().
as
<
int64_t
>
());
}
}
}
}
...
@@ -270,26 +273,22 @@ TEST(DynamicApi, UnionsRead) {
...
@@ -270,26 +273,22 @@ TEST(DynamicApi, UnionsRead) {
auto
dynamic
=
toDynamic
(
root
);
auto
dynamic
=
toDynamic
(
root
);
{
{
auto
u
=
dynamic
.
get
(
"union0"
).
as
<
DynamicUnion
>
();
auto
u
=
dynamic
.
get
(
"union0"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_MAYBE_EQ
(
w
,
u
.
which
(),
"u0f1s32"
,
w
->
getProto
().
getName
());
EXPECT_EQ
(
"u0f1s32"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_EQ
(
1234567
,
u
.
get
().
as
<
int32_t
>
());
EXPECT_EQ
(
1234567
,
u
.
get
().
as
<
int32_t
>
());
}
}
{
{
auto
u
=
dynamic
.
get
(
"union1"
).
as
<
DynamicUnion
>
();
auto
u
=
dynamic
.
get
(
"union1"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_MAYBE_EQ
(
w
,
u
.
which
(),
"u1f1sp"
,
w
->
getProto
().
getName
());
EXPECT_EQ
(
"u1f1sp"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_EQ
(
"foo"
,
u
.
get
().
as
<
Text
>
());
EXPECT_EQ
(
"foo"
,
u
.
get
().
as
<
Text
>
());
}
}
{
{
auto
u
=
dynamic
.
get
(
"union2"
).
as
<
DynamicUnion
>
();
auto
u
=
dynamic
.
get
(
"union2"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_MAYBE_EQ
(
w
,
u
.
which
(),
"u2f0s1"
,
w
->
getProto
().
getName
());
EXPECT_EQ
(
"u2f0s1"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_TRUE
(
u
.
get
().
as
<
bool
>
());
EXPECT_TRUE
(
u
.
get
().
as
<
bool
>
());
}
}
{
{
auto
u
=
dynamic
.
get
(
"union3"
).
as
<
DynamicUnion
>
();
auto
u
=
dynamic
.
get
(
"union3"
).
as
<
DynamicUnion
>
();
ASSERT_TRUE
(
u
.
which
()
!=
nullptr
);
EXPECT_MAYBE_EQ
(
w
,
u
.
which
(),
"u3f0s64"
,
w
->
getProto
().
getName
());
EXPECT_EQ
(
"u3f0s64"
,
u
.
which
()
->
getProto
().
getName
());
EXPECT_EQ
(
1234567890123456789ll
,
u
.
get
().
as
<
int64_t
>
());
EXPECT_EQ
(
1234567890123456789ll
,
u
.
get
().
as
<
int64_t
>
());
}
}
}
}
...
...
c++/src/capnproto/dynamic.c++
View file @
bdb86c21
...
@@ -169,20 +169,18 @@ kj::Maybe<StructSchema::Member> DynamicUnion::Builder::which() {
...
@@ -169,20 +169,18 @@ kj::Maybe<StructSchema::Member> DynamicUnion::Builder::which() {
}
}
DynamicValue
::
Reader
DynamicUnion
::
Reader
::
get
()
{
DynamicValue
::
Reader
DynamicUnion
::
Reader
::
get
()
{
auto
w
=
which
();
KJ_IF_MAYBE
(
w
,
which
())
{
if
(
w
==
nullptr
)
{
return
nullptr
;
}
else
{
return
DynamicValue
::
Reader
(
DynamicStruct
::
Reader
::
getImpl
(
reader
,
*
w
));
return
DynamicValue
::
Reader
(
DynamicStruct
::
Reader
::
getImpl
(
reader
,
*
w
));
}
else
{
return
nullptr
;
}
}
}
}
DynamicValue
::
Builder
DynamicUnion
::
Builder
::
get
()
{
DynamicValue
::
Builder
DynamicUnion
::
Builder
::
get
()
{
auto
w
=
which
();
KJ_IF_MAYBE
(
w
,
which
())
{
if
(
w
==
nullptr
)
{
return
nullptr
;
}
else
{
return
DynamicValue
::
Builder
(
DynamicStruct
::
Builder
::
getImpl
(
builder
,
*
w
));
return
DynamicValue
::
Builder
(
DynamicStruct
::
Builder
::
getImpl
(
builder
,
*
w
));
}
else
{
return
nullptr
;
}
}
}
}
...
@@ -256,22 +254,26 @@ Data::Builder DynamicUnion::Builder::initObjectAsData(Text::Reader name, uint si
...
@@ -256,22 +254,26 @@ Data::Builder DynamicUnion::Builder::initObjectAsData(Text::Reader name, uint si
}
}
StructSchema
::
Member
DynamicUnion
::
Builder
::
checkIsObject
()
{
StructSchema
::
Member
DynamicUnion
::
Builder
::
checkIsObject
()
{
auto
w
=
which
();
KJ_IF_MAYBE
(
w
,
which
())
{
PRECOND
(
w
!=
nullptr
,
"Can't get() unknown union value."
);
CHECK
(
w
->
getProto
().
getBody
().
which
()
==
schema
::
StructNode
::
Member
::
Body
::
FIELD_MEMBER
,
CHECK
(
w
->
getProto
().
getBody
().
which
()
==
schema
::
StructNode
::
Member
::
Body
::
FIELD_MEMBER
,
"Unsupported union member type."
);
"Unsupported union member type."
);
PRECOND
(
w
->
getProto
().
getBody
().
getFieldMember
().
getType
().
getBody
().
which
()
==
PRECOND
(
w
->
getProto
().
getBody
().
getFieldMember
().
getType
().
getBody
().
which
()
==
schema
::
Type
::
Body
::
OBJECT_TYPE
,
"Expected Object."
);
schema
::
Type
::
Body
::
OBJECT_TYPE
,
"Expected Object."
);
return
*
w
;
return
*
w
;
}
else
{
FAIL_PRECOND
(
"Can't get() unknown union value."
);
}
}
}
void
DynamicUnion
::
Builder
::
setDiscriminant
(
StructSchema
::
Member
member
)
{
void
DynamicUnion
::
Builder
::
setDiscriminant
(
StructSchema
::
Member
member
)
{
auto
containingUnion
=
member
.
getContainingUnion
();
KJ_IF_MAYBE
(
containingUnion
,
member
.
getContainingUnion
())
{
PRECOND
(
containingUnion
!=
nullptr
&&
*
containingUnion
==
schema
,
PRECOND
(
*
containingUnion
==
schema
,
"`member` is not a member of this union."
);
"`member` is not a member of this union."
);
builder
.
setDataField
<
uint16_t
>
(
builder
.
setDataField
<
uint16_t
>
(
schema
.
getProto
().
getBody
().
getUnionMember
().
getDiscriminantOffset
()
*
ELEMENTS
,
schema
.
getProto
().
getBody
().
getUnionMember
().
getDiscriminantOffset
()
*
ELEMENTS
,
member
.
getIndex
());
member
.
getIndex
());
}
else
{
FAIL_PRECOND
(
"`member` is not a member of this union."
);
}
}
}
void
DynamicUnion
::
Builder
::
setObjectDiscriminant
(
StructSchema
::
Member
member
)
{
void
DynamicUnion
::
Builder
::
setObjectDiscriminant
(
StructSchema
::
Member
member
)
{
...
@@ -874,16 +876,17 @@ void DynamicStruct::Builder::setImpl(
...
@@ -874,16 +876,17 @@ void DynamicStruct::Builder::setImpl(
switch
(
member
.
getProto
().
getBody
().
which
())
{
switch
(
member
.
getProto
().
getBody
().
which
())
{
case
schema
:
:
StructNode
::
Member
::
Body
::
UNION_MEMBER
:
{
case
schema
:
:
StructNode
::
Member
::
Body
::
UNION_MEMBER
:
{
auto
src
=
value
.
as
<
DynamicUnion
>
();
auto
src
=
value
.
as
<
DynamicUnion
>
();
auto
which
=
src
.
which
();
KJ_IF_MAYBE
(
which
,
src
.
which
())
{
RECOVERABLE_PRECOND
(
which
!=
nullptr
,
getImpl
(
builder
,
member
).
as
<
DynamicUnion
>
().
set
(
member
,
src
.
get
());
"Trying to copy a union value, but the union's discriminant is not recognized. It "
"was probably constructed using a newer version of the schema."
)
{
// Just don't copy anything.
return
;
return
;
}
else
{
FAIL_RECOVERABLE_PRECOND
(
"Trying to copy a union value, but the union's discriminant is not recognized. It "
"was probably constructed using a newer version of the schema."
)
{
// Just don't copy anything.
return
;
}
}
}
getImpl
(
builder
,
member
).
as
<
DynamicUnion
>
().
set
(
member
,
src
.
get
());
return
;
}
}
case
schema
:
:
StructNode
::
Member
::
Body
::
FIELD_MEMBER
:
{
case
schema
:
:
StructNode
::
Member
::
Body
::
FIELD_MEMBER
:
{
...
...
c++/src/capnproto/schema-test.c++
View file @
bdb86c21
...
@@ -76,10 +76,9 @@ TEST(Schema, Structs) {
...
@@ -76,10 +76,9 @@ TEST(Schema, Structs) {
EXPECT_ANY_THROW
(
member
.
asUnion
());
EXPECT_ANY_THROW
(
member
.
asUnion
());
kj
::
Maybe
<
StructSchema
::
Member
>
lookup
=
schema
.
findMemberByName
(
"voidField"
);
StructSchema
::
Member
lookup
=
schema
.
getMemberByName
(
"voidField"
);
ASSERT_TRUE
(
lookup
!=
nullptr
);
EXPECT_TRUE
(
lookup
==
member
);
EXPECT_TRUE
(
*
lookup
==
member
);
EXPECT_TRUE
(
lookup
!=
schema
.
getMembers
()[
1
]);
EXPECT_TRUE
(
*
lookup
!=
schema
.
getMembers
()[
1
]);
EXPECT_TRUE
(
schema
.
findMemberByName
(
"noSuchField"
)
==
nullptr
);
EXPECT_TRUE
(
schema
.
findMemberByName
(
"noSuchField"
)
==
nullptr
);
...
@@ -105,15 +104,15 @@ TEST(Schema, FieldLookupOutOfOrder) {
...
@@ -105,15 +104,15 @@ TEST(Schema, FieldLookupOutOfOrder) {
EXPECT_EQ
(
"garply"
,
schema
.
getMembers
()[
7
].
getProto
().
getName
());
EXPECT_EQ
(
"garply"
,
schema
.
getMembers
()[
7
].
getProto
().
getName
());
EXPECT_EQ
(
"baz"
,
schema
.
getMembers
()[
8
].
getProto
().
getName
());
EXPECT_EQ
(
"baz"
,
schema
.
getMembers
()[
8
].
getProto
().
getName
());
EXPECT_EQ
(
3
,
schema
.
findMemberByName
(
"foo"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
3
,
schema
.
getMemberByName
(
"foo"
).
getProto
().
getOrdinal
());
EXPECT_EQ
(
2
,
schema
.
findMemberByName
(
"bar"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
2
,
schema
.
getMemberByName
(
"bar"
).
getProto
().
getOrdinal
());
EXPECT_EQ
(
8
,
schema
.
findMemberByName
(
"baz"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
8
,
schema
.
getMemberByName
(
"baz"
).
getProto
().
getOrdinal
());
EXPECT_EQ
(
0
,
schema
.
findMemberByName
(
"qux"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
0
,
schema
.
getMemberByName
(
"qux"
).
getProto
().
getOrdinal
());
EXPECT_EQ
(
6
,
schema
.
findMemberByName
(
"quux"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
6
,
schema
.
getMemberByName
(
"quux"
).
getProto
().
getOrdinal
());
EXPECT_EQ
(
4
,
schema
.
findMemberByName
(
"corge"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
4
,
schema
.
getMemberByName
(
"corge"
).
getProto
().
getOrdinal
());
EXPECT_EQ
(
1
,
schema
.
findMemberByName
(
"grault"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
1
,
schema
.
getMemberByName
(
"grault"
).
getProto
().
getOrdinal
());
EXPECT_EQ
(
7
,
schema
.
findMemberByName
(
"garply"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
7
,
schema
.
getMemberByName
(
"garply"
).
getProto
().
getOrdinal
());
EXPECT_EQ
(
5
,
schema
.
findMemberByName
(
"waldo"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
5
,
schema
.
getMemberByName
(
"waldo"
).
getProto
().
getOrdinal
());
}
}
TEST
(
Schema
,
Unions
)
{
TEST
(
Schema
,
Unions
)
{
...
@@ -122,21 +121,18 @@ TEST(Schema, Unions) {
...
@@ -122,21 +121,18 @@ TEST(Schema, Unions) {
EXPECT_TRUE
(
schema
.
findMemberByName
(
"bit0"
)
!=
nullptr
);
EXPECT_TRUE
(
schema
.
findMemberByName
(
"bit0"
)
!=
nullptr
);
EXPECT_TRUE
(
schema
.
findMemberByName
(
"u1f0s8"
)
==
nullptr
);
EXPECT_TRUE
(
schema
.
findMemberByName
(
"u1f0s8"
)
==
nullptr
);
auto
maybeUnion1
=
schema
.
findMemberByName
(
"union1"
);
auto
union1
=
schema
.
getMemberByName
(
"union1"
).
asUnion
();
ASSERT_TRUE
(
maybeUnion1
!=
nullptr
);
auto
union1
=
maybeUnion1
->
asUnion
();
EXPECT_TRUE
(
union1
.
findMemberByName
(
"bin0"
)
==
nullptr
);
EXPECT_TRUE
(
union1
.
findMemberByName
(
"bin0"
)
==
nullptr
);
EXPECT_TRUE
(
union1
.
getContainingUnion
()
==
nullptr
);
EXPECT_TRUE
(
union1
.
getContainingUnion
()
==
nullptr
);
auto
maybeU1f0s8
=
union1
.
findMemberByName
(
"u1f0s8"
);
auto
u1f0s8
=
union1
.
getMemberByName
(
"u1f0s8"
);
ASSERT_TRUE
(
maybeU1f0s8
!=
nullptr
);
auto
u1f0s8
=
*
maybeU1f0s8
;
EXPECT_EQ
(
"u1f0s8"
,
u1f0s8
.
getProto
().
getName
());
EXPECT_EQ
(
"u1f0s8"
,
u1f0s8
.
getProto
().
getName
());
EXPECT_TRUE
(
u1f0s8
.
getContainingStruct
()
==
schema
);
EXPECT_TRUE
(
u1f0s8
.
getContainingStruct
()
==
schema
);
EXPECT_TRUE
(
*
u1f0s8
.
getContainingUnion
()
==
union1
);
KJ_IF_MAYBE
(
containing
,
u1f0s8
.
getContainingUnion
())
{
EXPECT_TRUE
(
*
containing
==
union1
);
}
else
{
ADD_FAILURE
()
<<
"u1f0s8.getContainingUnion() returned null"
;
}
EXPECT_TRUE
(
union1
.
findMemberByName
(
"u1f1s8"
)
!=
nullptr
);
EXPECT_TRUE
(
union1
.
findMemberByName
(
"u1f1s8"
)
!=
nullptr
);
EXPECT_TRUE
(
union1
.
findMemberByName
(
"u1f0s32"
)
!=
nullptr
);
EXPECT_TRUE
(
union1
.
findMemberByName
(
"u1f0s32"
)
!=
nullptr
);
...
@@ -166,10 +162,9 @@ TEST(Schema, Enums) {
...
@@ -166,10 +162,9 @@ TEST(Schema, Enums) {
EXPECT_EQ
(
"foo"
,
enumerant
.
getProto
().
getName
());
EXPECT_EQ
(
"foo"
,
enumerant
.
getProto
().
getName
());
EXPECT_TRUE
(
enumerant
.
getContainingEnum
()
==
schema
);
EXPECT_TRUE
(
enumerant
.
getContainingEnum
()
==
schema
);
kj
::
Maybe
<
EnumSchema
::
Enumerant
>
lookup
=
schema
.
findEnumerantByName
(
"foo"
);
EnumSchema
::
Enumerant
lookup
=
schema
.
getEnumerantByName
(
"foo"
);
ASSERT_TRUE
(
lookup
!=
nullptr
);
EXPECT_TRUE
(
lookup
==
enumerant
);
EXPECT_TRUE
(
*
lookup
==
enumerant
);
EXPECT_TRUE
(
lookup
!=
schema
.
getEnumerants
()[
1
]);
EXPECT_TRUE
(
*
lookup
!=
schema
.
getEnumerants
()[
1
]);
EXPECT_TRUE
(
schema
.
findEnumerantByName
(
"noSuchEnumerant"
)
==
nullptr
);
EXPECT_TRUE
(
schema
.
findEnumerantByName
(
"noSuchEnumerant"
)
==
nullptr
);
...
@@ -259,8 +254,7 @@ TEST(Schema, Lists) {
...
@@ -259,8 +254,7 @@ TEST(Schema, Lists) {
{
{
auto
context
=
Schema
::
from
<
TestAllTypes
>
();
auto
context
=
Schema
::
from
<
TestAllTypes
>
();
auto
type
=
context
.
findMemberByName
(
"enumList"
)
auto
type
=
context
.
getMemberByName
(
"enumList"
).
getProto
().
getBody
().
getFieldMember
().
getType
();
->
getProto
().
getBody
().
getFieldMember
().
getType
();
ListSchema
schema
=
ListSchema
::
of
(
type
.
getBody
().
getListType
(),
context
);
ListSchema
schema
=
ListSchema
::
of
(
type
.
getBody
().
getListType
(),
context
);
EXPECT_EQ
(
schema
::
Type
::
Body
::
ENUM_TYPE
,
schema
.
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
ENUM_TYPE
,
schema
.
whichElementType
());
...
...
c++/src/capnproto/schema.c++
View file @
bdb86c21
...
@@ -129,9 +129,11 @@ kj::Maybe<StructSchema::Member> StructSchema::findMemberByName(Text::Reader name
...
@@ -129,9 +129,11 @@ kj::Maybe<StructSchema::Member> StructSchema::findMemberByName(Text::Reader name
}
}
StructSchema
::
Member
StructSchema
::
getMemberByName
(
Text
::
Reader
name
)
const
{
StructSchema
::
Member
StructSchema
::
getMemberByName
(
Text
::
Reader
name
)
const
{
kj
::
Maybe
<
StructSchema
::
Member
>
member
=
findMemberByName
(
name
);
KJ_IF_MAYBE
(
member
,
findMemberByName
(
name
))
{
PRECOND
(
member
!=
nullptr
,
"struct has no such member"
,
name
);
return
*
member
;
return
*
member
;
}
else
{
FAIL_PRECOND
(
"struct has no such member"
,
name
);
}
}
}
kj
::
Maybe
<
StructSchema
::
Union
>
StructSchema
::
Member
::
getContainingUnion
()
const
{
kj
::
Maybe
<
StructSchema
::
Union
>
StructSchema
::
Member
::
getContainingUnion
()
const
{
...
@@ -155,9 +157,11 @@ kj::Maybe<StructSchema::Member> StructSchema::Union::findMemberByName(Text::Read
...
@@ -155,9 +157,11 @@ kj::Maybe<StructSchema::Member> StructSchema::Union::findMemberByName(Text::Read
}
}
StructSchema
::
Member
StructSchema
::
Union
::
getMemberByName
(
Text
::
Reader
name
)
const
{
StructSchema
::
Member
StructSchema
::
Union
::
getMemberByName
(
Text
::
Reader
name
)
const
{
kj
::
Maybe
<
StructSchema
::
Member
>
member
=
findMemberByName
(
name
);
KJ_IF_MAYBE
(
member
,
findMemberByName
(
name
))
{
PRECOND
(
member
!=
nullptr
,
"union has no such member"
,
name
);
return
*
member
;
return
*
member
;
}
else
{
FAIL_PRECOND
(
"union has no such member"
,
name
);
}
}
}
// -------------------------------------------------------------------
// -------------------------------------------------------------------
...
@@ -171,9 +175,11 @@ kj::Maybe<EnumSchema::Enumerant> EnumSchema::findEnumerantByName(Text::Reader na
...
@@ -171,9 +175,11 @@ kj::Maybe<EnumSchema::Enumerant> EnumSchema::findEnumerantByName(Text::Reader na
}
}
EnumSchema
::
Enumerant
EnumSchema
::
getEnumerantByName
(
Text
::
Reader
name
)
const
{
EnumSchema
::
Enumerant
EnumSchema
::
getEnumerantByName
(
Text
::
Reader
name
)
const
{
kj
::
Maybe
<
EnumSchema
::
Enumerant
>
enumerant
=
findEnumerantByName
(
name
);
KJ_IF_MAYBE
(
enumerant
,
findEnumerantByName
(
name
))
{
PRECOND
(
enumerant
!=
nullptr
,
"enum has no such enumerant"
,
name
);
return
*
enumerant
;
return
*
enumerant
;
}
else
{
FAIL_PRECOND
(
"enum has no such enumerant"
,
name
);
}
}
}
// -------------------------------------------------------------------
// -------------------------------------------------------------------
...
@@ -187,9 +193,11 @@ kj::Maybe<InterfaceSchema::Method> InterfaceSchema::findMethodByName(Text::Reade
...
@@ -187,9 +193,11 @@ kj::Maybe<InterfaceSchema::Method> InterfaceSchema::findMethodByName(Text::Reade
}
}
InterfaceSchema
::
Method
InterfaceSchema
::
getMethodByName
(
Text
::
Reader
name
)
const
{
InterfaceSchema
::
Method
InterfaceSchema
::
getMethodByName
(
Text
::
Reader
name
)
const
{
kj
::
Maybe
<
InterfaceSchema
::
Method
>
method
=
findMethodByName
(
name
);
KJ_IF_MAYBE
(
method
,
findMethodByName
(
name
))
{
PRECOND
(
method
!=
nullptr
,
"interface has no such method"
,
name
);
return
*
method
;
return
*
method
;
}
else
{
FAIL_PRECOND
(
"interface has no such method"
,
name
);
}
}
}
// =======================================================================================
// =======================================================================================
...
...
c++/src/capnproto/stringify.c++
View file @
bdb86c21
...
@@ -111,13 +111,11 @@ static void print(std::ostream& os, DynamicValue::Reader value,
...
@@ -111,13 +111,11 @@ static void print(std::ostream& os, DynamicValue::Reader value,
}
}
case
DynamicValue
:
:
ENUM
:
{
case
DynamicValue
:
:
ENUM
:
{
auto
enumValue
=
value
.
as
<
DynamicEnum
>
();
auto
enumValue
=
value
.
as
<
DynamicEnum
>
();
kj
::
Maybe
<
EnumSchema
::
Enumerant
>
enumerant
=
KJ_IF_MAYBE
(
enumerant
,
enumValue
.
getEnumerant
())
{
enumValue
.
getEnumerant
();
os
<<
enumerant
->
getProto
().
getName
().
c_str
();
if
(
enumerant
==
nullptr
)
{
}
else
{
// Unknown enum value; output raw number.
// Unknown enum value; output raw number.
os
<<
enumValue
.
getRaw
();
os
<<
enumValue
.
getRaw
();
}
else
{
os
<<
enumerant
->
getProto
().
getName
().
c_str
();
}
}
break
;
break
;
}
}
...
@@ -151,16 +149,15 @@ static void print(std::ostream& os, DynamicValue::Reader value,
...
@@ -151,16 +149,15 @@ static void print(std::ostream& os, DynamicValue::Reader value,
}
}
case
DynamicValue
:
:
UNION
:
{
case
DynamicValue
:
:
UNION
:
{
auto
unionValue
=
value
.
as
<
DynamicUnion
>
();
auto
unionValue
=
value
.
as
<
DynamicUnion
>
();
kj
::
Maybe
<
StructSchema
::
Member
>
tag
=
unionValue
.
which
();
KJ_IF_MAYBE
(
tag
,
unionValue
.
which
())
{
if
(
tag
==
nullptr
)
{
// Unknown union member; must have come from newer
// version of the protocol.
os
<<
"?"
;
}
else
{
os
<<
tag
->
getProto
().
getName
()
<<
"("
;
os
<<
tag
->
getProto
().
getName
()
<<
"("
;
print
(
os
,
unionValue
.
get
(),
print
(
os
,
unionValue
.
get
(),
tag
->
getProto
().
getBody
().
getFieldMember
().
getType
().
getBody
().
which
());
tag
->
getProto
().
getBody
().
getFieldMember
().
getType
().
getBody
().
which
());
os
<<
")"
;
os
<<
")"
;
}
else
{
// Unknown union member; must have come from newer
// version of the protocol.
os
<<
"?"
;
}
}
break
;
break
;
}
}
...
...
c++/src/capnproto/test-util.c++
View file @
bdb86c21
...
@@ -368,13 +368,20 @@ void checkList(T reader, std::initializer_list<ReaderFor<Element>> expected) {
...
@@ -368,13 +368,20 @@ void checkList(T reader, std::initializer_list<ReaderFor<Element>> expected) {
}
}
}
}
Text
::
Reader
name
(
DynamicEnum
e
)
{
KJ_IF_MAYBE
(
schema
,
e
.
getEnumerant
())
{
return
schema
->
getProto
().
getName
();
}
else
{
return
"(unknown enumerant)"
;
}
}
template
<
typename
T
>
template
<
typename
T
>
void
checkEnumList
(
T
reader
,
std
::
initializer_list
<
const
char
*>
expected
)
{
void
checkEnumList
(
T
reader
,
std
::
initializer_list
<
const
char
*>
expected
)
{
auto
list
=
reader
.
as
<
DynamicList
>
();
auto
list
=
reader
.
as
<
DynamicList
>
();
ASSERT_EQ
(
expected
.
size
(),
list
.
size
());
ASSERT_EQ
(
expected
.
size
(),
list
.
size
());
for
(
uint
i
=
0
;
i
<
expected
.
size
();
i
++
)
{
for
(
uint
i
=
0
;
i
<
expected
.
size
();
i
++
)
{
EXPECT_EQ
(
expected
.
begin
()[
i
],
EXPECT_EQ
(
expected
.
begin
()[
i
],
name
(
list
[
i
].
as
<
DynamicEnum
>
()));
list
[
i
].
as
<
DynamicEnum
>
().
getEnumerant
()
->
getProto
().
getName
());
}
}
}
}
...
@@ -416,8 +423,7 @@ void dynamicCheckTestMessage(Reader reader) {
...
@@ -416,8 +423,7 @@ void dynamicCheckTestMessage(Reader reader) {
EXPECT_EQ
(
"really nested"
,
subSubReader
.
get
(
"structField"
).
as
<
DynamicStruct
>
()
EXPECT_EQ
(
"really nested"
,
subSubReader
.
get
(
"structField"
).
as
<
DynamicStruct
>
()
.
get
(
"textField"
).
as
<
Text
>
());
.
get
(
"textField"
).
as
<
Text
>
());
}
}
EXPECT_EQ
(
"baz"
,
EXPECT_EQ
(
"baz"
,
name
(
subReader
.
get
(
"enumField"
).
as
<
DynamicEnum
>
()));
subReader
.
get
(
"enumField"
).
as
<
DynamicEnum
>
().
getEnumerant
()
->
getProto
().
getName
());
checkList
<
Void
>
(
subReader
.
get
(
"voidList"
),
{
Void
::
VOID
,
Void
::
VOID
,
Void
::
VOID
});
checkList
<
Void
>
(
subReader
.
get
(
"voidList"
),
{
Void
::
VOID
,
Void
::
VOID
,
Void
::
VOID
});
checkList
<
bool
>
(
subReader
.
get
(
"boolList"
),
{
false
,
true
,
false
,
true
,
true
});
checkList
<
bool
>
(
subReader
.
get
(
"boolList"
),
{
false
,
true
,
false
,
true
,
true
});
...
@@ -443,8 +449,7 @@ void dynamicCheckTestMessage(Reader reader) {
...
@@ -443,8 +449,7 @@ void dynamicCheckTestMessage(Reader reader) {
}
}
checkEnumList
(
subReader
.
get
(
"enumList"
),
{
"qux"
,
"bar"
,
"grault"
});
checkEnumList
(
subReader
.
get
(
"enumList"
),
{
"qux"
,
"bar"
,
"grault"
});
}
}
EXPECT_EQ
(
"corge"
,
EXPECT_EQ
(
"corge"
,
name
(
reader
.
get
(
"enumField"
).
as
<
DynamicEnum
>
()));
reader
.
get
(
"enumField"
).
as
<
DynamicEnum
>
().
getEnumerant
()
->
getProto
().
getName
());
EXPECT_EQ
(
6u
,
reader
.
get
(
"voidList"
).
as
<
DynamicList
>
().
size
());
EXPECT_EQ
(
6u
,
reader
.
get
(
"voidList"
).
as
<
DynamicList
>
().
size
());
checkList
<
bool
>
(
reader
.
get
(
"boolList"
),
{
true
,
false
,
false
,
true
});
checkList
<
bool
>
(
reader
.
get
(
"boolList"
),
{
true
,
false
,
false
,
true
});
...
...
c++/src/kj/common-test.c++
0 → 100644
View file @
bdb86c21
// 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 "common.h"
#include <gtest/gtest.h>
namespace
kj
{
namespace
{
TEST
(
Common
,
Maybe
)
{
{
Maybe
<
int
>
m
=
123
;
EXPECT_FALSE
(
m
==
nullptr
);
EXPECT_TRUE
(
m
!=
nullptr
);
KJ_IF_MAYBE
(
v
,
m
)
{
EXPECT_EQ
(
123
,
*
v
);
}
else
{
ADD_FAILURE
();
}
KJ_IF_MAYBE
(
v
,
mv
(
m
))
{
EXPECT_EQ
(
123
,
*
v
);
}
else
{
ADD_FAILURE
();
}
}
{
Maybe
<
int
>
m
=
nullptr
;
EXPECT_TRUE
(
m
==
nullptr
);
EXPECT_FALSE
(
m
!=
nullptr
);
KJ_IF_MAYBE
(
v
,
m
)
{
ADD_FAILURE
();
EXPECT_EQ
(
0
,
*
v
);
// avoid unused warning
}
KJ_IF_MAYBE
(
v
,
mv
(
m
))
{
ADD_FAILURE
();
EXPECT_EQ
(
0
,
*
v
);
// avoid unused warning
}
}
int
i
=
234
;
{
Maybe
<
int
&>
m
=
i
;
EXPECT_FALSE
(
m
==
nullptr
);
EXPECT_TRUE
(
m
!=
nullptr
);
KJ_IF_MAYBE
(
v
,
m
)
{
EXPECT_EQ
(
&
i
,
v
);
}
else
{
ADD_FAILURE
();
}
KJ_IF_MAYBE
(
v
,
mv
(
m
))
{
EXPECT_EQ
(
&
i
,
v
);
}
else
{
ADD_FAILURE
();
}
}
{
Maybe
<
int
&>
m
=
nullptr
;
EXPECT_TRUE
(
m
==
nullptr
);
EXPECT_FALSE
(
m
!=
nullptr
);
KJ_IF_MAYBE
(
v
,
m
)
{
ADD_FAILURE
();
EXPECT_EQ
(
0
,
*
v
);
// avoid unused warning
}
KJ_IF_MAYBE
(
v
,
mv
(
m
))
{
ADD_FAILURE
();
EXPECT_EQ
(
0
,
*
v
);
// avoid unused warning
}
}
{
Maybe
<
int
&>
m
=
&
i
;
EXPECT_FALSE
(
m
==
nullptr
);
EXPECT_TRUE
(
m
!=
nullptr
);
KJ_IF_MAYBE
(
v
,
m
)
{
EXPECT_EQ
(
&
i
,
v
);
}
else
{
ADD_FAILURE
();
}
KJ_IF_MAYBE
(
v
,
mv
(
m
))
{
EXPECT_EQ
(
&
i
,
v
);
}
else
{
ADD_FAILURE
();
}
}
{
Maybe
<
int
&>
m
=
upcast
<
int
*>
(
nullptr
);
EXPECT_TRUE
(
m
==
nullptr
);
EXPECT_FALSE
(
m
!=
nullptr
);
KJ_IF_MAYBE
(
v
,
m
)
{
ADD_FAILURE
();
EXPECT_EQ
(
0
,
*
v
);
// avoid unused warning
}
KJ_IF_MAYBE
(
v
,
mv
(
m
))
{
ADD_FAILURE
();
EXPECT_EQ
(
0
,
*
v
);
// avoid unused warning
}
}
{
Maybe
<
int
>
m
=
&
i
;
EXPECT_FALSE
(
m
==
nullptr
);
EXPECT_TRUE
(
m
!=
nullptr
);
KJ_IF_MAYBE
(
v
,
m
)
{
EXPECT_NE
(
v
,
&
i
);
EXPECT_EQ
(
234
,
*
v
);
}
else
{
ADD_FAILURE
();
}
KJ_IF_MAYBE
(
v
,
mv
(
m
))
{
EXPECT_NE
(
v
,
&
i
);
EXPECT_EQ
(
234
,
*
v
);
}
else
{
ADD_FAILURE
();
}
}
{
Maybe
<
int
>
m
=
upcast
<
int
*>
(
nullptr
);
EXPECT_TRUE
(
m
==
nullptr
);
EXPECT_FALSE
(
m
!=
nullptr
);
KJ_IF_MAYBE
(
v
,
m
)
{
ADD_FAILURE
();
EXPECT_EQ
(
0
,
*
v
);
// avoid unused warning
}
KJ_IF_MAYBE
(
v
,
mv
(
m
))
{
ADD_FAILURE
();
EXPECT_EQ
(
0
,
*
v
);
// avoid unused warning
}
}
}
class
Foo
{
public
:
virtual
~
Foo
()
{}
};
class
Bar
:
public
Foo
{
public
:
virtual
~
Bar
()
{}
};
class
Baz
:
public
Foo
{
public
:
virtual
~
Baz
()
{}
};
TEST
(
Common
,
Downcast
)
{
Bar
bar
;
Foo
&
foo
=
bar
;
EXPECT_EQ
(
&
bar
,
&
downcast
<
Bar
&>
(
foo
));
EXPECT_EQ
(
&
bar
,
downcast
<
Bar
*>
(
&
foo
));
EXPECT_ANY_THROW
(
downcast
<
Baz
&>
(
foo
));
EXPECT_ANY_THROW
(
downcast
<
Baz
*>
(
&
foo
));
#if KJ_NO_RTTI
EXPECT_TRUE
(
dynamicDowncastIfAvailable
<
Bar
&>
(
foo
)
==
nullptr
);
EXPECT_TRUE
(
dynamicDowncastIfAvailable
<
Baz
&>
(
foo
)
==
nullptr
);
#else
KJ_IF_MAYBE
(
m
,
dynamicDowncastIfAvailable
<
Bar
&>
(
foo
))
{
EXPECT_EQ
(
&
bar
,
m
);
}
else
{
ADD_FAILURE
()
<<
"Dynamic downcast returned null."
;
}
EXPECT_TRUE
(
dynamicDowncastIfAvailable
<
Baz
&>
(
foo
)
==
nullptr
);
#endif
}
}
// namespace
}
// namespace kj
c++/src/kj/common.h
View file @
bdb86c21
...
@@ -25,6 +25,8 @@
...
@@ -25,6 +25,8 @@
//
//
// This defines very simple utilities that are widely applicable.
// This defines very simple utilities that are widely applicable.
#include <stddef.h>
#ifndef KJ_COMMON_H_
#ifndef KJ_COMMON_H_
#define KJ_COMMON_H_
#define KJ_COMMON_H_
...
@@ -58,6 +60,14 @@ typedef unsigned char byte;
...
@@ -58,6 +60,14 @@ typedef unsigned char byte;
// =======================================================================================
// =======================================================================================
// Common macros, especially for common yet compiler-specific features.
// Common macros, especially for common yet compiler-specific features.
#ifndef KJ_NO_RTTI
#ifdef __GNUC__
#if !__GXX_RTTI
#define KJ_NO_RTTI
#endif
#endif
#endif
#define KJ_DISALLOW_COPY(classname) \
#define KJ_DISALLOW_COPY(classname) \
classname(const classname&) = delete; \
classname(const classname&) = delete; \
classname& operator=(const classname&) = delete
classname& operator=(const classname&) = delete
...
@@ -183,6 +193,263 @@ template<typename T> constexpr T&& fwd(RemoveReference<T>&& t) noexcept {
...
@@ -183,6 +193,263 @@ template<typename T> constexpr T&& fwd(RemoveReference<T>&& t) noexcept {
return
static_cast
<
T
&&>
(
t
);
return
static_cast
<
T
&&>
(
t
);
}
}
// =======================================================================================
// Manually invoking constructors and destructors
//
// ctor(x, ...) and dtor(x) invoke x's constructor or destructor, respectively.
// We want placement new, but we don't want to #include <new>. operator new cannot be defined in
// a namespace, and defining it globally conflicts with the definition in <new>. So we have to
// define a dummy type and an operator new that uses it.
namespace
internal
{
struct
PlacementNew
{};
}
// namespace internal
}
// namespace kj
inline
void
*
operator
new
(
size_t
,
kj
::
internal
::
PlacementNew
,
void
*
__p
)
noexcept
{
return
__p
;
}
namespace
kj
{
template
<
typename
T
,
typename
...
Params
>
inline
void
ctor
(
T
&
location
,
Params
&&
...
params
)
{
new
(
internal
::
PlacementNew
(),
&
location
)
T
(
kj
::
fwd
<
Params
>
(
params
)...);
}
template
<
typename
T
>
inline
void
dtor
(
T
&
location
)
{
location
.
~
T
();
}
// =======================================================================================
// Maybe
//
// Use in cases where you want to indicate that a value may be null. Using Maybe<T&> instead of T*
// forces the caller to handle the null case in order to satisfy the compiler, thus reliably
// preventing null pointer dereferences at runtime.
//
// Maybe<T> can be implicitly constructed from T and from nullptr. Additionally, it can be
// implicitly constructed from T*, in which case the pointer is checked for nullness at runtime.
// To read the value of a Maybe<T>, do:
//
// KJ_IF_MAYBE(value, someFuncReturningMaybe()) {
// doSomething(*value);
// } else {
// maybeWasNull();
// }
//
// KJ_IF_MAYBE's first parameter is a variable name which will be defined within the following
// block. The variable will behave like a (guaranteed non-null) pointer to the Maybe's value,
// though it may or may not actually be a pointer.
//
// Note that Maybe<T&> actually just wraps a pointer, whereas Maybe<T> wraps a T and a boolean
// indicating nullness.
template
<
typename
T
>
class
Maybe
;
namespace
internal
{
template
<
typename
T
>
class
NullableValue
{
// Class whose interface behaves much like T*, but actually contains an instance of T and a
// boolean flag indicating nullness.
public
:
inline
NullableValue
(
NullableValue
&&
other
)
noexcept
(
noexcept
(
T
(
instance
<
T
&&>
())))
:
isSet
(
other
.
isSet
)
{
if
(
isSet
)
{
ctor
(
value
,
kj
::
mv
(
other
.
value
));
}
}
inline
NullableValue
(
const
NullableValue
&
other
)
:
isSet
(
other
.
isSet
)
{
if
(
isSet
)
{
ctor
(
value
,
other
.
value
);
}
}
inline
~
NullableValue
()
{
if
(
isSet
)
{
dtor
(
value
);
}
}
inline
T
&
operator
*
()
{
return
value
;
}
inline
const
T
&
operator
*
()
const
{
return
value
;
}
inline
T
*
operator
->
()
{
return
&
value
;
}
inline
const
T
*
operator
->
()
const
{
return
&
value
;
}
inline
operator
T
*
()
{
return
isSet
?
&
value
:
nullptr
;
}
inline
operator
const
T
*
()
const
{
return
isSet
?
&
value
:
nullptr
;
}
private
:
// internal interface used by friends only
inline
NullableValue
()
noexcept
:
isSet
(
false
)
{}
inline
NullableValue
(
T
&&
t
)
noexcept
(
noexcept
(
T
(
instance
<
T
&&>
())))
:
isSet
(
true
)
{
ctor
(
value
,
kj
::
mv
(
t
));
}
inline
NullableValue
(
const
T
&
t
)
:
isSet
(
true
)
{
ctor
(
value
,
t
);
}
inline
NullableValue
(
const
T
*
t
)
:
isSet
(
t
!=
nullptr
)
{
if
(
isSet
)
ctor
(
value
,
*
t
);
}
template
<
typename
U
>
inline
NullableValue
(
NullableValue
<
U
>&&
other
)
noexcept
(
noexcept
(
T
(
instance
<
U
&&>
())))
:
isSet
(
other
.
isSet
)
{
if
(
isSet
)
{
ctor
(
value
,
kj
::
mv
(
other
.
value
));
}
}
template
<
typename
U
>
inline
NullableValue
(
const
NullableValue
<
U
>&
other
)
:
isSet
(
other
.
isSet
)
{
if
(
isSet
)
{
ctor
(
value
,
other
.
value
);
}
}
template
<
typename
U
>
inline
NullableValue
(
const
NullableValue
<
U
&>&
other
)
:
isSet
(
other
.
isSet
)
{
if
(
isSet
)
{
ctor
(
value
,
*
other
.
ptr
);
}
}
inline
NullableValue
(
decltype
(
nullptr
))
:
isSet
(
false
)
{}
inline
NullableValue
&
operator
=
(
NullableValue
&&
other
)
{
if
(
&
other
!=
this
)
{
if
(
isSet
)
{
dtor
(
value
);
}
isSet
=
other
.
isSet
;
if
(
isSet
)
{
ctor
(
value
,
kj
::
mv
(
other
.
value
));
}
}
return
*
this
;
}
inline
NullableValue
&
operator
=
(
const
NullableValue
&
other
)
{
if
(
&
other
!=
this
)
{
if
(
isSet
)
{
dtor
(
value
);
}
isSet
=
other
.
isSet
;
if
(
isSet
)
{
ctor
(
value
,
other
.
value
);
}
}
return
*
this
;
}
inline
bool
operator
==
(
decltype
(
nullptr
))
const
{
return
!
isSet
;
}
inline
bool
operator
!=
(
decltype
(
nullptr
))
const
{
return
isSet
;
}
private
:
bool
isSet
;
union
{
T
value
;
};
friend
class
kj
::
Maybe
<
T
>
;
template
<
typename
U
>
friend
NullableValue
<
U
>&&
readMaybe
(
Maybe
<
U
>&&
maybe
);
};
template
<
typename
T
>
inline
NullableValue
<
T
>&&
readMaybe
(
Maybe
<
T
>&&
maybe
)
{
return
kj
::
mv
(
maybe
.
ptr
);
}
template
<
typename
T
>
inline
T
*
readMaybe
(
Maybe
<
T
>&
maybe
)
{
return
maybe
.
ptr
;
}
template
<
typename
T
>
inline
const
T
*
readMaybe
(
const
Maybe
<
T
>&
maybe
)
{
return
maybe
.
ptr
;
}
template
<
typename
T
>
inline
T
*
readMaybe
(
Maybe
<
T
&>&&
maybe
)
{
return
maybe
.
ptr
;
}
template
<
typename
T
>
inline
T
*
readMaybe
(
const
Maybe
<
T
&>&
maybe
)
{
return
maybe
.
ptr
;
}
}
// namespace internal
#define KJ_IF_MAYBE(name, exp) if (auto name = ::kj::internal::readMaybe(exp))
template
<
typename
T
>
class
Maybe
{
public
:
Maybe
()
:
ptr
(
nullptr
)
{}
Maybe
(
T
&&
t
)
noexcept
(
noexcept
(
T
(
instance
<
T
&&>
())))
:
ptr
(
kj
::
mv
(
t
))
{}
Maybe
(
const
T
&
t
)
:
ptr
(
t
)
{}
Maybe
(
const
T
*
t
)
noexcept
:
ptr
(
t
)
{}
Maybe
(
Maybe
&&
other
)
noexcept
(
noexcept
(
T
(
instance
<
T
&&>
())))
:
ptr
(
kj
::
mv
(
other
.
ptr
))
{}
Maybe
(
const
Maybe
&
other
)
:
ptr
(
other
.
ptr
)
{}
template
<
typename
U
>
Maybe
(
Maybe
<
U
>&&
other
)
noexcept
(
noexcept
(
T
(
instance
<
U
&&>
())))
{
KJ_IF_MAYBE
(
val
,
kj
::
mv
(
other
))
{
ptr
=
*
val
;
}
}
template
<
typename
U
>
Maybe
(
const
Maybe
<
U
>&
other
)
{
KJ_IF_MAYBE
(
val
,
other
)
{
ptr
=
*
val
;
}
}
Maybe
(
decltype
(
nullptr
))
noexcept
:
ptr
(
nullptr
)
{}
inline
Maybe
&
operator
=
(
Maybe
&&
other
)
{
ptr
=
kj
::
mv
(
other
.
ptr
);
return
*
this
;
}
inline
Maybe
&
operator
=
(
const
Maybe
&
other
)
{
ptr
=
other
.
ptr
;
return
*
this
;
}
inline
bool
operator
==
(
decltype
(
nullptr
))
const
{
return
ptr
==
nullptr
;
}
inline
bool
operator
!=
(
decltype
(
nullptr
))
const
{
return
ptr
!=
nullptr
;
}
~
Maybe
()
noexcept
{}
private
:
internal
::
NullableValue
<
T
>
ptr
;
template
<
typename
U
>
friend
class
Maybe
;
template
<
typename
U
>
friend
internal
::
NullableValue
<
U
>&&
internal
::
readMaybe
(
Maybe
<
U
>&&
maybe
);
template
<
typename
U
>
friend
U
*
internal
::
readMaybe
(
Maybe
<
U
>&
maybe
);
template
<
typename
U
>
friend
const
U
*
internal
::
readMaybe
(
const
Maybe
<
U
>&
maybe
);
};
template
<
typename
T
>
class
Maybe
<
T
&>
{
public
:
Maybe
()
:
ptr
(
nullptr
)
{}
Maybe
(
T
&
t
)
noexcept
:
ptr
(
&
t
)
{}
Maybe
(
T
*
t
)
noexcept
:
ptr
(
t
)
{}
Maybe
(
const
Maybe
&
other
)
noexcept
:
ptr
(
other
.
ptr
)
{}
template
<
typename
U
>
Maybe
(
const
Maybe
<
U
&>&
other
)
:
ptr
(
other
.
ptr
)
{}
Maybe
(
decltype
(
nullptr
))
noexcept
:
ptr
(
nullptr
)
{}
inline
Maybe
&
operator
=
(
const
Maybe
&
other
)
{
ptr
=
other
.
ptr
;
return
*
this
;
}
inline
bool
operator
==
(
decltype
(
nullptr
))
const
{
return
ptr
==
nullptr
;
}
inline
bool
operator
!=
(
decltype
(
nullptr
))
const
{
return
ptr
!=
nullptr
;
}
~
Maybe
()
noexcept
{}
private
:
T
*
ptr
;
template
<
typename
U
>
friend
class
Maybe
;
template
<
typename
U
>
friend
U
*
internal
::
readMaybe
(
Maybe
<
U
&>&&
maybe
);
template
<
typename
U
>
friend
U
*
internal
::
readMaybe
(
const
Maybe
<
U
&>&
maybe
);
};
// =======================================================================================
// =======================================================================================
// Upcast/downcast
// Upcast/downcast
...
@@ -194,17 +461,23 @@ To upcast(From&& from) {
...
@@ -194,17 +461,23 @@ To upcast(From&& from) {
}
}
template
<
typename
To
,
typename
From
>
template
<
typename
To
,
typename
From
>
To
dynamicDowncastIfAvailable
(
From
*
from
)
{
Maybe
<
To
&>
dynamicDowncastIfAvailable
(
From
&
from
)
{
// If RTTI is disabled, always returns nullptr. Otherwise, works like dynamic_cast. Useful
// If RTTI is disabled, always returns nullptr. Otherwise, works like dynamic_cast. Useful
// in situations where dynamic_cast could allow an optimization, but isn't strictly necessary
// in situations where dynamic_cast could allow an optimization, but isn't strictly necessary
// for correctness. It is highly recommended that you try to arrange all your dynamic_casts
// for correctness. It is highly recommended that you try to arrange all your dynamic_casts
// this way, as a dynamic_cast that is necessary for correctness implies a flaw in the interface
// this way, as a dynamic_cast that is necessary for correctness implies a flaw in the interface
// design.
// design.
// Force a compile error if To is not a subtype of From. Cross-casting is rare; if it is needed
// we should have a separate cast function like dynamicCrosscastIfAvailable().
if
(
false
)
{
kj
::
upcast
<
From
*>
(
upcast
<
RemoveReference
<
To
>*>
(
nullptr
));
}
#if KJ_NO_RTTI
#if KJ_NO_RTTI
return
nullptr
;
return
nullptr
;
#else
#else
return
dynamic_cast
<
To
>
(
from
);
return
dynamic_cast
<
RemoveReference
<
To
>*>
(
&
from
);
#endif
#endif
}
}
...
@@ -229,9 +502,9 @@ To downcast(From* from) {
...
@@ -229,9 +502,9 @@ To downcast(From* from) {
}
}
template
<
typename
To
,
typename
From
>
template
<
typename
To
,
typename
From
>
To
downcast
(
From
&
&
from
)
{
To
downcast
(
From
&
from
)
{
// Reference version of downcast().
// Reference version of downcast().
return
*
kj
::
downcast
<
To
*>
(
&
from
);
return
*
kj
::
downcast
<
RemoveReference
<
To
>
*>
(
&
from
);
}
}
}
// namespace kj
}
// namespace kj
...
...
c++/src/kj/exception.c++
View file @
bdb86c21
...
@@ -67,8 +67,8 @@ Exception::Exception(const Exception& other) noexcept
...
@@ -67,8 +67,8 @@ Exception::Exception(const Exception& other) noexcept
description
(
str
(
other
.
description
)),
traceCount
(
other
.
traceCount
)
{
description
(
str
(
other
.
description
)),
traceCount
(
other
.
traceCount
)
{
memcpy
(
trace
,
other
.
trace
,
sizeof
(
trace
[
0
])
*
traceCount
);
memcpy
(
trace
,
other
.
trace
,
sizeof
(
trace
[
0
])
*
traceCount
);
if
(
other
.
context
!=
nullptr
)
{
KJ_IF_MAYBE
(
c
,
other
.
context
)
{
context
=
heap
<
Context
>
(
**
other
.
context
);
context
=
heap
<
Context
>
(
**
c
);
}
}
}
}
...
@@ -76,8 +76,8 @@ Exception::~Exception() noexcept {}
...
@@ -76,8 +76,8 @@ Exception::~Exception() noexcept {}
Exception
::
Context
::
Context
(
const
Context
&
other
)
noexcept
Exception
::
Context
::
Context
(
const
Context
&
other
)
noexcept
:
file
(
other
.
file
),
line
(
other
.
line
),
description
(
str
(
other
.
description
))
{
:
file
(
other
.
file
),
line
(
other
.
line
),
description
(
str
(
other
.
description
))
{
if
(
other
.
next
!=
nullptr
)
{
KJ_IF_MAYBE
(
n
,
other
.
next
)
{
next
=
heap
<
Context
>
(
**
other
.
next
);
next
=
heap
<
Context
>
(
**
n
);
}
}
}
}
...
@@ -89,20 +89,28 @@ const char* Exception::what() const noexcept {
...
@@ -89,20 +89,28 @@ const char* Exception::what() const noexcept {
uint
contextDepth
=
0
;
uint
contextDepth
=
0
;
const
Maybe
<
Own
<
Context
>>*
contextPtr
=
&
context
;
const
Maybe
<
Own
<
Context
>>*
contextPtr
=
&
context
;
while
(
*
contextPtr
!=
nullptr
)
{
for
(;;)
{
++
contextDepth
;
KJ_IF_MAYBE
(
c
,
*
contextPtr
)
{
contextPtr
=
&
(
***
contextPtr
).
next
;
++
contextDepth
;
contextPtr
=
&
(
*
c
)
->
next
;
}
else
{
break
;
}
}
}
Array
<
Array
<
char
>>
contextText
=
newArray
<
Array
<
char
>>
(
contextDepth
);
Array
<
Array
<
char
>>
contextText
=
newArray
<
Array
<
char
>>
(
contextDepth
);
contextDepth
=
0
;
contextDepth
=
0
;
contextPtr
=
&
context
;
contextPtr
=
&
context
;
while
(
*
contextPtr
!=
nullptr
)
{
for
(;;)
{
const
Context
&
node
=
***
contextPtr
;
KJ_IF_MAYBE
(
c
,
*
contextPtr
)
{
contextText
[
contextDepth
++
]
=
const
Context
&
node
=
**
c
;
str
(
node
.
file
,
":"
,
node
.
line
,
": context: "
,
node
.
description
,
"
\n
"
);
contextText
[
contextDepth
++
]
=
contextPtr
=
&
node
.
next
;
str
(
node
.
file
,
":"
,
node
.
line
,
": context: "
,
node
.
description
,
"
\n
"
);
contextPtr
=
&
node
.
next
;
}
else
{
break
;
}
}
}
// Must be careful to NUL-terminate this.
// Must be careful to NUL-terminate this.
...
...
c++/src/kj/exception.h
View file @
bdb86c21
...
@@ -88,10 +88,10 @@ public:
...
@@ -88,10 +88,10 @@ public:
};
};
inline
Maybe
<
const
Context
&>
getContext
()
const
{
inline
Maybe
<
const
Context
&>
getContext
()
const
{
if
(
context
==
nullptr
)
{
KJ_IF_MAYBE
(
c
,
context
)
{
return
nullptr
;
return
**
c
;
}
else
{
}
else
{
return
**
context
;
return
nullptr
;
}
}
}
}
...
...
c++/src/kj/type-safety.h
View file @
bdb86c21
...
@@ -34,214 +34,6 @@
...
@@ -34,214 +34,6 @@
namespace
kj
{
namespace
kj
{
// #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
{};
}
// namespace internal;
}
// namespace kj
inline
void
*
operator
new
(
std
::
size_t
,
kj
::
internal
::
PlacementNew
,
void
*
__p
)
noexcept
{
return
__p
;
}
namespace
kj
{
template
<
typename
T
,
typename
...
Params
>
void
constructAt
(
T
*
location
,
Params
&&
...
params
)
{
new
(
internal
::
PlacementNew
(),
location
)
T
(
kj
::
fwd
<
Params
>
(
params
)...);
}
// =======================================================================================
// Maybe
template
<
typename
T
>
class
Maybe
{
public
:
Maybe
()
:
isSet
(
false
)
{}
Maybe
(
T
&&
t
)
:
isSet
(
true
)
{
constructAt
(
&
value
,
kj
::
mv
(
t
));
}
Maybe
(
const
T
&
t
)
:
isSet
(
true
)
{
constructAt
(
&
value
,
t
);
}
Maybe
(
Maybe
&&
other
)
noexcept
(
noexcept
(
T
(
kj
::
mv
(
other
.
value
))))
:
isSet
(
other
.
isSet
)
{
if
(
isSet
)
{
constructAt
(
&
value
,
kj
::
mv
(
other
.
value
));
}
}
Maybe
(
const
Maybe
&
other
)
:
isSet
(
other
.
isSet
)
{
if
(
isSet
)
{
constructAt
(
&
value
,
other
.
value
);
}
}
template
<
typename
U
>
Maybe
(
Maybe
<
U
>&&
other
)
noexcept
(
noexcept
(
T
(
kj
::
mv
(
other
.
value
))))
:
isSet
(
other
.
isSet
)
{
if
(
isSet
)
{
constructAt
(
&
value
,
kj
::
mv
(
other
.
value
));
}
}
template
<
typename
U
>
Maybe
(
const
Maybe
<
U
>&
other
)
:
isSet
(
other
.
isSet
)
{
if
(
isSet
)
{
constructAt
(
&
value
,
other
.
value
);
}
}
template
<
typename
U
>
Maybe
(
const
Maybe
<
U
&>&
other
)
:
isSet
(
other
.
isSet
)
{
if
(
isSet
)
{
constructAt
(
&
value
,
*
other
.
ptr
);
}
}
Maybe
(
std
::
nullptr_t
)
:
isSet
(
false
)
{}
~
Maybe
()
{
if
(
isSet
)
{
value
.
~
T
();
}
}
template
<
typename
...
Params
>
inline
void
init
(
Params
&&
...
params
)
{
if
(
isSet
)
{
value
.
~
T
();
}
isSet
=
true
;
constructAt
(
&
value
,
kj
::
fwd
(
params
)...);
}
inline
T
&
operator
*
()
{
return
value
;
}
inline
const
T
&
operator
*
()
const
{
return
value
;
}
inline
T
*
operator
->
()
{
return
&
value
;
}
inline
const
T
*
operator
->
()
const
{
return
&
value
;
}
inline
Maybe
&
operator
=
(
Maybe
&&
other
)
{
if
(
&
other
!=
this
)
{
if
(
isSet
)
{
value
.
~
T
();
}
isSet
=
other
.
isSet
;
if
(
isSet
)
{
constructAt
(
&
value
,
kj
::
mv
(
other
.
value
));
}
}
return
*
this
;
}
inline
Maybe
&
operator
=
(
const
Maybe
&
other
)
{
if
(
&
other
!=
this
)
{
if
(
isSet
)
{
value
.
~
T
();
}
isSet
=
other
.
isSet
;
if
(
isSet
)
{
constructAt
(
&
value
,
other
.
value
);
}
}
return
*
this
;
}
bool
operator
==
(
const
Maybe
&
other
)
const
{
if
(
isSet
==
other
.
isSet
)
{
if
(
isSet
)
{
return
value
==
other
.
value
;
}
else
{
return
true
;
}
}
return
false
;
}
inline
bool
operator
!=
(
const
Maybe
&
other
)
const
{
return
!
(
*
this
==
other
);
}
inline
bool
operator
==
(
std
::
nullptr_t
)
const
{
return
!
isSet
;
}
inline
bool
operator
!=
(
std
::
nullptr_t
)
const
{
return
isSet
;
}
template
<
typename
Func
>
auto
map
(
const
Func
&
func
)
const
->
Maybe
<
decltype
(
func
(
instance
<
const
T
&>
()))
>
{
// Construct a new Maybe by applying the given function to the Maybe's value.
if
(
isSet
)
{
return
func
(
value
);
}
else
{
return
nullptr
;
}
}
template
<
typename
Func
>
auto
map
(
const
Func
&
func
)
->
Maybe
<
decltype
(
func
(
instance
<
T
&>
()))
>
{
// Construct a new Maybe by applying the given function to the Maybe's value.
if
(
isSet
)
{
return
func
(
value
);
}
else
{
return
nullptr
;
}
}
template
<
typename
Func
>
auto
moveMap
(
const
Func
&
func
)
->
Maybe
<
decltype
(
func
(
instance
<
T
&&>
()))
>
{
// Like map() but allows the function to take an rvalue reference to the value.
if
(
isSet
)
{
return
func
(
kj
::
mv
(
value
));
}
else
{
return
nullptr
;
}
}
private
:
bool
isSet
;
union
{
T
value
;
};
template
<
typename
U
>
friend
class
Maybe
;
};
template
<
typename
T
>
class
Maybe
<
T
&>
{
public
:
Maybe
()
:
ptr
(
nullptr
)
{}
Maybe
(
T
&
t
)
:
ptr
(
&
t
)
{}
Maybe
(
std
::
nullptr_t
)
:
ptr
(
nullptr
)
{}
template
<
typename
U
>
Maybe
(
const
Maybe
<
U
>&
other
)
{
if
(
other
==
nullptr
)
{
ptr
=
nullptr
;
}
else
{
ptr
=
other
.
operator
->
();
}
}
~
Maybe
()
noexcept
{}
inline
T
&
operator
*
()
{
return
*
ptr
;
}
inline
const
T
&
operator
*
()
const
{
return
*
ptr
;
}
inline
T
*
operator
->
()
{
return
ptr
;
}
inline
const
T
*
operator
->
()
const
{
return
ptr
;
}
inline
bool
operator
==
(
const
Maybe
&
other
)
const
{
return
ptr
==
other
.
ptr
;
}
inline
bool
operator
!=
(
const
Maybe
&
other
)
const
{
return
ptr
!=
other
.
ptr
;
}
inline
bool
operator
==
(
std
::
nullptr_t
)
const
{
return
ptr
==
nullptr
;
}
inline
bool
operator
!=
(
std
::
nullptr_t
)
const
{
return
ptr
!=
nullptr
;
}
private
:
T
*
ptr
;
template
<
typename
U
>
friend
class
Maybe
;
};
// =======================================================================================
// =======================================================================================
// Own<T> -- An owned pointer.
// Own<T> -- An owned pointer.
...
...
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