Enhancements for the netlist object properties

- more memory efficient (single pointer only)
- iterator for properties
- NetlistObject#property_keys in GSI
This commit is contained in:
Matthias Koefferlein 2019-11-12 23:00:49 +01:00
parent 47efb9d11b
commit d060147713
5 changed files with 90 additions and 9 deletions

View File

@ -26,30 +26,50 @@ namespace db
{
NetlistObject::NetlistObject ()
: tl::Object ()
: tl::Object (), mp_properties (0)
{
// .. nothing yet ..
}
NetlistObject::NetlistObject (const db::NetlistObject &other)
: tl::Object (other), m_properties (other.m_properties)
: tl::Object (other), mp_properties (0)
{
// .. nothing yet ..
if (other.mp_properties) {
mp_properties = new std::map<tl::Variant, tl::Variant> (*other.mp_properties);
}
}
NetlistObject::~NetlistObject ()
{
delete mp_properties;
mp_properties = 0;
}
NetlistObject &NetlistObject::operator= (const NetlistObject &other)
{
if (this != &other) {
tl::Object::operator= (other);
m_properties = other.m_properties;
delete mp_properties;
mp_properties = 0;
if (other.mp_properties) {
mp_properties = new std::map<tl::Variant, tl::Variant> (*other.mp_properties);
}
}
return *this;
}
tl::Variant NetlistObject::property (const tl::Variant &key) const
{
std::map<tl::Variant, tl::Variant>::const_iterator i = m_properties.find (key);
if (i == m_properties.end ()) {
if (! mp_properties) {
return tl::Variant ();
}
std::map<tl::Variant, tl::Variant>::const_iterator i = mp_properties->find (key);
if (i == mp_properties->end ()) {
return tl::Variant ();
} else {
return i->second;
@ -60,10 +80,35 @@ void
NetlistObject::set_property (const tl::Variant &key, const tl::Variant &value)
{
if (value.is_nil ()) {
m_properties.erase (key);
if (mp_properties) {
mp_properties->erase (key);
if (mp_properties->empty ()) {
delete mp_properties;
mp_properties = 0;
}
}
} else {
m_properties [key] = value;
if (! mp_properties) {
mp_properties = new std::map<tl::Variant, tl::Variant> ();
}
(*mp_properties) [key] = value;
}
}
static NetlistObject::property_table empty_properties;
NetlistObject::property_iterator
NetlistObject::begin_properties () const
{
return mp_properties ? mp_properties->begin () : empty_properties.begin ();
}
NetlistObject::property_iterator
NetlistObject::end_properties () const
{
return mp_properties ? mp_properties->end () : empty_properties.end ();
}
}

View File

@ -40,6 +40,9 @@ class DB_PUBLIC NetlistObject
: public tl::Object
{
public:
typedef std::map<tl::Variant, tl::Variant> property_table;
typedef property_table::const_iterator property_iterator;
/**
* @brief Default constructor
*/
@ -50,6 +53,11 @@ public:
*/
NetlistObject (const db::NetlistObject &object);
/**
* @brief Destructor
*/
~NetlistObject ();
/**
* @brief Assignment
*/
@ -67,8 +75,18 @@ public:
*/
void set_property (const tl::Variant &key, const tl::Variant &value);
/**
* @brief Iterator for the netlist properties (begin)
*/
property_iterator begin_properties () const;
/**
* @brief Iterator for the netlist properties (end)
*/
property_iterator end_properties () const;
private:
std::map<tl::Variant, tl::Variant> m_properties;
property_table *mp_properties;
};
}

View File

@ -34,6 +34,15 @@
namespace gsi
{
static std::vector<tl::Variant> property_keys (const db::NetlistObject *object)
{
std::vector<tl::Variant> v;
for (db::NetlistObject::property_iterator p = object->begin_properties (); p != object->end_properties (); ++p) {
v.push_back (p->first);
}
return v;
}
Class<db::NetlistObject> decl_dbNetlistObject ("db", "NetlistObject",
gsi::method ("property", &db::NetlistObject::property, gsi::arg ("key"),
"@brief Gets the property value for the given key or nil if there is no value with this key."
@ -41,6 +50,9 @@ Class<db::NetlistObject> decl_dbNetlistObject ("db", "NetlistObject",
gsi::method ("set_property", &db::NetlistObject::set_property, gsi::arg ("key"), gsi::arg ("value"),
"@brief Sets the property value for the given key.\n"
"Use a nil value to erase the property with this key."
) +
gsi::method_ext ("property_keys", &property_keys,
"@brief Gets the keys for the properties stored in this object."
),
"@brief The base class for some netlist objects.\n"
"The main purpose of this class is to supply user properties for netlist objects.\n"

View File

@ -344,9 +344,12 @@ TEST(3_CircuitBasic)
EXPECT_EQ (c.pin_by_name ("p1")->name (), "p1");
EXPECT_EQ (c.pin_by_name ("doesnt_exist") == 0, true);
EXPECT_EQ (c.pin_by_name ("p2")->name (), "p2");
EXPECT_EQ (c.pin_by_id (0)->begin_properties () == c.pin_by_id (0)->end_properties (), true);
EXPECT_EQ (c.pin_by_id (0)->property (17).to_string (), "nil");
c.pin_by_id (0)->set_property (17, 42);
EXPECT_EQ (c.pin_by_id (0)->begin_properties () == c.pin_by_id (0)->end_properties (), false);
EXPECT_EQ (c.pin_by_id (0)->begin_properties ()->second.to_string (), "42");
EXPECT_EQ (c.pin_by_id (0)->property (17).to_string (), "42");
db::Circuit c2 = c;

View File

@ -29,12 +29,15 @@ class DBNetlist_TestClass < TestBase
nlo = RBA::NetlistObject::new
assert_equal(nlo.property(17), nil)
assert_equal(nlo.property_keys.inspect, "[]")
nlo.set_property(17, 42)
assert_equal(nlo.property_keys.inspect, "[17]")
assert_equal(nlo.property(17), 42)
nlo2 = nlo.dup
assert_equal(nlo2.property(17), 42)
nlo.set_property(17, nil)
assert_equal(nlo.property_keys.inspect, "[]")
assert_equal(nlo.property(17), nil)
assert_equal(nlo2.property(17), 42)