CaptureKeys: Add support for std::map and std::unordered_map

This commit is contained in:
Alastair Robertson 2023-09-22 06:53:13 -07:00 committed by Alastair Robertson
parent 4afa2ff190
commit 5572e294f7
3 changed files with 305 additions and 14 deletions

View File

@ -0,0 +1,264 @@
# This file contains tests for core key-capture features at the top, followed
# by basic tests for each container type which supports key capture.
includes = ["map"]
definitions = '''
struct MapHolder {
std::map<int, int> captureMyKeys;
std::map<int, int> dontCaptureKeysHere;
};
enum class MyEnum {
One = 1,
Two = 2,
Three = 3,
};
'''
[cases]
[cases.int]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const std::map<int, int>&"]
setup = "return {{{1,2},{3,4}}};"
config_suffix = '''
[[codegen.capture_keys]]
top_level = true
'''
expect_json_v2 = '''[{
"name": "a0",
"typePath": ["a0"],
"members": [
{
"name": "[]",
"typePath": ["a0","[]"],
"data": 1,
"members": [
{"name": "key", "typePath": ["a0","[]","key"]},
{"name": "value", "typePath": ["a0","[]","value"]}
]
},
{
"name": "[]",
"typePath": ["a0","[]"],
"data": 3,
"members": [
{"name": "key", "typePath": ["a0","[]","key"]},
{"name": "value", "typePath": ["a0","[]","value"]}
]
}
]
}]'''
[cases.string]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const std::map<std::string, int>&"]
setup = '''return
{{
{"abc", 1},
{"hohoho", 2}
}};'''
config_suffix = '''
[[codegen.capture_keys]]
top_level = true
'''
expect_json_v2 = '''[{
"name": "a0",
"typePath": ["a0"],
"members": [
{
"name": "[]",
"typePath": ["a0","[]"],
"data": "abc",
"members": [
{"name": "key", "typePath": ["a0","[]","key"]},
{"name": "value", "typePath": ["a0","[]","value"]}
]
},
{
"name": "[]",
"typePath": ["a0","[]"],
"data": "hohoho",
"members": [
{"name": "key", "typePath": ["a0","[]","key"]},
{"name": "value", "typePath": ["a0","[]","value"]}
]
}
]
}]'''
[cases.enum]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const std::map<MyEnum, int>&"]
setup = "return {{{MyEnum::One,2},{MyEnum::Three,4}}};"
config_suffix = '''
[[codegen.capture_keys]]
top_level = true
'''
expect_json_v2 = '''[{
"name": "a0",
"typePath": ["a0"],
"members": [
{
"name": "[]",
"typePath": ["a0","[]"],
"data": 1,
"members": [
{"name": "key", "typePath": ["a0","[]","key"]},
{"name": "value", "typePath": ["a0","[]","value"]}
]
},
{
"name": "[]",
"typePath": ["a0","[]"],
"data": 3,
"members": [
{"name": "key", "typePath": ["a0","[]","key"]},
{"name": "value", "typePath": ["a0","[]","value"]}
]
}
]
}]'''
[cases.multi_level]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const std::map<int, std::map<std::string, std::vector<int>>>&"]
setup = '''return
{{
{123, {
{"haha", {1,2}}
}},
{456, {
{"uh oh", {3}},
{"spaghettio", {4,5,6}}
}}
}};'''
config_suffix = '''
[[codegen.capture_keys]]
top_level = true
'''
expect_json_v2 = '''[{
"name": "a0",
"typePath": ["a0"],
"members": [
{
"name": "[]",
"typePath": ["a0","[]"],
"data": 123,
"members": [
{"name": "key", "typePath": ["a0","[]","key"]},
{
"name": "value",
"typePath": ["a0","[]","value"],
"members": [
{
"name": "[]",
"typePath": ["a0","[]","value","[]"],
"NOT":"data",
"members": [
{"name": "key", "typePath": ["a0","[]","value","[]","key"]},
{"name": "value", "typePath": ["a0","[]","value","[]","value"]}
]
}
]
}
]
},
{
"name": "[]",
"typePath": ["a0","[]"],
"data": 456,
"members": [
{"name": "key", "typePath": ["a0","[]","key"]},
{
"name": "value",
"typePath": ["a0","[]","value"],
"members": [
{
"name": "[]",
"typePath": ["a0","[]","value","[]"],
"NOT":"data",
"members": [
{"name": "key", "typePath": ["a0","[]","value","[]","key"]},
{"name": "value", "typePath": ["a0","[]","value","[]","value"]}
]
},
{
"name": "[]",
"typePath": ["a0","[]","value","[]"],
"NOT":"data",
"members": [
{"name": "key", "typePath": ["a0","[]","value","[]","key"]},
{"name": "value", "typePath": ["a0","[]","value","[]","value"]}
]
}
]
}
]
}
]
}]'''
[cases.config]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const MapHolder&"]
setup = '''return {MapHolder{
.captureMyKeys{ {1,2},{3,4} },
.dontCaptureKeysHere{ {5,6} },
}};'''
config_suffix = '''
[[codegen.capture_keys]]
type = "MapHolder"
members = ["captureMyKeys"]
'''
expect_json_v2 = '''[{
"members": [
{
"name": "captureMyKeys",
"typePath": ["a0","captureMyKeys"],
"members": [
{
"name": "[]",
"typePath": ["a0","captureMyKeys","[]"],
"data": 1,
"members": [
{"name": "key", "typePath": ["a0","captureMyKeys","[]","key"]},
{"name": "value", "typePath": ["a0","captureMyKeys","[]","value"]}
]
},
{
"name": "[]",
"typePath": ["a0","captureMyKeys","[]"],
"data": 3,
"members": [
{"name": "key", "typePath": ["a0","captureMyKeys","[]","key"]},
{"name": "value", "typePath": ["a0","captureMyKeys","[]","value"]}
]
}
]
},
{
"name": "dontCaptureKeysHere",
"typePath": ["a0","dontCaptureKeysHere"],
"members": [
{
"name": "[]",
"typePath": ["a0","dontCaptureKeysHere","[]"],
"NOT":"data",
"members": [
{"name": "key", "typePath": ["a0","dontCaptureKeysHere","[]","key"]},
{"name": "value", "typePath": ["a0","dontCaptureKeysHere","[]","value"]}
]
}
]
}
]
}]'''
[cases.std_unordered_map]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const std::unordered_map<int, int>&"]
setup = "return {{{1,2}}};"
config_suffix = '''
[[codegen.capture_keys]]
top_level = true
'''
expect_json_v2 = '[{"members": [{"data": 1}]}]'

