Skip to content

Commit

Permalink
Fixed a few bugs, thanks to Clang
Browse files Browse the repository at this point in the history
  • Loading branch information
schombert committed Jan 20, 2023
1 parent 4fc506a commit 9a37516
Show file tree
Hide file tree
Showing 8 changed files with 1,393 additions and 27 deletions.
1 change: 0 additions & 1 deletion Catch_color_tutorial_tests/color_container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ float dcon::colored_thing_const_fat_id::get_blue() {
return get_color().blue;
}


void dcon::data_container::deserialize_rgb(std::byte const* start, std::byte const* end, load_record& record_in_out) {
if(!record_in_out.colored_thing_color) {
float const* found_red = nullptr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,6 @@ TEST_CASE("for compatactable remove in the other direction", "[core_datacontaine
REQUIRE(found_car == false);
}


TEST_CASE("for erasable basic relationship functions", "[core_datacontainer_tests]") {
auto ptr = std::make_unique< cob3::data_container >();

Expand Down
1 change: 1 addition & 0 deletions Catch_ecs_tutorial_tests/Catch_ecs_tutorial_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dcon::entity_id make_entity(dcon::data_container& dc) {
return dc.try_create_entity(dcon::position_id(), dcon::sprite_id());
}


TEST_CASE("destructor test", "[ecs_tutorial_tests]") {
auto ptr = std::make_unique<dcon::data_container>();

Expand Down
637 changes: 637 additions & 0 deletions Catch_serialization_tests/new_ser.hpp

Large diffs are not rendered by default.

637 changes: 637 additions & 0 deletions Catch_serialization_tests/old_ser.hpp

Large diffs are not rendered by default.

78 changes: 56 additions & 22 deletions CommonIncludes/unordered_dense.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
///////////////////////// ankerl::unordered_dense::{map, set} /////////////////////////

// A fast & densely stored hashmap and hashset based on robin-hood backward shift deletion.
// Version 2.0.0
// Version 3.0.2
// https://github.com/martinus/unordered_dense
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Expand Down Expand Up @@ -30,9 +30,9 @@
#define ANKERL_UNORDERED_DENSE_H

// see https://semver.org/spec/v2.0.0.html
#define ANKERL_UNORDERED_DENSE_VERSION_MAJOR 2 // NOLINT(cppcoreguidelines-macro-usage) incompatible API changes
#define ANKERL_UNORDERED_DENSE_VERSION_MAJOR 3 // NOLINT(cppcoreguidelines-macro-usage) incompatible API changes
#define ANKERL_UNORDERED_DENSE_VERSION_MINOR 0 // NOLINT(cppcoreguidelines-macro-usage) backwards compatible functionality
#define ANKERL_UNORDERED_DENSE_VERSION_PATCH 0 // NOLINT(cppcoreguidelines-macro-usage) backwards compatible bug fixes
#define ANKERL_UNORDERED_DENSE_VERSION_PATCH 2 // NOLINT(cppcoreguidelines-macro-usage) backwards compatible bug fixes

// API versioning with inline namespace, see https://www.foonathan.net/2018/11/inline-namespaces/
#define ANKERL_UNORDERED_DENSE_VERSION_CONCAT1(major, minor, patch) v##major##_##minor##_##patch
Expand Down Expand Up @@ -79,7 +79,15 @@
# if __has_include(<memory_resource>)
# undef ANKERL_UNORDERED_DENSE_PMR
# define ANKERL_UNORDERED_DENSE_PMR 1 // NOLINT(cppcoreguidelines-macro-usage)
# include <memory_resource> // for polymorphic_allocator
# define ANKERL_UNORDERED_DENSE_PMR_ALLOCATOR \
std::pmr::polymorphic_allocator // NOLINT(cppcoreguidelines-macro-usage)
# include <memory_resource> // for polymorphic_allocator
# elif __has_include(<experimental/memory_resource>)
# undef ANKERL_UNORDERED_DENSE_PMR
# define ANKERL_UNORDERED_DENSE_PMR 1 // NOLINT(cppcoreguidelines-macro-usage)
# define ANKERL_UNORDERED_DENSE_PMR_ALLOCATOR \
std::experimental::pmr::polymorphic_allocator // NOLINT(cppcoreguidelines-macro-usage)
# include <experimental/memory_resource> // for polymorphic_allocator
# endif
# endif

Expand Down Expand Up @@ -364,30 +372,48 @@ namespace ankerl::unordered_dense {
template <typename T>
using detect_iterator = typename T::iterator;

template <typename T>
using detect_reserve = decltype(std::declval<T&>().reserve(size_t{}));

// enable_if helpers

template <typename Mapped>
constexpr bool is_map_v = !std::is_void_v<Mapped>;

// clang-format off
template <typename Hash, typename KeyEqual>
constexpr bool is_transparent_v = is_detected_v<detect_is_transparent, Hash> && is_detected_v<detect_is_transparent, KeyEqual>;
// clang-format on

template <typename From, typename To1, typename To2>
constexpr bool is_neither_convertible_v = !std::is_convertible_v<From, To1> && !std::is_convertible_v<From, To2>;

template <typename T>
constexpr bool has_reserve = is_detected_v<detect_reserve, T>;

// base type for map has mapped_type
template <class T>
struct base_table_type_map {
using mapped_type = T;
};

// base type for set doesn't have mapped_type
struct base_table_type_set {
};

// This is it, the table. Doubles as map and set, and uses `void` for T when its used as a set.
template <class Key,
class T, // when void, treat it as a set.
class Hash,
class KeyEqual,
class AllocatorOrContainer,
class Bucket>
class table {
class table : public std::conditional_t<is_map_v<T>, base_table_type_map<T>, base_table_type_set> {
public:
using value_container_type = std::conditional_t<
is_detected_v<detect_iterator, AllocatorOrContainer>,
AllocatorOrContainer,
typename std::vector<typename std::conditional_t<std::is_void_v<T>, Key, std::pair<Key, T>>, AllocatorOrContainer>>;
typename std::vector<typename std::conditional_t<is_map_v<T>, std::pair<Key, T>, Key>, AllocatorOrContainer>>;

private:
using bucket_alloc =
Expand All @@ -399,7 +425,6 @@ namespace ankerl::unordered_dense {

public:
using key_type = Key;
using mapped_type = T;
using value_type = typename value_container_type::value_type;
using size_type = typename value_container_type::size_type;
using difference_type = typename value_container_type::difference_type;
Expand All @@ -410,8 +435,8 @@ namespace ankerl::unordered_dense {
using const_reference = typename value_container_type::const_reference;
using pointer = typename value_container_type::pointer;
using const_pointer = typename value_container_type::const_pointer;
using iterator = typename value_container_type::iterator;
using const_iterator = typename value_container_type::const_iterator;
using iterator = std::conditional_t<is_map_v<T>, typename value_container_type::iterator, const_iterator>;
using bucket_type = Bucket;

private:
Expand Down Expand Up @@ -478,10 +503,10 @@ namespace ankerl::unordered_dense {
}

[[nodiscard]] static constexpr auto get_key(value_type const& vt) -> key_type const& {
if constexpr(std::is_void_v<T>) {
return vt;
} else {
if constexpr(is_map_v<T>) {
return vt.first;
} else {
return vt;
}
}

Expand Down Expand Up @@ -748,13 +773,16 @@ namespace ankerl::unordered_dense {
: table(0) {
}

explicit table(size_t /*bucket_count*/,
explicit table(size_t bucket_count,
Hash const& hash = Hash(),
KeyEqual const& equal = KeyEqual(),
allocator_type const& alloc_or_container = allocator_type())
: m_values(alloc_or_container)
, m_hash(hash)
, m_equal(equal) {
if(0 != bucket_count) {
reserve(bucket_count);
}
}

table(size_t bucket_count, allocator_type const& alloc)
Expand Down Expand Up @@ -836,8 +864,10 @@ namespace ankerl::unordered_dense {
}

~table() {
auto ba = bucket_alloc(m_values.get_allocator());
bucket_alloc_traits::deallocate(ba, m_buckets, bucket_count());
if(nullptr != m_buckets) {
auto ba = bucket_alloc(m_values.get_allocator());
bucket_alloc_traits::deallocate(ba, m_buckets, bucket_count());
}
}

auto operator=(table const& other) -> table& {
Expand Down Expand Up @@ -1196,6 +1226,7 @@ namespace ankerl::unordered_dense {
return begin() + static_cast<difference_type>(value_idx_to_remove);
}

template <typename Q = T, std::enable_if_t<is_map_v<Q>, bool> = true>
auto erase(const_iterator it) -> iterator {
return erase(begin() + (it - cbegin()));
}
Expand Down Expand Up @@ -1387,7 +1418,10 @@ namespace ankerl::unordered_dense {

void reserve(size_t capa) {
capa = std::min(capa, max_size());
m_values.reserve(capa);
if constexpr(has_reserve<value_container_type>) {
// std::deque doesn't have reserve(). Make sure we only call when available
m_values.reserve(capa);
}
auto shifts = calc_shifts_for_size(std::max(capa, size()));
if(0 == m_num_buckets || shifts < m_shifts) {
m_shifts = shifts;
Expand Down Expand Up @@ -1423,14 +1457,14 @@ namespace ankerl::unordered_dense {
}
for(auto const& b_entry : b) {
auto it = a.find(get_key(b_entry));
if constexpr(std::is_void_v<T>) {
// set: only check that the key is here
if(a.end() == it) {
if constexpr(is_map_v<T>) {
// map: check that key is here, then also check that value is the same
if(a.end() == it || !(b_entry.second == it->second)) {
return false;
}
} else {
// map: check that key is here, then also check that value is the same
if(a.end() == it || !(b_entry.second == it->second)) {
// set: only check that the key is here
if(a.end() == it) {
return false;
}
}
Expand Down Expand Up @@ -1469,10 +1503,10 @@ namespace ankerl::unordered_dense {
class Hash = hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Bucket = bucket_type::standard>
using map = detail::table<Key, T, Hash, KeyEqual, std::pmr::polymorphic_allocator<std::pair<Key, T>>, Bucket>;
using map = detail::table<Key, T, Hash, KeyEqual, ANKERL_UNORDERED_DENSE_PMR_ALLOCATOR<std::pair<Key, T>>, Bucket>;

template <class Key, class Hash = hash<Key>, class KeyEqual = std::equal_to<Key>, class Bucket = bucket_type::standard>
using set = detail::table<Key, void, Hash, KeyEqual, std::pmr::polymorphic_allocator<Key>, Bucket>;
using set = detail::table<Key, void, Hash, KeyEqual, ANKERL_UNORDERED_DENSE_PMR_ALLOCATOR<Key>, Bucket>;

} // namespace pmr

Expand Down
60 changes: 57 additions & 3 deletions DataContainerGenerator/object_member_fragments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ void make_property_member_declarations(basic_builder& o, file_def const& parsed_
o + "#endif";
} else {
o + "DCON_RELEASE_INLINE void @namesp@set_@prop@(@index_type@ i, bool v) const" + block{
"container.@obj@_set_@prop@(id, i, v);";
o + "container.@obj@_set_@prop@(id, i, v);";
};
o + "DCON_RELEASE_INLINE void @namesp@resize_@prop@(uint32_t sz) const noexcept" + block{
o + "container.@obj@_resize_@prop@(sz);";
Expand Down Expand Up @@ -1930,6 +1930,25 @@ void join_setter_text(basic_builder& o, property_def const& ip, bool add_prefix,
};
}
break;
case property_type::object:
if(add_prefix) {
if(as_primary_key) {
o + "void @obj@_set_@prop@_from_@rel@(@obj@_id ref_id, @type@ const& val)" + block{
o + "@rel@_set_@prop@(@rel@_id(@rel@_id::value_base_t(ref_id.index())), val);";
};
} else {
o + "void @obj@_set_@prop@_from_@rel@(@obj@_id id, @type@ const& val)" + block{
o + "if(auto ref_id = @[email protected]_link_back_@[email protected]()[id.index()]; bool(ref_id))" + block{
o + "@rel@_set_@prop@(ref_id, val);";
};
};
}
} else {
o + "DCON_RELEASE_INLINE void @namesp@set_@prop@_from_@rel@(@type@ const& v) const noexcept" + block{
o + "container.@obj@_set_@prop@_from_@rel@(id, v);";
};
}
break;
case property_type::other:
break;
case property_type::array_bitfield:
Expand All @@ -1947,7 +1966,7 @@ void join_setter_text(basic_builder& o, property_def const& ip, bool add_prefix,
}
} else {
o + "DCON_RELEASE_INLINE void @namesp@set_@prop@_from_@rel@(@i_type@ i, bool v) const noexcept" + block{
"container.@obj@_set_@prop@_from_@rel@(id, i, v);";
o + "container.@obj@_set_@prop@_from_@rel@(id, i, v);";
};
}
break;
Expand All @@ -1968,7 +1987,7 @@ void join_setter_text(basic_builder& o, property_def const& ip, bool add_prefix,
}
} else {
o + "DCON_RELEASE_INLINE void @namesp@set_@prop@_from_@rel@(@i_type@ i, @type@ v) const noexcept" + block{
"container.@obj@_set_@prop@_from_@rel@(id, i, v);";
o + "container.@obj@_set_@prop@_from_@rel@(id, i, v);";
};
}
break;
Expand Down Expand Up @@ -2022,6 +2041,41 @@ void join_getter_text(basic_builder& o, property_def const& ip, bool add_prefix,
};
}
break;
case property_type::object:
if(add_prefix) {
if(ip.protection != protection_type::read_only && !ip.hook_set) {
if(as_primary_key) {
o + "@type@& @obj@_get_@prop@_from_@rel@(@obj@_id ref_id) const" + block{
o + "return @rel@_get_@prop@(@rel@_id(@rel@_id::value_base_t(ref_id.index())));";
};
} else {
o + "@type@& @obj@_get_@prop@_from_@rel@(@obj@_id id) const" + block{
o + "return @rel@_get_@prop@(@[email protected]_link_back_@[email protected]()[id.index()]);";
};
}
} else {
if(as_primary_key) {
o + "@type@ const& @obj@_get_@prop@_from_@rel@(@obj@_id ref_id) const" + block{
o + "return @rel@_get_@prop@(@rel@_id(@rel@_id::value_base_t(ref_id.index())));";
};
} else {
o + "@type@ const& @obj@_get_@prop@_from_@rel@(@obj@_id id) const" + block{
o + "return @rel@_get_@prop@(@[email protected]_link_back_@[email protected]()[id.index()]);";
};
}
}
} else {
if(ip.protection != protection_type::read_only && !ip.hook_set) {
o + "DCON_RELEASE_INLINE @type@& @namesp@get_@prop@_from_@rel@() const noexcept" + block{
o + "return container.@obj@_get_@prop@_from_@rel@(id);";
};
} else {
o + "DCON_RELEASE_INLINE @type@ const& @namesp@get_@prop@_from_@rel@() const noexcept" + block{
o + "return container.@obj@_get_@prop@_from_@rel@(id);";
};
}
}
break;
case property_type::vectorizable:
if(add_prefix) {
if(as_primary_key) {
Expand Down
5 changes: 5 additions & 0 deletions changes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
### version 0.2.1

- updated unordered_dense header
- Fixed a few bugs, thanks to Clang

### version 0.2.1

- updated unordered_dense header
- added an iterator interface (supporting `for(auto i : ...)` loops) for iterating over all of the object instances in the data container and all of the relationships linked via a `many` link to an object instance.

Expand Down

0 comments on commit 9a37516

Please sign in to comment.