mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-02-07 10:19:57 +08:00
Consolidate hand-rolled flat maps
This commit is contained in:
parent
48e5a46cbd
commit
db72ab626f
@ -212,6 +212,18 @@ namespace chaiscript {
|
|||||||
return final_value(t, base, exponent, neg_exponent);
|
return final_value(t, base, exponent, neg_exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct str_equal {
|
||||||
|
[[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept {
|
||||||
|
return t_lhs == t_rhs;
|
||||||
|
}
|
||||||
|
template<typename LHS, typename RHS>
|
||||||
|
[[nodiscard]] constexpr bool operator()(const LHS &t_lhs, const RHS &t_rhs) const noexcept {
|
||||||
|
return std::equal(t_lhs.begin(), t_lhs.end(), t_rhs.begin(), t_rhs.end());
|
||||||
|
}
|
||||||
|
struct is_transparent{};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct str_less {
|
struct str_less {
|
||||||
[[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept {
|
[[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept {
|
||||||
return t_lhs < t_rhs;
|
return t_lhs < t_rhs;
|
||||||
|
|||||||
@ -389,7 +389,7 @@ namespace chaiscript
|
|||||||
using SmallVector = std::vector<T>;
|
using SmallVector = std::vector<T>;
|
||||||
|
|
||||||
|
|
||||||
using Scope = utility::QuickFlatMap<std::string, Boxed_Value>;
|
using Scope = utility::QuickFlatMap<std::string, Boxed_Value, str_equal>;
|
||||||
using StackData = SmallVector<Scope>;
|
using StackData = SmallVector<Scope>;
|
||||||
using Stacks = SmallVector<StackData>;
|
using Stacks = SmallVector<StackData>;
|
||||||
using Call_Param_List = SmallVector<Boxed_Value>;
|
using Call_Param_List = SmallVector<Boxed_Value>;
|
||||||
@ -430,14 +430,14 @@ namespace chaiscript
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
using Type_Name_Map = std::map<std::string, chaiscript::Type_Info, str_less>;
|
using Type_Name_Map = std::map<std::string, chaiscript::Type_Info, str_less>;
|
||||||
using Scope = utility::QuickFlatMap<std::string, Boxed_Value>;
|
using Scope = utility::QuickFlatMap<std::string, Boxed_Value, str_equal>;
|
||||||
using StackData = Stack_Holder::StackData;
|
using StackData = Stack_Holder::StackData;
|
||||||
|
|
||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> m_functions;
|
utility::QuickFlatMap<std::string, std::shared_ptr<std::vector<Proxy_Function>>, str_equal> m_functions;
|
||||||
std::vector<std::pair<std::string, Proxy_Function>> m_function_objects;
|
utility::QuickFlatMap<std::string, Proxy_Function, str_equal> m_function_objects;
|
||||||
std::vector<std::pair<std::string, Boxed_Value>> m_boxed_functions;
|
utility::QuickFlatMap<std::string, Boxed_Value, str_equal> m_boxed_functions;
|
||||||
std::map<std::string, Boxed_Value, str_less> m_global_objects;
|
std::map<std::string, Boxed_Value, str_less> m_global_objects;
|
||||||
Type_Name_Map m_types;
|
Type_Name_Map m_types;
|
||||||
};
|
};
|
||||||
@ -745,9 +745,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
const auto &funs = get_functions_int();
|
const auto &funs = get_functions_int();
|
||||||
|
|
||||||
auto itr = find_keyed_value(funs, t_name, t_hint);
|
if (const auto itr = funs.find(t_name, t_hint); itr != funs.end())
|
||||||
|
|
||||||
if (itr != funs.end())
|
|
||||||
{
|
{
|
||||||
return std::make_pair(std::distance(funs.begin(), itr), itr->second);
|
return std::make_pair(std::distance(funs.begin(), itr), itr->second);
|
||||||
} else {
|
} else {
|
||||||
@ -771,9 +769,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
const auto &funs = get_boxed_functions_int();
|
const auto &funs = get_boxed_functions_int();
|
||||||
|
|
||||||
auto itr = find_keyed_value(funs, t_name, t_hint);
|
if (const auto itr = funs.find(t_name, t_hint); itr != funs.end())
|
||||||
|
|
||||||
if (itr != funs.end())
|
|
||||||
{
|
{
|
||||||
return std::make_pair(std::distance(funs.begin(), itr), itr->second);
|
return std::make_pair(std::distance(funs.begin(), itr), itr->second);
|
||||||
} else {
|
} else {
|
||||||
@ -787,8 +783,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
const auto &functions = get_functions_int();
|
return get_functions_int().count(name) > 0;
|
||||||
return find_keyed_value(functions, name) != functions.end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \returns All values in the local thread state in the parent scope, or if it doesn't exist,
|
/// \returns All values in the local thread state in the parent scope, or if it doesn't exist,
|
||||||
@ -1246,32 +1241,32 @@ namespace chaiscript
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() const noexcept
|
const decltype(State::m_boxed_functions) &get_boxed_functions_int() const noexcept
|
||||||
{
|
{
|
||||||
return m_state.m_boxed_functions;
|
return m_state.m_boxed_functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() noexcept
|
decltype(State::m_boxed_functions) &get_boxed_functions_int() noexcept
|
||||||
{
|
{
|
||||||
return m_state.m_boxed_functions;
|
return m_state.m_boxed_functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::pair<std::string, Proxy_Function>> &get_function_objects_int() const noexcept
|
const decltype(State::m_function_objects) &get_function_objects_int() const noexcept
|
||||||
{
|
{
|
||||||
return m_state.m_function_objects;
|
return m_state.m_function_objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<std::string, Proxy_Function>> &get_function_objects_int() noexcept
|
decltype(State::m_function_objects) &get_function_objects_int() noexcept
|
||||||
{
|
{
|
||||||
return m_state.m_function_objects;
|
return m_state.m_function_objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> &get_functions_int() const noexcept
|
const decltype(State::m_functions) &get_functions_int() const noexcept
|
||||||
{
|
{
|
||||||
return m_state.m_functions;
|
return m_state.m_functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> &get_functions_int() noexcept
|
decltype(State::m_functions) &get_functions_int() noexcept
|
||||||
{
|
{
|
||||||
return m_state.m_functions;
|
return m_state.m_functions;
|
||||||
}
|
}
|
||||||
@ -1360,63 +1355,17 @@ namespace chaiscript
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Container, typename Key, typename Value>
|
|
||||||
static void add_keyed_value(Container &t_c, const Key &t_key, Value &&t_value)
|
|
||||||
{
|
|
||||||
auto itr = find_keyed_value(t_c, t_key);
|
|
||||||
|
|
||||||
if (itr == t_c.end()) {
|
|
||||||
t_c.reserve(t_c.size() + 1); // tightly control growth of memory usage here
|
|
||||||
t_c.emplace_back(t_key, std::forward<Value>(t_value));
|
|
||||||
} else {
|
|
||||||
using value_type = typename Container::value_type;
|
|
||||||
*itr = value_type(t_key, std::forward<Value>(t_value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Container, typename Key>
|
|
||||||
static typename Container::iterator find_keyed_value(Container &t_c, const Key &t_key) noexcept
|
|
||||||
{
|
|
||||||
return std::find_if(t_c.begin(), t_c.end(),
|
|
||||||
[&t_key](const typename Container::value_type &o) {
|
|
||||||
return o.first == t_key;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Container, typename Key>
|
|
||||||
static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key) noexcept
|
|
||||||
{
|
|
||||||
return std::find_if(t_c.begin(), t_c.end(),
|
|
||||||
[&t_key](const typename Container::value_type &o) {
|
|
||||||
return std::equal(o.first.begin(), o.first.end(), t_key.begin(), t_key.end());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Container, typename Key>
|
|
||||||
static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key, const size_t t_hint) noexcept
|
|
||||||
{
|
|
||||||
if (t_c.size() > t_hint && t_c[t_hint].first == t_key) {
|
|
||||||
return std::next(t_c.begin(), static_cast<typename std::iterator_traits<typename Container::const_iterator>::difference_type>(t_hint));
|
|
||||||
} else {
|
|
||||||
return find_keyed_value(t_c, t_key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Implementation detail for adding a function.
|
/// Implementation detail for adding a function.
|
||||||
/// \throws exception::name_conflict_error if there's a function matching the given one being added
|
/// \throws exception::name_conflict_error if there's a function matching the given one being added
|
||||||
void add_function(const Proxy_Function &t_f, const std::string &t_name)
|
void add_function(const Proxy_Function &t_f, const std::string &t_name)
|
||||||
{
|
{
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
auto &funcs = get_functions_int();
|
|
||||||
|
|
||||||
auto itr = find_keyed_value(funcs, t_name);
|
|
||||||
|
|
||||||
Proxy_Function new_func =
|
Proxy_Function new_func =
|
||||||
[&]() -> Proxy_Function {
|
[&]() -> Proxy_Function {
|
||||||
|
auto &funcs = get_functions_int();
|
||||||
|
auto itr = funcs.find(t_name);
|
||||||
|
|
||||||
if (itr != funcs.end())
|
if (itr != funcs.end())
|
||||||
{
|
{
|
||||||
auto vec = *itr->second;
|
auto vec = *itr->second;
|
||||||
@ -1437,17 +1386,21 @@ namespace chaiscript
|
|||||||
// if the function is the only function but it also contains
|
// if the function is the only function but it also contains
|
||||||
// arithmetic operators, we must wrap it in a dispatch function
|
// arithmetic operators, we must wrap it in a dispatch function
|
||||||
// to allow for automatic arithmetic type conversions
|
// to allow for automatic arithmetic type conversions
|
||||||
std::vector<Proxy_Function> vec({t_f});
|
std::vector<Proxy_Function> vec;
|
||||||
funcs.emplace_back(t_name, std::make_shared<std::vector<Proxy_Function>>(vec));
|
vec.push_back(t_f);
|
||||||
|
funcs.insert(std::pair{t_name, std::make_shared<std::vector<Proxy_Function>>(vec)});
|
||||||
return std::make_shared<Dispatch_Function>(std::move(vec));
|
return std::make_shared<Dispatch_Function>(std::move(vec));
|
||||||
} else {
|
} else {
|
||||||
funcs.emplace_back(t_name, std::make_shared<std::vector<Proxy_Function>>(std::initializer_list<Proxy_Function>({t_f})));
|
auto vec = std::make_shared<std::vector<Proxy_Function>>();
|
||||||
|
vec->push_back(t_f);
|
||||||
|
funcs.insert(std::pair{t_name, vec});
|
||||||
return t_f;
|
return t_f;
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
add_keyed_value(get_boxed_functions_int(), t_name, const_var(new_func));
|
|
||||||
add_keyed_value(get_function_objects_int(), t_name, std::move(new_func));
|
get_boxed_functions_int().insert_or_assign(t_name, const_var(new_func));
|
||||||
|
get_function_objects_int().insert_or_assign(t_name, std::move(new_func));
|
||||||
}
|
}
|
||||||
|
|
||||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||||
|
|||||||
@ -3,15 +3,29 @@
|
|||||||
|
|
||||||
namespace chaiscript::utility {
|
namespace chaiscript::utility {
|
||||||
|
|
||||||
template<typename Key, typename Value>
|
template<typename Key, typename Value, typename Comparator=std::equal_to<>>
|
||||||
struct QuickFlatMap
|
struct QuickFlatMap
|
||||||
{
|
{
|
||||||
auto find(const Key &s) noexcept {
|
Comparator comparator;
|
||||||
return std::find_if(std::begin(data), std::end(data), [&s](const auto &d) { return d.first == s; });
|
|
||||||
|
template<typename Lookup>
|
||||||
|
auto find(const Lookup &s) noexcept {
|
||||||
|
return std::find_if(std::begin(data), std::end(data), [&s, this](const auto &d) { return comparator(d.first, s); });
|
||||||
}
|
}
|
||||||
|
|
||||||
auto find(const Key &s) const noexcept {
|
template<typename Lookup>
|
||||||
return std::find_if(std::begin(data), std::end(data), [&s](const auto &d) { return d.first == s; });
|
auto find(const Lookup &s) const noexcept {
|
||||||
|
return std::find_if(std::cbegin(data), std::cend(data), [&s, this](const auto &d) { return comparator(d.first, s); });
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Lookup>
|
||||||
|
auto find(const Lookup &s, const std::size_t t_hint) const noexcept {
|
||||||
|
if (data.size() > t_hint && comparator(data[t_hint].first, s)) {
|
||||||
|
const auto begin = std::cbegin(data);
|
||||||
|
return std::next(begin, static_cast<typename std::iterator_traits<std::decay_t<decltype(begin)>>::difference_type>(t_hint));
|
||||||
|
} else {
|
||||||
|
return find(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto size() const noexcept {
|
auto size() const noexcept {
|
||||||
@ -49,6 +63,7 @@ namespace chaiscript::utility {
|
|||||||
if (itr != data.end()) {
|
if (itr != data.end()) {
|
||||||
return itr->second;
|
return itr->second;
|
||||||
} else {
|
} else {
|
||||||
|
grow();
|
||||||
return data.emplace_back(s, Value()).second;
|
return data.emplace_back(s, Value()).second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,7 +106,8 @@ namespace chaiscript::utility {
|
|||||||
*itr = std::forward<M>(m);
|
*itr = std::forward<M>(m);
|
||||||
return std::pair{itr, false};
|
return std::pair{itr, false};
|
||||||
} else {
|
} else {
|
||||||
return std::pair{data.emplace(itr, std::move(key), std::forward<M>(m)), true};
|
grow();
|
||||||
|
return std::pair{data.emplace(data.end(), std::move(key), std::forward<M>(m)), true};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,10 +116,11 @@ namespace chaiscript::utility {
|
|||||||
auto insert_or_assign(const Key &key, M &&m)
|
auto insert_or_assign(const Key &key, M &&m)
|
||||||
{
|
{
|
||||||
if (auto itr = find(key); itr != data.end()) {
|
if (auto itr = find(key); itr != data.end()) {
|
||||||
*itr = std::forward<M>(m);
|
itr->second = std::forward<M>(m);
|
||||||
return std::pair{itr, false};
|
return std::pair{itr, false};
|
||||||
} else {
|
} else {
|
||||||
return std::pair{data.emplace(itr, key, std::forward<M>(m)), true};
|
grow();
|
||||||
|
return std::pair{data.emplace(data.end(), key, std::forward<M>(m)), true};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +133,8 @@ namespace chaiscript::utility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t count(const Key &s) const noexcept {
|
template<typename Lookup>
|
||||||
|
size_t count(const Lookup &s) const noexcept {
|
||||||
return (find(s) != data.end())?1:0;
|
return (find(s) != data.end())?1:0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,10 +149,18 @@ namespace chaiscript::utility {
|
|||||||
if (const auto itr = find(value.first); itr != data.end()) {
|
if (const auto itr = find(value.first); itr != data.end()) {
|
||||||
return std::pair{itr, false};
|
return std::pair{itr, false};
|
||||||
} else {
|
} else {
|
||||||
return std::pair{data.insert(itr, std::move(value)), true};
|
grow();
|
||||||
|
return std::pair{data.insert(data.end(), std::move(value)), true};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void grow() {
|
||||||
|
if ((data.capacity() - data.size()) == 0) {
|
||||||
|
data.reserve(data.size() + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user