View File

@ -76,7 +76,8 @@ auto tail = returnArg
for (const auto &entry: container) {
tail = tail.delegate([&key = entry.first, &value = entry.second](auto ret) {
auto next = ret.delegate([&key](typename TypeHandler<DB, T0>::type ret) {
auto start = maybeCaptureKey<captureKeys, DB, T0>(key, ret);
auto next = start.delegate([&key](typename TypeHandler<DB, T0>::type ret) {
return OIInternal::getSizeType<DB>(key, ret);
});
return OIInternal::getSizeType<DB>(value, next);
@ -92,9 +93,18 @@ func = "el.pointer = std::get<ParsedData::VarInt>(d.val).value;"
[[codegen.processor]]
type = """
types::st::List<DB, types::st::Pair<DB,
typename TypeHandler<DB, T0>::type,
typename TypeHandler<DB, T1>::type>>
std::conditional_t<captureKeys,
types::st::List<DB,
types::st::Pair<DB,
typename CaptureKeyHandler<DB, T0>::type,
types::st::Pair<DB,
typename TypeHandler<DB, T0>::type,
typename TypeHandler<DB, T1>::type>>>,
types::st::List<DB,
types::st::Pair<DB,
typename TypeHandler<DB, T0>::type,
typename TypeHandler<DB, T1>::type>>
>
"""
func = """
#ifdef __GLIBCXX__
@ -147,13 +157,16 @@ static constexpr std::array<inst::Field, 2> element_fields{
make_field<DB, T0>("key"),
make_field<DB, T1>("value"),
};
static constexpr auto processors = maybeCaptureKeysProcessor<captureKeys, DB, T0>();
static constexpr inst::Field element{
element_size,
element_size - sizeof(T0) - sizeof(T1),
"[]",
std::array<std::string_view, 0>{},
element_fields,
std::array<inst::ProcessorInst, 0>{},
processors,
};
auto list = std::get<ParsedData::List>(d.val);

View File

@ -33,8 +33,8 @@ void getSizeType(const %1%<K, T, H, KE, A> &container, size_t& returnArg)
for (auto const& it : container)
{
getSizeType(it.first, returnArg);
getSizeType(it.second, returnArg);
getSizeType(it.first, returnArg);
getSizeType(it.second, returnArg);
}
}
"""
@ -81,9 +81,13 @@ auto tail = returnArg
.write(container.bucket_count())
.write(container.size());
for (const auto &it : container) {
tail = tail.delegate([&it](auto ret) {
return OIInternal::getSizeType<DB>(it, ret);
for (const auto& kv : container) {
tail = tail.delegate([&kv](auto ret) {
auto start = maybeCaptureKey<captureKeys, DB, T0>(kv.first, ret);
auto next = start.delegate([&kv](typename TypeHandler<DB, T0>::type ret) {
return OIInternal::getSizeType<DB>(kv.first, ret);
});
return OIInternal::getSizeType<DB>(kv.second, next);
});
}
@ -108,9 +112,17 @@ el.container_stats.emplace(result::Element::ContainerStats {
[[codegen.processor]]
type = """
types::st::List<DB, types::st::Pair<DB,
typename TypeHandler<DB, T0>::type,
typename TypeHandler<DB, T1>::type>>
std::conditional_t<captureKeys,
types::st::List<DB,
types::st::Pair<DB,
typename CaptureKeyHandler<DB, T0>::type,
types::st::Pair<DB,
typename TypeHandler<DB, T0>::type,
typename TypeHandler<DB, T1>::type>>>,
types::st::List<DB, types::st::Pair<DB,
typename TypeHandler<DB, T0>::type,
typename TypeHandler<DB, T1>::type>>
>
"""
func = """
#ifdef __GLIBCXX__
@ -150,13 +162,15 @@ static constexpr std::array<inst::Field, 2> element_fields{
make_field<DB, T1>("value"),
};
static constexpr auto processors = maybeCaptureKeysProcessor<captureKeys, DB, T0>();
static constexpr auto element = inst::Field{
element_size,
element_size - sizeof(T0) - sizeof(T1),
"[]",
std::array<std::string_view, 0>{},
element_fields,
std::array<inst::ProcessorInst, 0>{},
processors,
};
for (size_t i = 0; i < list.length; i++)