#include "import_altium.hpp" #include "system/parts.hpp" #include "system/pins.hpp" #include "system/signals.hpp" #include #include #include namespace { std::string strip(const std::string &s) { size_t i = 0, j = s.size(); while (i < j && std::isspace((unsigned char)s[i])) ++i; while (j > i && std::isspace((unsigned char)s[j - 1])) --j; return s.substr(i, j - i); } } // namespace ImportAltium::ImportAltium(std::string filename) : ImportBase(filename) {} // Altium netlist text format: // * Parts section: blocks delimited by `[` and `]`. First non-empty line // inside a block is the part name. // * Signals section: blocks delimited by `(` and `)`. First non-empty line // is the signal name; subsequent lines are `partname-pinname` entries. // // Both sections may interleave; we make two passes — parts first so signals // can resolve their part references. void ImportAltium::parse(Signals *signals) { std::vector lines; std::string raw; while (std::getline(file_lines, raw)) lines.push_back(raw); enum class State { Out, In }; // Pass 1: parts. { State sta = State::Out; int lnum = 0; for (const auto &l : lines) { std::string t = strip(l); if (t == "]") { sta = State::Out; continue; } if (sta == State::Out) { if (t == "[") { sta = State::In; lnum = 0; } continue; } ++lnum; if (lnum == 1 && !t.empty() && !prts->exists(t)) { prts->add(new Part(t)); } } } // Pass 2: signals + pins. { State sta = State::Out; int lnum = 0; Signal *sig = nullptr; for (const auto &l : lines) { std::string t = strip(l); if (t == ")") { sta = State::Out; sig = nullptr; continue; } if (sta == State::Out) { if (t == "(") { sta = State::In; lnum = 0; sig = nullptr; } continue; } ++lnum; if (t.empty()) continue; if (lnum == 1) { sig = signals->merge(t); continue; } if (!sig) continue; // Split on first '-' so pin names containing dashes survive. auto dash = t.find('-'); if (dash == std::string::npos) continue; std::string pname = strip(t.substr(0, dash)); std::string pinname = strip(t.substr(dash + 1)); if (pname.empty() || pinname.empty()) continue; Part *prt = nullptr; try { prt = prts->get(pname); } catch (...) { continue; } if (prt->exists(pinname)) continue; Pin *pin = new Pin(pinname); try { prt->add(pin); } catch (...) { delete pin; continue; } sig->add(pin); pin->connect(sig); } } }