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
e7b9e4da
Commit
e7b9e4da
authored
May 13, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Schema convenience interface.
parent
80722b03
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
1075 additions
and
10 deletions
+1075
-10
blob-test.c++
c++/src/capnproto/blob-test.c++
+37
-0
blob.h
c++/src/capnproto/blob.h
+2
-6
generated-header-support.h
c++/src/capnproto/generated-header-support.h
+21
-0
message.h
c++/src/capnproto/message.h
+2
-2
schema-test.c++
c++/src/capnproto/schema-test.c++
+276
-0
schema.c++
c++/src/capnproto/schema.c++
+264
-0
schema.h
c++/src/capnproto/schema.h
+410
-0
test.capnp
c++/src/capnproto/test.capnp
+12
-0
CxxGenerator.hs
compiler/src/CxxGenerator.hs
+45
-1
c++-source.mustache
compiler/src/c++-source.mustache
+6
-1
No files found.
c++/src/capnproto/blob-test.c++
View file @
e7b9e4da
...
...
@@ -78,5 +78,42 @@ TEST(Blob, Data) {
EXPECT_EQ
(
Data
::
Reader
(
"az"
),
builder
.
slice
(
1
,
3
));
}
TEST
(
Blob
,
Compare
)
{
EXPECT_TRUE
(
Data
::
Reader
(
"foo"
)
==
Data
::
Reader
(
"foo"
));
EXPECT_FALSE
(
Data
::
Reader
(
"foo"
)
!=
Data
::
Reader
(
"foo"
));
EXPECT_TRUE
(
Data
::
Reader
(
"foo"
)
<=
Data
::
Reader
(
"foo"
));
EXPECT_TRUE
(
Data
::
Reader
(
"foo"
)
>=
Data
::
Reader
(
"foo"
));
EXPECT_FALSE
(
Data
::
Reader
(
"foo"
)
<
Data
::
Reader
(
"foo"
));
EXPECT_FALSE
(
Data
::
Reader
(
"foo"
)
>
Data
::
Reader
(
"foo"
));
EXPECT_FALSE
(
Data
::
Reader
(
"foo"
)
==
Data
::
Reader
(
"bar"
));
EXPECT_TRUE
(
Data
::
Reader
(
"foo"
)
!=
Data
::
Reader
(
"bar"
));
EXPECT_FALSE
(
Data
::
Reader
(
"foo"
)
<=
Data
::
Reader
(
"bar"
));
EXPECT_TRUE
(
Data
::
Reader
(
"foo"
)
>=
Data
::
Reader
(
"bar"
));
EXPECT_FALSE
(
Data
::
Reader
(
"foo"
)
<
Data
::
Reader
(
"bar"
));
EXPECT_TRUE
(
Data
::
Reader
(
"foo"
)
>
Data
::
Reader
(
"bar"
));
EXPECT_FALSE
(
Data
::
Reader
(
"bar"
)
==
Data
::
Reader
(
"foo"
));
EXPECT_TRUE
(
Data
::
Reader
(
"bar"
)
!=
Data
::
Reader
(
"foo"
));
EXPECT_TRUE
(
Data
::
Reader
(
"bar"
)
<=
Data
::
Reader
(
"foo"
));
EXPECT_FALSE
(
Data
::
Reader
(
"bar"
)
>=
Data
::
Reader
(
"foo"
));
EXPECT_TRUE
(
Data
::
Reader
(
"bar"
)
<
Data
::
Reader
(
"foo"
));
EXPECT_FALSE
(
Data
::
Reader
(
"bar"
)
>
Data
::
Reader
(
"foo"
));
EXPECT_FALSE
(
Data
::
Reader
(
"foobar"
)
==
Data
::
Reader
(
"foo"
));
EXPECT_TRUE
(
Data
::
Reader
(
"foobar"
)
!=
Data
::
Reader
(
"foo"
));
EXPECT_FALSE
(
Data
::
Reader
(
"foobar"
)
<=
Data
::
Reader
(
"foo"
));
EXPECT_TRUE
(
Data
::
Reader
(
"foobar"
)
>=
Data
::
Reader
(
"foo"
));
EXPECT_FALSE
(
Data
::
Reader
(
"foobar"
)
<
Data
::
Reader
(
"foo"
));
EXPECT_TRUE
(
Data
::
Reader
(
"foobar"
)
>
Data
::
Reader
(
"foo"
));
EXPECT_FALSE
(
Data
::
Reader
(
"foo"
)
==
Data
::
Reader
(
"foobar"
));
EXPECT_TRUE
(
Data
::
Reader
(
"foo"
)
!=
Data
::
Reader
(
"foobar"
));
EXPECT_TRUE
(
Data
::
Reader
(
"foo"
)
<=
Data
::
Reader
(
"foobar"
));
EXPECT_FALSE
(
Data
::
Reader
(
"foo"
)
>=
Data
::
Reader
(
"foobar"
));
EXPECT_TRUE
(
Data
::
Reader
(
"foo"
)
<
Data
::
Reader
(
"foobar"
));
EXPECT_FALSE
(
Data
::
Reader
(
"foo"
)
>
Data
::
Reader
(
"foobar"
));
}
}
// namespace
}
// namespace capnproto
c++/src/capnproto/blob.h
View file @
e7b9e4da
...
...
@@ -114,12 +114,8 @@ public:
typedef
Text
Reads
;
inline
Reader
()
:
Data
::
Reader
(
""
,
0
)
{}
inline
Reader
(
const
char
*
text
)
:
Data
::
Reader
(
text
,
strlen
(
text
))
{
CAPNPROTO_INLINE_DPRECOND
(
text
[
size
()]
==
'\0'
,
"Text must be NUL-terminated."
);
}
inline
Reader
(
char
*
text
)
:
Data
::
Reader
(
text
,
strlen
(
text
))
{
CAPNPROTO_INLINE_DPRECOND
(
text
[
size
()]
==
'\0'
,
"Text must be NUL-terminated."
);
}
inline
Reader
(
const
char
*
text
)
:
Data
::
Reader
(
text
,
strlen
(
text
))
{}
inline
Reader
(
char
*
text
)
:
Data
::
Reader
(
text
,
strlen
(
text
))
{}
inline
Reader
(
const
char
*
text
,
uint
size
)
:
Data
::
Reader
(
text
,
size
)
{
CAPNPROTO_INLINE_DPRECOND
(
text
[
size
]
==
'\0'
,
"Text must be NUL-terminated."
);
}
...
...
c++/src/capnproto/generated-header-support.h
View file @
e7b9e4da
...
...
@@ -121,8 +121,29 @@ struct PointerHelpers<TrustedMessage> {
#endif
struct
RawSchema
{
// The generated code defines a constant RawSchema for every compiled declaration.
//
// This is an internal structure which could change in the future.
const
word
*
encodedNode
;
// Encoded SchemaNode, readable via readMessageTrusted<schema::Node>(encodedNode).
const
RawSchema
*
const
*
dependencies
;
// Pointers to other types on which this one depends, sorted by ID.
// TODO(someday): Make this a hashtable.
struct
MemberInfo
{
uint16_t
unionIndex
;
// 0 = not in a union, >0 = parent union's index + 1
uint16_t
index
;
// index of the member
};
const
MemberInfo
*
membersByName
;
// Indexes of members sorted by name. Used to implement name lookup.
// TODO(someday): Make this a hashtable.
uint32_t
dependencyCount
;
uint32_t
memberCount
;
// Sizes of above tables.
};
template
<
typename
T
>
...
...
c++/src/capnproto/message.h
View file @
e7b9e4da
...
...
@@ -179,14 +179,14 @@ static typename RootType::Reader readMessageTrusted(const word* data);
// To create a trusted message, build a message using a MallocAllocator whose preferred segment
// size is larger than the message size. This guarantees that the message will be allocated as a
// single segment, meaning getSegmentsForOutput() returns a single word array. That word array
// is your message; you may pass a pointer to its first word into readTrusted() to read the
// is your message; you may pass a pointer to its first word into read
Message
Trusted() to read the
// message.
//
// This can be particularly handy for embedding messages in generated code: you can
// embed the raw bytes (using AlignedData) then make a Reader for it using this. This is the way
// default values are embedded in code generated by the Cap'n Proto compiler. E.g., if you have
// a message MyMessage, you can read its default value like so:
// MyMessage::Reader reader = Message<MyMessage>::
Read
Trusted(MyMessage::DEFAULT.words);
// MyMessage::Reader reader = Message<MyMessage>::
readMessage
Trusted(MyMessage::DEFAULT.words);
template
<
typename
Type
>
static
typename
Type
::
Reader
defaultValue
();
...
...
c++/src/capnproto/schema-test.c++
0 → 100644
View file @
e7b9e4da
// 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.
// 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 "schema.h"
#include <gtest/gtest.h>
#include "test-util.h"
namespace
capnproto
{
namespace
internal
{
namespace
{
TEST
(
Schema
,
Structs
)
{
StructSchema
schema
=
Schema
::
from
<
TestAllTypes
>
();
EXPECT_EQ
(
typeId
<
TestAllTypes
>
(),
schema
.
getProto
().
getId
());
EXPECT_TRUE
(
schema
.
getDependency
(
typeId
<
TestEnum
>
())
==
Schema
::
from
<
TestEnum
>
());
EXPECT_TRUE
(
schema
.
getDependency
(
typeId
<
TestEnum
>
())
!=
schema
);
EXPECT_TRUE
(
schema
.
getDependency
(
typeId
<
TestAllTypes
>
())
==
Schema
::
from
<
TestAllTypes
>
());
EXPECT_TRUE
(
schema
.
getDependency
(
typeId
<
TestAllTypes
>
())
==
schema
);
EXPECT_ANY_THROW
(
schema
.
getDependency
(
typeId
<
TestDefaults
>
()));
EXPECT_TRUE
(
schema
.
asStruct
()
==
schema
);
EXPECT_ANY_THROW
(
schema
.
asEnum
());
EXPECT_ANY_THROW
(
schema
.
asInterface
());
ASSERT_EQ
(
schema
.
members
().
size
(),
schema
.
getProto
().
getBody
().
getStructNode
().
getMembers
().
size
());
StructSchema
::
Member
member
=
schema
.
members
()[
0
];
EXPECT_EQ
(
"voidField"
,
member
.
getProto
().
getName
());
EXPECT_TRUE
(
member
.
getContainingStruct
()
==
schema
);
EXPECT_TRUE
(
member
.
getContainingUnion
()
==
nullptr
);
EXPECT_ANY_THROW
(
member
.
asUnion
());
Maybe
<
StructSchema
::
Member
>
lookup
=
schema
.
findMemberByName
(
"voidField"
);
ASSERT_TRUE
(
lookup
!=
nullptr
);
EXPECT_TRUE
(
*
lookup
==
member
);
EXPECT_TRUE
(
*
lookup
!=
schema
.
members
()[
1
]);
EXPECT_TRUE
(
schema
.
findMemberByName
(
"noSuchField"
)
==
nullptr
);
EXPECT_TRUE
(
schema
.
findMemberByName
(
"int32Field"
)
!=
nullptr
);
EXPECT_TRUE
(
schema
.
findMemberByName
(
"float32List"
)
!=
nullptr
);
EXPECT_TRUE
(
schema
.
findMemberByName
(
"dataList"
)
!=
nullptr
);
EXPECT_TRUE
(
schema
.
findMemberByName
(
"textField"
)
!=
nullptr
);
EXPECT_TRUE
(
schema
.
findMemberByName
(
"structField"
)
!=
nullptr
);
}
TEST
(
Schema
,
FieldLookupOutOfOrder
)
{
// Tests that name lookup works correctly when the fields are defined out-of-order in the schema
// file.
auto
schema
=
Schema
::
from
<
test
::
TestOutOfOrder
>
().
asStruct
();
EXPECT_EQ
(
"qux"
,
schema
.
members
()[
0
].
getProto
().
getName
());
EXPECT_EQ
(
"grault"
,
schema
.
members
()[
1
].
getProto
().
getName
());
EXPECT_EQ
(
"bar"
,
schema
.
members
()[
2
].
getProto
().
getName
());
EXPECT_EQ
(
"foo"
,
schema
.
members
()[
3
].
getProto
().
getName
());
EXPECT_EQ
(
"corge"
,
schema
.
members
()[
4
].
getProto
().
getName
());
EXPECT_EQ
(
"waldo"
,
schema
.
members
()[
5
].
getProto
().
getName
());
EXPECT_EQ
(
"quux"
,
schema
.
members
()[
6
].
getProto
().
getName
());
EXPECT_EQ
(
"garply"
,
schema
.
members
()[
7
].
getProto
().
getName
());
EXPECT_EQ
(
"baz"
,
schema
.
members
()[
8
].
getProto
().
getName
());
EXPECT_EQ
(
3
,
schema
.
findMemberByName
(
"foo"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
2
,
schema
.
findMemberByName
(
"bar"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
8
,
schema
.
findMemberByName
(
"baz"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
0
,
schema
.
findMemberByName
(
"qux"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
6
,
schema
.
findMemberByName
(
"quux"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
4
,
schema
.
findMemberByName
(
"corge"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
1
,
schema
.
findMemberByName
(
"grault"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
7
,
schema
.
findMemberByName
(
"garply"
)
->
getProto
().
getOrdinal
());
EXPECT_EQ
(
5
,
schema
.
findMemberByName
(
"waldo"
)
->
getProto
().
getOrdinal
());
}
TEST
(
Schema
,
Unions
)
{
auto
schema
=
Schema
::
from
<
TestUnion
>
().
asStruct
();
EXPECT_TRUE
(
schema
.
findMemberByName
(
"bit0"
)
!=
nullptr
);
EXPECT_TRUE
(
schema
.
findMemberByName
(
"u1f0s8"
)
==
nullptr
);
auto
maybeUnion1
=
schema
.
findMemberByName
(
"union1"
);
ASSERT_TRUE
(
maybeUnion1
!=
nullptr
);
auto
union1
=
maybeUnion1
->
asUnion
();
EXPECT_TRUE
(
union1
.
findMemberByName
(
"bin0"
)
==
nullptr
);
EXPECT_TRUE
(
union1
.
getContainingUnion
()
==
nullptr
);
auto
maybeU1f0s8
=
union1
.
findMemberByName
(
"u1f0s8"
);
ASSERT_TRUE
(
maybeU1f0s8
!=
nullptr
);
auto
u1f0s8
=
*
maybeU1f0s8
;
EXPECT_EQ
(
"u1f0s8"
,
u1f0s8
.
getProto
().
getName
());
EXPECT_TRUE
(
u1f0s8
.
getContainingStruct
()
==
schema
);
EXPECT_TRUE
(
*
u1f0s8
.
getContainingUnion
()
==
union1
);
EXPECT_TRUE
(
union1
.
findMemberByName
(
"u1f1s8"
)
!=
nullptr
);
EXPECT_TRUE
(
union1
.
findMemberByName
(
"u1f0s32"
)
!=
nullptr
);
EXPECT_TRUE
(
union1
.
findMemberByName
(
"u1f0sp"
)
!=
nullptr
);
EXPECT_TRUE
(
union1
.
findMemberByName
(
"u1f1s1"
)
!=
nullptr
);
EXPECT_TRUE
(
union1
.
findMemberByName
(
"u0f0s1"
)
==
nullptr
);
EXPECT_TRUE
(
union1
.
findMemberByName
(
"u2f0s8"
)
==
nullptr
);
EXPECT_TRUE
(
union1
.
findMemberByName
(
"noSuchField"
)
==
nullptr
);
}
TEST
(
Schema
,
Enums
)
{
EnumSchema
schema
=
Schema
::
from
<
TestEnum
>
();
EXPECT_EQ
(
typeId
<
TestEnum
>
(),
schema
.
getProto
().
getId
());
EXPECT_ANY_THROW
(
schema
.
getDependency
(
typeId
<
TestAllTypes
>
()));
EXPECT_ANY_THROW
(
schema
.
getDependency
(
typeId
<
TestEnum
>
()));
EXPECT_ANY_THROW
(
schema
.
asStruct
());
EXPECT_ANY_THROW
(
schema
.
asInterface
());
EXPECT_TRUE
(
schema
.
asEnum
()
==
schema
);
ASSERT_EQ
(
schema
.
enumerants
().
size
(),
schema
.
getProto
().
getBody
().
getEnumNode
().
getEnumerants
().
size
());
EnumSchema
::
Enumerant
enumerant
=
schema
.
enumerants
()[
0
];
EXPECT_EQ
(
"foo"
,
enumerant
.
getProto
().
getName
());
EXPECT_TRUE
(
enumerant
.
getContainingEnum
()
==
schema
);
Maybe
<
EnumSchema
::
Enumerant
>
lookup
=
schema
.
findEnumerantByName
(
"foo"
);
ASSERT_TRUE
(
lookup
!=
nullptr
);
EXPECT_TRUE
(
*
lookup
==
enumerant
);
EXPECT_TRUE
(
*
lookup
!=
schema
.
enumerants
()[
1
]);
EXPECT_TRUE
(
schema
.
findEnumerantByName
(
"noSuchEnumerant"
)
==
nullptr
);
EXPECT_TRUE
(
schema
.
findEnumerantByName
(
"bar"
)
!=
nullptr
);
EXPECT_TRUE
(
schema
.
findEnumerantByName
(
"qux"
)
!=
nullptr
);
EXPECT_TRUE
(
schema
.
findEnumerantByName
(
"corge"
)
!=
nullptr
);
EXPECT_TRUE
(
schema
.
findEnumerantByName
(
"grault"
)
!=
nullptr
);
}
// TODO(someday): Test interface schemas when interfaces are implemented.
TEST
(
Schema
,
Lists
)
{
EXPECT_EQ
(
schema
::
Type
::
Body
::
VOID_TYPE
,
Schema
::
from
<
List
<
Void
>>
().
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
BOOL_TYPE
,
Schema
::
from
<
List
<
bool
>>
().
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
INT8_TYPE
,
Schema
::
from
<
List
<
int8_t
>>
().
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
INT16_TYPE
,
Schema
::
from
<
List
<
int16_t
>>
().
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
INT32_TYPE
,
Schema
::
from
<
List
<
int32_t
>>
().
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
INT64_TYPE
,
Schema
::
from
<
List
<
int64_t
>>
().
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
UINT8_TYPE
,
Schema
::
from
<
List
<
uint8_t
>>
().
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
UINT16_TYPE
,
Schema
::
from
<
List
<
uint16_t
>>
().
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
UINT32_TYPE
,
Schema
::
from
<
List
<
uint32_t
>>
().
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
UINT64_TYPE
,
Schema
::
from
<
List
<
uint64_t
>>
().
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
FLOAT32_TYPE
,
Schema
::
from
<
List
<
float
>>
().
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
FLOAT64_TYPE
,
Schema
::
from
<
List
<
double
>>
().
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
TEXT_TYPE
,
Schema
::
from
<
List
<
Text
>>
().
whichElementType
());
EXPECT_EQ
(
schema
::
Type
::
Body
::
DATA_TYPE
,
Schema
::
from
<
List
<
Data
>>
().
whichElementType
());
EXPECT_ANY_THROW
(
Schema
::
from
<
List
<
uint16_t
>>
().
getStructElementType
());
EXPECT_ANY_THROW
(
Schema
::
from
<
List
<
uint16_t
>>
().
getEnumElementType
());
EXPECT_ANY_THROW
(
Schema
::
from
<
List
<
uint16_t
>>
().
getInterfaceElementType
());
EXPECT_ANY_THROW
(
Schema
::
from
<
List
<
uint16_t
>>
().
getListElementType
());
{
ListSchema
schema
=
Schema
::
from
<
List
<
TestAllTypes
>>
();
EXPECT_EQ
(
schema
::
Type
::
Body
::
STRUCT_TYPE
,
schema
.
whichElementType
());
EXPECT_TRUE
(
schema
.
getStructElementType
()
==
Schema
::
from
<
TestAllTypes
>
());
EXPECT_ANY_THROW
(
schema
.
getEnumElementType
());
EXPECT_ANY_THROW
(
schema
.
getInterfaceElementType
());
EXPECT_ANY_THROW
(
schema
.
getListElementType
());
}
{
ListSchema
schema
=
Schema
::
from
<
List
<
TestEnum
>>
();
EXPECT_EQ
(
schema
::
Type
::
Body
::
ENUM_TYPE
,
schema
.
whichElementType
());
EXPECT_TRUE
(
schema
.
getEnumElementType
()
==
Schema
::
from
<
TestEnum
>
());
EXPECT_ANY_THROW
(
schema
.
getStructElementType
());
EXPECT_ANY_THROW
(
schema
.
getInterfaceElementType
());
EXPECT_ANY_THROW
(
schema
.
getListElementType
());
}
// TODO(someday): Test interfaces.
{
ListSchema
schema
=
Schema
::
from
<
List
<
List
<
int32_t
>>>
();
EXPECT_EQ
(
schema
::
Type
::
Body
::
LIST_TYPE
,
schema
.
whichElementType
());
EXPECT_ANY_THROW
(
schema
.
getStructElementType
());
EXPECT_ANY_THROW
(
schema
.
getEnumElementType
());
EXPECT_ANY_THROW
(
schema
.
getInterfaceElementType
());
ListSchema
inner
=
schema
.
getListElementType
();
EXPECT_EQ
(
schema
::
Type
::
Body
::
INT32_TYPE
,
inner
.
whichElementType
());
}
{
ListSchema
schema
=
Schema
::
from
<
List
<
List
<
TestAllTypes
>>>
();
EXPECT_EQ
(
schema
::
Type
::
Body
::
LIST_TYPE
,
schema
.
whichElementType
());
EXPECT_ANY_THROW
(
schema
.
getStructElementType
());
EXPECT_ANY_THROW
(
schema
.
getEnumElementType
());
EXPECT_ANY_THROW
(
schema
.
getInterfaceElementType
());
ListSchema
inner
=
schema
.
getListElementType
();
EXPECT_EQ
(
schema
::
Type
::
Body
::
STRUCT_TYPE
,
inner
.
whichElementType
());
EXPECT_TRUE
(
inner
.
getStructElementType
()
==
Schema
::
from
<
TestAllTypes
>
());
}
{
ListSchema
schema
=
Schema
::
from
<
List
<
List
<
TestEnum
>>>
();
EXPECT_EQ
(
schema
::
Type
::
Body
::
LIST_TYPE
,
schema
.
whichElementType
());
EXPECT_ANY_THROW
(
schema
.
getStructElementType
());
EXPECT_ANY_THROW
(
schema
.
getEnumElementType
());
EXPECT_ANY_THROW
(
schema
.
getInterfaceElementType
());
ListSchema
inner
=
schema
.
getListElementType
();
EXPECT_EQ
(
schema
::
Type
::
Body
::
ENUM_TYPE
,
inner
.
whichElementType
());
EXPECT_TRUE
(
inner
.
getEnumElementType
()
==
Schema
::
from
<
TestEnum
>
());
}
{
auto
context
=
Schema
::
from
<
TestAllTypes
>
();
auto
type
=
context
.
findMemberByName
(
"enumList"
)
->
getProto
().
getBody
().
getFieldMember
().
getType
();
ListSchema
schema
=
ListSchema
::
of
(
type
.
getBody
().
getListType
(),
context
);
EXPECT_EQ
(
schema
::
Type
::
Body
::
ENUM_TYPE
,
schema
.
whichElementType
());
EXPECT_TRUE
(
schema
.
getEnumElementType
()
==
Schema
::
from
<
TestEnum
>
());
EXPECT_ANY_THROW
(
schema
.
getStructElementType
());
EXPECT_ANY_THROW
(
schema
.
getInterfaceElementType
());
EXPECT_ANY_THROW
(
schema
.
getListElementType
());
}
}
}
// namespace
}
// namespace internal
}
// namespace capnproto
c++/src/capnproto/schema.c++
0 → 100644
View file @
e7b9e4da
// 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.
#define CAPNPROTO_PRIVATE
#include "schema.h"
#include "message.h"
#include "logging.h"
namespace
capnproto
{
schema
::
Node
::
Reader
Schema
::
getProto
()
const
{
return
readMessageTrusted
<
schema
::
Node
>
(
raw
->
encodedNode
);
}
Schema
Schema
::
getDependency
(
uint64_t
id
)
const
{
uint
lower
=
0
;
uint
upper
=
raw
->
dependencyCount
;
while
(
lower
<
upper
)
{
uint
mid
=
(
lower
+
upper
)
/
2
;
Schema
candidate
(
raw
->
dependencies
[
mid
]);
uint64_t
candidateId
=
candidate
.
getProto
().
getId
();
if
(
candidateId
==
id
)
{
return
candidate
;
}
else
if
(
candidateId
<
id
)
{
lower
=
mid
+
1
;
}
else
{
upper
=
mid
;
}
}
FAIL_PRECOND
(
"Requested ID not found in dependency table."
,
id
);
return
Schema
();
}
StructSchema
Schema
::
asStruct
()
const
{
PRECOND
(
getProto
().
getBody
().
which
()
==
schema
::
Node
::
Body
::
STRUCT_NODE
,
"Tried to use non-struct schema as a struct."
,
getProto
().
getDisplayName
());
return
StructSchema
(
raw
);
}
EnumSchema
Schema
::
asEnum
()
const
{
PRECOND
(
getProto
().
getBody
().
which
()
==
schema
::
Node
::
Body
::
ENUM_NODE
,
"Tried to use non-enum schema as an enum."
,
getProto
().
getDisplayName
());
return
EnumSchema
(
raw
);
}
InterfaceSchema
Schema
::
asInterface
()
const
{
PRECOND
(
getProto
().
getBody
().
which
()
==
schema
::
Node
::
Body
::
INTERFACE_NODE
,
"Tried to use non-interface schema as an interface."
,
getProto
().
getDisplayName
());
return
InterfaceSchema
(
raw
);
}
// =======================================================================================
namespace
{
template
<
typename
List
>
auto
findSchemaMemberByName
(
const
internal
::
RawSchema
*
raw
,
Text
::
Reader
name
,
uint
unionIndex
,
List
&&
list
)
->
Maybe
<
RemoveReference
<
decltype
(
list
[
0
])
>>
{
uint
lower
=
0
;
uint
upper
=
raw
->
memberCount
;
while
(
lower
<
upper
)
{
uint
mid
=
(
lower
+
upper
)
/
2
;
const
internal
::
RawSchema
::
MemberInfo
&
member
=
raw
->
membersByName
[
mid
];
if
(
member
.
unionIndex
==
unionIndex
)
{
auto
candidate
=
list
[
member
.
index
];
Text
::
Reader
candidateName
=
candidate
.
getProto
().
getName
();
if
(
candidateName
==
name
)
{
return
candidate
;
}
else
if
(
candidateName
<
name
)
{
lower
=
mid
+
1
;
}
else
{
upper
=
mid
;
}
}
else
if
(
member
.
unionIndex
<
unionIndex
)
{
lower
=
mid
+
1
;
}
else
{
upper
=
mid
;
}
}
return
nullptr
;
}
}
// namespace
StructSchema
::
MemberList
StructSchema
::
members
()
const
{
return
MemberList
(
*
this
,
0
,
getProto
().
getBody
().
getStructNode
().
getMembers
());
}
Maybe
<
StructSchema
::
Member
>
StructSchema
::
findMemberByName
(
Text
::
Reader
name
)
const
{
return
findSchemaMemberByName
(
raw
,
name
,
0
,
members
());
}
Maybe
<
StructSchema
::
Union
>
StructSchema
::
Member
::
getContainingUnion
()
const
{
if
(
unionIndex
==
0
)
return
nullptr
;
return
parent
.
members
()[
unionIndex
-
1
].
asUnion
();
}
StructSchema
::
Union
StructSchema
::
Member
::
asUnion
()
const
{
PRECOND
(
proto
.
getBody
().
which
()
==
schema
::
StructNode
::
Member
::
Body
::
UNION_MEMBER
,
"Tried to use non-union struct member as a union."
,
parent
.
getProto
().
getDisplayName
(),
proto
.
getName
());
return
Union
(
*
this
);
}
StructSchema
::
MemberList
StructSchema
::
Union
::
members
()
const
{
return
MemberList
(
parent
,
index
+
1
,
proto
.
getBody
().
getUnionMember
().
getMembers
());
}
Maybe
<
StructSchema
::
Member
>
StructSchema
::
Union
::
findMemberByName
(
Text
::
Reader
name
)
const
{
return
findSchemaMemberByName
(
parent
.
raw
,
name
,
index
+
1
,
members
());
}
// -------------------------------------------------------------------
EnumSchema
::
EnumerantList
EnumSchema
::
enumerants
()
const
{
return
EnumerantList
(
*
this
,
getProto
().
getBody
().
getEnumNode
().
getEnumerants
());
}
Maybe
<
EnumSchema
::
Enumerant
>
EnumSchema
::
findEnumerantByName
(
Text
::
Reader
name
)
const
{
return
findSchemaMemberByName
(
raw
,
name
,
0
,
enumerants
());
}
// -------------------------------------------------------------------
InterfaceSchema
::
MethodList
InterfaceSchema
::
methods
()
const
{
return
MethodList
(
*
this
,
getProto
().
getBody
().
getInterfaceNode
().
getMethods
());
}
Maybe
<
InterfaceSchema
::
Method
>
InterfaceSchema
::
findMethodByName
(
Text
::
Reader
name
)
const
{
return
findSchemaMemberByName
(
raw
,
name
,
0
,
methods
());
}
// =======================================================================================
ListSchema
ListSchema
::
of
(
schema
::
Type
::
Body
::
Which
primitiveType
)
{
switch
(
primitiveType
)
{
case
schema
:
:
Type
::
Body
::
VOID_TYPE
:
case
schema
:
:
Type
::
Body
::
BOOL_TYPE
:
case
schema
:
:
Type
::
Body
::
INT8_TYPE
:
case
schema
:
:
Type
::
Body
::
INT16_TYPE
:
case
schema
:
:
Type
::
Body
::
INT32_TYPE
:
case
schema
:
:
Type
::
Body
::
INT64_TYPE
:
case
schema
:
:
Type
::
Body
::
UINT8_TYPE
:
case
schema
:
:
Type
::
Body
::
UINT16_TYPE
:
case
schema
:
:
Type
::
Body
::
UINT32_TYPE
:
case
schema
:
:
Type
::
Body
::
UINT64_TYPE
:
case
schema
:
:
Type
::
Body
::
FLOAT32_TYPE
:
case
schema
:
:
Type
::
Body
::
FLOAT64_TYPE
:
case
schema
:
:
Type
::
Body
::
TEXT_TYPE
:
case
schema
:
:
Type
::
Body
::
DATA_TYPE
:
break
;
case
schema
:
:
Type
::
Body
::
STRUCT_TYPE
:
case
schema
:
:
Type
::
Body
::
ENUM_TYPE
:
case
schema
:
:
Type
::
Body
::
INTERFACE_TYPE
:
case
schema
:
:
Type
::
Body
::
LIST_TYPE
:
FAIL_PRECOND
(
"Must use one of the other ListSchema::of() overloads for complex types."
);
break
;
case
schema
:
:
Type
::
Body
::
OBJECT_TYPE
:
FAIL_PRECOND
(
"List(Object) not supported."
);
break
;
}
return
ListSchema
(
primitiveType
);
}
ListSchema
ListSchema
::
of
(
schema
::
Type
::
Reader
elementType
,
Schema
context
)
{
auto
body
=
elementType
.
getBody
();
switch
(
body
.
which
())
{
case
schema
:
:
Type
::
Body
::
VOID_TYPE
:
case
schema
:
:
Type
::
Body
::
BOOL_TYPE
:
case
schema
:
:
Type
::
Body
::
INT8_TYPE
:
case
schema
:
:
Type
::
Body
::
INT16_TYPE
:
case
schema
:
:
Type
::
Body
::
INT32_TYPE
:
case
schema
:
:
Type
::
Body
::
INT64_TYPE
:
case
schema
:
:
Type
::
Body
::
UINT8_TYPE
:
case
schema
:
:
Type
::
Body
::
UINT16_TYPE
:
case
schema
:
:
Type
::
Body
::
UINT32_TYPE
:
case
schema
:
:
Type
::
Body
::
UINT64_TYPE
:
case
schema
:
:
Type
::
Body
::
FLOAT32_TYPE
:
case
schema
:
:
Type
::
Body
::
FLOAT64_TYPE
:
case
schema
:
:
Type
::
Body
::
TEXT_TYPE
:
case
schema
:
:
Type
::
Body
::
DATA_TYPE
:
return
of
(
body
.
which
());
case
schema
:
:
Type
::
Body
::
STRUCT_TYPE
:
return
of
(
context
.
getDependency
(
body
.
getStructType
()).
asStruct
());
case
schema
:
:
Type
::
Body
::
ENUM_TYPE
:
return
of
(
context
.
getDependency
(
body
.
getEnumType
()).
asEnum
());
case
schema
:
:
Type
::
Body
::
INTERFACE_TYPE
:
return
of
(
context
.
getDependency
(
body
.
getInterfaceType
()).
asInterface
());
case
schema
:
:
Type
::
Body
::
LIST_TYPE
:
return
of
(
of
(
body
.
getListType
(),
context
));
case
schema
:
:
Type
::
Body
::
OBJECT_TYPE
:
FAIL_PRECOND
(
"List(Object) not supported."
);
return
ListSchema
();
}
FAIL_CHECK
(
"missing switch case"
);
return
ListSchema
();
}
StructSchema
ListSchema
::
getStructElementType
()
const
{
PRECOND
(
nestingDepth
==
0
&&
elementType
==
schema
::
Type
::
Body
::
STRUCT_TYPE
,
"ListSchema::getStructElementType(): The elements are not structs."
);
return
elementSchema
.
asStruct
();
}
EnumSchema
ListSchema
::
getEnumElementType
()
const
{
PRECOND
(
nestingDepth
==
0
&&
elementType
==
schema
::
Type
::
Body
::
ENUM_TYPE
,
"ListSchema::getEnumElementType(): The elements are not enums."
);
return
elementSchema
.
asEnum
();
}
InterfaceSchema
ListSchema
::
getInterfaceElementType
()
const
{
PRECOND
(
nestingDepth
==
0
&&
elementType
==
schema
::
Type
::
Body
::
INTERFACE_TYPE
,
"ListSchema::getInterfaceElementType(): The elements are not interfaces."
);
return
elementSchema
.
asInterface
();
}
ListSchema
ListSchema
::
getListElementType
()
const
{
PRECOND
(
nestingDepth
>
0
,
"ListSchema::getListElementType(): The elements are not lists."
);
return
ListSchema
(
elementType
,
nestingDepth
-
1
,
elementSchema
);
}
}
// namespace capnproto
c++/src/capnproto/schema.h
0 → 100644
View file @
e7b9e4da
// 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.
#ifndef CAPNPROTO_SCHEMA_H_
#define CAPNPROTO_SCHEMA_H_
#include "schema.capnp.h"
namespace
capnproto
{
class
Schema
;
class
StructSchema
;
class
EnumSchema
;
class
InterfaceSchema
;
class
ListSchema
;
template
<
typename
T
,
Kind
k
=
kind
<
T
>
()
>
struct
SchemaType_
{
typedef
Schema
Type
;
};
template
<
typename
T
>
struct
SchemaType_
<
T
,
Kind
::
PRIMITIVE
>
{
typedef
schema
::
Type
::
Body
::
Which
Type
;
};
template
<
typename
T
>
struct
SchemaType_
<
T
,
Kind
::
BLOB
>
{
typedef
schema
::
Type
::
Body
::
Which
Type
;
};
template
<
typename
T
>
struct
SchemaType_
<
T
,
Kind
::
ENUM
>
{
typedef
EnumSchema
Type
;
};
template
<
typename
T
>
struct
SchemaType_
<
T
,
Kind
::
STRUCT
>
{
typedef
StructSchema
Type
;
};
template
<
typename
T
>
struct
SchemaType_
<
T
,
Kind
::
INTERFACE
>
{
typedef
InterfaceSchema
Type
;
};
template
<
typename
T
>
struct
SchemaType_
<
T
,
Kind
::
LIST
>
{
typedef
ListSchema
Type
;
};
template
<
typename
T
>
using
SchemaType
=
typename
SchemaType_
<
T
>::
Type
;
// SchemaType<T> is the type of T's schema, e.g. StructSchema if T is a struct.
class
Schema
{
// Convenience wrapper around capnproto::schema::Node.
public
:
inline
Schema
()
:
raw
(
nullptr
)
{}
template
<
typename
T
>
static
inline
SchemaType
<
T
>
from
()
{
return
SchemaType
<
T
>::
template
fromImpl
<
T
>
();
}
// Get the Schema for a particular compiled-in type.
schema
::
Node
::
Reader
getProto
()
const
;
Schema
getDependency
(
uint64_t
id
)
const
;
// Gets the Schema for one of this Schema's dependencies. For example, if this Schema is for a
// struct, you could look up the schema for one of its fields' types. Throws an exception if this
// schema doesn't actually depend on the given id. Note that annotation declarations are not
// considered dependencies for this purpose.
StructSchema
asStruct
()
const
;
EnumSchema
asEnum
()
const
;
InterfaceSchema
asInterface
()
const
;
// Cast the Schema to a specific type. Throws an exception if the type doesn't match.
inline
bool
operator
==
(
const
Schema
&
other
)
const
{
return
raw
==
other
.
raw
;
}
inline
bool
operator
!=
(
const
Schema
&
other
)
const
{
return
raw
!=
other
.
raw
;
}
// Determine whether two Schemas are wrapping the exact same underlying data, by identity. If
// you want to check if two Schemas represent the same type (but possibly different versions of
// it), compare their IDs instead.
private
:
const
internal
::
RawSchema
*
raw
;
inline
explicit
Schema
(
const
internal
::
RawSchema
*
raw
)
:
raw
(
raw
)
{}
template
<
typename
T
>
static
inline
Schema
fromImpl
()
{
return
Schema
(
&
internal
::
rawSchema
<
T
>
());
}
friend
class
StructSchema
;
friend
class
EnumSchema
;
friend
class
InterfaceSchema
;
};
// -------------------------------------------------------------------
class
StructSchema
:
public
Schema
{
public
:
StructSchema
()
=
default
;
class
Member
;
class
Union
;
class
MemberList
;
MemberList
members
()
const
;
Maybe
<
Member
>
findMemberByName
(
Text
::
Reader
name
)
const
;
private
:
StructSchema
(
const
internal
::
RawSchema
*
raw
)
:
Schema
(
raw
)
{}
template
<
typename
T
>
static
inline
StructSchema
fromImpl
()
{
return
StructSchema
(
&
internal
::
rawSchema
<
T
>
());
}
friend
class
Schema
;
};
class
StructSchema
::
Member
{
public
:
Member
()
=
default
;
inline
schema
::
StructNode
::
Member
::
Reader
getProto
()
const
{
return
proto
;
}
inline
StructSchema
getContainingStruct
()
const
{
return
parent
;
}
inline
uint
getIndex
()
const
{
return
index
;
}
// Get the index of this member within the containing struct or union.
Maybe
<
Union
>
getContainingUnion
()
const
;
// If this a member of a union, gets the containing union schema.
Union
asUnion
()
const
;
// Cast the member to a Union. Throws an exception if not a union.
inline
bool
operator
==
(
const
Member
&
other
)
const
;
inline
bool
operator
!=
(
const
Member
&
other
)
const
{
return
!
(
*
this
==
other
);
}
private
:
StructSchema
parent
;
uint
unionIndex
;
// 0 = none, >0 = actual union index - 1
uint
index
;
mutable
schema
::
StructNode
::
Member
::
Reader
proto
;
// TODO(soon): Make all reader methods const and then remove this ugly use of "mutable".
inline
Member
(
StructSchema
parent
,
uint
unionIndex
,
uint
index
,
schema
::
StructNode
::
Member
::
Reader
proto
)
:
parent
(
parent
),
unionIndex
(
unionIndex
),
index
(
index
),
proto
(
proto
)
{}
friend
class
StructSchema
;
};
class
StructSchema
::
Union
:
public
Member
{
public
:
Union
()
=
default
;
MemberList
members
()
const
;
Maybe
<
Member
>
findMemberByName
(
Text
::
Reader
name
)
const
;
private
:
inline
Union
(
const
Member
&
base
)
:
Member
(
base
)
{}
friend
class
StructSchema
;
};
class
StructSchema
::
MemberList
{
public
:
inline
uint
size
()
const
{
return
list
.
size
();
}
inline
Member
operator
[](
uint
index
)
const
{
return
Member
(
parent
,
unionIndex
,
index
,
list
[
index
]);
}
typedef
internal
::
IndexingIterator
<
MemberList
,
Member
>
iterator
;
inline
iterator
begin
()
const
{
return
iterator
(
this
,
0
);
}
inline
iterator
end
()
const
{
return
iterator
(
this
,
size
());
}
private
:
StructSchema
parent
;
uint
unionIndex
;
List
<
schema
::
StructNode
::
Member
>::
Reader
list
;
inline
MemberList
(
StructSchema
parent
,
uint
unionIndex
,
List
<
schema
::
StructNode
::
Member
>::
Reader
list
)
:
parent
(
parent
),
unionIndex
(
unionIndex
),
list
(
list
)
{}
friend
class
StructSchema
;
};
// -------------------------------------------------------------------
class
EnumSchema
:
public
Schema
{
public
:
class
Enumerant
;
class
EnumerantList
;
EnumerantList
enumerants
()
const
;
Maybe
<
Enumerant
>
findEnumerantByName
(
Text
::
Reader
name
)
const
;
private
:
EnumSchema
(
const
internal
::
RawSchema
*
raw
)
:
Schema
(
raw
)
{}
template
<
typename
T
>
static
inline
EnumSchema
fromImpl
()
{
return
EnumSchema
(
&
internal
::
rawSchema
<
T
>
());
}
friend
class
Schema
;
};
class
EnumSchema
::
Enumerant
{
public
:
Enumerant
()
=
default
;
inline
schema
::
EnumNode
::
Enumerant
::
Reader
getProto
()
const
{
return
proto
;
}
inline
EnumSchema
getContainingEnum
()
{
return
parent
;
}
inline
uint16_t
getOrdinal
()
{
return
ordinal
;
}
inline
bool
operator
==
(
const
Enumerant
&
other
)
const
;
inline
bool
operator
!=
(
const
Enumerant
&
other
)
const
{
return
!
(
*
this
==
other
);
}
private
:
EnumSchema
parent
;
uint16_t
ordinal
;
mutable
schema
::
EnumNode
::
Enumerant
::
Reader
proto
;
// TODO(soon): Make all reader methods const and then remove this ugly use of "mutable".
inline
Enumerant
(
EnumSchema
parent
,
uint16_t
ordinal
,
schema
::
EnumNode
::
Enumerant
::
Reader
proto
)
:
parent
(
parent
),
ordinal
(
ordinal
),
proto
(
proto
)
{}
friend
class
EnumSchema
;
};
class
EnumSchema
::
EnumerantList
{
public
:
inline
uint
size
()
const
{
return
list
.
size
();
}
inline
Enumerant
operator
[](
uint
index
)
const
{
return
Enumerant
(
parent
,
index
,
list
[
index
]);
}
typedef
internal
::
IndexingIterator
<
EnumerantList
,
Enumerant
>
iterator
;
inline
iterator
begin
()
const
{
return
iterator
(
this
,
0
);
}
inline
iterator
end
()
const
{
return
iterator
(
this
,
size
());
}
private
:
EnumSchema
parent
;
List
<
schema
::
EnumNode
::
Enumerant
>::
Reader
list
;
inline
EnumerantList
(
EnumSchema
parent
,
List
<
schema
::
EnumNode
::
Enumerant
>::
Reader
list
)
:
parent
(
parent
),
list
(
list
)
{}
friend
class
EnumSchema
;
};
// -------------------------------------------------------------------
class
InterfaceSchema
:
public
Schema
{
public
:
class
Method
;
class
MethodList
;
MethodList
methods
()
const
;
Maybe
<
Method
>
findMethodByName
(
Text
::
Reader
name
)
const
;
private
:
InterfaceSchema
(
const
internal
::
RawSchema
*
raw
)
:
Schema
(
raw
)
{}
template
<
typename
T
>
static
inline
InterfaceSchema
fromImpl
()
{
return
InterfaceSchema
(
&
internal
::
rawSchema
<
T
>
());
}
friend
class
Schema
;
};
class
InterfaceSchema
::
Method
{
public
:
Method
()
=
default
;
inline
schema
::
InterfaceNode
::
Method
::
Reader
getProto
()
const
{
return
proto
;
}
inline
InterfaceSchema
getContainingInterface
()
{
return
parent
;
}
inline
uint16_t
getOrdinal
()
{
return
ordinal
;
}
inline
bool
operator
==
(
const
Method
&
other
)
const
;
inline
bool
operator
!=
(
const
Method
&
other
)
const
{
return
!
(
*
this
==
other
);
}
private
:
InterfaceSchema
parent
;
uint16_t
ordinal
;
mutable
schema
::
InterfaceNode
::
Method
::
Reader
proto
;
// TODO(soon): Make all reader methods const and then remove this ugly use of "mutable".
inline
Method
(
InterfaceSchema
parent
,
uint16_t
ordinal
,
schema
::
InterfaceNode
::
Method
::
Reader
proto
)
:
parent
(
parent
),
ordinal
(
ordinal
),
proto
(
proto
)
{}
friend
class
InterfaceSchema
;
};
class
InterfaceSchema
::
MethodList
{
public
:
inline
uint
size
()
const
{
return
list
.
size
();
}
inline
Method
operator
[](
uint
index
)
const
{
return
Method
(
parent
,
index
,
list
[
index
]);
}
typedef
internal
::
IndexingIterator
<
MethodList
,
Method
>
iterator
;
inline
iterator
begin
()
const
{
return
iterator
(
this
,
0
);
}
inline
iterator
end
()
const
{
return
iterator
(
this
,
size
());
}
private
:
InterfaceSchema
parent
;
List
<
schema
::
InterfaceNode
::
Method
>::
Reader
list
;
inline
MethodList
(
InterfaceSchema
parent
,
List
<
schema
::
InterfaceNode
::
Method
>::
Reader
list
)
:
parent
(
parent
),
list
(
list
)
{}
friend
class
InterfaceSchema
;
};
// -------------------------------------------------------------------
class
ListSchema
{
// ListSchema is a little different because list types are not described by schema nodes. So,
// ListSchema doesn't subclass Schema.
public
:
ListSchema
()
=
default
;
static
ListSchema
of
(
schema
::
Type
::
Body
::
Which
primitiveType
);
static
ListSchema
of
(
StructSchema
elementType
);
static
ListSchema
of
(
EnumSchema
elementType
);
static
ListSchema
of
(
InterfaceSchema
elementType
);
static
ListSchema
of
(
ListSchema
elementType
);
// Construct the schema for a list of the given type.
static
ListSchema
of
(
schema
::
Type
::
Reader
elementType
,
Schema
context
);
// Construct from an element type schema. Requires a context which can handle getDependency()
// requests for any type ID found in the schema.
inline
schema
::
Type
::
Body
::
Which
whichElementType
()
const
;
// Get the element type's "which()". ListSchema does not actually store a schema::Type::Reader
// describing the element type, but if it did, this would be equivalent to calling
// .getBody().which() on that type.
StructSchema
getStructElementType
()
const
;
EnumSchema
getEnumElementType
()
const
;
InterfaceSchema
getInterfaceElementType
()
const
;
ListSchema
getListElementType
()
const
;
// Get the schema for complex element types. Each of these throws an exception if the element
// type is not of the requested kind.
private
:
schema
::
Type
::
Body
::
Which
elementType
;
uint8_t
nestingDepth
;
// 0 for T, 1 for List(T), 2 for List(List(T)), ...
Schema
elementSchema
;
// if elementType is struct, enum, interface...
inline
ListSchema
(
schema
::
Type
::
Body
::
Which
elementType
)
:
elementType
(
elementType
),
nestingDepth
(
0
)
{}
inline
ListSchema
(
schema
::
Type
::
Body
::
Which
elementType
,
Schema
elementSchema
)
:
elementType
(
elementType
),
nestingDepth
(
0
),
elementSchema
(
elementSchema
)
{}
inline
ListSchema
(
schema
::
Type
::
Body
::
Which
elementType
,
uint8_t
nestingDepth
,
Schema
elementSchema
)
:
elementType
(
elementType
),
nestingDepth
(
nestingDepth
),
elementSchema
(
elementSchema
)
{}
template
<
typename
T
>
struct
FromImpl
;
template
<
typename
T
>
static
inline
ListSchema
fromImpl
()
{
return
FromImpl
<
T
>::
get
();
}
friend
class
Schema
;
};
// =======================================================================================
// inline implementation
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
Void
>
()
{
return
schema
::
Type
::
Body
::
VOID_TYPE
;
}
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
bool
>
()
{
return
schema
::
Type
::
Body
::
BOOL_TYPE
;
}
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
int8_t
>
()
{
return
schema
::
Type
::
Body
::
INT8_TYPE
;
}
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
int16_t
>
()
{
return
schema
::
Type
::
Body
::
INT16_TYPE
;
}
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
int32_t
>
()
{
return
schema
::
Type
::
Body
::
INT32_TYPE
;
}
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
int64_t
>
()
{
return
schema
::
Type
::
Body
::
INT64_TYPE
;
}
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
uint8_t
>
()
{
return
schema
::
Type
::
Body
::
UINT8_TYPE
;
}
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
uint16_t
>
()
{
return
schema
::
Type
::
Body
::
UINT16_TYPE
;
}
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
uint32_t
>
()
{
return
schema
::
Type
::
Body
::
UINT32_TYPE
;
}
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
uint64_t
>
()
{
return
schema
::
Type
::
Body
::
UINT64_TYPE
;
}
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
float
>
()
{
return
schema
::
Type
::
Body
::
FLOAT32_TYPE
;
}
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
double
>
()
{
return
schema
::
Type
::
Body
::
FLOAT64_TYPE
;
}
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
Text
>
()
{
return
schema
::
Type
::
Body
::
TEXT_TYPE
;
}
template
<>
inline
schema
::
Type
::
Body
::
Which
Schema
::
from
<
Data
>
()
{
return
schema
::
Type
::
Body
::
DATA_TYPE
;
}
inline
bool
StructSchema
::
Member
::
operator
==
(
const
Member
&
other
)
const
{
return
parent
==
other
.
parent
&&
unionIndex
==
other
.
unionIndex
&&
index
==
other
.
index
;
}
inline
bool
EnumSchema
::
Enumerant
::
operator
==
(
const
Enumerant
&
other
)
const
{
return
parent
==
other
.
parent
&&
ordinal
==
other
.
ordinal
;
}
inline
bool
InterfaceSchema
::
Method
::
operator
==
(
const
Method
&
other
)
const
{
return
parent
==
other
.
parent
&&
ordinal
==
other
.
ordinal
;
}
inline
ListSchema
ListSchema
::
of
(
StructSchema
elementType
)
{
return
ListSchema
(
schema
::
Type
::
Body
::
STRUCT_TYPE
,
0
,
elementType
);
}
inline
ListSchema
ListSchema
::
of
(
EnumSchema
elementType
)
{
return
ListSchema
(
schema
::
Type
::
Body
::
ENUM_TYPE
,
0
,
elementType
);
}
inline
ListSchema
ListSchema
::
of
(
InterfaceSchema
elementType
)
{
return
ListSchema
(
schema
::
Type
::
Body
::
INTERFACE_TYPE
,
0
,
elementType
);
}
inline
ListSchema
ListSchema
::
of
(
ListSchema
elementType
)
{
return
ListSchema
(
elementType
.
elementType
,
elementType
.
nestingDepth
+
1
,
elementType
.
elementSchema
);
}
inline
schema
::
Type
::
Body
::
Which
ListSchema
::
whichElementType
()
const
{
return
nestingDepth
==
0
?
elementType
:
schema
::
Type
::
Body
::
LIST_TYPE
;
}
template
<
typename
T
>
struct
ListSchema
::
FromImpl
<
List
<
T
>>
{
static
inline
ListSchema
get
()
{
return
of
(
Schema
::
from
<
T
>
());
}
};
}
// namespace capnproto
#endif // CAPNPROTO_SCHEMA_H_
c++/src/capnproto/test.capnp
View file @
e7b9e4da
...
...
@@ -164,6 +164,18 @@ struct TestObject {
objectField @0 :Object;
}
struct TestOutOfOrder {
foo @3 :Text;
bar @2 :Text;
baz @8 :Text;
qux @0 :Text;
quux @6 :Text;
corge @4 :Text;
grault @1 :Text;
garply @7 :Text;
waldo @5 :Text;
}
struct TestUnion {
union0 @0 union {
# Pack union 0 under ideal conditions: there is no unused padding space prior to it.
...
...
compiler/src/CxxGenerator.hs
View file @
e7b9e4da
...
...
@@ -32,9 +32,10 @@ import qualified Data.Digest.MD5 as MD5
import
qualified
Data.Map
as
Map
import
qualified
Data.Set
as
Set
import
qualified
Data.List
as
List
import
Data.Maybe
(
catMaybes
)
import
Data.Maybe
(
catMaybes
,
mapMaybe
)
import
Data.Binary.IEEE754
(
floatToWord
,
doubleToWord
)
import
Data.Map
((
!
))
import
Data.Function
(
on
)
import
Text.Printf
(
printf
)
import
Text.Hastache
import
Text.Hastache.Context
...
...
@@ -277,11 +278,47 @@ descDependencies (DescMethod d) =
concat
$
typeDependencies
(
methodReturnType
d
)
:
map
paramDependencies
(
methodParams
d
)
descDependencies
_
=
[]
memberIndexes
::
Int
->
[(
Int
,
Int
)]
memberIndexes
unionIndex
=
zip
(
repeat
unionIndex
)
[
0
..
]
memberTable
(
DescStruct
desc
)
=
let
-- Fields and unions of the struct.
topMembers
=
zip
(
memberIndexes
0
)
$
mapMaybe
memberName
$
List
.
sortBy
(
compare
`
on
`
ordinal
)
$
structMembers
desc
-- Fields of each union.
innerMembers
=
zipWith
indexedUnionMembers
[
1
..
]
$
List
.
sortBy
(
compare
`
on
`
unionNumber
)
$
structUnions
desc
ordinal
(
DescField
f
)
=
fieldNumber
f
ordinal
(
DescUnion
u
)
=
unionNumber
u
ordinal
_
=
65536
-- doesn't really matter what this is; will be filtered out later
memberName
(
DescField
f
)
=
Just
$
fieldName
f
memberName
(
DescUnion
u
)
=
Just
$
unionName
u
memberName
_
=
Nothing
indexedUnionMembers
i
u
=
zip
(
memberIndexes
i
)
$
mapMaybe
memberName
$
List
.
sortBy
(
compare
`
on
`
ordinal
)
$
unionMembers
u
in
concat
$
topMembers
:
innerMembers
memberTable
(
DescEnum
desc
)
=
zip
(
memberIndexes
0
)
$
map
enumerantName
$
List
.
sortBy
(
compare
`
on
`
enumerantNumber
)
$
enumerants
desc
memberTable
(
DescInterface
desc
)
=
zip
(
memberIndexes
0
)
$
map
methodName
$
List
.
sortBy
(
compare
`
on
`
methodNumber
)
$
interfaceMethods
desc
memberTable
_
=
[]
outerFileContext
schemaNodes
=
fileContext
where
schemaDepContext
parent
i
=
mkStrContext
context
where
context
"dependencyId"
=
MuVariable
(
printf
"%016x"
i
::
String
)
context
s
=
parent
s
schemaMemberByNameContext
parent
(
ui
,
mi
)
=
mkStrContext
context
where
context
"memberUnionIndex"
=
MuVariable
ui
context
"memberIndex"
=
MuVariable
mi
context
s
=
parent
s
schemaContext
parent
desc
=
mkStrContext
context
where
node
=
schemaNodes
!
descId
desc
...
...
@@ -289,11 +326,18 @@ outerFileContext schemaNodes = fileContext where
depIds
=
map
head
$
List
.
group
$
List
.
sort
$
descDependencies
desc
membersByName
=
map
fst
$
List
.
sortBy
(
compare
`
on
`
memberByNameKey
)
$
memberTable
desc
memberByNameKey
((
unionIndex
,
_
),
name
)
=
(
unionIndex
,
name
)
context
"schemaWordCount"
=
MuVariable
$
div
(
length
node
+
7
)
8
context
"schemaBytes"
=
MuVariable
$
delimit
",
\n
"
codeLines
context
"schemaId"
=
MuVariable
(
printf
"%016x"
(
descId
desc
)
::
String
)
context
"schemaDependencyCount"
=
MuVariable
$
length
depIds
context
"schemaDependencies"
=
MuList
$
map
(
schemaDepContext
context
)
depIds
context
"schemaMemberCount"
=
MuVariable
$
length
membersByName
context
"schemaMembersByName"
=
MuList
$
map
(
schemaMemberByNameContext
context
)
membersByName
context
s
=
parent
s
enumerantContext
parent
desc
=
mkStrContext
context
where
...
...
compiler/src/c++-source.mustache
View file @
e7b9e4da
...
...
@@ -64,8 +64,13 @@ static const ::capnproto::internal::RawSchema* const d_{{schemaId}}[] = {
{{/
schemaDependencies
}}
nullptr
};
static const ::capnproto::internal::RawSchema::MemberInfo m_
{{
schemaId
}}
[] = {
{{#
schemaMembersByName
}}
{
{{
memberUnionIndex
}}
,
{{
memberIndex
}}
},
{{/
schemaMembersByName
}}
};
const ::capnproto::internal::RawSchema s_
{{
schemaId
}}
= {
b_
{{
schemaId
}}
.words, d_
{{
schemaId
}}
b_
{{
schemaId
}}
.words, d_
{{
schemaId
}}
, m_
{{
schemaId
}}
,
{{
schemaDependencyCount
}}
,
{{
schemaMemberCount
}}
};
{{/
typeSchema
}}
{{/
fileTypes
}}
...
...
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