From 551a80b70be379f4e2d6de88b460daa66c20179e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 19 Apr 2023 23:28:38 +0200 Subject: [PATCH] Preparing OASIS test mode for forward references --- .../streamers/oasis/db_plugin/dbOASISFormat.h | 8 +- .../oasis/db_plugin/dbOASISWriter.cc | 700 +++++++++--------- .../streamers/oasis/db_plugin/dbOASISWriter.h | 8 + 3 files changed, 373 insertions(+), 343 deletions(-) diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISFormat.h b/src/plugins/streamers/oasis/db_plugin/dbOASISFormat.h index 05cc203ea..12e68c3de 100644 --- a/src/plugins/streamers/oasis/db_plugin/dbOASISFormat.h +++ b/src/plugins/streamers/oasis/db_plugin/dbOASISFormat.h @@ -101,7 +101,8 @@ public: * @brief The constructor */ OASISWriterOptions () - : compression_level (2), write_cblocks (true), strict_mode (true), recompress (false), permissive (false), write_std_properties (1), subst_char ("*") + : compression_level (2), write_cblocks (true), strict_mode (true), recompress (false), permissive (false), + write_std_properties (1), subst_char ("*"), tables_at_end (false) { // .. nothing yet .. } @@ -166,6 +167,11 @@ public: */ std::string subst_char; + /** + * @brief Hidden option, for testing mainly: write tables at end to force forward references + */ + bool tables_at_end; + /** * @brief Implementation of FormatSpecificWriterOptions */ diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.cc b/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.cc index bb4b13576..a47e7ffcf 100644 --- a/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.cc +++ b/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.cc @@ -666,9 +666,11 @@ OASISWriter::OASISWriter () mp_layout (0), mp_cell (0), m_layer (0), m_datatype (0), + m_write_context_info (false), m_in_cblock (false), m_propname_id (0), m_propstring_id (0), + m_textstring_id (0), m_proptables_written (false), m_progress (tl::to_string (tr ("Writing OASIS file")), 10000) { @@ -1150,6 +1152,313 @@ OASISWriter::reset_modal_variables () mm_last_value_list.reset (); } +void +OASISWriter::write_propname_table (size_t &propnames_table_pos, const std::vector &cells, const db::Layout &layout, const std::vector > &layers) +{ + // write the property names collected so far in the order of the ID's. + + std::vector > rev_pn; + rev_pn.reserve (m_propnames.size ()); + for (auto p = m_propnames.begin (); p != m_propnames.end (); ++p) { + rev_pn.push_back (std::make_pair (p->second, p->first)); + } + std::sort (rev_pn.begin (), rev_pn.end ()); + + for (auto p = rev_pn.begin (); p != rev_pn.end (); ++p) { + tl_assert (p->first == (unsigned long)(p - rev_pn.begin ())); + begin_table (propnames_table_pos); + write_record_id (7); + write_nstring (p->second.c_str ()); + } + + // collect and write the future property names + + std::set prop_ids_done; + + for (auto cell = cells.begin (); cell != cells.end (); ++cell) { + + const db::Cell &cref (layout.cell (*cell)); + + if (cref.prop_id () != 0) { + begin_table (propnames_table_pos); + emit_propname_def (cref.prop_id ()); + } + + for (db::Cell::const_iterator inst = cref.begin (); ! inst.at_end (); ++inst) { + if (inst->has_prop_id () && inst->prop_id () != 0 && prop_ids_done.find (inst->prop_id ()) == prop_ids_done.end ()) { + prop_ids_done.insert (inst->prop_id ()); + begin_table (propnames_table_pos); + emit_propname_def (inst->prop_id ()); + m_progress.set (mp_stream->pos ()); + } + } + + for (auto l = layers.begin (); l != layers.end (); ++l) { + db::ShapeIterator shape (cref.shapes (l->first).begin (db::ShapeIterator::Properties | db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Texts)); + while (! shape.at_end ()) { + if (shape->has_prop_id () && shape->prop_id () != 0 && prop_ids_done.find (shape->prop_id ()) == prop_ids_done.end ()) { + prop_ids_done.insert (shape->prop_id ()); + begin_table (propnames_table_pos); + emit_propname_def (shape->prop_id ()); + m_progress.set (mp_stream->pos ()); + } + shape.finish_array (); + } + } + + } + + // if needed, emit property name required for the PCell or meta info context information + + if (m_write_context_info && m_propnames.find (std::string (klayout_context_name)) == m_propnames.end ()) { + + bool has_context = false; + for (auto cell = cells.begin (); cell != cells.end () && ! has_context; ++cell) { + LayoutOrCellContextInfo ci; + has_context = layout.has_context_info (*cell) && layout.get_context_info (*cell, ci); + } + + if (has_context) { + m_propnames.insert (std::make_pair (std::string (klayout_context_name), m_propname_id++)); + begin_table (propnames_table_pos); + write_record_id (7); + write_nstring (klayout_context_name); + } + + } + + end_table (propnames_table_pos); +} + +void +OASISWriter::write_propstring_table (size_t &propstrings_table_pos, const std::vector &cells, const db::Layout &layout, const std::vector > &layers) +{ + // write the property strings collected so far in the order of the ID's. + + std::vector > rev_ps; + rev_ps.reserve (m_propstrings.size ()); + for (auto p = m_propstrings.begin (); p != m_propstrings.end (); ++p) { + rev_ps.push_back (std::make_pair (p->second, &p->first)); + } + std::sort (rev_ps.begin (), rev_ps.end ()); + + tl_assert (rev_ps.size () == size_t (m_propstring_id)); + + for (auto p = rev_ps.begin (); p != rev_ps.end (); ++p) { + tl_assert (p->first == (unsigned long)(p - rev_ps.begin ())); + begin_table (propstrings_table_pos); + write_record_id (9); + write_nstring (p->second->c_str ()); + } + + // collect and write the future property strings + + std::set prop_ids_done; + + for (auto cell = cells.begin (); cell != cells.end (); ++cell) { + + const db::Cell &cref (layout.cell (*cell)); + + if (cref.prop_id () != 0 && prop_ids_done.find (cref.prop_id ()) == prop_ids_done.end ()) { + prop_ids_done.insert (cref.prop_id ()); + begin_table (propstrings_table_pos); + emit_propstring_def (cref.prop_id ()); + } + + for (db::Cell::const_iterator inst = cref.begin (); ! inst.at_end (); ++inst) { + if (inst->has_prop_id () && inst->prop_id () != 0 && prop_ids_done.find (inst->prop_id ()) == prop_ids_done.end ()) { + prop_ids_done.insert (inst->prop_id ()); + begin_table (propstrings_table_pos); + emit_propstring_def (inst->prop_id ()); + m_progress.set (mp_stream->pos ()); + } + } + + for (auto l = layers.begin (); l != layers.end (); ++l) { + db::ShapeIterator shape (cref.shapes (l->first).begin (db::ShapeIterator::Properties | db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Texts)); + while (! shape.at_end ()) { + if (shape->has_prop_id () && shape->prop_id () != 0 && prop_ids_done.find (shape->prop_id ()) == prop_ids_done.end ()) { + prop_ids_done.insert (shape->prop_id ()); + begin_table (propstrings_table_pos); + emit_propstring_def (shape->prop_id ()); + m_progress.set (mp_stream->pos ()); + } + shape.finish_array (); + } + } + + } + + if (m_write_context_info) { + + // emit property string id's required for the PCell and meta info context information + std::vector context_prop_strings; + + for (auto cell = cells.begin (); cell != cells.end (); ++cell) { + + m_progress.set (mp_stream->pos ()); + context_prop_strings.clear (); + + if (layout.has_context_info (*cell) && layout.get_context_info (*cell, context_prop_strings)) { + + for (auto c = context_prop_strings.begin (); c != context_prop_strings.end (); ++c) { + if (m_propstrings.insert (std::make_pair (*c, m_propstring_id)).second) { + begin_table (propstrings_table_pos); + write_record_id (9); + write_bstring (c->c_str ()); + ++m_propstring_id; + } + } + + } + + } + + } + + end_table (propstrings_table_pos); +} + +void +OASISWriter::write_cellname_table (size_t &cellnames_table_pos, const std::vector &cells_by_index, const std::map *cell_positions, const db::Layout &layout) +{ + bool sequential = true; + for (auto cell = cells_by_index.begin (); cell != cells_by_index.end () && sequential; ++cell) { + sequential = (*cell == db::cell_index_type (cell - cells_by_index.begin ())); + } + + // CELLNAME (implicit or explicit) + for (auto cell = cells_by_index.begin (); cell != cells_by_index.end (); ++cell) { + + begin_table (cellnames_table_pos); + + write_record_id (sequential ? 3 : 4); + write_nstring (layout.cell_name (*cell)); + if (! sequential) { + write ((unsigned long) *cell); + } + + if (m_options.write_std_properties > 1) { + + reset_modal_variables (); + + // write S_BOUNDING_BOX entries + + std::vector values; + + // TODO: how to set the "depends on external cells" flag? + db::Box bbox = layout.cell (*cell).bbox (); + if (bbox.empty ()) { + // empty box + values.push_back (tl::Variant ((unsigned int) 0x2)); + bbox = db::Box (0, 0, 0, 0); + } else { + values.push_back (tl::Variant ((unsigned int) 0x0)); + } + + values.push_back (tl::Variant (bbox.left ())); + values.push_back (tl::Variant (bbox.bottom ())); + values.push_back (tl::Variant (bbox.width ())); + values.push_back (tl::Variant (bbox.height ())); + + write_property_def (s_bounding_box_name, values, true); + + // PROPERTY record with S_CELL_OFFSET + if (cell_positions) { + std::map::const_iterator pp = cell_positions->find (*cell); + if (pp != cell_positions->end ()) { + write_property_def (s_cell_offset_name, tl::Variant (pp->second), true); + } else { + write_property_def (s_cell_offset_name, tl::Variant (size_t (0)), true); + } + } + + } + + } + + end_table (cellnames_table_pos); +} + +void +OASISWriter::write_textstring_table (size_t &textstrings_table_pos, const std::vector &cells, const db::Layout &layout, const std::vector > &layers) +{ + // write present text strings + + // collect present strings by ID + std::vector > rev_ts; + rev_ts.reserve (m_textstrings.size ()); + for (auto p = m_textstrings.begin (); p != m_textstrings.end (); ++p) { + rev_ts.push_back (std::make_pair (p->second, &p->first)); + } + std::sort (rev_ts.begin (), rev_ts.end ()); + + tl_assert (rev_ts.size () == size_t (m_textstring_id)); + + for (auto t = rev_ts.begin (); t != rev_ts.end (); ++t) { + tl_assert (t->first == (unsigned long)(t - rev_ts.begin ())); + begin_table (textstrings_table_pos); + write_record_id (5); + write_nstring (t->second->c_str ()); + } + + // collect future test strings + + for (auto cell = cells.begin (); cell != cells.end (); ++cell) { + + const db::Cell &cref (layout.cell (*cell)); + for (auto l = layers.begin (); l != layers.end (); ++l) { + db::ShapeIterator shape (cref.shapes (l->first).begin (db::ShapeIterator::Texts)); + while (! shape.at_end ()) { + if (m_textstrings.insert (std::make_pair (shape->text_string (), m_textstring_id)).second) { + begin_table (textstrings_table_pos); + write_record_id (5); + write_astring (shape->text_string ()); + ++m_textstring_id; + m_progress.set (mp_stream->pos ()); + } + ++shape; + } + } + + } + + end_table (textstrings_table_pos); +} + +void +OASISWriter::write_layername_table (size_t &layernames_table_pos, const std::vector > &layers) +{ + for (auto l = layers.begin (); l != layers.end (); ++l) { + + if (! l->second.name.empty ()) { + + begin_table (layernames_table_pos); + + // write mappings to text layer and shape layers + write_record_id (11); + write_nstring (l->second.name.c_str ()); + write_byte (3); + write ((unsigned long) l->second.layer); + write_byte (3); + write ((unsigned long) l->second.datatype); + + write_record_id (12); + write_nstring (l->second.name.c_str ()); + write_byte (3); + write ((unsigned long) l->second.layer); + write_byte (3); + write ((unsigned long) l->second.datatype); + + m_progress.set (mp_stream->pos ()); + + } + + } + + end_table (layernames_table_pos); +} + static bool must_write_cell (const db::Cell &cref) { // Don't write proxy cells which are not employed @@ -1162,6 +1471,7 @@ static bool skip_cell_body (const db::Cell &cref) return cref.is_ghost_cell () && cref.empty (); } + void OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLayoutOptions &options) { @@ -1172,6 +1482,7 @@ OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::Save m_layer = m_datatype = 0; m_in_cblock = false; m_cblock_buffer.clear (); + m_write_context_info = options.write_context_info (); m_options = options.get_options (); mp_stream = &stream; @@ -1252,6 +1563,7 @@ OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::Save // We will collect the standard properties here: m_propstring_id = m_propname_id = 0; + m_textstring_id = 0; m_proptables_written = false; std::vector > init_props; @@ -1321,295 +1633,28 @@ OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::Save } - // build property name and value string tables - - { + // write the tables - // write the property names collected so far in the order of the ID's. - - std::vector > rev_pn; - rev_pn.reserve (m_propnames.size ()); - for (std::map ::const_iterator p = m_propnames.begin (); p != m_propnames.end (); ++p) { - rev_pn.push_back (std::make_pair (p->second, p->first)); - } - std::sort (rev_pn.begin (), rev_pn.end ()); + if (! m_options.tables_at_end) { - for (std::vector >::const_iterator p = rev_pn.begin (); p != rev_pn.end (); ++p) { - tl_assert (p->first == (unsigned long)(p - rev_pn.begin ())); - begin_table (propnames_table_pos); - write_record_id (7); - write_nstring (p->second.c_str ()); + write_propname_table (propnames_table_pos, cells, layout, layers); + write_propstring_table (propstrings_table_pos, cells, layout, layers); + + // Now we cannot open new property ID's in strict mode + m_proptables_written = true; + + // build cell name table now in non-strict mode (in strict mode it is written at the + // end because then we have the cell positions fo S_CELL_OFFSET) + if (! m_options.strict_mode) { + write_cellname_table (cellnames_table_pos, cells_by_index, 0, layout); } - // collect and write the future property names - - std::set prop_ids_done; - - for (std::vector::const_iterator cell = cells.begin (); cell != cells.end (); ++cell) { - - const db::Cell &cref (layout.cell (*cell)); - - if (cref.prop_id () != 0) { - begin_table (propnames_table_pos); - emit_propname_def (cref.prop_id ()); - } - - for (db::Cell::const_iterator inst = cref.begin (); ! inst.at_end (); ++inst) { - if (inst->has_prop_id () && inst->prop_id () != 0 && prop_ids_done.find (inst->prop_id ()) == prop_ids_done.end ()) { - prop_ids_done.insert (inst->prop_id ()); - begin_table (propnames_table_pos); - emit_propname_def (inst->prop_id ()); - m_progress.set (mp_stream->pos ()); - } - } - - for (std::vector >::const_iterator l = layers.begin (); l != layers.end (); ++l) { - db::ShapeIterator shape (cref.shapes (l->first).begin (db::ShapeIterator::Properties | db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Texts)); - while (! shape.at_end ()) { - if (shape->has_prop_id () && shape->prop_id () != 0 && prop_ids_done.find (shape->prop_id ()) == prop_ids_done.end ()) { - prop_ids_done.insert (shape->prop_id ()); - begin_table (propnames_table_pos); - emit_propname_def (shape->prop_id ()); - m_progress.set (mp_stream->pos ()); - } - shape.finish_array (); - } - } - - } - - // if needed, emit property name required for the PCell or meta info context information - - if (options.write_context_info () && m_propnames.find (std::string (klayout_context_name)) == m_propnames.end ()) { - - bool has_context = false; - for (auto cell = cells.begin (); cell != cells.end () && ! has_context; ++cell) { - LayoutOrCellContextInfo ci; - has_context = layout.has_context_info (*cell) && layout.get_context_info (*cell, ci); - } - - if (has_context) { - m_propnames.insert (std::make_pair (std::string (klayout_context_name), m_propname_id++)); - begin_table (propnames_table_pos); - write_record_id (7); - write_nstring (klayout_context_name); - } - - } - - end_table (propnames_table_pos); + write_textstring_table (textstrings_table_pos, cells, layout, layers); + write_layername_table (layernames_table_pos, layers); } - { - - // write the property strings collected so far in the order of the ID's. - - std::vector > rev_ps; - rev_ps.reserve (m_propstrings.size ()); - for (std::map ::const_iterator p = m_propstrings.begin (); p != m_propstrings.end (); ++p) { - rev_ps.push_back (std::make_pair (p->second, p->first)); - } - std::sort (rev_ps.begin (), rev_ps.end ()); - - for (std::vector >::const_iterator p = rev_ps.begin (); p != rev_ps.end (); ++p) { - tl_assert (p->first == (unsigned long)(p - rev_ps.begin ())); - begin_table (propstrings_table_pos); - write_record_id (9); - write_nstring (p->second.c_str ()); - } - - // collect and write the future property strings - - std::set prop_ids_done; - - for (std::vector::const_iterator cell = cells.begin (); cell != cells.end (); ++cell) { - - const db::Cell &cref (layout.cell (*cell)); - - if (cref.prop_id () != 0 && prop_ids_done.find (cref.prop_id ()) == prop_ids_done.end ()) { - prop_ids_done.insert (cref.prop_id ()); - begin_table (propnames_table_pos); - emit_propstring_def (cref.prop_id ()); - } - - for (db::Cell::const_iterator inst = cref.begin (); ! inst.at_end (); ++inst) { - if (inst->has_prop_id () && inst->prop_id () != 0 && prop_ids_done.find (inst->prop_id ()) == prop_ids_done.end ()) { - prop_ids_done.insert (inst->prop_id ()); - begin_table (propstrings_table_pos); - emit_propstring_def (inst->prop_id ()); - m_progress.set (mp_stream->pos ()); - } - } - - for (std::vector >::const_iterator l = layers.begin (); l != layers.end (); ++l) { - db::ShapeIterator shape (cref.shapes (l->first).begin (db::ShapeIterator::Properties | db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Texts)); - while (! shape.at_end ()) { - if (shape->has_prop_id () && shape->prop_id () != 0 && prop_ids_done.find (shape->prop_id ()) == prop_ids_done.end ()) { - prop_ids_done.insert (shape->prop_id ()); - begin_table (propstrings_table_pos); - emit_propstring_def (shape->prop_id ()); - m_progress.set (mp_stream->pos ()); - } - shape.finish_array (); - } - } - - } - - if (options.write_context_info ()) { - - // emit property string id's required for the PCell and meta info context information - std::vector context_prop_strings; - - for (std::vector::const_iterator cell = cells.begin (); cell != cells.end (); ++cell) { - - m_progress.set (mp_stream->pos ()); - context_prop_strings.clear (); - - if (layout.has_context_info (*cell) && layout.get_context_info (*cell, context_prop_strings)) { - - for (std::vector ::const_iterator c = context_prop_strings.begin (); c != context_prop_strings.end (); ++c) { - if (m_propstrings.insert (std::make_pair (*c, m_propstring_id)).second) { - begin_table (propstrings_table_pos); - write_record_id (9); - write_bstring (c->c_str ()); - ++m_propstring_id; - } - } - - } - - } - - } - - end_table (propstrings_table_pos); - - } - - // Now we cannot open new property ID's in strict mode - m_proptables_written = true; - - // build cell name table now in non-strict mode (in strict mode it is written at the - // end because then we have the cell positions fo S_CELL_OFFSET) - - if (! m_options.strict_mode) { - - size_t pos = 0; - - bool sequential = true; - for (std::vector::const_iterator cell = cells_by_index.begin (); cell != cells_by_index.end () && sequential; ++cell) { - sequential = (*cell == db::cell_index_type (cell - cells_by_index.begin ())); - } - - // CELLNAME (implicit or explicit) - for (std::vector::const_iterator cell = cells_by_index.begin (); cell != cells_by_index.end (); ++cell) { - - begin_table (pos); - - write_record_id (sequential ? 3 : 4); - write_nstring (layout.cell_name (*cell)); - if (! sequential) { - write ((unsigned long) *cell); - } - - if (m_options.write_std_properties > 1) { - - reset_modal_variables (); - - // write S_BOUNDING_BOX entries - - std::vector values; - - // TODO: how to set the "depends on external cells" flag? - db::Box bbox = layout.cell (*cell).bbox (); - if (bbox.empty ()) { - // empty box - values.push_back (tl::Variant ((unsigned int) 0x2)); - bbox = db::Box (0, 0, 0, 0); - } else { - values.push_back (tl::Variant ((unsigned int) 0x0)); - } - - values.push_back (tl::Variant (bbox.left ())); - values.push_back (tl::Variant (bbox.bottom ())); - values.push_back (tl::Variant (bbox.width ())); - values.push_back (tl::Variant (bbox.height ())); - - write_property_def (s_bounding_box_name, values, true); - - } - - } - - end_table (pos); - - } - - // build text string table - - { - - unsigned int id = 0; - - for (std::vector::const_iterator cell = cells.begin (); cell != cells.end (); ++cell) { - - const db::Cell &cref (layout.cell (*cell)); - for (std::vector >::const_iterator l = layers.begin (); l != layers.end (); ++l) { - db::ShapeIterator shape (cref.shapes (l->first).begin (db::ShapeIterator::Texts)); - while (! shape.at_end ()) { - if (m_textstrings.insert (std::make_pair (shape->text_string (), id)).second) { - begin_table (textstrings_table_pos); - write_record_id (5); - write_astring (shape->text_string ()); - ++id; - m_progress.set (mp_stream->pos ()); - } - ++shape; - } - } - - } - - end_table (textstrings_table_pos); - - } - - // write layernames table - - { - - for (std::vector >::const_iterator l = layers.begin (); l != layers.end (); ++l) { - - if (! l->second.name.empty ()) { - - begin_table (layernames_table_pos); - - // write mappings to text layer and shape layers - write_record_id (11); - write_nstring (l->second.name.c_str ()); - write_byte (3); - write ((unsigned long) l->second.layer); - write_byte (3); - write ((unsigned long) l->second.datatype); - - write_record_id (12); - write_nstring (l->second.name.c_str ()); - write_byte (3); - write ((unsigned long) l->second.layer); - write_byte (3); - write ((unsigned long) l->second.datatype); - - m_progress.set (mp_stream->pos ()); - - } - - } - - end_table (layernames_table_pos); - - } + // write cells for (std::vector::const_iterator cell = cells.begin (); cell != cells.end (); ++cell) { @@ -1694,66 +1739,31 @@ OASISWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::Save } + // write the tables if at end + + if (m_options.tables_at_end) { + + // do not consider future items as everything has been collected + std::vector no_cells; + std::vector > no_layers; + + write_propname_table (propnames_table_pos, no_cells, layout, no_layers); + write_propstring_table (propstrings_table_pos, no_cells, layout, no_layers); + + // Now we cannot open new property ID's in strict mode + m_proptables_written = true; + + write_textstring_table (textstrings_table_pos, no_cells, layout, no_layers); + + // write all layers here + write_layername_table (layernames_table_pos, layers); + + } + // write cell table at the end in strict mode (in that mode we need the cell positions // for the S_CELL_OFFSET properties) - - if (m_options.strict_mode) { - - bool sequential = true; - for (std::vector::const_iterator cell = cells_by_index.begin (); cell != cells_by_index.end () && sequential; ++cell) { - sequential = (*cell == db::cell_index_type (cell - cells_by_index.begin ())); - } - - for (std::vector::const_iterator cell = cells_by_index.begin (); cell != cells_by_index.end (); ++cell) { - - begin_table (cellnames_table_pos); - - // CELLNAME (explicit) - write_record_id (sequential ? 3 : 4); - write_nstring (layout.cell_name (*cell)); - if (! sequential) { - write ((unsigned long) *cell); - } - - reset_modal_variables (); - - if (m_options.write_std_properties > 1) { - - // write S_BOUNDING_BOX entries - - std::vector values; - - // TODO: how to set the "depends on external cells" flag? - db::Box bbox = layout.cell (*cell).bbox (); - if (bbox.empty ()) { - // empty box - values.push_back (tl::Variant ((unsigned int) 0x2)); - bbox = db::Box (0, 0, 0, 0); - } else { - values.push_back (tl::Variant ((unsigned int) 0x0)); - } - - values.push_back (tl::Variant (bbox.left ())); - values.push_back (tl::Variant (bbox.bottom ())); - values.push_back (tl::Variant (bbox.width ())); - values.push_back (tl::Variant (bbox.height ())); - - write_property_def (s_bounding_box_name, values, true); - - } - - // PROPERTY record with S_CELL_OFFSET - std::map::const_iterator pp = cell_positions.find (*cell); - if (pp != cell_positions.end ()) { - write_property_def (s_cell_offset_name, tl::Variant (pp->second), true); - } else { - write_property_def (s_cell_offset_name, tl::Variant (size_t (0)), true); - } - - } - - end_table (cellnames_table_pos); - + if (m_options.tables_at_end || m_options.strict_mode) { + write_cellname_table (cellnames_table_pos, cells_by_index, &cell_positions, layout); } // END record @@ -2349,9 +2359,15 @@ OASISWriter::write (const db::Text &text, db::properties_id_type prop_id, const m_progress.set (mp_stream->pos ()); db::Trans trans = text.trans (); + + unsigned long text_id = 0; std::map ::const_iterator ts = m_textstrings.find (text.string ()); - tl_assert (ts != m_textstrings.end ()); - unsigned long text_id = ts->second; + if (ts == m_textstrings.end ()) { + text_id = m_textstring_id++; + m_textstrings.insert (std::make_pair (text.string (), text_id)); + } else { + text_id = ts->second; + } unsigned char info = 0x20; diff --git a/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.h b/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.h index 6a853f370..0dd319515 100644 --- a/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.h +++ b/src/plugins/streamers/oasis/db_plugin/dbOASISWriter.h @@ -203,12 +203,14 @@ private: const db::Cell *mp_cell; int m_layer; int m_datatype; + bool m_write_context_info; std::vector m_pointlist; tl::OutputMemoryStream m_cblock_buffer; tl::OutputMemoryStream m_cblock_compressed; bool m_in_cblock; unsigned long m_propname_id; unsigned long m_propstring_id; + unsigned long m_textstring_id; bool m_proptables_written; std::map m_textstrings; @@ -308,6 +310,12 @@ private: void write_pointlist (const std::vector &pointlist, bool for_polygons); void write_inst_with_rep (const db::CellInstArray &inst, db::properties_id_type prop_id, const db::Vector &disp, const db::Repetition &rep); + + void write_propname_table (size_t &propnames_table_pos, const std::vector &cells, const Layout &layout, const std::vector > &layers); + void write_propstring_table (size_t &propstrings_table_pos, const std::vector &cells, const Layout &layout, const std::vector > &layers); + void write_cellname_table (size_t &cellnames_table_pos, const std::vector &cells_by_index, const std::map *cell_positions, const Layout &layout); + void write_textstring_table (size_t &textstrings_table_pos, const std::vector &cells, const Layout &layout, const std::vector > &layers); + void write_layername_table (size_t &layernames_table_pos, const std::vector > &layers); }; } // namespace db