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
9c567060
Commit
9c567060
authored
Aug 14, 2018
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Replace JsonCodec STL maps with KJ maps.
parent
842e0d59
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
137 additions
and
132 deletions
+137
-132
json.c++
c++/src/capnp/compat/json.c++
+108
-126
generated-header-support.h
c++/src/capnp/generated-header-support.h
+1
-0
schema.c++
c++/src/capnp/schema.c++
+11
-5
schema.h
c++/src/capnp/schema.h
+17
-1
No files found.
c++/src/capnp/compat/json.c++
View file @
9c567060
...
@@ -23,8 +23,6 @@
...
@@ -23,8 +23,6 @@
#include <math.h> // for HUGEVAL to check for overflow in strtod
#include <math.h> // for HUGEVAL to check for overflow in strtod
#include <stdlib.h> // strtod
#include <stdlib.h> // strtod
#include <errno.h> // for strtod errors
#include <errno.h> // for strtod errors
#include <unordered_map>
#include <map>
#include <capnp/orphan.h>
#include <capnp/orphan.h>
#include <kj/debug.h>
#include <kj/debug.h>
#include <kj/function.h>
#include <kj/function.h>
...
@@ -35,31 +33,15 @@
...
@@ -35,31 +33,15 @@
namespace
capnp
{
namespace
capnp
{
namespace
{
struct
TypeHash
{
size_t
operator
()(
const
Type
&
type
)
const
{
return
type
.
hashCode
();
}
};
struct
FieldHash
{
size_t
operator
()(
const
StructSchema
::
Field
&
field
)
const
{
return
field
.
getIndex
()
^
field
.
getContainingStruct
().
getProto
().
getId
();
}
};
}
// namespace
struct
JsonCodec
::
Impl
{
struct
JsonCodec
::
Impl
{
bool
prettyPrint
=
false
;
bool
prettyPrint
=
false
;
HasMode
hasMode
=
HasMode
::
NON_NULL
;
HasMode
hasMode
=
HasMode
::
NON_NULL
;
size_t
maxNestingDepth
=
64
;
size_t
maxNestingDepth
=
64
;
std
::
unordered_map
<
Type
,
HandlerBase
*
,
TypeHash
>
typeHandlers
;
kj
::
HashMap
<
Type
,
HandlerBase
*
>
typeHandlers
;
std
::
unordered_map
<
StructSchema
::
Field
,
HandlerBase
*
,
FieldHash
>
fieldHandlers
;
kj
::
HashMap
<
StructSchema
::
Field
,
HandlerBase
*
>
fieldHandlers
;
std
::
unordered_map
<
Type
,
kj
::
Maybe
<
kj
::
Own
<
AnnotatedHandler
>>
,
TypeHash
>
annotatedHandlers
;
kj
::
HashMap
<
Type
,
kj
::
Maybe
<
kj
::
Own
<
AnnotatedHandler
>>
>
annotatedHandlers
;
std
::
unordered_map
<
Type
,
kj
::
Own
<
AnnotatedEnumHandler
>
,
TypeHash
>
annotatedEnumHandlers
;
kj
::
HashMap
<
Type
,
kj
::
Own
<
AnnotatedEnumHandler
>
>
annotatedEnumHandlers
;
kj
::
StringTree
encodeRaw
(
JsonValue
::
Reader
value
,
uint
indent
,
bool
&
multiline
,
kj
::
StringTree
encodeRaw
(
JsonValue
::
Reader
value
,
uint
indent
,
bool
&
multiline
,
bool
hasPrefix
)
const
{
bool
hasPrefix
)
const
{
...
@@ -235,9 +217,8 @@ void JsonCodec::encode(DynamicValue::Reader input, Type type, JsonValue::Builder
...
@@ -235,9 +217,8 @@ void JsonCodec::encode(DynamicValue::Reader input, Type type, JsonValue::Builder
// TODO(soon): For interfaces, check for handlers on superclasses, per documentation...
// TODO(soon): For interfaces, check for handlers on superclasses, per documentation...
// TODO(soon): For branded types, should we check for handlers on the generic?
// TODO(soon): For branded types, should we check for handlers on the generic?
// TODO(someday): Allow registering handlers for "all structs", "all lists", etc?
// TODO(someday): Allow registering handlers for "all structs", "all lists", etc?
auto
iter
=
impl
->
typeHandlers
.
find
(
type
);
KJ_IF_MAYBE
(
handler
,
impl
->
typeHandlers
.
find
(
type
))
{
if
(
iter
!=
impl
->
typeHandlers
.
end
())
{
(
*
handler
)
->
encodeBase
(
*
this
,
input
,
output
);
iter
->
second
->
encodeBase
(
*
this
,
input
,
output
);
return
;
return
;
}
}
...
@@ -383,9 +364,8 @@ void JsonCodec::encode(DynamicValue::Reader input, Type type, JsonValue::Builder
...
@@ -383,9 +364,8 @@ void JsonCodec::encode(DynamicValue::Reader input, Type type, JsonValue::Builder
void
JsonCodec
::
encodeField
(
StructSchema
::
Field
field
,
DynamicValue
::
Reader
input
,
void
JsonCodec
::
encodeField
(
StructSchema
::
Field
field
,
DynamicValue
::
Reader
input
,
JsonValue
::
Builder
output
)
const
{
JsonValue
::
Builder
output
)
const
{
auto
iter
=
impl
->
fieldHandlers
.
find
(
field
);
KJ_IF_MAYBE
(
handler
,
impl
->
fieldHandlers
.
find
(
field
))
{
if
(
iter
!=
impl
->
fieldHandlers
.
end
())
{
(
*
handler
)
->
encodeBase
(
*
this
,
input
,
output
);
iter
->
second
->
encodeBase
(
*
this
,
input
,
output
);
return
;
return
;
}
}
...
@@ -416,9 +396,8 @@ void JsonCodec::decodeField(StructSchema::Field fieldSchema, JsonValue::Reader f
...
@@ -416,9 +396,8 @@ void JsonCodec::decodeField(StructSchema::Field fieldSchema, JsonValue::Reader f
Orphanage
orphanage
,
DynamicStruct
::
Builder
output
)
const
{
Orphanage
orphanage
,
DynamicStruct
::
Builder
output
)
const
{
auto
fieldType
=
fieldSchema
.
getType
();
auto
fieldType
=
fieldSchema
.
getType
();
auto
iter
=
impl
->
fieldHandlers
.
find
(
fieldSchema
);
KJ_IF_MAYBE
(
handler
,
impl
->
fieldHandlers
.
find
(
fieldSchema
))
{
if
(
iter
!=
impl
->
fieldHandlers
.
end
())
{
output
.
adopt
(
fieldSchema
,
(
*
handler
)
->
decodeBase
(
*
this
,
fieldValue
,
fieldType
,
orphanage
));
output
.
adopt
(
fieldSchema
,
iter
->
second
->
decodeBase
(
*
this
,
fieldValue
,
fieldType
,
orphanage
));
}
else
{
}
else
{
output
.
adopt
(
fieldSchema
,
decode
(
fieldValue
,
fieldType
,
orphanage
));
output
.
adopt
(
fieldSchema
,
decode
(
fieldValue
,
fieldType
,
orphanage
));
}
}
...
@@ -427,9 +406,8 @@ void JsonCodec::decodeField(StructSchema::Field fieldSchema, JsonValue::Reader f
...
@@ -427,9 +406,8 @@ void JsonCodec::decodeField(StructSchema::Field fieldSchema, JsonValue::Reader f
void
JsonCodec
::
decode
(
JsonValue
::
Reader
input
,
DynamicStruct
::
Builder
output
)
const
{
void
JsonCodec
::
decode
(
JsonValue
::
Reader
input
,
DynamicStruct
::
Builder
output
)
const
{
auto
type
=
output
.
getSchema
();
auto
type
=
output
.
getSchema
();
auto
iter
=
impl
->
typeHandlers
.
find
(
type
);
KJ_IF_MAYBE
(
handler
,
impl
->
typeHandlers
.
find
(
type
))
{
if
(
iter
!=
impl
->
typeHandlers
.
end
())
{
return
(
*
handler
)
->
decodeStructBase
(
*
this
,
input
,
output
);
return
iter
->
second
->
decodeStructBase
(
*
this
,
input
,
output
);
}
}
decodeObject
(
input
,
type
,
Orphanage
::
getForMessageContaining
(
output
),
output
);
decodeObject
(
input
,
type
,
Orphanage
::
getForMessageContaining
(
output
),
output
);
...
@@ -437,9 +415,8 @@ void JsonCodec::decode(JsonValue::Reader input, DynamicStruct::Builder output) c
...
@@ -437,9 +415,8 @@ void JsonCodec::decode(JsonValue::Reader input, DynamicStruct::Builder output) c
Orphan
<
DynamicValue
>
JsonCodec
::
decode
(
Orphan
<
DynamicValue
>
JsonCodec
::
decode
(
JsonValue
::
Reader
input
,
Type
type
,
Orphanage
orphanage
)
const
{
JsonValue
::
Reader
input
,
Type
type
,
Orphanage
orphanage
)
const
{
auto
iter
=
impl
->
typeHandlers
.
find
(
type
);
KJ_IF_MAYBE
(
handler
,
impl
->
typeHandlers
.
find
(
type
))
{
if
(
iter
!=
impl
->
typeHandlers
.
end
())
{
return
(
*
handler
)
->
decodeBase
(
*
this
,
input
,
type
,
orphanage
);
return
iter
->
second
->
decodeBase
(
*
this
,
input
,
type
,
orphanage
);
}
}
switch
(
type
.
which
())
{
switch
(
type
.
which
())
{
...
@@ -883,13 +860,13 @@ void JsonCodec::HandlerBase::decodeStructBase(
...
@@ -883,13 +860,13 @@ void JsonCodec::HandlerBase::decodeStructBase(
}
}
void
JsonCodec
::
addTypeHandlerImpl
(
Type
type
,
HandlerBase
&
handler
)
{
void
JsonCodec
::
addTypeHandlerImpl
(
Type
type
,
HandlerBase
&
handler
)
{
impl
->
typeHandlers
[
type
]
=
&
handler
;
impl
->
typeHandlers
.
insert
(
type
,
&
handler
)
;
}
}
void
JsonCodec
::
addFieldHandlerImpl
(
StructSchema
::
Field
field
,
Type
type
,
HandlerBase
&
handler
)
{
void
JsonCodec
::
addFieldHandlerImpl
(
StructSchema
::
Field
field
,
Type
type
,
HandlerBase
&
handler
)
{
KJ_REQUIRE
(
type
==
field
.
getType
(),
KJ_REQUIRE
(
type
==
field
.
getType
(),
"handler type did not match field type for addFieldHandler()"
);
"handler type did not match field type for addFieldHandler()"
);
impl
->
fieldHandlers
[
field
]
=
&
handler
;
impl
->
fieldHandlers
.
insert
(
field
,
&
handler
)
;
}
}
// =======================================================================================
// =======================================================================================
...
@@ -960,15 +937,15 @@ public:
...
@@ -960,15 +937,15 @@ public:
unionTagName
=
unionDeclName
;
unionTagName
=
unionDeclName
;
}
}
KJ_IF_MAYBE
(
u
,
unionTagName
)
{
KJ_IF_MAYBE
(
u
,
unionTagName
)
{
fieldsByName
.
insert
(
std
::
make_pair
(
*
u
,
FieldNameInfo
{
fieldsByName
.
insert
(
*
u
,
FieldNameInfo
{
FieldNameInfo
::
UNION_TAG
,
0
,
0
,
nullptr
FieldNameInfo
::
UNION_TAG
,
0
,
0
,
nullptr
})
)
;
});
}
}
if
(
d
->
hasValueName
())
{
if
(
d
->
hasValueName
())
{
fieldsByName
.
insert
(
std
::
make_pair
(
d
->
getValueName
(),
FieldNameInfo
{
fieldsByName
.
insert
(
d
->
getValueName
(),
FieldNameInfo
{
FieldNameInfo
::
UNION_VALUE
,
0
,
0
,
nullptr
FieldNameInfo
::
UNION_VALUE
,
0
,
0
,
nullptr
})
)
;
});
}
}
}
}
...
@@ -1043,16 +1020,20 @@ public:
...
@@ -1043,16 +1020,20 @@ public:
kj
::
StringPtr
flattenedName
;
kj
::
StringPtr
flattenedName
;
kj
::
String
ownName
;
kj
::
String
ownName
;
if
(
info
.
prefix
.
size
()
>
0
)
{
if
(
info
.
prefix
.
size
()
>
0
)
{
ownName
=
kj
::
str
(
info
.
prefix
,
entry
.
first
);
ownName
=
kj
::
str
(
info
.
prefix
,
entry
.
key
);
flattenedName
=
ownName
;
flattenedName
=
ownName
;
}
else
{
}
else
{
flattenedName
=
entry
.
first
;
flattenedName
=
entry
.
key
;
}
}
fieldsByName
.
insert
(
std
::
make_pair
(
flattenedName
,
FieldNameInfo
{
fieldsByName
.
upsert
(
flattenedName
,
FieldNameInfo
{
isUnionMember
?
FieldNameInfo
::
FLATTENED_FROM_UNION
:
FieldNameInfo
::
FLATTENED
,
isUnionMember
?
FieldNameInfo
::
FLATTENED_FROM_UNION
:
FieldNameInfo
::
FLATTENED
,
field
.
getIndex
(),
(
uint
)
info
.
prefix
.
size
(),
kj
::
mv
(
ownName
)
field
.
getIndex
(),
(
uint
)
info
.
prefix
.
size
(),
kj
::
mv
(
ownName
)
}));
},
[
&
](
FieldNameInfo
&
existing
,
FieldNameInfo
&&
replacement
)
{
KJ_REQUIRE
(
existing
.
type
==
FieldNameInfo
::
FLATTENED_FROM_UNION
&&
replacement
.
type
==
FieldNameInfo
::
FLATTENED_FROM_UNION
,
"flattened members have the same name and are not mutually exclusive"
);
});
}
}
}
}
...
@@ -1070,17 +1051,17 @@ public:
...
@@ -1070,17 +1051,17 @@ public:
}
}
if
(
!
isUnionWithValueName
)
{
if
(
!
isUnionWithValueName
)
{
fieldsByName
.
insert
(
std
::
make_pair
(
info
.
name
,
kj
::
mv
(
nameInfo
)
));
fieldsByName
.
insert
(
info
.
name
,
kj
::
mv
(
nameInfo
));
}
}
}
}
if
(
isUnionMember
)
{
if
(
isUnionMember
)
{
unionTagValues
.
insert
(
std
::
make_pair
(
info
.
nameForDiscriminant
,
field
)
);
unionTagValues
.
insert
(
info
.
nameForDiscriminant
,
field
);
}
}
// Look for dependencies that we need to add.
// Look for dependencies that we need to add.
while
(
type
.
isList
())
type
=
type
.
asList
().
getElementType
();
while
(
type
.
isList
())
type
=
type
.
asList
().
getElementType
();
if
(
codec
.
impl
->
typeHandlers
.
count
(
type
)
==
0
)
{
if
(
codec
.
impl
->
typeHandlers
.
find
(
type
)
==
nullptr
)
{
switch
(
type
.
which
())
{
switch
(
type
.
which
())
{
case
schema
:
:
Type
::
STRUCT
:
case
schema
:
:
Type
::
STRUCT
:
dependencies
.
add
(
type
.
asStruct
());
dependencies
.
add
(
type
.
asStruct
());
...
@@ -1190,10 +1171,10 @@ private:
...
@@ -1190,10 +1171,10 @@ private:
kj
::
String
ownName
;
kj
::
String
ownName
;
};
};
std
::
m
ap
<
kj
::
StringPtr
,
FieldNameInfo
>
fieldsByName
;
kj
::
HashM
ap
<
kj
::
StringPtr
,
FieldNameInfo
>
fieldsByName
;
// Maps JSON names to info needed to parse them.
// Maps JSON names to info needed to parse them.
std
::
m
ap
<
kj
::
StringPtr
,
StructSchema
::
Field
>
unionTagValues
;
kj
::
HashM
ap
<
kj
::
StringPtr
,
StructSchema
::
Field
>
unionTagValues
;
// If the parent struct is a flattened union, it has a tag field which is a string with one of
// If the parent struct is a flattened union, it has a tag field which is a string with one of
// these values. The map maps to the union member to set.
// these values. The map maps to the union member to set.
...
@@ -1265,63 +1246,60 @@ private:
...
@@ -1265,63 +1246,60 @@ private:
kj
::
HashMap
<
const
void
*
,
StructSchema
::
Field
>&
unionsSeen
)
const
{
kj
::
HashMap
<
const
void
*
,
StructSchema
::
Field
>&
unionsSeen
)
const
{
KJ_ASSERT
(
output
.
getSchema
()
==
schema
);
KJ_ASSERT
(
output
.
getSchema
()
==
schema
);
auto
iter
=
fieldsByName
.
find
(
name
);
KJ_IF_MAYBE
(
info
,
fieldsByName
.
find
(
name
))
{
if
(
iter
==
fieldsByName
.
end
())
{
switch
(
info
->
type
)
{
// Ignore undefined field.
case
FieldNameInfo
:
:
NORMAL
:
{
return
true
;
auto
field
=
output
.
getSchema
().
getFields
()[
info
->
index
];
}
codec
.
decodeField
(
field
,
value
,
Orphanage
::
getForMessageContaining
(
output
),
output
);
return
true
;
auto
&
info
=
iter
->
second
;
switch
(
info
.
type
)
{
case
FieldNameInfo
:
:
NORMAL
:
{
auto
field
=
output
.
getSchema
().
getFields
()[
info
.
index
];
codec
.
decodeField
(
field
,
value
,
Orphanage
::
getForMessageContaining
(
output
),
output
);
return
true
;
}
case
FieldNameInfo
:
:
FLATTENED
:
return
KJ_ASSERT_NONNULL
(
fields
[
info
.
index
].
flattenHandler
)
.
decodeField
(
codec
,
name
.
slice
(
info
.
prefixLength
),
value
,
output
.
get
(
output
.
getSchema
().
getFields
()[
info
.
index
]).
as
<
DynamicStruct
>
(),
unionsSeen
);
case
FieldNameInfo
:
:
UNION_TAG
:
{
KJ_REQUIRE
(
value
.
isString
(),
"Expected string value."
);
// Mark that we've seen a union tag for this struct.
const
void
*
ptr
=
getUnionInstanceIdentifier
(
output
);
auto
iter
=
unionTagValues
.
find
(
value
.
getString
());
if
(
iter
!=
unionTagValues
.
end
())
{
unionsSeen
.
insert
(
ptr
,
iter
->
second
);
}
return
true
;
}
case
FieldNameInfo
:
:
FLATTENED_FROM_UNION
:
{
const
void
*
ptr
=
getUnionInstanceIdentifier
(
output
);
KJ_IF_MAYBE
(
variant
,
unionsSeen
.
find
(
ptr
))
{
bool
alreadyInitialized
=
output
.
which
()
.
map
([
&
](
auto
f
)
{
return
f
==
*
variant
;
})
.
orDefault
(
false
);
auto
child
=
alreadyInitialized
?
output
.
get
(
*
variant
)
:
output
.
init
(
*
variant
);
return
KJ_ASSERT_NONNULL
(
fields
[
variant
->
getIndex
()].
flattenHandler
)
.
decodeField
(
codec
,
name
.
slice
(
info
.
prefixLength
),
value
,
child
.
as
<
DynamicStruct
>
(),
unionsSeen
);
}
else
{
// We haven't seen the union tag yet, so we can't parse this field yet. Try again later.
return
false
;
}
}
}
case
FieldNameInfo
:
:
FLATTENED
:
case
FieldNameInfo
:
:
UNION_VALUE
:
{
return
KJ_ASSERT_NONNULL
(
fields
[
info
->
index
].
flattenHandler
)
const
void
*
ptr
=
getUnionInstanceIdentifier
(
output
);
.
decodeField
(
codec
,
name
.
slice
(
info
->
prefixLength
),
value
,
KJ_IF_MAYBE
(
variant
,
unionsSeen
.
find
(
ptr
))
{
output
.
get
(
output
.
getSchema
().
getFields
()[
info
->
index
]).
as
<
DynamicStruct
>
(),
codec
.
decodeField
(
*
variant
,
value
,
Orphanage
::
getForMessageContaining
(
output
),
output
);
unionsSeen
);
case
FieldNameInfo
:
:
UNION_TAG
:
{
KJ_REQUIRE
(
value
.
isString
(),
"Expected string value."
);
// Mark that we've seen a union tag for this struct.
const
void
*
ptr
=
getUnionInstanceIdentifier
(
output
);
KJ_IF_MAYBE
(
field
,
unionTagValues
.
find
(
value
.
getString
()))
{
unionsSeen
.
insert
(
ptr
,
*
field
);
}
return
true
;
return
true
;
}
else
{
}
// We haven't seen the union tag yet, so we can't parse this field yet. Try again later.
case
FieldNameInfo
:
:
FLATTENED_FROM_UNION
:
{
return
false
;
const
void
*
ptr
=
getUnionInstanceIdentifier
(
output
);
KJ_IF_MAYBE
(
variant
,
unionsSeen
.
find
(
ptr
))
{
bool
alreadyInitialized
=
output
.
which
()
.
map
([
&
](
auto
f
)
{
return
f
==
*
variant
;
})
.
orDefault
(
false
);
auto
child
=
alreadyInitialized
?
output
.
get
(
*
variant
)
:
output
.
init
(
*
variant
);
return
KJ_ASSERT_NONNULL
(
fields
[
variant
->
getIndex
()].
flattenHandler
)
.
decodeField
(
codec
,
name
.
slice
(
info
->
prefixLength
),
value
,
child
.
as
<
DynamicStruct
>
(),
unionsSeen
);
}
else
{
// We haven't seen the union tag yet, so we can't parse this field yet. Try again later.
return
false
;
}
}
case
FieldNameInfo
:
:
UNION_VALUE
:
{
const
void
*
ptr
=
getUnionInstanceIdentifier
(
output
);
KJ_IF_MAYBE
(
variant
,
unionsSeen
.
find
(
ptr
))
{
codec
.
decodeField
(
*
variant
,
value
,
Orphanage
::
getForMessageContaining
(
output
),
output
);
return
true
;
}
else
{
// We haven't seen the union tag yet, so we can't parse this field yet. Try again later.
return
false
;
}
}
}
}
}
}
KJ_UNREACHABLE
;
KJ_UNREACHABLE
;
}
else
{
// Ignore undefined field.
return
true
;
}
}
}
const
void
*
getUnionInstanceIdentifier
(
DynamicStruct
::
Builder
obj
)
const
{
const
void
*
getUnionInstanceIdentifier
(
DynamicStruct
::
Builder
obj
)
const
{
...
@@ -1351,7 +1329,7 @@ public:
...
@@ -1351,7 +1329,7 @@ public:
}
}
builder
.
add
(
name
);
builder
.
add
(
name
);
nameToValue
.
insert
(
std
::
make_pair
(
name
,
e
.
getIndex
()
));
nameToValue
.
insert
(
name
,
e
.
getIndex
(
));
}
}
valueToName
=
builder
.
finish
();
valueToName
=
builder
.
finish
();
...
@@ -1370,16 +1348,16 @@ public:
...
@@ -1370,16 +1348,16 @@ public:
if
(
input
.
isNumber
())
{
if
(
input
.
isNumber
())
{
return
DynamicEnum
(
schema
,
static_cast
<
uint16_t
>
(
input
.
getNumber
()));
return
DynamicEnum
(
schema
,
static_cast
<
uint16_t
>
(
input
.
getNumber
()));
}
else
{
}
else
{
auto
iter
=
nameToValue
.
find
(
input
.
getString
());
uint16_t
val
=
KJ_REQUIRE_NONNULL
(
nameToValue
.
find
(
input
.
getString
()),
KJ_REQUIRE
(
iter
!=
nameToValue
.
end
(),
"invalid enum value"
,
input
.
getString
());
"invalid enum value"
,
input
.
getString
());
return
DynamicEnum
(
schema
.
getEnumerants
()[
iter
->
second
]);
return
DynamicEnum
(
schema
.
getEnumerants
()[
val
]);
}
}
}
}
private
:
private
:
EnumSchema
schema
;
EnumSchema
schema
;
kj
::
Array
<
kj
::
StringPtr
>
valueToName
;
kj
::
Array
<
kj
::
StringPtr
>
valueToName
;
std
::
m
ap
<
kj
::
StringPtr
,
uint16_t
>
nameToValue
;
kj
::
HashM
ap
<
kj
::
StringPtr
,
uint16_t
>
nameToValue
;
};
};
class
JsonCodec
::
JsonValueHandler
final
:
public
JsonCodec
::
Handler
<
DynamicStruct
>
{
class
JsonCodec
::
JsonValueHandler
final
:
public
JsonCodec
::
Handler
<
DynamicStruct
>
{
...
@@ -1400,10 +1378,6 @@ public:
...
@@ -1400,10 +1378,6 @@ public:
}
}
private
:
private
:
EnumSchema
schema
;
kj
::
Array
<
kj
::
StringPtr
>
valueToName
;
std
::
map
<
kj
::
StringPtr
,
uint16_t
>
nameToValue
;
void
rawCopy
(
AnyStruct
::
Reader
input
,
AnyStruct
::
Builder
output
)
const
{
void
rawCopy
(
AnyStruct
::
Reader
input
,
AnyStruct
::
Builder
output
)
const
{
// HACK: Manually copy using AnyStruct, so that if JsonValue's definition changes, this code
// HACK: Manually copy using AnyStruct, so that if JsonValue's definition changes, this code
// doesn't need to be updated. However, note that if JsonValue ever adds new fields that
// doesn't need to be updated. However, note that if JsonValue ever adds new fields that
...
@@ -1426,20 +1400,27 @@ private:
...
@@ -1426,20 +1400,27 @@ private:
JsonCodec
::
AnnotatedHandler
&
JsonCodec
::
loadAnnotatedHandler
(
JsonCodec
::
AnnotatedHandler
&
JsonCodec
::
loadAnnotatedHandler
(
StructSchema
schema
,
kj
::
Maybe
<
json
::
DiscriminatorOptions
::
Reader
>
discriminator
,
StructSchema
schema
,
kj
::
Maybe
<
json
::
DiscriminatorOptions
::
Reader
>
discriminator
,
kj
::
Maybe
<
kj
::
StringPtr
>
unionDeclName
,
kj
::
Vector
<
Schema
>&
dependencies
)
{
kj
::
Maybe
<
kj
::
StringPtr
>
unionDeclName
,
kj
::
Vector
<
Schema
>&
dependencies
)
{
auto
insertResult
=
impl
->
annotatedHandlers
.
insert
(
std
::
make_pair
(
schema
,
nullptr
));
auto
&
entry
=
impl
->
annotatedHandlers
.
upsert
(
schema
,
nullptr
,
if
(
insertResult
.
second
)
{
[
&
](
kj
::
Maybe
<
kj
::
Own
<
AnnotatedHandler
>>&
existing
,
auto
dummy
)
{
KJ_ASSERT
(
existing
!=
nullptr
,
"cyclic JSON flattening detected"
,
schema
.
getProto
().
getDisplayName
());
});
KJ_IF_MAYBE
(
v
,
entry
.
value
)
{
// Already exists.
return
**
v
;
}
else
{
// Not seen before.
// Not seen before.
auto
newHandler
=
kj
::
heap
<
AnnotatedHandler
>
(
auto
newHandler
=
kj
::
heap
<
AnnotatedHandler
>
(
*
this
,
schema
,
discriminator
,
unionDeclName
,
dependencies
);
*
this
,
schema
,
discriminator
,
unionDeclName
,
dependencies
);
auto
&
result
=
*
newHandler
;
auto
&
result
=
*
newHandler
;
insertResult
.
first
->
second
=
kj
::
mv
(
newHandler
);
// Map may have changed, so we have to look up again.
KJ_ASSERT_NONNULL
(
impl
->
annotatedHandlers
.
find
(
schema
))
=
kj
::
mv
(
newHandler
);
addTypeHandler
(
schema
,
result
);
addTypeHandler
(
schema
,
result
);
return
result
;
return
result
;
}
else
KJ_IF_MAYBE
(
handler
,
insertResult
.
first
->
second
)
{
};
return
**
handler
;
}
else
{
KJ_FAIL_REQUIRE
(
"cyclic JSON flattening detected"
,
schema
.
getProto
().
getDisplayName
());
}
}
}
void
JsonCodec
::
handleByAnnotation
(
Schema
schema
)
{
void
JsonCodec
::
handleByAnnotation
(
Schema
schema
)
{
...
@@ -1460,11 +1441,12 @@ void JsonCodec::handleByAnnotation(Schema schema) {
...
@@ -1460,11 +1441,12 @@ void JsonCodec::handleByAnnotation(Schema schema) {
}
}
case
schema
:
:
Node
::
ENUM
:
{
case
schema
:
:
Node
::
ENUM
:
{
auto
enumSchema
=
schema
.
asEnum
();
auto
enumSchema
=
schema
.
asEnum
();
auto
&
slot
=
impl
->
annotatedEnumHandlers
[
enumSchema
];
impl
->
annotatedEnumHandlers
.
findOrCreate
(
enumSchema
,
[
&
]()
{
if
(
slot
.
get
()
==
nullptr
)
{
auto
handler
=
kj
::
heap
<
AnnotatedEnumHandler
>
(
enumSchema
);
slot
=
kj
::
heap
<
AnnotatedEnumHandler
>
(
enumSchema
);
addTypeHandler
(
enumSchema
,
*
handler
);
addTypeHandler
(
enumSchema
,
*
slot
);
return
kj
::
HashMap
<
Type
,
kj
::
Own
<
AnnotatedEnumHandler
>>::
Entry
{
}
enumSchema
,
kj
::
mv
(
handler
)
};
});
break
;
break
;
}
}
default
:
default
:
...
...
c++/src/capnp/generated-header-support.h
View file @
9c567060
...
@@ -35,6 +35,7 @@
...
@@ -35,6 +35,7 @@
#include "any.h"
#include "any.h"
#include <kj/string.h>
#include <kj/string.h>
#include <kj/string-tree.h>
#include <kj/string-tree.h>
#include <kj/hash.h>
namespace
capnp
{
namespace
capnp
{
...
...
c++/src/capnp/schema.c++
View file @
9c567060
...
@@ -25,6 +25,12 @@
...
@@ -25,6 +25,12 @@
namespace
capnp
{
namespace
capnp
{
namespace
schema
{
uint
KJ_HASHCODE
(
Type
::
Which
w
)
{
return
kj
::
hashCode
(
static_cast
<
uint16_t
>
(
w
));
}
// TODO(cleanup): Cap'n Proto does not declare stringifiers nor hashers for `Which` enums, unlike
// all other enums. Fix that and remove this.
}
namespace
_
{
// private
namespace
_
{
// private
// Null schemas generated using the below schema file with:
// Null schemas generated using the below schema file with:
...
@@ -868,7 +874,7 @@ bool Type::operator==(const Type& other) const {
...
@@ -868,7 +874,7 @@ bool Type::operator==(const Type& other) const {
KJ_UNREACHABLE
;
KJ_UNREACHABLE
;
}
}
size_
t
Type
::
hashCode
()
const
{
uin
t
Type
::
hashCode
()
const
{
switch
(
baseType
)
{
switch
(
baseType
)
{
case
schema
:
:
Type
::
VOID
:
case
schema
:
:
Type
::
VOID
:
case
schema
:
:
Type
::
BOOL
:
case
schema
:
:
Type
::
BOOL
:
...
@@ -884,12 +890,12 @@ size_t Type::hashCode() const {
...
@@ -884,12 +890,12 @@ size_t Type::hashCode() const {
case
schema
:
:
Type
::
FLOAT64
:
case
schema
:
:
Type
::
FLOAT64
:
case
schema
:
:
Type
::
TEXT
:
case
schema
:
:
Type
::
TEXT
:
case
schema
:
:
Type
::
DATA
:
case
schema
:
:
Type
::
DATA
:
return
(
static_cast
<
size_t
>
(
baseType
)
<<
3
)
+
listDepth
;
return
kj
::
hashCode
(
baseType
,
listDepth
)
;
case
schema
:
:
Type
::
STRUCT
:
case
schema
:
:
Type
::
STRUCT
:
case
schema
:
:
Type
::
ENUM
:
case
schema
:
:
Type
::
ENUM
:
case
schema
:
:
Type
::
INTERFACE
:
case
schema
:
:
Type
::
INTERFACE
:
return
reinterpret_cast
<
size_t
>
(
schema
)
+
listDepth
;
return
kj
::
hashCode
(
schema
,
listDepth
)
;
case
schema
:
:
Type
::
LIST
:
case
schema
:
:
Type
::
LIST
:
KJ_UNREACHABLE
;
KJ_UNREACHABLE
;
...
@@ -897,9 +903,9 @@ size_t Type::hashCode() const {
...
@@ -897,9 +903,9 @@ size_t Type::hashCode() const {
case
schema
:
:
Type
::
ANY_POINTER
:
{
case
schema
:
:
Type
::
ANY_POINTER
:
{
// Trying to comply with strict aliasing rules. Hopefully the compiler realizes that
// Trying to comply with strict aliasing rules. Hopefully the compiler realizes that
// both branches compile to the same instructions and can optimize it away.
// both branches compile to the same instructions and can optimize it away.
size
_t
val
=
scopeId
!=
0
||
isImplicitParam
?
uint16
_t
val
=
scopeId
!=
0
||
isImplicitParam
?
paramIndex
:
static_cast
<
uint16_t
>
(
anyPointerKind
);
paramIndex
:
static_cast
<
uint16_t
>
(
anyPointerKind
);
return
(
val
<<
1
|
isImplicitParam
)
^
scopeId
;
return
kj
::
hashCode
(
val
,
isImplicitParam
,
scopeId
)
;
}
}
}
}
...
...
c++/src/capnp/schema.h
View file @
9c567060
...
@@ -30,6 +30,7 @@
...
@@ -30,6 +30,7 @@
#endif
#endif
#include <capnp/schema.capnp.h>
#include <capnp/schema.capnp.h>
#include <kj/hash.h>
#include <kj/windows-sanity.h> // work-around macro conflict with `VOID`
#include <kj/windows-sanity.h> // work-around macro conflict with `VOID`
namespace
capnp
{
namespace
capnp
{
...
@@ -129,6 +130,8 @@ public:
...
@@ -129,6 +130,8 @@ public:
// you want to check if two Schemas represent the same type (but possibly different versions of
// you want to check if two Schemas represent the same type (but possibly different versions of
// it), compare their IDs instead.
// it), compare their IDs instead.
inline
uint
hashCode
()
const
{
return
kj
::
hashCode
(
raw
);
}
template
<
typename
T
>
template
<
typename
T
>
void
requireUsableAs
()
const
;
void
requireUsableAs
()
const
;
// Throws an exception if a value with this Schema cannot safely be cast to a native value of
// Throws an exception if a value with this Schema cannot safely be cast to a native value of
...
@@ -302,6 +305,7 @@ public:
...
@@ -302,6 +305,7 @@ public:
inline
bool
operator
==
(
const
Field
&
other
)
const
;
inline
bool
operator
==
(
const
Field
&
other
)
const
;
inline
bool
operator
!=
(
const
Field
&
other
)
const
{
return
!
(
*
this
==
other
);
}
inline
bool
operator
!=
(
const
Field
&
other
)
const
{
return
!
(
*
this
==
other
);
}
inline
uint
hashCode
()
const
;
private
:
private
:
StructSchema
parent
;
StructSchema
parent
;
...
@@ -400,6 +404,7 @@ public:
...
@@ -400,6 +404,7 @@ public:
inline
bool
operator
==
(
const
Enumerant
&
other
)
const
;
inline
bool
operator
==
(
const
Enumerant
&
other
)
const
;
inline
bool
operator
!=
(
const
Enumerant
&
other
)
const
{
return
!
(
*
this
==
other
);
}
inline
bool
operator
!=
(
const
Enumerant
&
other
)
const
{
return
!
(
*
this
==
other
);
}
inline
uint
hashCode
()
const
;
private
:
private
:
EnumSchema
parent
;
EnumSchema
parent
;
...
@@ -492,6 +497,7 @@ public:
...
@@ -492,6 +497,7 @@ public:
inline
bool
operator
==
(
const
Method
&
other
)
const
;
inline
bool
operator
==
(
const
Method
&
other
)
const
;
inline
bool
operator
!=
(
const
Method
&
other
)
const
{
return
!
(
*
this
==
other
);
}
inline
bool
operator
!=
(
const
Method
&
other
)
const
{
return
!
(
*
this
==
other
);
}
inline
uint
hashCode
()
const
;
private
:
private
:
InterfaceSchema
parent
;
InterfaceSchema
parent
;
...
@@ -644,7 +650,7 @@ public:
...
@@ -644,7 +650,7 @@ public:
bool
operator
==
(
const
Type
&
other
)
const
;
bool
operator
==
(
const
Type
&
other
)
const
;
inline
bool
operator
!=
(
const
Type
&
other
)
const
{
return
!
(
*
this
==
other
);
}
inline
bool
operator
!=
(
const
Type
&
other
)
const
{
return
!
(
*
this
==
other
);
}
size_
t
hashCode
()
const
;
uin
t
hashCode
()
const
;
inline
Type
wrapInList
(
uint
depth
=
1
)
const
;
inline
Type
wrapInList
(
uint
depth
=
1
)
const
;
// Return the Type formed by wrapping this type in List() `depth` times.
// Return the Type formed by wrapping this type in List() `depth` times.
...
@@ -796,6 +802,16 @@ inline bool InterfaceSchema::Method::operator==(const Method& other) const {
...
@@ -796,6 +802,16 @@ inline bool InterfaceSchema::Method::operator==(const Method& other) const {
return
parent
==
other
.
parent
&&
ordinal
==
other
.
ordinal
;
return
parent
==
other
.
parent
&&
ordinal
==
other
.
ordinal
;
}
}
inline
uint
StructSchema
::
Field
::
hashCode
()
const
{
return
kj
::
hashCode
(
parent
,
index
);
}
inline
uint
EnumSchema
::
Enumerant
::
hashCode
()
const
{
return
kj
::
hashCode
(
parent
,
index
);
}
inline
uint
InterfaceSchema
::
Method
::
hashCode
()
const
{
return
kj
::
hashCode
(
parent
,
index
);
}
inline
ListSchema
ListSchema
::
of
(
StructSchema
elementType
)
{
inline
ListSchema
ListSchema
::
of
(
StructSchema
elementType
)
{
return
ListSchema
(
Type
(
elementType
));
return
ListSchema
(
Type
(
elementType
));
}
}
...
...
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