mirror of
https://github.com/holub/mame
synced 2025-07-05 09:57:47 +03:00
Added a phashmap_t object for faster lookups. (nw)
This commit is contained in:
parent
f6ea498ecf
commit
1c9b70aabd
@ -136,27 +136,6 @@ device_t *setup_t::register_dev(const pstring &classname, const pstring &name)
|
||||
}
|
||||
}
|
||||
|
||||
void setup_t::remove_dev(const pstring &name)
|
||||
{
|
||||
device_t *dev = netlist().m_devices.find_by_name(name);
|
||||
pstring temp = name + ".";
|
||||
if (dev == NULL)
|
||||
netlist().error("Device %s does not exist\n", name.cstr());
|
||||
|
||||
remove_start_with<tagmap_terminal_t>(m_terminals, temp);
|
||||
remove_start_with<tagmap_param_t>(m_params, temp);
|
||||
|
||||
const link_t *p = m_links.data();
|
||||
while (p != NULL)
|
||||
{
|
||||
const link_t *n = p+1;
|
||||
if (temp.equals(p->e1.substr(0,temp.len())) || temp.equals(p->e2.substr(0,temp.len())))
|
||||
m_links.remove(*p);
|
||||
p = n;
|
||||
}
|
||||
netlist().m_devices.remove_by_name(name);
|
||||
}
|
||||
|
||||
void setup_t::register_model(const pstring &model)
|
||||
{
|
||||
m_models.add(model);
|
||||
@ -164,7 +143,7 @@ void setup_t::register_model(const pstring &model)
|
||||
|
||||
void setup_t::register_alias_nofqn(const pstring &alias, const pstring &out)
|
||||
{
|
||||
if (!(m_alias.add(link_t(alias, out), false)==true))
|
||||
if (!m_alias.add(alias, out))
|
||||
netlist().error("Error adding alias %s to alias list\n", alias.cstr());
|
||||
}
|
||||
|
||||
@ -266,9 +245,9 @@ void setup_t::register_object(device_t &dev, const pstring &name, object_t &obj)
|
||||
{
|
||||
param_t ¶m = dynamic_cast<param_t &>(obj);
|
||||
//printf("name: %s\n", name.cstr());
|
||||
const pstring val = m_params_temp.find_by_name(name).e2;
|
||||
if (val != "")
|
||||
if (m_params_temp.contains(name))
|
||||
{
|
||||
const pstring val = m_params_temp[name];
|
||||
switch (param.param_type())
|
||||
{
|
||||
case param_t::DOUBLE:
|
||||
@ -302,7 +281,7 @@ void setup_t::register_object(device_t &dev, const pstring &name, object_t &obj)
|
||||
netlist().error("Parameter is not supported %s : %s\n", name.cstr(), val.cstr());
|
||||
}
|
||||
}
|
||||
if (!(m_params.add(¶m, false)==true))
|
||||
if (!m_params.add(param.name(), ¶m))
|
||||
netlist().error("Error adding parameter %s to parameter list\n", name.cstr());
|
||||
}
|
||||
break;
|
||||
@ -400,16 +379,16 @@ void setup_t::register_param(const pstring ¶m, const pstring &value)
|
||||
{
|
||||
pstring fqn = build_fqn(param);
|
||||
|
||||
int idx = m_params_temp.index_by_name(fqn);
|
||||
int idx = m_params_temp.index_of(fqn);
|
||||
if (idx < 0)
|
||||
{
|
||||
if (!(m_params_temp.add(link_t(fqn, value), false)==true))
|
||||
if (!m_params_temp.add(fqn, value))
|
||||
netlist().error("Unexpected error adding parameter %s to parameter list\n", param.cstr());
|
||||
}
|
||||
else
|
||||
{
|
||||
netlist().warning("Overwriting %s old <%s> new <%s>\n", fqn.cstr(), m_params_temp[idx].e2.cstr(), value.cstr());
|
||||
m_params_temp[idx].e2 = value;
|
||||
netlist().warning("Overwriting %s old <%s> new <%s>\n", fqn.cstr(), m_params_temp.value_at(idx).cstr(), value.cstr());
|
||||
m_params_temp[fqn] = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -421,7 +400,8 @@ const pstring setup_t::resolve_alias(const pstring &name) const
|
||||
/* FIXME: Detect endless loop */
|
||||
do {
|
||||
ret = temp;
|
||||
temp = m_alias.find_by_name(ret).e2;
|
||||
int p = m_alias.index_of(ret);
|
||||
temp = (p>=0 ? m_alias.value_at(p) : "");
|
||||
} while (temp != "");
|
||||
|
||||
NL_VERBOSE_OUT(("%s==>%s\n", name.cstr(), ret.cstr()));
|
||||
@ -480,14 +460,14 @@ param_t *setup_t::find_param(const pstring ¶m_in, bool required)
|
||||
const pstring param_in_fqn = build_fqn(param_in);
|
||||
|
||||
const pstring &outname = resolve_alias(param_in_fqn);
|
||||
param_t *ret;
|
||||
int ret;
|
||||
|
||||
ret = m_params.find_by_name(outname);
|
||||
if (ret == NULL && required)
|
||||
ret = m_params.index_of(outname);
|
||||
if (ret < 0 && required)
|
||||
netlist().error("parameter %s(%s) not found!\n", param_in_fqn.cstr(), outname.cstr());
|
||||
if (ret != NULL)
|
||||
if (ret != -1)
|
||||
NL_VERBOSE_OUT(("Found parameter %s\n", outname.cstr()));
|
||||
return ret;
|
||||
return (ret == -1 ? NULL : m_params.value_at(ret));
|
||||
}
|
||||
|
||||
// FIXME avoid dynamic cast here
|
||||
|
@ -32,9 +32,6 @@
|
||||
#define NET_REGISTER_DEV_X(_type, _name) \
|
||||
setup.register_dev(# _type, # _name);
|
||||
|
||||
#define NET_REMOVE_DEV(_name) \
|
||||
setup.remove_dev(# _name);
|
||||
|
||||
#define NET_REGISTER_SIGNAL(_type, _name) \
|
||||
NET_REGISTER_DEV(_type ## _ ## sig, _name)
|
||||
|
||||
@ -133,10 +130,8 @@ namespace netlist
|
||||
const pstring &name() const { return e1; }
|
||||
};
|
||||
|
||||
typedef pnamedlist_t<link_t> tagmap_nstring_t;
|
||||
typedef pnamedlist_t<param_t *> tagmap_param_t;
|
||||
//typedef pnamedlist_t<link_t> tagmap_nstring_t;
|
||||
typedef pnamedlist_t<core_terminal_t *> tagmap_terminal_t;
|
||||
typedef plist_t<link_t> tagmap_link_t;
|
||||
|
||||
setup_t(netlist_t *netlist);
|
||||
~setup_t();
|
||||
@ -217,10 +212,11 @@ namespace netlist
|
||||
|
||||
netlist_t *m_netlist;
|
||||
|
||||
tagmap_nstring_t m_alias;
|
||||
tagmap_param_t m_params;
|
||||
tagmap_link_t m_links;
|
||||
tagmap_nstring_t m_params_temp;
|
||||
phashmap_t<pstring, pstring> m_alias;
|
||||
phashmap_t<pstring, param_t *> m_params;
|
||||
phashmap_t<pstring, pstring> m_params_temp;
|
||||
|
||||
plist_t<link_t> m_links;
|
||||
|
||||
factory_list_t *m_factory;
|
||||
|
||||
@ -245,6 +241,7 @@ namespace netlist
|
||||
const pstring resolve_alias(const pstring &name) const;
|
||||
devices::nld_base_proxy *get_d_a_proxy(core_terminal_t &out);
|
||||
|
||||
#if 0
|
||||
template <class T>
|
||||
void remove_start_with(T &hm, pstring &sw)
|
||||
{
|
||||
@ -258,6 +255,7 @@ namespace netlist
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
@ -606,6 +606,146 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// hashmap list
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class C>
|
||||
struct phash_functor
|
||||
{
|
||||
unsigned hash(const C &v) { return (unsigned) v; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct phash_functor<pstring>
|
||||
{
|
||||
unsigned hash(const pstring &v)
|
||||
{
|
||||
const char *string = v.cstr();
|
||||
unsigned result = *string++;
|
||||
for (UINT8 c = *string++; c != 0; c = *string++)
|
||||
result = (result*33) ^ c;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/* some primes 53, 97, 193, 389, 769, 1543, 3079, 6151 */
|
||||
template <class K, class V, class H = phash_functor<K> >
|
||||
class phashmap_t
|
||||
{
|
||||
public:
|
||||
phashmap_t() : m_hash(389)
|
||||
{
|
||||
for (unsigned i=0; i<m_hash.size(); i++)
|
||||
m_hash[i] = -1;
|
||||
}
|
||||
|
||||
struct element_t
|
||||
{
|
||||
element_t() { }
|
||||
element_t(K key, unsigned hash, V value)
|
||||
: m_key(key), m_hash(hash), m_value(value), m_next(-1)
|
||||
{}
|
||||
K m_key;
|
||||
unsigned m_hash;
|
||||
V m_value;
|
||||
int m_next;
|
||||
};
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_values.clear();
|
||||
for (unsigned i=0; i<m_hash.size(); i++)
|
||||
m_hash[i] = -1;
|
||||
}
|
||||
|
||||
bool contains(const K &key) const
|
||||
{
|
||||
return (get_idx(key) >= 0);
|
||||
}
|
||||
|
||||
int index_of(const K &key) const
|
||||
{
|
||||
return get_idx(key);
|
||||
}
|
||||
|
||||
unsigned size() const { return m_values.size(); }
|
||||
|
||||
bool add(const K &key, const V &value)
|
||||
{
|
||||
H h;
|
||||
const unsigned hash=h.hash(key);
|
||||
const unsigned pos = hash % m_hash.size();
|
||||
if (m_hash[pos] == -1)
|
||||
{
|
||||
unsigned vpos = m_values.size();
|
||||
m_values.add(element_t(key, hash, value));
|
||||
m_hash[pos] = vpos;
|
||||
}
|
||||
else
|
||||
{
|
||||
int ep = m_hash[pos];
|
||||
|
||||
for (; ep != -1; ep = m_values[ep].m_next)
|
||||
{
|
||||
if (m_values[ep].m_hash == hash && m_values[ep].m_key == key )
|
||||
return false; /* duplicate */
|
||||
}
|
||||
unsigned vpos = m_values.size();
|
||||
m_values.add(element_t(key, hash, value));
|
||||
m_values[vpos].m_next = m_hash[pos];
|
||||
m_hash[pos] = vpos;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
V& operator[](const K &key)
|
||||
{
|
||||
int p = get_idx(key);
|
||||
if (p == -1)
|
||||
{
|
||||
p = m_values.size();
|
||||
add(key, V());
|
||||
}
|
||||
return m_values[p].m_value;
|
||||
}
|
||||
|
||||
const V& operator[](const K &key) const
|
||||
{
|
||||
int p = get_idx(key);
|
||||
if (p == -1)
|
||||
{
|
||||
p = m_values.size();
|
||||
add(key, V());
|
||||
}
|
||||
return m_values[p].m_value;
|
||||
}
|
||||
|
||||
V& value_at(const unsigned pos) { return m_values[pos].m_value; }
|
||||
const V& value_at(const unsigned pos) const { return m_values[pos].m_value; }
|
||||
|
||||
V& key_at(const unsigned pos) const { return m_values[pos].m_key; }
|
||||
private:
|
||||
|
||||
int get_idx(const K &key) const
|
||||
{
|
||||
H h;
|
||||
const unsigned hash=h.hash(key);
|
||||
const unsigned pos = hash % m_hash.size();
|
||||
|
||||
for (int ep = m_hash[pos]; ep != -1; ep = m_values[ep].m_next)
|
||||
{
|
||||
if (m_values[ep].m_hash == hash && m_values[ep].m_key == key )
|
||||
return ep;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
plist_t<element_t> m_values;
|
||||
parray_t<int> m_hash;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// sort a list ... slow, I am lazy
|
||||
// elements must support ">" operator.
|
||||
|
@ -75,3 +75,4 @@ template<> ATTR_COLD void pstate_manager_t::save_item(pstate_callback_t &state,
|
||||
m_save.add(p);
|
||||
state.register_state(*this, stname);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user