sorted vector instead hash map for property block

This commit is contained in:
2019-04-06 21:18:35 +07:00
parent 400da781b8
commit 061078d0bc
3 changed files with 168 additions and 40 deletions

View File

@@ -615,13 +615,49 @@ namespace e2d
v2f, v3f, v4f,
m2f, m3f, m4f>;
template < typename T >
class property_map final {
public:
property_map() = default;
property_map(property_map&& other) = default;
property_map& operator=(property_map&& other) = default;
property_map(const property_map& other) = default;
property_map& operator=(const property_map& other) = default;
T* find(str_hash key) noexcept;
const T* find(str_hash key) const noexcept;
void assign(str_hash key, T&& value);
void assign(str_hash key, const T& value);
void clear() noexcept;
std::size_t size() const noexcept;
template < typename F >
void foreach(F&& f) const;
void merge(const property_map& other);
bool equals(const property_map& other) const noexcept;
private:
struct entry {
str_hash key;
T value;
public:
entry(str_hash k, T&& v);
entry(str_hash k, const T& v);
bool operator==(const entry& other) const;
};
vector<entry> entries_;
};
class property_block final {
public:
property_block() = default;
~property_block() noexcept = default;
property_block(property_block&&) noexcept = default;
property_block& operator=(property_block&&) noexcept = default;
property_block(property_block&&) = default;
property_block& operator=(property_block&&) = default;
property_block(const property_block&) = default;
property_block& operator=(const property_block&) = default;
@@ -652,8 +688,8 @@ namespace e2d
std::size_t sampler_count() const noexcept;
std::size_t property_count() const noexcept;
private:
hash_map<str_hash, sampler_state> samplers_;
hash_map<str_hash, property_value> properties_;
property_map<sampler_state> samplers_;
property_map<property_value> properties_;
};
class pass_state final {

View File

@@ -75,36 +75,138 @@ namespace e2d
#undef DEFINE_ADD_ATTRIBUTE_SPECIALIZATION
//
// render::property_map::entry
//
template < typename T >
render::property_map<T>::entry::entry(str_hash k, T&& v)
: key(k), value(std::move(v)) {}
template < typename T >
render::property_map<T>::entry::entry(str_hash k, const T& v)
: key(k), value(v) {}
template < typename T >
bool render::property_map<T>::entry::operator==(const entry& other) const {
return key == other.key
&& value == other.value;
}
//
// render::property_map
//
template < typename T >
T* render::property_map<T>::find(str_hash key) noexcept {
const auto iter = std::lower_bound(
entries_.begin(), entries_.end(), key,
[](const entry& e, str_hash key){
return e.key < key;
});
if ( iter != entries_.end() && iter->key == key ) {
return &iter->value;
}
return nullptr;
}
template < typename T >
const T* render::property_map<T>::find(str_hash key) const noexcept {
const auto iter = std::lower_bound(
entries_.begin(), entries_.end(), key,
[](const entry& e, str_hash key){
return e.key < key;
});
if ( iter != entries_.end() && iter->key == key ) {
return &iter->value;
}
return nullptr;
}
template < typename T >
void render::property_map<T>::assign(str_hash key, T&& value) {
const auto iter = std::lower_bound(
entries_.begin(), entries_.end(), key,
[](const entry& e, str_hash key){
return e.key < key;
});
if ( iter != entries_.end() && iter->key == key ) {
iter->value = std::move(value);
} else {
entries_.emplace(iter, key, std::move(value));
}
}
template < typename T >
void render::property_map<T>::assign(str_hash key, const T& value) {
const auto iter = std::lower_bound(
entries_.begin(), entries_.end(), key,
[](const entry& e, str_hash key){
return e.key < key;
});
if ( iter != entries_.end() && iter->key == key ) {
iter->value = value;
} else {
entries_.emplace(iter, key, value);
}
}
template < typename T >
void render::property_map<T>::clear() noexcept {
entries_.clear();
}
template < typename T >
std::size_t render::property_map<T>::size() const noexcept {
return entries_.size();
}
template < typename T >
template < typename F >
void render::property_map<T>::foreach(F&& f) const {
for ( std::size_t i = 0, e = entries_.size(); i < e; ++i ) {
f(entries_[i].key, entries_[i].value);
}
}
template < typename T >
void render::property_map<T>::merge(const property_map& other) {
other.foreach([this](str_hash name, const T& value){
assign(name, value);
});
}
template < typename T >
bool render::property_map<T>::equals(const property_map& other) const noexcept {
return entries_ == other.entries_;
}
//
// render::property_block
//
template < typename T >
render::property_block& render::property_block::property(str_hash name, T&& v) {
properties_[name] = std::forward<T>(v);
properties_.assign(name, std::forward<T>(v));
return *this;
}
template < typename T >
const T* render::property_block::property(str_hash name) const noexcept {
const auto iter = properties_.find(name);
return iter != properties_.end()
? stdex::get_if<T>(&iter->second)
const property_value* prop = properties_.find(name);
return prop
? stdex::get_if<T>(*prop)
: nullptr;
}
template < typename F >
void render::property_block::foreach_by_samplers(F&& f) const {
for ( const auto& p : samplers_ ) {
stdex::invoke(f, p.first, p.second);
}
samplers_.foreach(std::forward<F>(f));
}
template < typename F >
void render::property_block::foreach_by_properties(F&& f) const {
for ( const auto& p : properties_ ) {
stdex::invoke(f, p.first, p.second);
}
properties_.foreach(std::forward<F>(f));
}
//

View File

@@ -717,56 +717,46 @@ namespace e2d
}
render::property_block& render::property_block::merge(const property_block& pb) {
pb.foreach_by_properties([this](str_hash name, const property_value& v){
property(name, v);
});
pb.foreach_by_samplers([this](str_hash name, const sampler_state& s){
sampler(name, s);
});
properties_.merge(pb.properties_);
samplers_.merge(pb.samplers_);
return *this;
}
bool render::property_block::equals(const property_block& other) const noexcept {
return properties_ == other.properties_
&& samplers_ == other.samplers_;
if ( properties_.size() != other.properties_.size() ) {
return false;
}
if ( samplers_.size() != other.samplers_.size() ) {
return false;
}
return properties_.equals(other.properties_)
&& samplers_.equals(other.samplers_);
}
render::property_block& render::property_block::sampler(str_hash name, const sampler_state& s) {
samplers_[name] = s;
samplers_.assign(name, s);
return *this;
}
render::sampler_state* render::property_block::sampler(str_hash name) noexcept {
const auto iter = samplers_.find(name);
return iter != samplers_.end()
? &iter->second
: nullptr;
return samplers_.find(name);
}
const render::sampler_state* render::property_block::sampler(str_hash name) const noexcept {
const auto iter = samplers_.find(name);
return iter != samplers_.end()
? &iter->second
: nullptr;
return samplers_.find(name);
}
render::property_block& render::property_block::property(str_hash name, const property_value& v) {
properties_[name] = v;
properties_.assign(name, v);
return *this;
}
render::property_value* render::property_block::property(str_hash name) noexcept {
const auto iter = properties_.find(name);
return iter != properties_.end()
? &iter->second
: nullptr;
return properties_.find(name);
}
const render::property_value* render::property_block::property(str_hash name) const noexcept {
const auto iter = properties_.find(name);
return iter != properties_.end()
? &iter->second
: nullptr;
return properties_.find(name);
}
std::size_t render::property_block::sampler_count() const noexcept {