diff --git a/src/db/db/dbTechnology.cc b/src/db/db/dbTechnology.cc index 2ed47818d..ad4eb63cf 100644 --- a/src/db/db/dbTechnology.cc +++ b/src/db/db/dbTechnology.cc @@ -80,7 +80,7 @@ Technologies::instance () static tl::XMLElementList xml_elements () { - return make_element ((Technologies::const_iterator (Technologies::*) () const) &Technologies::begin, (Technologies::const_iterator (Technologies::*) () const) &Technologies::end, &Technologies::add, "technology", + return make_element ((Technologies::const_iterator (Technologies::*) () const) &Technologies::begin, (Technologies::const_iterator (Technologies::*) () const) &Technologies::end, &Technologies::add_void, "technology", Technology::xml_elements () ); } @@ -92,7 +92,7 @@ Technologies::to_xml () const db::Technologies copy; for (const_iterator t = begin (); t != end (); ++t) { if (t->is_persisted ()) { - copy.add (new Technology (*t)); + copy.add (*t); } } @@ -110,7 +110,7 @@ Technologies::load_from_xml (const std::string &s) db::Technologies copy; for (const_iterator t = begin (); t != end (); ++t) { if (! t->is_persisted ()) { - copy.add (new Technology (*t)); + copy.add (*t); } } @@ -121,34 +121,31 @@ Technologies::load_from_xml (const std::string &s) *this = copy; } -void -Technologies::add_tech (Technology *tech, bool replace_same) +db::Technology * +Technologies::add_tech (const Technology &tech, bool replace_same) { - if (! tech) { - return; - } - - std::unique_ptr tech_ptr (tech); - Technology *t = 0; for (tl::stable_vector::iterator i = m_technologies.begin (); !t && i != m_technologies.end (); ++i) { - if (i->name () == tech->name ()) { + if (i->name () == tech.name ()) { t = i.operator-> (); } } if (t) { if (replace_same) { - *t = *tech; + *t = tech; } else { - throw tl::Exception (tl::to_string (tr ("A technology with this name already exists: ")) + tech->name ()); + throw tl::Exception (tl::to_string (tr ("A technology with this name already exists: ")) + tech.name ()); } } else { - m_technologies.push_back (tech_ptr.release ()); - tech->technology_changed_with_sender_event.add (this, &Technologies::technology_changed); + t = new Technology (tech); + m_technologies.push_back (t); + t->technology_changed_with_sender_event.add (this, &Technologies::technology_changed); } technologies_changed (); + + return t; } void diff --git a/src/db/db/dbTechnology.h b/src/db/db/dbTechnology.h index 9d68d93cf..9327b6d2d 100644 --- a/src/db/db/dbTechnology.h +++ b/src/db/db/dbTechnology.h @@ -121,24 +121,34 @@ public: /** * @brief Adds a technology to the setup * - * The container becomes owner of the technology object. - * Replaces a technology with the name of the given technology. + * @return A reference to the new Technology object + * + * If a technology with the given name already exists, it is replaced. */ - void add (Technology *technology) + db::Technology *add (const Technology &technology) { - add_tech (technology, true /*replace*/); + return add_tech (technology, true /*replace*/); } /** * @brief Adds a technology with a new name * + * @return A reference to the new Technology object + * * Like \add, but throws an exception if a technology with this name - * already exists. Takes over ownership over the technology object. - * The technology object is discarded if an exception is thrown. + * already exists. */ - void add_new (Technology *technology) + db::Technology *add_new (const Technology &technology) { - add_tech (technology, false /*throws exception on same name*/); + return add_tech (technology, false /*throws exception on same name*/); + } + + /** + * @brief Same as add, but no return value (for XML binding) + */ + void add_void (const Technology &technology) + { + add (technology); } /** @@ -244,7 +254,7 @@ private: bool m_changed; bool m_in_update; - void add_tech (Technology *technology, bool replace_same); + Technology *add_tech(const Technology &technology, bool replace_same); }; /** diff --git a/src/db/db/gsiDeclDbTechnologies.cc b/src/db/db/gsiDeclDbTechnologies.cc index 7b442971f..e9d045526 100644 --- a/src/db/db/gsiDeclDbTechnologies.cc +++ b/src/db/db/gsiDeclDbTechnologies.cc @@ -45,10 +45,14 @@ static db::Technology *technology_by_name (const std::string &name) static db::Technology *create_technology (const std::string &name) { - db::Technology *tech = new db::Technology (); - tech->set_name (name); - db::Technologies::instance ()->add_new (tech); - return tech; + db::Technology tech; + tech.set_name (name); + return db::Technologies::instance ()->add_new (tech); +} + +static db::Technology *register_technology (const db::Technology &tech) +{ + return db::Technologies::instance ()->add_new (tech); } static void remove_technology (const std::string &name) @@ -291,10 +295,24 @@ gsi::Class technology_decl ("db", "Technology", gsi::method ("create_technology", &create_technology, gsi::arg ("name"), "@brief Creates a new (empty) technology with the given name\n" "\n" + "The new technology is already registered in the system.\n" + "\n" "This method returns a reference to the new technology." ) + + gsi::method ("register_technology", ®ister_technology, gsi::arg ("tech"), + "@brief Registers a technology in the system\n" + "\n" + "Only after a technology is registered, it can be used in the system, e.g. by " + "specifying its name in \\Layout#technology_name. While \\create_technology already registers " + "the technology, this method allows registering a Technology object that has created in other ways.\n" + "\n" + "This method returns a reference to the new technology object which is a copy of the argument. " + "\\remove_technology can be used to remove a technology registered by this method.\n" + "\n" + "This method has been introduced in version 0.28.14." + ) + gsi::method ("remove_technology", &remove_technology, gsi::arg ("name"), - "@brief Removes the technology with the given name\n" + "@brief Removes the technology with the given name from the system\n" ) + gsi::method ("technologies_to_xml", &technologies_to_xml, "@brief Returns a XML representation of all technologies registered in the system\n" @@ -317,12 +335,13 @@ gsi::Class technology_decl ("db", "Technology", gsi::method ("technologies_from_xml", &technologies_from_xml, gsi::arg ("xml"), "@brief Loads the technologies from a XML representation\n" "\n" - "See \\technologies_to_xml for details. This method is the corresponding setter." + "See \\technologies_to_xml for details." ) + gsi::method ("technology_from_xml", &technology_from_xml, gsi::arg ("xml"), "@brief Loads the technology from a XML representation\n" "\n" - "See \\technology_to_xml for details." + "See \\technology_to_xml for details. Note that this function will create " + "a new Technology object which is not registered in the system. See \\Technology#register for details." ) + gsi::method_ext ("component_names", &get_component_names, "@brief Gets the names of all components available for \\component" @@ -338,6 +357,21 @@ gsi::Class technology_decl ("db", "Technology", "definitions are returned with \\technology_by_name. Use \\create_technology to register " "new technologies and \\remove_technology to delete technologies.\n" "\n" + "Note that a Technology object needs to be registered in the system, before its name " + "can be used to specify a technology, for example in \\Layout#technology_name. " + "Technology objects created by \\create_technology are automatically registered. " + "If you create a Technology object directly, you need to register it explicitly:" + "\n" + "@code\n" + "tech = RBA::Technology::new\n" + "tech.load(\"mytech.lyt\")\n" + "RBA::Technology::register(tech)\n" + "@/code\n" + "\n" + "Note that in the latter example, an exception will be thrown if a technology with the same " + "name already exists. Also note, that \\Technology#register will register a copy of the " + "object, so modifying it after registration will not have any effect.\n" + "\n" "The Technology class has been introduced in version 0.25.\n" ); diff --git a/src/lay/lay/layTechSetupDialog.cc b/src/lay/lay/layTechSetupDialog.cc index ae62c3ab4..8700a9416 100644 --- a/src/lay/lay/layTechSetupDialog.cc +++ b/src/lay/lay/layTechSetupDialog.cc @@ -775,13 +775,13 @@ BEGIN_PROTECTED } } - db::Technology *nt = new db::Technology (*t); + db::Technology nt (*t); - nt->set_tech_file_path (tl::to_string (tech_dir.absoluteFilePath (tn + QString::fromUtf8 (".lyt")))); - nt->set_default_base_path (tl::to_string (tech_dir.absolutePath ())); - nt->set_persisted (false); - nt->set_name (tl::to_string (tn)); - nt->set_description (std::string ()); + nt.set_tech_file_path (tl::to_string (tech_dir.absoluteFilePath (tn + QString::fromUtf8 (".lyt")))); + nt.set_default_base_path (tl::to_string (tech_dir.absolutePath ())); + nt.set_persisted (false); + nt.set_name (tl::to_string (tn)); + nt.set_description (std::string ()); m_technologies.add (nt); update_tech_tree (); @@ -900,12 +900,7 @@ BEGIN_PROTECTED db::Technology t; t.load (fn); - - if (m_technologies.has_technology (t.name ())) { - *m_technologies.technology_by_name (t.name ()) = t; - } else { - m_technologies.add (new db::Technology (t)); - } + m_technologies.add (t); update_tech_tree (); select_tech (*m_technologies.technology_by_name (t.name ())); diff --git a/src/lay/lay/layTechnologyController.cc b/src/lay/lay/layTechnologyController.cc index 212e2a7df..7fcfb0f85 100644 --- a/src/lay/lay/layTechnologyController.cc +++ b/src/lay/lay/layTechnologyController.cc @@ -536,7 +536,7 @@ TechnologyController::rescan (db::Technologies &technologies) technologies.clear (); for (db::Technologies::const_iterator t = current.begin (); t != current.end (); ++t) { if (t->is_persisted ()) { - technologies.add (new db::Technology (*t)); + technologies.add (*t); } } @@ -596,7 +596,7 @@ TechnologyController::rescan (db::Technologies &technologies) t.set_persisted (false); // don't save that one in the configuration t.set_readonly (readonly || ! QFileInfo (dir.filePath (*lf)).isWritable ()); t.set_grain_name (grain_name); - technologies.add (new db::Technology (t)); + technologies.add (t); } catch (tl::Exception &ex) { tl::warn << tl::to_string (QObject::tr ("Unable to auto-import technology file ")) << tl::to_string (*lf) << ": " << ex.msg (); @@ -608,14 +608,14 @@ TechnologyController::rescan (db::Technologies &technologies) for (std::vector::const_iterator t = m_temp_tech.begin (); t != m_temp_tech.end (); ++t) { - db::Technology *tech = new db::Technology (*t); if (tl::verbosity () >= 20) { - tl::info << "Registering special technology from " << tech->tech_file_path () << " as " << tech->name (); + tl::info << "Registering special technology from " << t->tech_file_path () << " as " << t->name (); } + + db::Technology *tech = technologies.add (*t); tech->set_persisted (false); // don't save that one in the configuration tech->set_tech_file_path (std::string ()); // don't save to a file either tech->set_readonly (true); // don't edit - technologies.add (tech); } } diff --git a/src/rba/unit_tests/rbaTests.cc b/src/rba/unit_tests/rbaTests.cc index ec0fcb24a..b5c5f4162 100644 --- a/src/rba/unit_tests/rbaTests.cc +++ b/src/rba/unit_tests/rbaTests.cc @@ -137,6 +137,7 @@ RUBYTEST (dbTilingProcessorTest, "dbTilingProcessorTest.rb") RUBYTEST (dbTransTest, "dbTransTest.rb") RUBYTEST (dbVectorTest, "dbVectorTest.rb") RUBYTEST (dbUtilsTests, "dbUtilsTests.rb") +RUBYTEST (dbTechnologies, "dbTechnologies.rb") RUBYTEST (edtTest, "edtTest.rb") RUBYTEST (extNetTracer, "extNetTracer.rb") RUBYTEST (imgObject, "imgObject.rb") @@ -147,7 +148,6 @@ RUBYTEST (layMacro, "layMacro.rb") RUBYTEST (layMenuTest, "layMenuTest.rb") RUBYTEST (layPixelBuffer, "layPixelBuffer.rb") RUBYTEST (laySession, "laySession.rb") -RUBYTEST (layTechnologies, "layTechnologies.rb") RUBYTEST (laySaveLayoutOptions, "laySaveLayoutOptions.rb") #if defined(HAVE_QT) && defined(HAVE_QTBINDINGS) RUBYTEST (qtbinding, "qtbinding.rb") diff --git a/testdata/ruby/layTechnologies.rb b/testdata/ruby/dbTechnologies.rb similarity index 95% rename from testdata/ruby/layTechnologies.rb rename to testdata/ruby/dbTechnologies.rb index 29ab17734..d4f6e9a66 100644 --- a/testdata/ruby/layTechnologies.rb +++ b/testdata/ruby/dbTechnologies.rb @@ -73,6 +73,16 @@ END RBA::Technology::remove_technology("MINE2") assert_equal(RBA::Technology::technology_names.inspect, '[""]') + # registration + tech = RBA::Technology::new + tech.name = "NEW" + tech.dbu = 0.5 + tech_new = RBA::Technology::register_technology(tech) + tech._destroy + assert_equal(RBA::Technology::technology_names.inspect, '["", "NEW"]') + assert_equal(tech_new.dbu, 0.5) + assert_equal(tech_new.name, "NEW") + end def test_2