Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DictionaryTrait #573

Merged
merged 12 commits into from
Sep 28, 2023
1 change: 1 addition & 0 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ set(CUBOS_CORE_SOURCE
"src/cubos/core/reflection/traits/constructible.cpp"
"src/cubos/core/reflection/traits/fields.cpp"
"src/cubos/core/reflection/traits/array.cpp"
"src/cubos/core/reflection/traits/dictionary.cpp"
"src/cubos/core/reflection/external/primitives.cpp"

"src/cubos/core/data/serializer.cpp"
Expand Down
115 changes: 115 additions & 0 deletions core/include/cubos/core/reflection/external/map.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/// @file
/// @brief Reflection declaration for `std::map`.
/// @ingroup core-reflection

#pragma once

#include <map>

#include <cubos/core/reflection/traits/constructible_utils.hpp>
#include <cubos/core/reflection/traits/dictionary.hpp>
#include <cubos/core/reflection/type.hpp>

CUBOS_REFLECT_EXTERNAL_TEMPLATE((typename K, typename V), (std::map<K, V>))
{
using Map = std::map<K, V>;

auto dictionaryTrait = DictionaryTrait(
reflect<K>(), reflect<V>(),
[](const void* instance) -> std::size_t { return static_cast<const Map*>(instance)->size(); } /*length*/,
[](uintptr_t instance, bool writeable) -> void* {
if (writeable)
{
return new typename Map::iterator(reinterpret_cast<Map*>(instance)->begin());
}

return new typename Map::const_iterator(reinterpret_cast<const Map*>(instance)->cbegin());
} /*begin*/,
[](uintptr_t instance, const void* key, bool writeable) -> void* {
if (writeable)
{
auto it = reinterpret_cast<Map*>(instance)->find(*reinterpret_cast<const K*>(key));
if (it == reinterpret_cast<Map*>(instance)->end())
{
return nullptr;
}
return new typename Map::iterator(it);
}

auto it = reinterpret_cast<const Map*>(instance)->find(*reinterpret_cast<const K*>(key));
if (it == reinterpret_cast<const Map*>(instance)->end())
{
return nullptr;
}
return new typename Map::const_iterator(it);

Check warning on line 44 in core/include/cubos/core/reflection/external/map.hpp

View check run for this annotation

Codecov / codecov/patch

core/include/cubos/core/reflection/external/map.hpp#L44

Added line #L44 was not covered by tests
} /*find*/,
[](uintptr_t instance, void* iterator, bool writeable) -> bool {
if (writeable)
{
++*static_cast<typename Map::iterator*>(iterator);
return *static_cast<typename Map::iterator*>(iterator) != reinterpret_cast<Map*>(instance)->end();
}

++*static_cast<typename Map::const_iterator*>(iterator);
return *static_cast<typename Map::const_iterator*>(iterator) !=
reinterpret_cast<const Map*>(instance)->cend();

Check warning on line 55 in core/include/cubos/core/reflection/external/map.hpp

View check run for this annotation

Codecov / codecov/patch

core/include/cubos/core/reflection/external/map.hpp#L53-L55

Added lines #L53 - L55 were not covered by tests
} /*advance*/,
[](void* iterator, bool writeable) {
if (writeable)
{
delete static_cast<typename Map::iterator*>(iterator);
}
else
{
delete static_cast<typename Map::const_iterator*>(iterator);

Check warning on line 64 in core/include/cubos/core/reflection/external/map.hpp

View check run for this annotation

Codecov / codecov/patch

core/include/cubos/core/reflection/external/map.hpp#L64

Added line #L64 was not covered by tests
}
} /*stop*/,
[](const void* iterator, bool writeable) -> const void* {
if (writeable)
{
return &(*static_cast<const typename Map::iterator*>(iterator))->first;
}

return &(*static_cast<const typename Map::const_iterator*>(iterator))->first;
} /*key*/,
[](const void* iterator, bool writeable) -> uintptr_t {
if (writeable)
{
return reinterpret_cast<uintptr_t>(&(*static_cast<const typename Map::iterator*>(iterator))->second);
}

return reinterpret_cast<uintptr_t>(&(*static_cast<const typename Map::const_iterator*>(iterator))->second);
} /*value*/);

// We supply the insert functions depending on the constructibility of the value type.

if constexpr (std::is_default_constructible<V>::value)
{
dictionaryTrait.setInsertDefault([](void* instance, const void* key) {
auto* map = static_cast<Map*>(instance);
map->emplace(std::piecewise_construct, std::make_tuple(*static_cast<const K*>(key)), std::make_tuple());
});
}

if constexpr (std::is_copy_constructible<V>::value)
{
dictionaryTrait.setInsertCopy([](void* instance, const void* key, const void* value) {
auto* map = static_cast<Map*>(instance);
map->emplace(*static_cast<const K*>(key), *static_cast<const V*>(value));
});
}

// Since V must be moveable for all std::map<K, V>, we always supply this function.
dictionaryTrait.setInsertMove([](void* instance, const void* key, void* value) {
auto* map = static_cast<Map*>(instance);
map->emplace(*static_cast<const K*>(key), std::move(*static_cast<V*>(value)));
});

dictionaryTrait.setErase([](void* instance, const void* iterator) {
static_cast<Map*>(instance)->erase(*static_cast<const typename Map::iterator*>(iterator));
});

return Type::create("std::map<" + reflect<K>().name() + ", " + reflect<V>().name() + ">")
.with(dictionaryTrait)
.with(autoConstructibleTrait<std::map<K, V>>());
}
115 changes: 115 additions & 0 deletions core/include/cubos/core/reflection/external/unordered_map.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/// @file
/// @brief Reflection declaration for `std::unordered_map`.
/// @ingroup core-reflection

#pragma once

#include <unordered_map>

#include <cubos/core/reflection/traits/constructible_utils.hpp>
#include <cubos/core/reflection/traits/dictionary.hpp>
#include <cubos/core/reflection/type.hpp>

CUBOS_REFLECT_EXTERNAL_TEMPLATE((typename K, typename V), (std::unordered_map<K, V>))
{
using Map = std::unordered_map<K, V>;

auto dictionaryTrait = DictionaryTrait(
reflect<K>(), reflect<V>(),
[](const void* instance) -> std::size_t { return static_cast<const Map*>(instance)->size(); } /*length*/,
[](uintptr_t instance, bool writeable) -> void* {
if (writeable)
{
return new typename Map::iterator(reinterpret_cast<Map*>(instance)->begin());
}

return new typename Map::const_iterator(reinterpret_cast<const Map*>(instance)->cbegin());
} /*begin*/,
[](uintptr_t instance, const void* key, bool writeable) -> void* {
if (writeable)
{
auto it = reinterpret_cast<Map*>(instance)->find(*reinterpret_cast<const K*>(key));
if (it == reinterpret_cast<Map*>(instance)->end())
{
return nullptr;
}
return new typename Map::iterator(it);
}

auto it = reinterpret_cast<const Map*>(instance)->find(*reinterpret_cast<const K*>(key));
if (it == reinterpret_cast<const Map*>(instance)->end())
{
return nullptr;
}
return new typename Map::const_iterator(it);

Check warning on line 44 in core/include/cubos/core/reflection/external/unordered_map.hpp

View check run for this annotation

Codecov / codecov/patch

core/include/cubos/core/reflection/external/unordered_map.hpp#L44

Added line #L44 was not covered by tests
} /*find*/,
[](uintptr_t instance, void* iterator, bool writeable) {
if (writeable)
{
++*static_cast<typename Map::iterator*>(iterator);
return *static_cast<typename Map::iterator*>(iterator) != reinterpret_cast<Map*>(instance)->end();
}

++*static_cast<typename Map::const_iterator*>(iterator);
return *static_cast<typename Map::const_iterator*>(iterator) !=
reinterpret_cast<const Map*>(instance)->cend();

Check warning on line 55 in core/include/cubos/core/reflection/external/unordered_map.hpp

View check run for this annotation

Codecov / codecov/patch

core/include/cubos/core/reflection/external/unordered_map.hpp#L53-L55

Added lines #L53 - L55 were not covered by tests
} /*advance*/,
[](void* iterator, bool writeable) {
if (writeable)
{
delete static_cast<typename Map::iterator*>(iterator);
}
else
{
delete static_cast<typename Map::const_iterator*>(iterator);

Check warning on line 64 in core/include/cubos/core/reflection/external/unordered_map.hpp

View check run for this annotation

Codecov / codecov/patch

core/include/cubos/core/reflection/external/unordered_map.hpp#L64

Added line #L64 was not covered by tests
}
} /*stop*/,
[](const void* iterator, bool writeable) -> const void* {
if (writeable)
{
return &(*static_cast<const typename Map::iterator*>(iterator))->first;
}

return &(*static_cast<const typename Map::const_iterator*>(iterator))->first;
} /*key*/,
[](const void* iterator, bool writeable) -> uintptr_t {
if (writeable)
{
return reinterpret_cast<uintptr_t>(&(*static_cast<const typename Map::iterator*>(iterator))->second);
}

return reinterpret_cast<uintptr_t>(&(*static_cast<const typename Map::const_iterator*>(iterator))->second);
} /*value*/);

// We supply the insert functions depending on the constructibility of the value type.

if constexpr (std::is_default_constructible<V>::value)
{
dictionaryTrait.setInsertDefault([](void* instance, const void* key) {
auto* map = static_cast<Map*>(instance);
map->emplace(std::piecewise_construct, std::make_tuple(*static_cast<const K*>(key)), std::make_tuple());
});
}

if constexpr (std::is_copy_constructible<V>::value)
{
dictionaryTrait.setInsertCopy([](void* instance, const void* key, const void* value) {
auto* map = static_cast<Map*>(instance);
map->emplace(*static_cast<const K*>(key), *static_cast<const V*>(value));
});
}

// Since V must be moveable for all std::unordered_map<K, V>, we always supply this function.
dictionaryTrait.setInsertMove([](void* instance, const void* key, void* value) {
auto* map = static_cast<Map*>(instance);
map->emplace(*static_cast<const K*>(key), std::move(*static_cast<V*>(value)));
});

dictionaryTrait.setErase([](void* instance, const void* iterator) {
static_cast<Map*>(instance)->erase(*static_cast<const typename Map::iterator*>(iterator));
});

return Type::create("std::unordered_map<" + reflect<K>().name() + ", " + reflect<V>().name() + ">")
.with(dictionaryTrait)
.with(autoConstructibleTrait<std::unordered_map<K, V>>());
}
Loading
Loading