From fa30fd0f7b764a7215b0ccce4113efc343afb2e5 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 29 Apr 2025 22:19:59 +0200 Subject: [PATCH] WIP, MALY reader --- .../streamers/maly/db_plugin/dbMALY.cc | 80 +++++ src/plugins/streamers/maly/db_plugin/dbMALY.h | 31 +- .../streamers/maly/db_plugin/dbMALYReader.cc | 321 ++++++++++++------ .../streamers/maly/db_plugin/dbMALYReader.h | 87 ++++- 4 files changed, 405 insertions(+), 114 deletions(-) diff --git a/src/plugins/streamers/maly/db_plugin/dbMALY.cc b/src/plugins/streamers/maly/db_plugin/dbMALY.cc index b53b4b449..954514f79 100644 --- a/src/plugins/streamers/maly/db_plugin/dbMALY.cc +++ b/src/plugins/streamers/maly/db_plugin/dbMALY.cc @@ -38,6 +38,86 @@ MALYDiagnostics::~MALYDiagnostics () // .. nothing yet .. } +// --------------------------------------------------------------- +// MALYData implementation + +std::string +MALYTitle::to_string () const +{ + std::string res; + res += "\"" + string + "\" " + transformation.to_string (); + res += tl::sprintf (" %g,%g,%g", width, height, pitch); + if (font == Standard) { + res += " [Standard]"; + } else if (font == Native) { + res += " [Native]"; + } + return res; +} + +std::string +MALYStructure::to_string () const +{ + std::string res; + res += path + "{" + topcell + "}"; + if (layer < 0) { + res += "(*)"; + } else { + res += tl::sprintf ("(%d)", layer); + } + + if (! mname.empty ()) { + res += " mname(" + mname + ")"; + } + if (! ename.empty ()) { + res += " ename(" + ename + ")"; + } + if (! dname.empty ()) { + res += " dname(" + dname + ")"; + } + + res += " "; + res += size.to_string (); + + res += " "; + res += transformation.to_string (); + + if (nx > 1 || ny > 1) { + res += tl::sprintf (" [%.12gx%d,%.12gx%d]", dx, nx, dy, ny); + } + + return res; +} + +std::string +MALYMask::to_string () const +{ + std::string res; + res += "Mask " + name + "\n"; + res += " Size " + tl::to_string (size_um); + + for (auto t = titles.begin (); t != titles.end (); ++t) { + res += "\n Title " + t->to_string (); + } + for (auto s = structures.begin (); s != structures.end (); ++s) { + res += "\n Ref " + s->to_string (); + } + return res; +} + +std::string +MALYData::to_string () const +{ + std::string res; + for (auto m = masks.begin (); m != masks.end (); ++m) { + if (m != masks.begin ()) { + res += "\n"; + } + res += m->to_string (); + } + return res; +} + // --------------------------------------------------------------- // MALY format declaration diff --git a/src/plugins/streamers/maly/db_plugin/dbMALY.h b/src/plugins/streamers/maly/db_plugin/dbMALY.h index ec904e969..bdcbaae7b 100644 --- a/src/plugins/streamers/maly/db_plugin/dbMALY.h +++ b/src/plugins/streamers/maly/db_plugin/dbMALY.h @@ -76,9 +76,9 @@ public: */ enum Type { - String = 0, // A user-defined string - Date = 1, // The date - Serial = 2 // A serial number + String = 0, // A user-defined string + Date = 1, // The date + Serial = 2 // A serial number }; /** @@ -86,8 +86,9 @@ public: */ enum Font { - Standard = 0, // Standard font - Native = 1 // Native tool font + FontNotSet = 0, // Undef + Standard = 1, // Standard font + Native = 2 // Native tool font }; /** @@ -127,6 +128,11 @@ public: * @brief The font to be used */ Font font; + + /** + * @brief Returns a string representing the structure + */ + std::string to_string () const; }; /** @@ -204,6 +210,11 @@ public: * A value of -1 means "all". */ int layer; + + /** + * @brief Returns a string representing the structure + */ + std::string to_string () const; }; /** @@ -240,6 +251,11 @@ public: * @brief The list of titles */ std::list titles; + + /** + * @brief Returns a string representing the mask + */ + std::string to_string () const; }; /** @@ -258,6 +274,11 @@ public: * @brief The masks defined by the file */ std::list masks; + + /** + * @brief Returns a string representing the data set + */ + std::string to_string () const; }; } diff --git a/src/plugins/streamers/maly/db_plugin/dbMALYReader.cc b/src/plugins/streamers/maly/db_plugin/dbMALYReader.cc index ebf2d7b0b..5d9086c48 100644 --- a/src/plugins/streamers/maly/db_plugin/dbMALYReader.cc +++ b/src/plugins/streamers/maly/db_plugin/dbMALYReader.cc @@ -42,88 +42,14 @@ namespace db { -// --------------------------------------------------------------- -// Some helper structures to collect data - -struct MALYReaderTitleSpec -{ - MALYReaderTitleSpec () - : enabled (false), width (1.0), height (1.0), pitch (1.0) - { } - - bool enabled; - db::DTrans trans; - double width, height, pitch; -}; - -struct MALYReaderTitleData -{ - MALYReaderTitleData () - { } - - MALYReaderTitleSpec date_spec; - MALYReaderTitleSpec serial_spec; - std::list > string_titles; -}; - -struct MALYReaderParametersData -{ - MALYReaderParametersData () - : base (Center), array_base (Center), masksize (0.0), maskmirror (false), font (MALYTitle::Standard) - { } - - enum Base - { - Origin, - Center, - LowerLeft - }; - - Base base; - Base array_base; - double masksize; - bool maskmirror; - MALYTitle::Font font; - std::list > roots; -}; - -struct MALYReaderStrRefData -{ - MALYReaderStrRefData () - : layer (-1), scale (1.0), nx (1), ny (1), dx (0.0), dy (0.0) - { } - - std::string file; - std::string name; - int layer; - db::DVector org; - db::DBox size; - double scale; - int nx, ny; - double dx, dy; -}; - -struct MALYReaderStrGroupData -{ - std::string name; - std::list refs; -}; - -struct MALYReaderMaskData -{ - MALYReaderParametersData parameters; - MALYReaderTitleData title; - std::list strgroups; -}; - - // --------------------------------------------------------------- // MALYReader MALYReader::MALYReader (tl::InputStream &s) : m_stream (s), m_progress (tl::to_string (tr ("Reading MALY file")), 1000), - m_dbu (0.001) + m_dbu (0.001), + m_last_record_line (0) { m_progress.set_format (tl::to_string (tr ("%.0fk lines"))); m_progress.set_format_unit (1000.0); @@ -171,6 +97,8 @@ MALYReader::read (db::Layout &layout, const db::LoadLayoutOptions &options) MALYData data = read_maly_file (); + // @@@ + std::cout << data.to_string () << std::endl; // @@@ finish_layers (layout); @@ -187,18 +115,26 @@ tl::Extractor MALYReader::read_record () { if (! m_record_returned.empty ()) { + m_record = m_record_returned; + m_record_returned.clear (); + return tl::Extractor (m_record.c_str ()); + } while (! m_stream.at_end ()) { + + m_last_record_line = m_stream.line_number (); m_record = read_record_internal (); + tl::Extractor ex (m_record.c_str ()); if (ex.test ("+")) { error (tl::to_string (tr ("'+' character past first column - did you mean to continue a line?"))); } else if (! ex.at_end ()) { return ex; } + } return tl::Extractor (); @@ -333,12 +269,12 @@ MALYReader::extract_title_trans (tl::Extractor &ex, MALYReaderTitleSpec &spec) spec.trans = db::DTrans (rot, ymirror, db::DVector (x, y)); } -static -MALYReaderParametersData::Base string_to_base (const std::string &string) +MALYReader::MALYReaderParametersData::Base +MALYReader::string_to_base (const std::string &string) { if (string == "ORIGIN") { return MALYReaderParametersData::Origin; - } else if (string == "LOWERLEFT") { // @@@? + } else if (string == "LOWERLEFT") { return MALYReaderParametersData::LowerLeft; } else if (string == "CENTER") { return MALYReaderParametersData::Center; @@ -531,7 +467,27 @@ MALYReader::read_strgroup (MALYReaderStrGroupData &data) tl::Extractor ex = read_record (); if (end_section (ex)) { + break; + + } else if (ex.test ("PROPERTY")) { + + if (data.refs.empty ()) { + error (tl::to_string (tr ("PROPERTY entry without a preceeding SREF or AREF"))); + } + + while (! ex.at_end ()) { + if (ex.test ("DNAME")) { + ex.read_word_or_quoted (data.refs.back ().dname); + } else if (ex.test ("ENAME")) { + ex.read_word_or_quoted (data.refs.back ().ename); + } else if (ex.test ("MNAME")) { + ex.read_word_or_quoted (data.refs.back ().mname); + } else { + error (tl::to_string (tr ("Unknown PROPERTY item"))); + } + } + } else if ((is_sref = ex.test ("SREF")) || ex.test ("AREF")) { data.refs.push_back (MALYReaderStrRefData ()); @@ -633,13 +589,15 @@ MALYReader::read_maskset (MALYData &data) if (end_section (ex)) { ex.expect_end (); - // @@@ create_masks (cmask, masks, data); + create_masks (cmask, masks, data); return true; } else if (begin_section (ex, "MASK")) { - ex.expect_end (); masks.push_back (MALYReaderMaskData ()); + ex.read (masks.back ().name); + + ex.expect_end (); read_mask (masks.back ()); } else if (begin_section (ex, "CMASK")) { @@ -654,6 +612,183 @@ MALYReader::read_maskset (MALYData &data) } } +void +MALYReader::create_masks (const MALYReaderMaskData &cmask, const std::list &masks, MALYData &data) +{ + for (auto i = masks.begin (); i != masks.end (); ++i) { + + data.masks.push_back (MALYMask ()); + MALYMask &m = data.masks.back (); + + m.name = i->name; + + m.size_um = i->parameters.masksize * 25400.0; + if (m.size_um < db::epsilon) { + m.size_um = cmask.parameters.masksize * 25400.0; + } + if (m.size_um < db::epsilon) { + m.size_um = 7.0 * 25400.0; // @@@? + } + + MALYTitle::Font font = i->parameters.font; + if (font == MALYTitle::FontNotSet) { + font = cmask.parameters.font; + } + if (font == MALYTitle::FontNotSet) { + font = MALYTitle::Standard; // @@@? + } + + const MALYReaderTitleSpec *date_spec = 0; + if (i->title.date_spec.enabled) { + date_spec = &i->title.date_spec; + } else if (cmask.title.date_spec.enabled) { + date_spec = &cmask.title.date_spec; + } + if (date_spec) { + m.titles.push_back (create_title (MALYTitle::Date, *date_spec, font, std::string (""))); + } + + const MALYReaderTitleSpec *serial_spec = 0; + if (i->title.serial_spec.enabled) { + serial_spec = &i->title.serial_spec; + } else if (cmask.title.serial_spec.enabled) { + serial_spec = &cmask.title.serial_spec; + } + if (date_spec) { + m.titles.push_back (create_title (MALYTitle::Serial, *serial_spec, font, std::string (""))); + } + + for (auto t = i->title.string_titles.begin (); t != i->title.string_titles.end (); ++t) { + m.titles.push_back (create_title (MALYTitle::String, t->second, font, t->first)); + } + for (auto t = cmask.title.string_titles.begin (); t != cmask.title.string_titles.end (); ++t) { + m.titles.push_back (create_title (MALYTitle::String, t->second, font, t->first)); + } + + MALYReaderParametersData::Base base = i->parameters.base; + if (base == MALYReaderParametersData::BaseNotSet) { + base = cmask.parameters.base; + } + if (base == MALYReaderParametersData::BaseNotSet) { + base = MALYReaderParametersData::Center; // @@@? + } + + MALYReaderParametersData::Base array_base = MALYReaderParametersData::BaseNotSet; + if (array_base == MALYReaderParametersData::BaseNotSet) { + array_base = cmask.parameters.base; + } + if (array_base == MALYReaderParametersData::BaseNotSet) { + array_base = MALYReaderParametersData::Center; // @@@? + } + + for (auto sg = cmask.strgroups.begin (); sg != cmask.strgroups.end (); ++sg) { + for (auto s = sg->refs.begin (); s != sg->refs.end (); ++s) { + m.structures.push_back (create_structure (i->parameters, cmask.parameters, *s, sg->name, base, array_base)); + } + } + for (auto sg = i->strgroups.begin (); sg != i->strgroups.end (); ++sg) { + for (auto s = sg->refs.begin (); s != sg->refs.end (); ++s) { + m.structures.push_back (create_structure (i->parameters, cmask.parameters, *s, sg->name, base, array_base)); + } + } + + } +} + +MALYTitle +MALYReader::create_title (MALYTitle::Type type, const MALYReaderTitleSpec &data, MALYTitle::Font font, const std::string &string) +{ + MALYTitle title; + + title.transformation = data.trans; + title.width = data.width; + title.height = data.height; + title.pitch = data.pitch; + title.type = type; + title.font = font; + title.string = string; + + return title; +} + +MALYStructure +MALYReader::create_structure (const MALYReaderParametersData &mparam, const MALYReaderParametersData &cparam, const MALYReaderStrRefData &data, const std::string & /*strgroup_name*/, MALYReaderParametersData::Base base, MALYReaderParametersData::Base array_base) +{ + MALYStructure str; + + str.size = data.size; + str.dname = data.dname; + str.ename = data.ename; + str.mname = data.mname; + str.topcell = data.name; + str.nx = std::max (1, data.nx); + str.ny = std::max (1, data.ny); + str.dx = data.dx; + str.dy = data.dy; + str.layer = data.layer; + + str.path = resolve_path (mparam, data.file); + if (str.path.empty ()) { + str.path = resolve_path (cparam, data.file); + } + if (str.path.empty ()) { + // try any fail later ... + str.path = data.file; + } + + MALYReaderParametersData::Base eff_base = (data.nx > 1 || data.ny > 1) ? array_base : base; + + db::DPoint rp; + switch (eff_base) { + case MALYReaderParametersData::LowerLeft: + rp = data.size.p1 (); + break; + case MALYReaderParametersData::Center: + default: + // NOTE: the center implies the whole array's center in case of an AREF + rp = (data.size + data.size.moved (db::DVector (str.dx * (str.nx - 1), str.dy * (str.ny - 1)))).center (); + break; + case MALYReaderParametersData::Origin: + break; + } + + db::DCplxTrans mirr (mparam.maskmirror != cparam.maskmirror ? db::DFTrans::m90 : db::DFTrans::r0); + str.transformation = mirr * db::DCplxTrans (data.scale, 0.0, false, data.org + (db::DPoint () - rp)); + + return str; +} + +std::string +MALYReader::resolve_path (const MALYReaderParametersData ¶m, const std::string &path) +{ + if (tl::is_absolute (path)) { + + return path; + + } else { + + // NOTE: we don't differentiate by file type here. Each root is used in the + // same way to find the actual file. + // Relative paths are always resolved relative to the MALY file. + + for (auto r = param.roots.begin (); r != param.roots.end (); ++r) { + + std::string p = tl::combine_path (r->second, path); + if (! tl::is_absolute (p)) { + p = tl::combine_path (tl::dirname (m_stream.source ()), p); + } + + if (tl::file_exists (p)) { + return p; + } + + } + + } + + return std::string (); +} + void MALYReader::do_read_maly_file (MALYData &data) { @@ -663,7 +798,7 @@ MALYReader::do_read_maly_file (MALYData &data) } std::string version; - ex.read (version, "."); + ex.read_word (version, "."); // @@@ TODO: what to do with version string? ex.expect_end (); @@ -685,7 +820,7 @@ MALYReader::do_read_maly_file (MALYData &data) void MALYReader::error (const std::string &msg) { - throw MALYReaderException (msg, m_stream.line_number (), m_stream.source ()); + throw MALYReaderException (msg, m_last_record_line, m_stream.source ()); } void @@ -702,7 +837,7 @@ MALYReader::warn (const std::string &msg, int wl) int ws = compress_warning (msg); if (ws < 0) { tl::warn << msg - << tl::to_string (tr (" (line=")) << m_stream.line_number () + << tl::to_string (tr (" (line=")) << m_last_record_line << tl::to_string (tr (", file=")) << m_stream.source () << ")"; } else if (ws == 0) { @@ -710,24 +845,6 @@ MALYReader::warn (const std::string &msg, int wl) } } -std::string -MALYReader::resolve_path (const std::string &path) -{ - tl::URI path_uri (path); - - if (tl::is_absolute (path_uri.path ())) { - - return path_uri.to_string (); - - } else { - - tl::URI source_uri (m_stream.source ()); - source_uri.set_path (tl::dirname (source_uri.path ())); - return source_uri.resolved (tl::URI (path)).to_string (); - - } -} - void MALYReader::do_read (db::Layout &layout, db::cell_index_type cell_index, tl::TextInputStream &stream) { diff --git a/src/plugins/streamers/maly/db_plugin/dbMALYReader.h b/src/plugins/streamers/maly/db_plugin/dbMALYReader.h index e8544782a..8face4692 100644 --- a/src/plugins/streamers/maly/db_plugin/dbMALYReader.h +++ b/src/plugins/streamers/maly/db_plugin/dbMALYReader.h @@ -45,12 +45,6 @@ namespace db { -class MALYReaderMaskData; -class MALYReaderTitleData; -class MALYReaderParametersData; -class MALYReaderStrGroupData; -class MALYReaderTitleSpec; - /** * @brief Generic base class of MALY reader exceptions */ @@ -145,15 +139,89 @@ public: virtual void warn (const std::string &txt, int wl = 1); private: + struct MALYReaderTitleSpec + { + MALYReaderTitleSpec () + : enabled (false), width (1.0), height (1.0), pitch (1.0) + { } + + bool enabled; + db::DTrans trans; + double width, height, pitch; + }; + + struct MALYReaderTitleData + { + MALYReaderTitleData () + { } + + MALYReaderTitleSpec date_spec; + MALYReaderTitleSpec serial_spec; + std::list > string_titles; + }; + + struct MALYReaderParametersData + { + MALYReaderParametersData () + : base (BaseNotSet), array_base (BaseNotSet), masksize (0.0), maskmirror (false), font (MALYTitle::FontNotSet) + { } + + enum Base + { + BaseNotSet, + Origin, + Center, + LowerLeft + }; + + Base base; + Base array_base; + double masksize; + bool maskmirror; + MALYTitle::Font font; + std::list > roots; + }; + + struct MALYReaderStrRefData + { + MALYReaderStrRefData () + : layer (-1), scale (1.0), nx (1), ny (1), dx (0.0), dy (0.0) + { } + + std::string file; + std::string name; + std::string dname, ename, mname; + int layer; + db::DVector org; + db::DBox size; + double scale; + int nx, ny; + double dx, dy; + }; + + struct MALYReaderStrGroupData + { + std::string name; + std::list refs; + }; + + struct MALYReaderMaskData + { + std::string name; + MALYReaderParametersData parameters; + MALYReaderTitleData title; + std::list strgroups; + }; + tl::TextInputStream m_stream; tl::AbsoluteProgress m_progress; double m_dbu; + unsigned int m_last_record_line; std::string m_record; std::string m_record_returned; std::list m_sections; void do_read (db::Layout &layout, db::cell_index_type to_cell, tl::TextInputStream &stream); - std::string resolve_path(const std::string &path); MALYData read_maly_file (); tl::Extractor read_record (); void unget_record (); @@ -169,6 +237,11 @@ private: bool begin_section (tl::Extractor &ex, const std::string &name = std::string ()); bool end_section (tl::Extractor &ex); void skip_section (); + MALYTitle create_title (MALYTitle::Type type, const MALYReaderTitleSpec &data, MALYTitle::Font font, const std::string &string); + void create_masks (const MALYReaderMaskData &cmask, const std::list &masks, MALYData &data); + MALYStructure create_structure (const MALYReaderParametersData &mparam, const MALYReaderParametersData &cparam, const MALYReaderStrRefData &data, const std::string &strgroup_name, MALYReaderParametersData::Base base, MALYReaderParametersData::Base array_base); + std::string resolve_path (const MALYReaderParametersData ¶m, const std::string &path); + static MALYReaderParametersData::Base string_to_base (const std::string &string); }; }