Add a new HashMap implementation
Adds a new, cleaned up, HashMap implementation. * Uses Robin Hood Hashing (https://en.wikipedia.org/wiki/Hash_table#Robin_Hood_hashing). * Keeps elements in a double linked list for simpler, ordered, iteration. * Allows keeping iterators for later use in removal (Unlike Map<>, it does not do much for performance vs keeping the key, but helps replace old code). * Uses a more modern C++ iterator API, deprecates the old one. * Supports custom allocator (in case there is a wish to use a paged one). This class aims to unify all the associative template usage and replace it by this one: * Map<> (whereas key order does not matter, which is 99% of cases) * HashMap<> * OrderedHashMap<> * OAHashMap<>
This commit is contained in:
+15
-12
@@ -73,7 +73,7 @@ void ConfigFile::set_value(const String &p_section, const String &p_key, const V
|
||||
|
||||
} else {
|
||||
if (!values.has(p_section)) {
|
||||
values[p_section] = OrderedHashMap<String, Variant>();
|
||||
values[p_section] = HashMap<String, Variant>();
|
||||
}
|
||||
|
||||
values[p_section][p_key] = p_value;
|
||||
@@ -102,16 +102,16 @@ bool ConfigFile::has_section_key(const String &p_section, const String &p_key) c
|
||||
}
|
||||
|
||||
void ConfigFile::get_sections(List<String> *r_sections) const {
|
||||
for (OrderedHashMap<String, OrderedHashMap<String, Variant>>::ConstElement E = values.front(); E; E = E.next()) {
|
||||
r_sections->push_back(E.key());
|
||||
for (const KeyValue<String, HashMap<String, Variant>> &E : values) {
|
||||
r_sections->push_back(E.key);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigFile::get_section_keys(const String &p_section, List<String> *r_keys) const {
|
||||
ERR_FAIL_COND_MSG(!values.has(p_section), vformat("Cannot get keys from nonexistent section \"%s\".", p_section));
|
||||
|
||||
for (OrderedHashMap<String, Variant>::ConstElement E = values[p_section].front(); E; E = E.next()) {
|
||||
r_keys->push_back(E.key());
|
||||
for (const KeyValue<String, Variant> &E : values[p_section]) {
|
||||
r_keys->push_back(E.key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,18 +174,21 @@ Error ConfigFile::save_encrypted_pass(const String &p_path, const String &p_pass
|
||||
}
|
||||
|
||||
Error ConfigFile::_internal_save(Ref<FileAccess> file) {
|
||||
for (OrderedHashMap<String, OrderedHashMap<String, Variant>>::Element E = values.front(); E; E = E.next()) {
|
||||
if (E != values.front()) {
|
||||
bool first = true;
|
||||
for (const KeyValue<String, HashMap<String, Variant>> &E : values) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
file->store_string("\n");
|
||||
}
|
||||
if (!E.key().is_empty()) {
|
||||
file->store_string("[" + E.key() + "]\n\n");
|
||||
if (!E.key.is_empty()) {
|
||||
file->store_string("[" + E.key + "]\n\n");
|
||||
}
|
||||
|
||||
for (OrderedHashMap<String, Variant>::Element F = E.get().front(); F; F = F.next()) {
|
||||
for (const KeyValue<String, Variant> &F : E.value) {
|
||||
String vstr;
|
||||
VariantWriter::write_to_string(F.get(), vstr);
|
||||
file->store_string(F.key().property_name_encode() + "=" + vstr + "\n");
|
||||
VariantWriter::write_to_string(F.value, vstr);
|
||||
file->store_string(F.key.property_name_encode() + "=" + vstr + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,13 +33,13 @@
|
||||
|
||||
#include "core/io/file_access.h"
|
||||
#include "core/object/ref_counted.h"
|
||||
#include "core/templates/ordered_hash_map.h"
|
||||
#include "core/templates/hash_map.h"
|
||||
#include "core/variant/variant_parser.h"
|
||||
|
||||
class ConfigFile : public RefCounted {
|
||||
GDCLASS(ConfigFile, RefCounted);
|
||||
|
||||
OrderedHashMap<String, OrderedHashMap<String, Variant>> values;
|
||||
HashMap<String, HashMap<String, Variant>> values;
|
||||
|
||||
PackedStringArray _get_sections() const;
|
||||
PackedStringArray _get_section_keys(const String &p_section) const;
|
||||
|
||||
@@ -53,8 +53,8 @@ bool MissingResource::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
}
|
||||
|
||||
void MissingResource::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
for (OrderedHashMap<StringName, Variant>::ConstElement E = properties.front(); E; E = E.next()) {
|
||||
p_list->push_back(PropertyInfo(E.value().get_type(), E.key()));
|
||||
for (const KeyValue<StringName, Variant> &E : properties) {
|
||||
p_list->push_back(PropertyInfo(E.value.get_type(), E.key));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
class MissingResource : public Resource {
|
||||
GDCLASS(MissingResource, Resource)
|
||||
OrderedHashMap<StringName, Variant> properties;
|
||||
HashMap<StringName, Variant> properties;
|
||||
|
||||
String original_class;
|
||||
bool recording_properties = false;
|
||||
|
||||
+6
-11
@@ -478,10 +478,8 @@ void ResourceCache::clear() {
|
||||
if (resources.size()) {
|
||||
ERR_PRINT("Resources still in use at exit (run with --verbose for details).");
|
||||
if (OS::get_singleton()->is_stdout_verbose()) {
|
||||
const String *K = nullptr;
|
||||
while ((K = resources.next(K))) {
|
||||
Resource *r = resources[*K];
|
||||
print_line(vformat("Resource still in use: %s (%s)", *K, r->get_class()));
|
||||
for (const KeyValue<String, Resource *> &E : resources) {
|
||||
print_line(vformat("Resource still in use: %s (%s)", E.key, E.value->get_class()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -516,10 +514,8 @@ Resource *ResourceCache::get(const String &p_path) {
|
||||
|
||||
void ResourceCache::get_cached_resources(List<Ref<Resource>> *p_resources) {
|
||||
lock.read_lock();
|
||||
const String *K = nullptr;
|
||||
while ((K = resources.next(K))) {
|
||||
Resource *r = resources[*K];
|
||||
p_resources->push_back(Ref<Resource>(r));
|
||||
for (KeyValue<String, Resource *> &E : resources) {
|
||||
p_resources->push_back(Ref<Resource>(E.value));
|
||||
}
|
||||
lock.read_unlock();
|
||||
}
|
||||
@@ -544,9 +540,8 @@ void ResourceCache::dump(const char *p_file, bool p_short) {
|
||||
ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file at path '" + String::utf8(p_file) + "'.");
|
||||
}
|
||||
|
||||
const String *K = nullptr;
|
||||
while ((K = resources.next(K))) {
|
||||
Resource *r = resources[*K];
|
||||
for (KeyValue<String, Resource *> &E : resources) {
|
||||
Resource *r = E.value;
|
||||
|
||||
if (!type_count.has(r->get_class())) {
|
||||
type_count[r->get_class()] = 0;
|
||||
|
||||
+11
-11
@@ -149,12 +149,12 @@ Error ResourceUID::save_to_cache() {
|
||||
|
||||
cache_entries = 0;
|
||||
|
||||
for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) {
|
||||
f->store_64(E.key());
|
||||
uint32_t s = E.get().cs.length();
|
||||
for (KeyValue<ID, Cache> &E : unique_ids) {
|
||||
f->store_64(E.key);
|
||||
uint32_t s = E.value.cs.length();
|
||||
f->store_32(s);
|
||||
f->store_buffer((const uint8_t *)E.get().cs.ptr(), s);
|
||||
E.get().saved_to_cache = true;
|
||||
f->store_buffer((const uint8_t *)E.value.cs.ptr(), s);
|
||||
E.value.saved_to_cache = true;
|
||||
cache_entries++;
|
||||
}
|
||||
|
||||
@@ -202,8 +202,8 @@ Error ResourceUID::update_cache() {
|
||||
MutexLock l(mutex);
|
||||
|
||||
Ref<FileAccess> f;
|
||||
for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) {
|
||||
if (!E.get().saved_to_cache) {
|
||||
for (KeyValue<ID, Cache> &E : unique_ids) {
|
||||
if (!E.value.saved_to_cache) {
|
||||
if (f.is_null()) {
|
||||
f = FileAccess::open(get_cache_file(), FileAccess::READ_WRITE); //append
|
||||
if (f.is_null()) {
|
||||
@@ -211,11 +211,11 @@ Error ResourceUID::update_cache() {
|
||||
}
|
||||
f->seek_end();
|
||||
}
|
||||
f->store_64(E.key());
|
||||
uint32_t s = E.get().cs.length();
|
||||
f->store_64(E.key);
|
||||
uint32_t s = E.value.cs.length();
|
||||
f->store_32(s);
|
||||
f->store_buffer((const uint8_t *)E.get().cs.ptr(), s);
|
||||
E.get().saved_to_cache = true;
|
||||
f->store_buffer((const uint8_t *)E.value.cs.ptr(), s);
|
||||
E.value.saved_to_cache = true;
|
||||
cache_entries++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
#include "core/string/string_name.h"
|
||||
#include "core/templates/ordered_hash_map.h"
|
||||
#include "core/templates/hash_map.h"
|
||||
|
||||
class ResourceUID : public Object {
|
||||
GDCLASS(ResourceUID, Object)
|
||||
@@ -53,7 +53,7 @@ private:
|
||||
bool saved_to_cache = false;
|
||||
};
|
||||
|
||||
OrderedHashMap<ID, Cache> unique_ids; //unique IDs and utf8 paths (less memory used)
|
||||
HashMap<ID, Cache> unique_ids; //unique IDs and utf8 paths (less memory used)
|
||||
static ResourceUID *singleton;
|
||||
|
||||
uint32_t cache_entries = 0;
|
||||
|
||||
Reference in New Issue
Block a user