diff --git a/src/db/db/dbNetlistExtractor.cc b/src/db/db/dbNetlistExtractor.cc index 5f8259ffd..9d785f76b 100644 --- a/src/db/db/dbNetlistExtractor.cc +++ b/src/db/db/dbNetlistExtractor.cc @@ -65,20 +65,18 @@ build_net_name_equivalence (const db::Layout *layout, const db::Connectivity &co { std::map > prop_by_name; -#if 0 // @@@ - for (db::PropertiesRepository::iterator i = layout->properties_repository ().begin (); i != layout->properties_repository ().end (); ++i) { - for (db::PropertiesRepository::properties_set::const_iterator p = i->second.begin (); p != i->second.end (); ++p) { - if (p->first == net_name_id) { - std::string nn = p->second.to_string (); - for (std::list::const_iterator jp = jn_pattern.begin (); jp != jn_pattern.end (); ++jp) { - if (jp->match (nn)) { - prop_by_name [nn].insert (db::prop_id_to_attr (i->first)); - } + { + db::PropertiesRepository::properties_id_set with_name = db::PropertiesRepository::instance ().properties_ids_by_name (net_name_id); + for (auto i = with_name.begin (); i != with_name.end (); ++i) { + const db::PropertiesSet &props = db::properties (*i); + std::string nn = props.value (net_name_id).to_string (); + for (std::list::const_iterator jp = jn_pattern.begin (); jp != jn_pattern.end (); ++jp) { + if (jp->match (nn)) { + prop_by_name [nn].insert (db::prop_id_to_attr (*i)); } } } } -#endif // include pseudo-attributes for global nets to implement "join_with" for global nets for (size_t gid = 0; gid < conn.global_nets (); ++gid) { @@ -115,18 +113,16 @@ build_net_name_equivalence_for_explicit_connections (const db::Layout *layout, c { std::map > prop_by_name; -#if 0 // @@@ - for (db::PropertiesRepository::iterator i = layout->properties_repository ().begin (); i != layout->properties_repository ().end (); ++i) { - for (db::PropertiesRepository::properties_set::const_iterator p = i->second.begin (); p != i->second.end (); ++p) { - if (p->first == net_name_id) { - std::string nn = p->second.to_string (); - if (nets_to_join.find (nn) != nets_to_join.end ()) { - prop_by_name [nn].insert (db::prop_id_to_attr (i->first)); - } + { + db::PropertiesRepository::properties_id_set with_name = db::PropertiesRepository::instance ().properties_ids_by_name (net_name_id); + for (auto i = with_name.begin (); i != with_name.end (); ++i) { + const db::PropertiesSet &props = db::properties (*i); + std::string nn = props.value (net_name_id).to_string (); + if (nets_to_join.find (nn) != nets_to_join.end ()) { + prop_by_name [nn].insert (db::prop_id_to_attr (*i)); } } } -#endif // include pseudo-attributes for global nets to implement "join_with" for global nets for (size_t gid = 0; gid < conn.global_nets (); ++gid) { diff --git a/src/db/db/dbPropertiesRepository.cc b/src/db/db/dbPropertiesRepository.cc index e574bab0b..bdee8ca6e 100644 --- a/src/db/db/dbPropertiesRepository.cc +++ b/src/db/db/dbPropertiesRepository.cc @@ -187,6 +187,12 @@ PropertiesSet::insert (db::property_names_id_type nid, const tl::Variant &value) m_map.insert (std::make_pair (nid, db::property_values_id (value))); } +void +PropertiesSet::insert_by_id (db::property_names_id_type nid, db::property_values_id_type vid) +{ + m_map.insert (std::make_pair (nid, vid)); +} + void PropertiesSet::merge (const db::PropertiesSet &other) { @@ -230,10 +236,19 @@ PropertiesSet::to_list_var () const // ---------------------------------------------------------------------------------- // PropertiesRepository implementation -PropertiesRepository &PropertiesRepository::instance () +static PropertiesRepository s_instance; +static PropertiesRepository *sp_temp_instance = 0; + +PropertiesRepository & +PropertiesRepository::instance () { - static PropertiesRepository s_instance; - return s_instance; + return sp_temp_instance ? *sp_temp_instance : s_instance; +} + +void +PropertiesRepository::replace_instance_temporarily (db::PropertiesRepository *temp) +{ + sp_temp_instance = temp; } PropertiesRepository::PropertiesRepository () @@ -383,17 +398,28 @@ PropertiesRepository::is_valid_property_values_id (property_values_id_type id) c } PropertiesRepository::properties_id_set -PropertiesRepository::properties_ids_by_name_value (db::property_names_id_type name, db::property_values_id_type value) const +PropertiesRepository::properties_ids_by_name (db::property_names_id_type name_id) const +{ + tl::MutexLocker locker (&m_lock); + + auto ni = m_properties_by_name_table.find (name_id); + if (ni == m_properties_by_name_table.end ()) { + return properties_id_set (); + } else { + return ni->second; + } +} + +PropertiesRepository::properties_id_set +PropertiesRepository::properties_ids_by_name_value (db::property_names_id_type name_id, db::property_values_id_type value_id) const { tl::MutexLocker locker (&m_lock); - db::property_names_id_type name_id = property_names_id (name); auto ni = m_properties_by_name_table.find (name_id); if (ni == m_properties_by_name_table.end ()) { return properties_id_set (); } - db::property_values_id_type value_id = property_values_id (value); auto vi = m_properties_by_value_table.find (value_id); if (vi == m_properties_by_value_table.end ()) { return properties_id_set (); @@ -405,7 +431,7 @@ PropertiesRepository::properties_ids_by_name_value (db::property_names_id_type n } // ---------------------------------------------------------------------------------- -// PropertiesRepository implementation +// PropertiesTranslator implementation PropertiesTranslator::PropertiesTranslator () : m_pass (true), m_null (true) @@ -478,64 +504,81 @@ PropertiesTranslator::make_pass_all () } PropertiesTranslator -PropertiesTranslator::make_filter (const std::set &keys) +PropertiesTranslator::make_filter (const std::set &keys, db::PropertiesRepository &repo) { - std::map map; + db::PropertiesRepository::properties_id_set ids; std::set names_selected; -#if 0 // @@@ later for (auto k = keys.begin (); k != keys.end (); ++k) { - names_selected.insert (repo.prop_name_id (*k)); + + db::property_names_id_type nid = repo.prop_name_id (*k); + names_selected.insert (nid); + + db::PropertiesRepository::properties_id_set ids_with_name = repo.properties_ids_by_name (nid); + ids.insert (ids_with_name.begin (), ids_with_name.end ()); + } - db::PropertiesRepository org_repo = repo; // @@@ should not be available + std::map map; - for (auto p = org_repo.begin (); p != org_repo.end (); ++p) { - db::PropertiesRepository::properties_set new_set; - for (auto i = p->second.begin (); i != p->second.end (); ++i) { - if (names_selected.find (i->first) != names_selected.end ()) { - new_set.insert (*i); + for (auto i = ids.begin (); i != ids.end (); ++i) { + + const db::PropertiesSet &props = db::properties (*i); + db::PropertiesSet new_props; + + for (auto p = props.begin (); p != props.end (); ++p) { + if (names_selected.find (p->first) != names_selected.end ()) { + new_props.insert_by_id (p->first, p->second); } } - if (! new_set.empty ()) { - map.insert (std::make_pair (p->first, repo.properties_id (new_set))); + + if (! new_props.empty ()) { + map.insert (std::make_pair (*i, new_props == props ? *i : repo.properties_id (new_props))); } + } -#endif // @@@ return PropertiesTranslator (map); } PropertiesTranslator -PropertiesTranslator::make_key_mapper (const std::map &keys) +PropertiesTranslator::make_key_mapper (const std::map &keys, db::PropertiesRepository &repo) { - std::map map; + db::PropertiesRepository::properties_id_set ids; std::map name_map; -#if 0 // @@@ later for (auto k = keys.begin (); k != keys.end (); ++k) { - name_map.insert (std::make_pair (repo.prop_name_id (k->first), repo.prop_name_id (k->second))); + + db::property_names_id_type nid = repo.prop_name_id (k->first); + name_map.insert (std::make_pair (nid, repo.prop_name_id (k->second))); + + db::PropertiesRepository::properties_id_set ids_with_name = repo.properties_ids_by_name (nid); + ids.insert (ids_with_name.begin (), ids_with_name.end ()); + } - db::PropertiesRepository org_repo = repo; // @@@ should not be available + std::map map; - for (auto p = org_repo.begin (); p != org_repo.end (); ++p) { - db::PropertiesRepository::properties_set new_set; - for (auto i = p->second.begin (); i != p->second.end (); ++i) { - auto nm = name_map.find (i->first); + for (auto i = ids.begin (); i != ids.end (); ++i) { + + const db::PropertiesSet &props = db::properties (*i); + db::PropertiesSet new_props; + + for (auto p = props.begin (); p != props.end (); ++p) { + auto nm = name_map.find (p->first); if (nm != name_map.end ()) { - new_set.insert (std::make_pair (nm->second, i->second)); + new_props.insert_by_id (nm->second, p->second); } } - if (! new_set.empty ()) { - map.insert (std::make_pair (p->first, repo.properties_id (new_set))); + + if (! new_props.empty ()) { + map.insert (std::make_pair (*i, new_props == props ? *i : repo.properties_id (new_props))); } + } -#endif return PropertiesTranslator (map); } - } // namespace db diff --git a/src/db/db/dbPropertiesRepository.h b/src/db/db/dbPropertiesRepository.h index 7d7155a6f..a83fdc369 100644 --- a/src/db/db/dbPropertiesRepository.h +++ b/src/db/db/dbPropertiesRepository.h @@ -203,6 +203,11 @@ public: */ void insert (db::property_names_id_type name_id, const tl::Variant &value); + /** + * @brief Inserts a value by ID for the given name ID + */ + void insert_by_id (db::property_names_id_type name_id, db::property_values_id_type value_id); + /** * @brief Merge another properties set into self */ @@ -292,11 +297,26 @@ class DB_PUBLIC PropertiesRepository public: typedef std::set properties_id_set; + /** + * @brief Default constructor + * + * This constructor is mainly provided for test purposes. + */ + PropertiesRepository (); + /** * @brief Gets the singleton instance of the properties repository */ static PropertiesRepository &instance (); + /** + * @brief Temporarily replace the singleton instance + * + * This method is intended for testing purposes only. Passing 0 for the + * repository argument resets back to the global singleton. + */ + static void replace_instance_temporarily (db::PropertiesRepository *temp); + /** * @brief Gets the name ID for a property name * @@ -372,12 +392,19 @@ public: /** * @brief Lookup a table of properties id's by a name value pair * - * For a given name/value pair, this method returns a vector of ids - * of property sets that contain the given name/value pair. This method - * is intended for use with the properties_id resolution algorithm. + * For a given name/value pair, this method returns a set of property IDs + * of property sets that contain the given name/value pair. */ properties_id_set properties_ids_by_name_value (db::property_names_id_type name, db::property_values_id_type value) const; + /** + * @brief Lookup a table of properties id's by a name + * + * For a given name, this method returns a set of property IDs + * of property sets that contain the given name. + */ + properties_id_set properties_ids_by_name (db::property_names_id_type name) const; + /** * @brief Collect memory statistics */ @@ -432,11 +459,6 @@ private: std::map m_properties_by_value_table; mutable tl::Mutex m_lock; - - /** - * @brief Default constructor - */ - PropertiesRepository (); }; /** @@ -534,16 +556,20 @@ public: * @brief Factory: create a filter translator * * The translator delivered by this function will leave only the given keys in the properties. + * + * If no repository is given, the translator acts on the singleton instance. */ - static PropertiesTranslator make_filter (const std::set &keys); + static PropertiesTranslator make_filter (const std::set &keys, db::PropertiesRepository &repo = db::PropertiesRepository::instance ()); /** * @brief Factory: create a key mapper translator * * The translator delivered by this function will translate the given keys to new ones * and remove non-listed keys. + * + * If no repository is given, the translator acts on the singleton instance. */ - static PropertiesTranslator make_key_mapper (const std::map &keys); + static PropertiesTranslator make_key_mapper (const std::map &keys, db::PropertiesRepository &repo = db::PropertiesRepository::instance ()); private: std::map m_map; diff --git a/src/db/unit_tests/dbPropertiesRepositoryTests.cc b/src/db/unit_tests/dbPropertiesRepositoryTests.cc index 930d5d94b..c5e266f6d 100644 --- a/src/db/unit_tests/dbPropertiesRepositoryTests.cc +++ b/src/db/unit_tests/dbPropertiesRepositoryTests.cc @@ -26,242 +26,189 @@ #include "tlString.h" #include "tlUnitTest.h" -#if 0 // @@@ -TEST(1) +namespace { + +/** + * @brief Installs a temporary repository instance for testing + * + * By using a temp instance, we do not disturb other tests. + */ +class TempPropertiesRepository { - tl::Variant v; +public: + TempPropertiesRepository () + { + db::PropertiesRepository::replace_instance_temporarily (&m_temp); + } - EXPECT_EQ (std::string (v.to_parsable_string ()) == "nil", true); + ~TempPropertiesRepository () + { + db::PropertiesRepository::replace_instance_temporarily (0); + } - v = 1l; - EXPECT_EQ (std::string (v.to_parsable_string ()) == "#1", true); - EXPECT_EQ (v.to_long () == 1, true); +private: + db::PropertiesRepository m_temp; +}; - v = "102"; - EXPECT_EQ (std::string (v.to_parsable_string ()) == "'102'", true); - - v = 2l; - EXPECT_EQ (std::string (v.to_parsable_string ()) == "#2", true); - EXPECT_EQ (v.is_long (), true); - EXPECT_EQ (v.is_double (), false); - EXPECT_EQ (v.is_a_string (), false); - EXPECT_EQ (v.to_long () == 2, true); - EXPECT_EQ (v.to_double () == 2, true); - - v = tl::Variant (); - EXPECT_EQ (std::string (v.to_parsable_string ()) == "nil", true); - EXPECT_EQ (v.is_double (), false); - EXPECT_EQ (v.is_a_string (), false); - EXPECT_EQ (v.is_long (), false); - EXPECT_EQ (v.is_nil (), true); - EXPECT_EQ (v.is_list (), false); - - v = tl::Variant ((long) 1); - EXPECT_EQ (std::string (v.to_parsable_string ()) == "#1", true); - EXPECT_EQ (v.to_long () == 1, true); - EXPECT_EQ (v.to_double () == 1, true); - EXPECT_EQ (v.is_double (), false); - EXPECT_EQ (v.is_a_string (), false); - - v = tl::Variant ("A"); - EXPECT_EQ (std::string (v.to_parsable_string ()) == "'A'", true); - EXPECT_EQ (v.is_double (), false); - EXPECT_EQ (v.is_a_string (), true); - EXPECT_EQ (v.is_long (), false); - - EXPECT_EQ (v < tl::Variant (), false); - EXPECT_EQ (tl::Variant (1l) < v, true); - EXPECT_EQ (tl::Variant ("B") < v, false); - EXPECT_EQ (tl::Variant ("A") < v, false); - EXPECT_EQ (tl::Variant (" ") < v, true); } -TEST(2) +TEST(BasicNames) { db::PropertiesRepository rep; tl::Variant n1 ("Hallo"); tl::Variant n2 ("AAA"); - size_t id1 = rep.prop_name_id (n1); - size_t id2 = rep.prop_name_id (n2); - - EXPECT_EQ (id1, size_t (0)); - EXPECT_EQ (id2, size_t (1)); + db::property_names_id_type id1 = rep.prop_name_id (n1); + db::property_names_id_type id2 = rep.prop_name_id (n2); + db::property_names_id_type id1_copy = id1, id2_copy = id2; id2 = rep.prop_name_id (n2); id1 = rep.prop_name_id (n1); - EXPECT_EQ (id1, size_t (0)); - EXPECT_EQ (id2, size_t (1)); + EXPECT_EQ (id1, id1_copy); + EXPECT_EQ (id2, id2_copy); - EXPECT_EQ (rep.prop_name (0) == n1, true); - EXPECT_EQ (rep.prop_name (1) == n2, true); - - db::PropertiesRepository rep2; - rep2 = rep; - - id2 = rep2.prop_name_id (n2); - id1 = rep2.prop_name_id (n1); - - EXPECT_EQ (id1, size_t (0)); - EXPECT_EQ (id2, size_t (1)); - - EXPECT_EQ (rep2.prop_name (0) == n1, true); - EXPECT_EQ (rep2.prop_name (1) == n2, true); - - db::PropertiesRepository empty_rep; - rep2 = empty_rep; - - id1 = rep2.prop_name_id (n2); - EXPECT_EQ (id1, size_t (0)); + EXPECT_EQ (db::property_name (id1) == n1, true); + EXPECT_EQ (db::property_name (id2) == n2, true); } -TEST(3) +TEST(BasicValues) { db::PropertiesRepository rep; - tl::Variant n1 (1.5); - tl::Variant n2 ("AAA"); + tl::Variant v1 ("X"); + tl::Variant v2 (17); - size_t id1 = rep.prop_name_id (n1); - size_t id2 = rep.prop_name_id (n2); + db::property_values_id_type id1 = rep.prop_value_id (v1); + db::property_values_id_type id2 = rep.prop_value_id (v2); + db::property_values_id_type id1_copy = id1, id2_copy = id2; - EXPECT_EQ (id1, size_t (0)); - EXPECT_EQ (id2, size_t (1)); + id2 = rep.prop_value_id (v2); + id1 = rep.prop_value_id (v1); - id2 = rep.prop_name_id (n2); - id1 = rep.prop_name_id (n1); + EXPECT_EQ (id1, id1_copy); + EXPECT_EQ (id2, id2_copy); - EXPECT_EQ (id1, size_t (0)); - EXPECT_EQ (id2, size_t (1)); - - EXPECT_EQ (rep.prop_name (0) == n1, true); - EXPECT_EQ (rep.prop_name (1) == n2, true); - - db::PropertiesRepository rep2; - rep2 = rep; - - id2 = rep2.prop_name_id (n2); - id1 = rep2.prop_name_id (n1); - - EXPECT_EQ (id1, size_t (0)); - EXPECT_EQ (id2, size_t (1)); - - EXPECT_EQ (rep2.prop_name (0) == n1, true); - EXPECT_EQ (rep2.prop_name (1) == n2, true); - - db::PropertiesRepository empty_rep; - rep2 = empty_rep; - - id1 = rep2.prop_name_id (n2); - EXPECT_EQ (id1, size_t (0)); + EXPECT_EQ (db::property_value (id1) == v1, true); + EXPECT_EQ (db::property_value (id2) == v2, true); } -TEST(4) +TEST(BasicPropertySetsInRepository) { - db::PropertiesRepository::properties_set set1; - db::PropertiesRepository::properties_set set2; + db::PropertiesSet set1; + db::PropertiesSet set2; - set1.insert (std::make_pair (0, tl::Variant (15l))); - set1.insert (std::make_pair (10, tl::Variant (0.125))); + set1.insert_by_id (0, 1); + set1.insert (10, 2); - set2.insert (std::make_pair (0, tl::Variant (15l))); - set2.insert (std::make_pair (9, tl::Variant ("Ein String"))); + set2.insert (0, 1); + set2.insert (9, 3); + set2.insert (2, 5); db::PropertiesRepository rep; - size_t id1 = rep.properties_id (set1); - size_t id2 = rep.properties_id (set2); - - EXPECT_EQ (id1, size_t (1)); - EXPECT_EQ (id2, size_t (2)); + db::properties_id_type id1 = rep.properties_id (set1); + db::properties_id_type id2 = rep.properties_id (set2); + db::properties_id_type id1_copy = id1, id2_copy = id2; id2 = rep.properties_id (set2); id1 = rep.properties_id (set1); - EXPECT_EQ (id1, size_t (1)); - EXPECT_EQ (id2, size_t (2)); + EXPECT_EQ (id1, id1_copy); + EXPECT_EQ (id2, id2_copy); - EXPECT_EQ (rep.properties (1) == set1, true); - EXPECT_EQ (rep.properties (2) == set2, true); - - db::PropertiesRepository rep2; - rep2 = rep; - - id2 = rep2.properties_id (set2); - id1 = rep2.properties_id (set1); - - EXPECT_EQ (id1, size_t (1)); - EXPECT_EQ (id2, size_t (2)); - - EXPECT_EQ (rep2.properties (1) == set1, true); - EXPECT_EQ (rep2.properties (2) == set2, true); - - db::PropertiesRepository empty_rep; - rep2 = empty_rep; - - id1 = rep2.properties_id (set2); - EXPECT_EQ (id1, size_t (1)); + EXPECT_EQ (rep.properties (id1) == set1, true); + EXPECT_EQ (rep.properties (id2) == set2, true); } -TEST(5) +TEST(PropertySets) { - tl::Variant v; - tl::Extractor ex (" #10 a"); - ex.read (v); - ex.expect ("a"); - EXPECT_EQ (v == tl::Variant ((long) 10), true); - ex = tl::Extractor (" ## 12.5 a"); - ex.read (v); - ex.expect ("a"); - EXPECT_EQ (v == tl::Variant (12.5), true); - ex = tl::Extractor (" Aber a"); - ex.read (v); - ex.expect ("a"); - EXPECT_EQ (v == tl::Variant ("Aber"), true); - ex = tl::Extractor (" Aber a"); - ex.read (v); - ex.expect ("a"); - EXPECT_EQ (v == tl::Variant ("Aber"), true); - ex = tl::Extractor (" (Aber_, ##2.500, (#05,x) ,() ) a"); - ex.read (v); - ex.expect ("a"); - EXPECT_EQ (std::string (v.to_parsable_string ()), "('Aber_',##2.5,(#5,'x'),())"); + TempPropertiesRepository tmp_repo; + + db::PropertiesSet ps1; + db::PropertiesSet ps2; + + EXPECT_EQ (ps1.empty (), true); + EXPECT_EQ (ps1.size (), size_t (0)); + EXPECT_EQ (ps1.value (tl::Variant (17)).is_nil (), true); + EXPECT_EQ (ps1 == ps2, true); + EXPECT_EQ (ps1 != ps2, false); + EXPECT_EQ (ps1 < ps2, false); + EXPECT_EQ (ps2 < ps1, false); + + ps1.insert (tl::Variant (17), tl::Variant ("value")); + EXPECT_EQ (ps1.empty (), false); + EXPECT_EQ (ps1.size (), size_t (1)); + EXPECT_EQ (ps1.has_value (tl::Variant (17)), true); + EXPECT_EQ (ps1.has_value (tl::Variant ()), false); + EXPECT_EQ (ps1.has_value (tl::Variant ("x")), false); + EXPECT_EQ (ps1.value (tl::Variant (17)).to_string (), "value"); + EXPECT_EQ (ps1.value (tl::Variant ("x")).is_nil (), true); + EXPECT_EQ (ps1.value (db::property_names_id (17)).to_string (), "value"); + EXPECT_EQ (ps1.value (db::property_names_id ("x")).is_nil (), true); + EXPECT_EQ (ps1 [tl::Variant (17)].to_string (), "value"); + EXPECT_EQ (ps1 [tl::Variant ("x")].is_nil (), true); + EXPECT_EQ (ps1 == ps2, false); + EXPECT_EQ (ps1 != ps2, true); + EXPECT_EQ (ps1 < ps2, true); + EXPECT_EQ (ps2 < ps1, false); + + ps2.swap (ps1); + EXPECT_EQ (ps1.value (tl::Variant (17)).is_nil (), true); + EXPECT_EQ (ps2.value (tl::Variant (17)).to_string (), "value"); + + ps2 = ps1; + EXPECT_EQ (ps1.value (tl::Variant (17)).to_string (), "value"); + EXPECT_EQ (ps1.value (tl::Variant ("x")).is_nil (), true); + EXPECT_EQ (ps1 == ps2, true); + EXPECT_EQ (ps1 != ps2, false); + EXPECT_EQ (ps1 < ps2, false); + EXPECT_EQ (ps2 < ps1, false); + + ps2.erase (tl::Variant (17)); + EXPECT_EQ (ps2.value (tl::Variant (17)).is_nil (), true); + EXPECT_EQ (ps2.has_value (tl::Variant (17)), false); + EXPECT_EQ (ps2.size (), size_t (0)); + EXPECT_EQ (ps2.empty (), true); + + ps1.clear (); + EXPECT_EQ (ps1.size (), size_t (0)); + EXPECT_EQ (ps1.empty (), true); } -TEST(6) +TEST(PropertySetsMerge) { - db::PropertiesRepository rep; + TempPropertiesRepository tmp_repo; - tl::Variant n1(1); - tl::Variant n2(1l); + db::PropertiesSet ps1, ps2; + ps1.insert (tl::Variant (17), tl::Variant ("value")); + ps2.insert (tl::Variant ("x"), tl::Variant (42)); - EXPECT_EQ (n1 == n2, true); - EXPECT_EQ (n1 < n2, false); - EXPECT_EQ (n2 < n1, false); + ps1.merge (ps2); - size_t id1 = rep.prop_name_id (n1); - size_t id2 = rep.prop_name_id (n2); - - EXPECT_EQ (id1, size_t (0)); - EXPECT_EQ (id2, size_t (0)); - - db::PropertiesRepository::properties_set set1; - db::PropertiesRepository::properties_set set2; - - set1.insert (std::make_pair (0, tl::Variant ("JTAG_DIO1"))); - set2.insert (std::make_pair (0, tl::Variant (2))); - - size_t pid1 = rep.properties_id (set1); - size_t pid2 = rep.properties_id (set2); - - EXPECT_EQ (pid1, size_t (1)); - EXPECT_EQ (pid2, size_t (2)); + EXPECT_EQ (ps1.to_dict_var ().to_string (), "..."); } +TEST(PropertySetsConversions) +{ + TempPropertiesRepository tmp_repo; -TEST(10_PropertiesTranslator) + db::PropertiesSet ps1; + ps1.insert (tl::Variant (17), tl::Variant ("value")); + ps1.insert (tl::Variant ("x"), tl::Variant (42)); + + EXPECT_EQ (ps1.to_dict_var ().to_string (), "..."); + EXPECT_EQ (ps1.to_list_var ().to_string (), "..."); + + auto ps1_map = ps1.to_map (); + EXPECT_EQ (ps1_map.size (), size_t (2)); + EXPECT_EQ (ps1_map.find (tl::Variant (17))->second.to_string (), "value"); + EXPECT_EQ (ps1_map.find (tl::Variant ("x"))->second.to_string (), "42"); + EXPECT_EQ (ps1_map.find (tl::Variant (42)) == ps1_map.end (), true); +} + +TEST(PropertiesTranslator) { EXPECT_EQ (db::PropertiesTranslator ().is_null (), true); EXPECT_EQ (db::PropertiesTranslator ().is_pass (), true); @@ -278,118 +225,111 @@ TEST(10_PropertiesTranslator) db::property_names_id_type key2 = rp.prop_name_id (2); db::property_names_id_type key3 = rp.prop_name_id (3); - db::PropertiesRepository::properties_set ps; - ps.insert (std::make_pair (key1, 100)); - ps.insert (std::make_pair (key2, 101)); + db::PropertiesSet ps; + ps.insert (key1, 100); + ps.insert (key2, 101); db::properties_id_type prop1a = rp.properties_id (ps); - EXPECT_EQ (prop2string (rp, prop1a), "1=100\n2=101"); + EXPECT_EQ (db::prop2string (prop1a), "1=100\n2=101"); ps.clear (); - ps.insert (std::make_pair (key1, 0)); - ps.insert (std::make_pair (key2, 101)); + ps.insert (key1, 0); + ps.insert (key2, 101); db::properties_id_type prop1b = rp.properties_id (ps); - EXPECT_EQ (prop2string (rp, prop1b), "1=0\n2=101"); + EXPECT_EQ (db::prop2string (prop1b), "1=0\n2=101"); ps.clear (); - ps.insert (std::make_pair (key1, 100)); - ps.insert (std::make_pair (key3, 102)); + ps.insert (key1, 100); + ps.insert (key3, 102); db::properties_id_type prop2 = rp.properties_id (ps); - EXPECT_EQ (prop2string (rp, prop2), "1=100\n3=102"); + EXPECT_EQ (db::prop2string (prop2), "1=100\n3=102"); ps.clear (); - ps.insert (std::make_pair (key1, 100)); + ps.insert (key1, 100); db::properties_id_type prop3 = rp.properties_id (ps); - EXPECT_EQ (prop2string (rp, prop3), "1=100"); - - db::PropertiesRepository rp_org = rp; + EXPECT_EQ (db::prop2string (prop3), "1=100"); db::PropertiesTranslator t; - EXPECT_EQ (prop2string (rp, t (prop1a)), "1=100\n2=101"); - EXPECT_EQ (prop2string (rp, t (prop1b)), "1=0\n2=101"); - EXPECT_EQ (prop2string (rp, t (prop2)), "1=100\n3=102"); - EXPECT_EQ (prop2string (rp, t (prop3)), "1=100"); + EXPECT_EQ (db::prop2string (t (prop1a)), "1=100\n2=101"); + EXPECT_EQ (db::prop2string (t (prop1b)), "1=0\n2=101"); + EXPECT_EQ (db::prop2string (t (prop2)), "1=100\n3=102"); + EXPECT_EQ (db::prop2string (t (prop3)), "1=100"); t = db::PropertiesTranslator::make_pass_all (); - EXPECT_EQ (prop2string (rp, t (prop1a)), "1=100\n2=101"); - EXPECT_EQ (prop2string (rp, t (prop1b)), "1=0\n2=101"); - EXPECT_EQ (prop2string (rp, t (prop2)), "1=100\n3=102"); - EXPECT_EQ (prop2string (rp, t (prop3)), "1=100"); + EXPECT_EQ (db::prop2string (t (prop1a)), "1=100\n2=101"); + EXPECT_EQ (db::prop2string (t (prop1b)), "1=0\n2=101"); + EXPECT_EQ (db::prop2string (t (prop2)), "1=100\n3=102"); + EXPECT_EQ (db::prop2string (t (prop3)), "1=100"); t = db::PropertiesTranslator::make_remove_all (); - EXPECT_EQ (prop2string (rp, t (prop1a)), ""); - EXPECT_EQ (prop2string (rp, t (prop1b)), ""); - EXPECT_EQ (prop2string (rp, t (prop2)), ""); - EXPECT_EQ (prop2string (rp, t (prop3)), ""); + EXPECT_EQ (db::prop2string (t (prop1a)), ""); + EXPECT_EQ (db::prop2string (t (prop1b)), ""); + EXPECT_EQ (db::prop2string (t (prop2)), ""); + EXPECT_EQ (db::prop2string (t (prop3)), ""); std::set kf; kf.insert (1); - t = db::PropertiesTranslator::make_filter (rp, kf); - EXPECT_EQ (prop2string (rp, t (prop1a)), "1=100"); - EXPECT_EQ (prop2string (rp, t (prop1b)), "1=0"); - EXPECT_EQ (prop2string (rp, t (prop2)), "1=100"); - EXPECT_EQ (prop2string (rp, t (prop3)), "1=100"); + t = db::PropertiesTranslator::make_filter (kf, rp); + EXPECT_EQ (db::prop2string (t (prop1a)), "1=100"); + EXPECT_EQ (db::prop2string (t (prop1b)), "1=0"); + EXPECT_EQ (db::prop2string (t (prop2)), "1=100"); + EXPECT_EQ (db::prop2string (t (prop3)), "1=100"); kf.insert (3); - t = db::PropertiesTranslator::make_filter (rp, kf); - EXPECT_EQ (prop2string (rp, t (prop1a)), "1=100"); - EXPECT_EQ (prop2string (rp, t (prop1b)), "1=0"); - EXPECT_EQ (prop2string (rp, t (prop2)), "1=100\n3=102"); - EXPECT_EQ (prop2string (rp, t (prop3)), "1=100"); + t = db::PropertiesTranslator::make_filter (kf, rp); + EXPECT_EQ (db::prop2string (t (prop1a)), "1=100"); + EXPECT_EQ (db::prop2string (t (prop1b)), "1=0"); + EXPECT_EQ (db::prop2string (t (prop2)), "1=100\n3=102"); + EXPECT_EQ (db::prop2string (t (prop3)), "1=100"); std::map km; km[1] = 4; km[3] = 1; - t = db::PropertiesTranslator::make_key_mapper (rp, km); - EXPECT_EQ (prop2string (rp, t (prop1a)), "4=100"); - EXPECT_EQ (prop2string (rp, t (prop1b)), "4=0"); - EXPECT_EQ (prop2string (rp, t (prop2)), "1=102\n4=100"); - EXPECT_EQ (prop2string (rp, t (prop3)), "4=100"); + t = db::PropertiesTranslator::make_key_mapper (km, rp); + EXPECT_EQ (db::prop2string (t (prop1a)), "4=100"); + EXPECT_EQ (db::prop2string (t (prop1b)), "4=0"); + EXPECT_EQ (db::prop2string (t (prop2)), "1=102\n4=100"); + EXPECT_EQ (db::prop2string (t (prop3)), "4=100"); kf.clear (); kf.insert (4); - t = db::PropertiesTranslator::make_filter (rp, kf) * db::PropertiesTranslator::make_key_mapper (rp, km); + t = db::PropertiesTranslator::make_filter (kf, rp) * db::PropertiesTranslator::make_key_mapper (km, rp); EXPECT_EQ (t.is_empty (), false); - EXPECT_EQ (prop2string (rp, t (prop1a)), "4=100"); - EXPECT_EQ (prop2string (rp, t (prop1b)), "4=0"); - EXPECT_EQ (prop2string (rp, t (prop2)), "4=100"); - EXPECT_EQ (prop2string (rp, t (prop3)), "4=100"); + EXPECT_EQ (db::prop2string (t (prop1a)), "4=100"); + EXPECT_EQ (db::prop2string (t (prop1b)), "4=0"); + EXPECT_EQ (db::prop2string (t (prop2)), "4=100"); + EXPECT_EQ (db::prop2string (t (prop3)), "4=100"); kf.clear (); kf.insert (3); - t = db::PropertiesTranslator::make_filter (rp, kf) * db::PropertiesTranslator::make_key_mapper (rp, km); + t = db::PropertiesTranslator::make_filter (kf, rp) * db::PropertiesTranslator::make_key_mapper (km, rp); EXPECT_EQ (t.is_empty (), true); - EXPECT_EQ (prop2string (rp, t (prop1a)), ""); - EXPECT_EQ (prop2string (rp, t (prop1b)), ""); - EXPECT_EQ (prop2string (rp, t (prop2)), ""); - EXPECT_EQ (prop2string (rp, t (prop3)), ""); + EXPECT_EQ (db::prop2string (t (prop1a)), ""); + EXPECT_EQ (db::prop2string (t (prop1b)), ""); + EXPECT_EQ (db::prop2string (t (prop2)), ""); + EXPECT_EQ (db::prop2string (t (prop3)), ""); - t = db::PropertiesTranslator::make_key_mapper (rp, km) * db::PropertiesTranslator::make_filter (rp, kf); + t = db::PropertiesTranslator::make_key_mapper (km, rp) * db::PropertiesTranslator::make_filter (kf, rp); EXPECT_EQ (t.is_empty (), false); - EXPECT_EQ (prop2string (rp, t (prop1a)), ""); - EXPECT_EQ (prop2string (rp, t (prop1b)), ""); - EXPECT_EQ (prop2string (rp, t (prop2)), "1=102"); - EXPECT_EQ (prop2string (rp, t (prop3)), ""); + EXPECT_EQ (db::prop2string (t (prop1a)), ""); + EXPECT_EQ (db::prop2string (t (prop1b)), ""); + EXPECT_EQ (db::prop2string (t (prop2)), "1=102"); + EXPECT_EQ (db::prop2string (t (prop3)), ""); - rp = rp_org; - - t = db::PropertiesTranslator::make_key_mapper (rp, km); - t = db::PropertiesTranslator::make_filter (rp, kf) * t; + t = db::PropertiesTranslator::make_key_mapper (km, rp); + t = db::PropertiesTranslator::make_filter (kf, rp) * t; EXPECT_EQ (t.is_empty (), true); - EXPECT_EQ (prop2string (rp, t (prop1a)), ""); - EXPECT_EQ (prop2string (rp, t (prop1b)), ""); - EXPECT_EQ (prop2string (rp, t (prop2)), ""); - EXPECT_EQ (prop2string (rp, t (prop3)), ""); + EXPECT_EQ (db::prop2string (t (prop1a)), ""); + EXPECT_EQ (db::prop2string (t (prop1b)), ""); + EXPECT_EQ (db::prop2string (t (prop2)), ""); + EXPECT_EQ (db::prop2string (t (prop3)), ""); - rp = rp_org; - - t = db::PropertiesTranslator::make_filter (rp, kf); - t = db::PropertiesTranslator::make_key_mapper (rp, km) * t; + t = db::PropertiesTranslator::make_filter (kf, rp); + t = db::PropertiesTranslator::make_key_mapper (km, rp) * t; EXPECT_EQ (t.is_empty (), false); - EXPECT_EQ (prop2string (rp, t (prop1a)), ""); - EXPECT_EQ (prop2string (rp, t (prop1b)), ""); - EXPECT_EQ (prop2string (rp, t (prop2)), "1=102"); - EXPECT_EQ (prop2string (rp, t (prop3)), ""); + EXPECT_EQ (db::prop2string (t (prop1a)), ""); + EXPECT_EQ (db::prop2string (t (prop1b)), ""); + EXPECT_EQ (db::prop2string (t (prop2)), "1=102"); + EXPECT_EQ (db::prop2string (t (prop3)), ""); } -#endif diff --git a/src/edt/edt/edtPartialService.cc b/src/edt/edt/edtPartialService.cc index 89258d416..849f1f06b 100644 --- a/src/edt/edt/edtPartialService.cc +++ b/src/edt/edt/edtPartialService.cc @@ -3406,9 +3406,10 @@ PartialService::handle_guiding_shape_changes () parent_inst = s->first.back ().inst_ptr; } - // @@@ name by id, don't repeat key + db::property_names_id_type name_id = db::property_names_id ("name"); + const db::PropertiesSet &input_props = db::properties (s->first.shape ().prop_id ()); - tl::Variant name_value = input_props.value (tl::Variant ("name")); + tl::Variant name_value = input_props.value (name_id); if (name_value.is_nil ()) { return false; } @@ -3431,7 +3432,7 @@ PartialService::handle_guiding_shape_changes () db::Shapes::shape_iterator sh = layout->cell (new_inst.cell_index ()).shapes (layout->guiding_shape_layer ()).begin (db::ShapeIterator::All); while (! sh.at_end ()) { const db::PropertiesSet &props = db::properties (sh->prop_id ()); - if (props.value (tl::Variant ("name")) == shape_name) { + if (props.value (name_id) == shape_name) { lay::ObjectInstPath inst_path = s->first; inst_path.back ().inst_ptr = new_inst; inst_path.back ().array_inst = new_inst.begin (); diff --git a/src/tl/unit_tests/tlVariantTests.cc b/src/tl/unit_tests/tlVariantTests.cc index d03a56d1c..e34b23e5a 100644 --- a/src/tl/unit_tests/tlVariantTests.cc +++ b/src/tl/unit_tests/tlVariantTests.cc @@ -1276,4 +1276,80 @@ TEST(10) EXPECT_EQ (vnan < vnan, false); } +// some tests originally from PropertiesRepositoryTests +TEST(11) +{ + tl::Variant v; + + EXPECT_EQ (std::string (v.to_parsable_string ()) == "nil", true); + + v = 1l; + EXPECT_EQ (std::string (v.to_parsable_string ()) == "#1", true); + EXPECT_EQ (v.to_long () == 1, true); + + v = "102"; + EXPECT_EQ (std::string (v.to_parsable_string ()) == "'102'", true); + + v = 2l; + EXPECT_EQ (std::string (v.to_parsable_string ()) == "#2", true); + EXPECT_EQ (v.is_long (), true); + EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.is_a_string (), false); + EXPECT_EQ (v.to_long () == 2, true); + EXPECT_EQ (v.to_double () == 2, true); + + v = tl::Variant (); + EXPECT_EQ (std::string (v.to_parsable_string ()) == "nil", true); + EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.is_a_string (), false); + EXPECT_EQ (v.is_long (), false); + EXPECT_EQ (v.is_nil (), true); + EXPECT_EQ (v.is_list (), false); + + v = tl::Variant ((long) 1); + EXPECT_EQ (std::string (v.to_parsable_string ()) == "#1", true); + EXPECT_EQ (v.to_long () == 1, true); + EXPECT_EQ (v.to_double () == 1, true); + EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.is_a_string (), false); + + v = tl::Variant ("A"); + EXPECT_EQ (std::string (v.to_parsable_string ()) == "'A'", true); + EXPECT_EQ (v.is_double (), false); + EXPECT_EQ (v.is_a_string (), true); + EXPECT_EQ (v.is_long (), false); + + EXPECT_EQ (v < tl::Variant (), false); + EXPECT_EQ (tl::Variant (1l) < v, true); + EXPECT_EQ (tl::Variant ("B") < v, false); + EXPECT_EQ (tl::Variant ("A") < v, false); + EXPECT_EQ (tl::Variant (" ") < v, true); +} + +// some tests originally from PropertiesRepositoryTests +TEST(12) +{ + tl::Variant v; + tl::Extractor ex (" #10 a"); + ex.read (v); + ex.expect ("a"); + EXPECT_EQ (v == tl::Variant ((long) 10), true); + ex = tl::Extractor (" ## 12.5 a"); + ex.read (v); + ex.expect ("a"); + EXPECT_EQ (v == tl::Variant (12.5), true); + ex = tl::Extractor (" Aber a"); + ex.read (v); + ex.expect ("a"); + EXPECT_EQ (v == tl::Variant ("Aber"), true); + ex = tl::Extractor (" Aber a"); + ex.read (v); + ex.expect ("a"); + EXPECT_EQ (v == tl::Variant ("Aber"), true); + ex = tl::Extractor (" (Aber_, ##2.500, (#05,x) ,() ) a"); + ex.read (v); + ex.expect ("a"); + EXPECT_EQ (std::string (v.to_parsable_string ()), "('Aber_',##2.5,(#5,'x'),())"); +} + }