Core: Expand std::initializer_list support

This commit is contained in:
Thaddeus Crews
2024-08-21 13:32:25 -05:00
parent fafc07335b
commit 361e3b4fe8
17 changed files with 177 additions and 9 deletions

View File

@@ -703,6 +703,13 @@ public:
capacity(INITIAL_CAPACITY - 1) { capacity(INITIAL_CAPACITY - 1) {
} }
AHashMap(std::initializer_list<KeyValue<TKey, TValue>> p_init) {
reserve(p_init.size());
for (const KeyValue<TKey, TValue> &E : p_init) {
insert(E.key, E.value);
}
}
void reset() { void reset() {
if (elements != nullptr) { if (elements != nullptr) {
if constexpr (!(std::is_trivially_destructible_v<TKey> && std::is_trivially_destructible_v<TValue>)) { if constexpr (!(std::is_trivially_destructible_v<TKey> && std::is_trivially_destructible_v<TValue>)) {

View File

@@ -36,6 +36,7 @@
#include "core/templates/safe_refcount.h" #include "core/templates/safe_refcount.h"
#include <string.h> #include <string.h>
#include <initializer_list>
#include <type_traits> #include <type_traits>
template <typename T> template <typename T>
@@ -250,6 +251,7 @@ public:
_FORCE_INLINE_ CowData() {} _FORCE_INLINE_ CowData() {}
_FORCE_INLINE_ ~CowData(); _FORCE_INLINE_ ~CowData();
_FORCE_INLINE_ CowData(std::initializer_list<T> p_init);
_FORCE_INLINE_ CowData(const CowData<T> &p_from) { _ref(p_from); } _FORCE_INLINE_ CowData(const CowData<T> &p_from) { _ref(p_from); }
_FORCE_INLINE_ CowData(CowData<T> &&p_from) { _FORCE_INLINE_ CowData(CowData<T> &&p_from) {
_ptr = p_from._ptr; _ptr = p_from._ptr;
@@ -492,6 +494,19 @@ CowData<T>::~CowData() {
_unref(); _unref();
} }
template <typename T>
CowData<T>::CowData(std::initializer_list<T> p_init) {
Error err = resize(p_init.size());
if (err != OK) {
return;
}
Size i = 0;
for (const T &element : p_init) {
set(i++, element);
}
}
#if defined(__GNUC__) && !defined(__clang__) #if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif

View File

@@ -37,6 +37,8 @@
#include "core/templates/paged_allocator.h" #include "core/templates/paged_allocator.h"
#include "core/templates/pair.h" #include "core/templates/pair.h"
#include <initializer_list>
/** /**
* A HashMap implementation that uses open addressing with Robin Hood hashing. * A HashMap implementation that uses open addressing with Robin Hood hashing.
* Robin Hood hashing swaps out entries that have a smaller probing distance * Robin Hood hashing swaps out entries that have a smaller probing distance
@@ -640,6 +642,13 @@ public:
capacity_index = MIN_CAPACITY_INDEX; capacity_index = MIN_CAPACITY_INDEX;
} }
HashMap(std::initializer_list<KeyValue<TKey, TValue>> p_init) {
reserve(p_init.size());
for (const KeyValue<TKey, TValue> &E : p_init) {
insert(E.key, E.value);
}
}
uint32_t debug_get_hash(uint32_t p_index) { uint32_t debug_get_hash(uint32_t p_index) {
if (num_elements == 0) { if (num_elements == 0) {
return 0; return 0;

View File

@@ -445,6 +445,13 @@ public:
capacity_index = MIN_CAPACITY_INDEX; capacity_index = MIN_CAPACITY_INDEX;
} }
HashSet(std::initializer_list<TKey> p_init) {
reserve(p_init.size());
for (const TKey &E : p_init) {
insert(E);
}
}
void reset() { void reset() {
clear(); clear();

View File

@@ -35,6 +35,8 @@
#include "core/os/memory.h" #include "core/os/memory.h"
#include "core/templates/sort_array.h" #include "core/templates/sort_array.h"
#include <initializer_list>
/** /**
* Generic Templatized Linked List Implementation. * Generic Templatized Linked List Implementation.
* The implementation differs from the STL one because * The implementation differs from the STL one because
@@ -763,6 +765,12 @@ public:
List() {} List() {}
List(std::initializer_list<T> p_init) {
for (const T &E : p_init) {
push_back(E);
}
}
~List() { ~List() {
clear(); clear();
if (_data) { if (_data) {

View File

@@ -34,6 +34,7 @@
#include "core/math/math_funcs.h" #include "core/math/math_funcs.h"
#include "core/os/memory.h" #include "core/os/memory.h"
#include "core/templates/hashfuncs.h" #include "core/templates/hashfuncs.h"
#include "core/templates/pair.h"
/** /**
* A HashMap implementation that uses open addressing with Robin Hood hashing. * A HashMap implementation that uses open addressing with Robin Hood hashing.
@@ -353,6 +354,13 @@ public:
return it; return it;
} }
OAHashMap(std::initializer_list<KeyValue<TKey, TValue>> p_init) {
reserve(p_init.size());
for (const KeyValue<TKey, TValue> &E : p_init) {
set(E.key, E.value);
}
}
OAHashMap(const OAHashMap &p_other) { OAHashMap(const OAHashMap &p_other) {
(*this) = p_other; (*this) = p_other;
} }

View File

@@ -35,6 +35,8 @@
#include "core/os/memory.h" #include "core/os/memory.h"
#include "core/templates/pair.h" #include "core/templates/pair.h"
#include <initializer_list>
// based on the very nice implementation of rb-trees by: // based on the very nice implementation of rb-trees by:
// https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html // https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
@@ -763,6 +765,12 @@ public:
_copy_from(p_map); _copy_from(p_map);
} }
RBMap(std::initializer_list<KeyValue<K, V>> p_init) {
for (const KeyValue<K, V> &E : p_init) {
insert(E.key, E.value);
}
}
_FORCE_INLINE_ RBMap() {} _FORCE_INLINE_ RBMap() {}
~RBMap() { ~RBMap() {

View File

@@ -34,6 +34,8 @@
#include "core/os/memory.h" #include "core/os/memory.h"
#include "core/typedefs.h" #include "core/typedefs.h"
#include <initializer_list>
// based on the very nice implementation of rb-trees by: // based on the very nice implementation of rb-trees by:
// https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html // https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
@@ -701,6 +703,12 @@ public:
_copy_from(p_set); _copy_from(p_set);
} }
RBSet(std::initializer_list<T> p_init) {
for (const T &E : p_init) {
insert(E);
}
}
_FORCE_INLINE_ RBSet() {} _FORCE_INLINE_ RBSet() {}
~RBSet() { ~RBSet() {

View File

@@ -36,6 +36,7 @@
#include <atomic> #include <atomic>
#include <functional> #include <functional>
#include <initializer_list>
#include <type_traits> #include <type_traits>
// Design goals for these classes: // Design goals for these classes:
@@ -226,6 +227,13 @@ public:
return true; return true;
} }
_FORCE_INLINE_ SafeList() {}
_FORCE_INLINE_ SafeList(std::initializer_list<T> p_init) {
for (const T &E : p_init) {
insert(E);
}
}
~SafeList() { ~SafeList() {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (!maybe_cleanup()) { if (!maybe_cleanup()) {

View File

@@ -283,15 +283,8 @@ public:
} }
_FORCE_INLINE_ Vector() {} _FORCE_INLINE_ Vector() {}
_FORCE_INLINE_ Vector(std::initializer_list<T> p_init) { _FORCE_INLINE_ Vector(std::initializer_list<T> p_init) :
Error err = _cowdata.resize(p_init.size()); _cowdata(p_init) {}
ERR_FAIL_COND(err);
Size i = 0;
for (const T &element : p_init) {
_cowdata.set(i++, element);
}
}
_FORCE_INLINE_ Vector(const Vector &p_from) { _cowdata._ref(p_from._cowdata); } _FORCE_INLINE_ Vector(const Vector &p_from) { _cowdata._ref(p_from._cowdata); }
_FORCE_INLINE_ Vector(Vector &&p_from) : _FORCE_INLINE_ Vector(Vector &&p_from) :
_cowdata(std::move(p_from._cowdata)) {} _cowdata(std::move(p_from._cowdata)) {}

View File

@@ -194,6 +194,8 @@ public:
} }
_FORCE_INLINE_ VMap() {} _FORCE_INLINE_ VMap() {}
_FORCE_INLINE_ VMap(std::initializer_list<T> p_init) :
_cowdata(p_init) {}
_FORCE_INLINE_ VMap(const VMap &p_from) { _cowdata._ref(p_from._cowdata); } _FORCE_INLINE_ VMap(const VMap &p_from) { _cowdata._ref(p_from._cowdata); }
inline void operator=(const VMap &p_from) { inline void operator=(const VMap &p_from) {

View File

@@ -137,6 +137,10 @@ public:
inline const T &operator[](int p_index) const { inline const T &operator[](int p_index) const {
return _data[p_index]; return _data[p_index];
} }
_FORCE_INLINE_ VSet() {}
_FORCE_INLINE_ VSet(std::initializer_list<T> p_init) :
_data(p_init) {}
}; };
#endif // VSET_H #endif // VSET_H

View File

@@ -37,6 +37,24 @@
namespace TestAHashMap { namespace TestAHashMap {
TEST_CASE("[AHashMap] List initialization") {
AHashMap<int, String> map{ { 0, "A" }, { 1, "B" }, { 2, "C" }, { 3, "D" }, { 4, "E" } };
CHECK(map.size() == 5);
CHECK(map[0] == "A");
CHECK(map[1] == "B");
CHECK(map[2] == "C");
CHECK(map[3] == "D");
CHECK(map[4] == "E");
}
TEST_CASE("[AHashMap] List initialization with existing elements") {
AHashMap<int, String> map{ { 0, "A" }, { 0, "B" }, { 0, "C" }, { 0, "D" }, { 0, "E" } };
CHECK(map.size() == 1);
CHECK(map[0] == "E");
}
TEST_CASE("[AHashMap] Insert element") { TEST_CASE("[AHashMap] Insert element") {
AHashMap<int, int> map; AHashMap<int, int> map;
AHashMap<int, int>::Iterator e = map.insert(42, 84); AHashMap<int, int>::Iterator e = map.insert(42, 84);

View File

@@ -37,6 +37,24 @@
namespace TestHashMap { namespace TestHashMap {
TEST_CASE("[HashMap] List initialization") {
HashMap<int, String> map{ { 0, "A" }, { 1, "B" }, { 2, "C" }, { 3, "D" }, { 4, "E" } };
CHECK(map.size() == 5);
CHECK(map[0] == "A");
CHECK(map[1] == "B");
CHECK(map[2] == "C");
CHECK(map[3] == "D");
CHECK(map[4] == "E");
}
TEST_CASE("[HashMap] List initialization with existing elements") {
HashMap<int, String> map{ { 0, "A" }, { 0, "B" }, { 0, "C" }, { 0, "D" }, { 0, "E" } };
CHECK(map.size() == 1);
CHECK(map[0] == "E");
}
TEST_CASE("[HashMap] Insert element") { TEST_CASE("[HashMap] Insert element") {
HashMap<int, int> map; HashMap<int, int> map;
HashMap<int, int>::Iterator e = map.insert(42, 84); HashMap<int, int>::Iterator e = map.insert(42, 84);

View File

@@ -37,6 +37,24 @@
namespace TestHashSet { namespace TestHashSet {
TEST_CASE("[HashSet] List initialization") {
HashSet<int> set{ 0, 1, 2, 3, 4 };
CHECK(set.size() == 5);
CHECK(set.has(0));
CHECK(set.has(1));
CHECK(set.has(2));
CHECK(set.has(3));
CHECK(set.has(4));
}
TEST_CASE("[HashSet] List initialization with existing elements") {
HashSet<int> set{ 0, 0, 0, 0, 0 };
CHECK(set.size() == 1);
CHECK(set.has(0));
}
TEST_CASE("[HashSet] Insert element") { TEST_CASE("[HashSet] Insert element") {
HashSet<int> set; HashSet<int> set;
HashSet<int>::Iterator e = set.insert(42); HashSet<int>::Iterator e = set.insert(42);

View File

@@ -45,6 +45,17 @@ static void populate_integers(List<int> &p_list, List<int>::Element *r_elements[
} }
} }
TEST_CASE("[List] List initialization") {
List<int> list{ 0, 1, 2, 3, 4 };
CHECK(list.size() == 5);
CHECK(list.get(0) == 0);
CHECK(list.get(1) == 1);
CHECK(list.get(2) == 2);
CHECK(list.get(3) == 3);
CHECK(list.get(4) == 4);
}
TEST_CASE("[List] Push/pop back") { TEST_CASE("[List] Push/pop back") {
List<String> list; List<String> list;

View File

@@ -38,6 +38,32 @@
namespace TestOAHashMap { namespace TestOAHashMap {
TEST_CASE("[OAHashMap] List initialization") {
OAHashMap<int, String> map{ { 0, "A" }, { 1, "B" }, { 2, "C" }, { 3, "D" }, { 4, "E" } };
CHECK(map.get_num_elements() == 5);
String value;
CHECK(map.lookup(0, value));
CHECK(value == "A");
CHECK(map.lookup(1, value));
CHECK(value == "B");
CHECK(map.lookup(2, value));
CHECK(value == "C");
CHECK(map.lookup(3, value));
CHECK(value == "D");
CHECK(map.lookup(4, value));
CHECK(value == "E");
}
TEST_CASE("[OAHashMap] List initialization with existing elements") {
OAHashMap<int, String> map{ { 0, "A" }, { 0, "B" }, { 0, "C" }, { 0, "D" }, { 0, "E" } };
CHECK(map.get_num_elements() == 1);
String value;
CHECK(map.lookup(0, value));
CHECK(value == "E");
}
TEST_CASE("[OAHashMap] Insert element") { TEST_CASE("[OAHashMap] Insert element") {
OAHashMap<int, int> map; OAHashMap<int, int> map;
map.insert(42, 84); map.insert(42, 84);