From d0601477132b0b708902fc0bf3f81e60020ac19e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 12 Nov 2019 23:00:49 +0100 Subject: [PATCH] Enhancements for the netlist object properties - more memory efficient (single pointer only) - iterator for properties - NetlistObject#property_keys in GSI --- src/db/db/dbNetlistObject.cc | 61 +++++++++++++++++++++++++---- src/db/db/dbNetlistObject.h | 20 +++++++++- src/db/db/gsiDeclDbNetlist.cc | 12 ++++++ src/db/unit_tests/dbNetlistTests.cc | 3 ++ testdata/ruby/dbNetlist.rb | 3 ++ 5 files changed, 90 insertions(+), 9 deletions(-) diff --git a/src/db/db/dbNetlistObject.cc b/src/db/db/dbNetlistObject.cc index beaf305b1..522417b0d 100644 --- a/src/db/db/dbNetlistObject.cc +++ b/src/db/db/dbNetlistObject.cc @@ -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 (*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 (*other.mp_properties); + } + } return *this; } tl::Variant NetlistObject::property (const tl::Variant &key) const { - std::map::const_iterator i = m_properties.find (key); - if (i == m_properties.end ()) { + if (! mp_properties) { + return tl::Variant (); + } + + std::map::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 (); + } + (*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 (); +} + } diff --git a/src/db/db/dbNetlistObject.h b/src/db/db/dbNetlistObject.h index a275cd71a..d1dac4891 100644 --- a/src/db/db/dbNetlistObject.h +++ b/src/db/db/dbNetlistObject.h @@ -40,6 +40,9 @@ class DB_PUBLIC NetlistObject : public tl::Object { public: + typedef std::map 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 m_properties; + property_table *mp_properties; }; } diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index 3bb08efd4..4b96f916c 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -34,6 +34,15 @@ namespace gsi { +static std::vector property_keys (const db::NetlistObject *object) +{ + std::vector v; + for (db::NetlistObject::property_iterator p = object->begin_properties (); p != object->end_properties (); ++p) { + v.push_back (p->first); + } + return v; +} + Class 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 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" diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index 043d32151..c3056e4aa 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -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; diff --git a/testdata/ruby/dbNetlist.rb b/testdata/ruby/dbNetlist.rb index 0d8abac9b..695eb4e38 100644 --- a/testdata/ruby/dbNetlist.rb +++ b/testdata/ruby/dbNetlist.rb @@ -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)