mirror of https://github.com/KLayout/klayout.git
986 lines
23 KiB
C++
986 lines
23 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2020 Matthias Koefferlein
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
#include "dbStreamLayers.h"
|
|
#include "dbLayoutUtils.h"
|
|
|
|
#include "tlException.h"
|
|
#include "tlString.h"
|
|
|
|
#include <stdio.h>
|
|
#include <set>
|
|
#include <sstream>
|
|
|
|
namespace db
|
|
{
|
|
|
|
// ---------------------------------------------------------------
|
|
// LayerMap
|
|
|
|
/// A helper class to join two datatype map members
|
|
struct LmapJoinOp1
|
|
{
|
|
void operator() (std::set<unsigned int> &a, const std::set<unsigned int> &b)
|
|
{
|
|
a.insert (b.begin (), b.end ());
|
|
}
|
|
};
|
|
|
|
/// A helper class to join two layer map members
|
|
/// (this implementation basically merged the datatype maps)
|
|
struct LmapJoinOp2
|
|
{
|
|
void operator() (LayerMap::datatype_map &a, const LayerMap::datatype_map &b)
|
|
{
|
|
LmapJoinOp1 op1;
|
|
a.add (b.begin (), b.end (), op1);
|
|
}
|
|
};
|
|
|
|
/// A helper class to implement the unmap operation
|
|
struct LmapEraseDatatypeInterval
|
|
{
|
|
LmapEraseDatatypeInterval (unsigned int dfrom, unsigned int dto)
|
|
: m_dfrom (dfrom), m_dto (dto)
|
|
{ }
|
|
|
|
void operator() (LayerMap::datatype_map &a, const LayerMap::datatype_map &)
|
|
{
|
|
if (is_static_ld (m_dfrom) && is_static_ld (m_dto)) {
|
|
a.erase (m_dfrom, m_dto + 1);
|
|
} else {
|
|
a.clear ();
|
|
}
|
|
}
|
|
|
|
private:
|
|
unsigned int m_dfrom, m_dto;
|
|
};
|
|
|
|
/// Utility typedefs for the expression parser
|
|
typedef std::pair<ld_type, ld_type> ld_interval;
|
|
|
|
/// Utility typedefs for the expression parser
|
|
typedef std::vector<ld_interval> ld_interval_vector;
|
|
|
|
|
|
LayerMap::LayerMap ()
|
|
: m_ld_map (), m_next_index (0)
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
bool
|
|
LayerMap::is_mapped (const LDPair &p) const
|
|
{
|
|
const datatype_map *dm = m_ld_map.mapped (p.layer);
|
|
if (!dm) {
|
|
return false;
|
|
}
|
|
const std::set<unsigned int> *l = dm->mapped (p.datatype);
|
|
return (l && ! l->empty ());
|
|
}
|
|
|
|
bool
|
|
LayerMap::is_mapped (const std::string &n) const
|
|
{
|
|
std::map<std::string, std::set<unsigned int> >::const_iterator m = m_name_map.find (n);
|
|
return m != m_name_map.end () && ! m->second.empty ();
|
|
}
|
|
|
|
bool
|
|
LayerMap::is_mapped (const db::LayerProperties &p) const
|
|
{
|
|
std::set<unsigned int> m;
|
|
if (p.layer >= 0 && p.datatype >= 0) {
|
|
if (is_mapped (db::LDPair (p.layer, p.datatype))) {
|
|
return true;
|
|
}
|
|
}
|
|
if (! p.name.empty ()) {
|
|
return is_mapped (p.name);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
std::set<unsigned int>
|
|
LayerMap::logical (const LDPair &p) const
|
|
{
|
|
return logical_internal (p, false);
|
|
}
|
|
|
|
std::set<unsigned int>
|
|
LayerMap::logical (const std::string &n) const
|
|
{
|
|
return logical_internal (n, false);
|
|
}
|
|
|
|
std::set<unsigned int>
|
|
LayerMap::logical (const db::LayerProperties &p) const
|
|
{
|
|
return logical_internal (p, false);
|
|
}
|
|
|
|
std::set<unsigned int>
|
|
LayerMap::logical_internal (const LDPair &p, bool allow_placeholder) const
|
|
{
|
|
const datatype_map *dm = m_ld_map.mapped (p.layer);
|
|
if (dm) {
|
|
const std::set<unsigned int> *l = dm->mapped (p.datatype);
|
|
if (l && (allow_placeholder || ! is_placeholder (*l))) {
|
|
return *l;
|
|
}
|
|
}
|
|
return std::set<unsigned int> ();
|
|
}
|
|
|
|
std::set<unsigned int>
|
|
LayerMap::logical_internal (const std::string &n, bool allow_placeholder) const
|
|
{
|
|
std::map<std::string, std::set<unsigned int> >::const_iterator m = m_name_map.find (n);
|
|
if (m != m_name_map.end () && (allow_placeholder || ! is_placeholder (m->second))) {
|
|
return m->second;
|
|
} else {
|
|
return std::set<unsigned int> ();
|
|
}
|
|
}
|
|
|
|
std::set<unsigned int>
|
|
LayerMap::logical_internal (const db::LayerProperties &p, bool allow_placeholder) const
|
|
{
|
|
std::set<unsigned int> m;
|
|
if (p.layer >= 0 && p.datatype >= 0) {
|
|
m = logical_internal (db::LDPair (p.layer, p.datatype), allow_placeholder);
|
|
}
|
|
if (m.empty () && ! p.name.empty ()) {
|
|
m = logical_internal (p.name, allow_placeholder);
|
|
}
|
|
return m;
|
|
}
|
|
|
|
bool
|
|
LayerMap::is_placeholder (const std::set<unsigned int> &m) const
|
|
{
|
|
for (std::set<unsigned int>::const_iterator i = m.begin (); i != m.end (); ++i) {
|
|
if (m_placeholders.size () > std::numeric_limits<unsigned int>::max () - *i) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const db::LayerProperties *
|
|
LayerMap::target (unsigned int l) const
|
|
{
|
|
std::map<unsigned int, LayerProperties>::const_iterator i = m_target_layers.find (l);
|
|
if (i != m_target_layers.end ()) {
|
|
return & i->second;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
std::set<unsigned int>
|
|
LayerMap::logical (const db::LayerProperties &p, db::Layout &layout) const
|
|
{
|
|
std::set<unsigned int> l = logical_internal (p, true);
|
|
if (is_placeholder (l)) {
|
|
return const_cast<LayerMap *> (this)->substitute_placeholder (p, l, layout);
|
|
} else {
|
|
return l;
|
|
}
|
|
}
|
|
|
|
std::set<unsigned int>
|
|
LayerMap::logical (const db::LDPair &p, db::Layout &layout) const
|
|
{
|
|
std::set<unsigned int> l = logical_internal (p, true);
|
|
if (is_placeholder (l)) {
|
|
return const_cast<LayerMap *> (this)->substitute_placeholder (db::LayerProperties (p.layer, p.datatype), l, layout);
|
|
} else {
|
|
return l;
|
|
}
|
|
}
|
|
|
|
std::set<unsigned int>
|
|
LayerMap::substitute_placeholder (const db::LayerProperties &p, const std::set<unsigned int> &m, db::Layout &layout)
|
|
{
|
|
std::set<unsigned int> res;
|
|
for (std::set<unsigned int>::const_iterator i = m.begin (); i != m.end (); ++i) {
|
|
|
|
if (m_placeholders.size () > std::numeric_limits<unsigned int>::max () - *i) {
|
|
|
|
const db::LayerProperties &lp_ph = m_placeholders [std::numeric_limits<unsigned int>::max () - *i];
|
|
db::LayerProperties lp_new = p;
|
|
lp_new.layer = db::ld_combine (p.layer, lp_ph.layer);
|
|
lp_new.datatype = db::ld_combine (p.datatype, lp_ph.datatype);
|
|
|
|
unsigned int l_new = layout.insert_layer (lp_new);
|
|
map (p, l_new, lp_new);
|
|
res.insert (l_new);
|
|
|
|
} else {
|
|
res.insert (*i);
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static std::string format_interval (ld_type l1, ld_type l2)
|
|
{
|
|
if (l1 == 0 && l2 == std::numeric_limits<ld_type>::max ()) {
|
|
return "*";
|
|
} else if (l2 == std::numeric_limits<ld_type>::max ()) {
|
|
return tl::to_string (l1) + "-*";
|
|
} else if (l1 + 1 < l2) {
|
|
return tl::to_string (l1) + "-" + tl::to_string (l2 - 1);
|
|
} else {
|
|
return tl::to_string (l1);
|
|
}
|
|
}
|
|
|
|
static std::vector<std::pair<ld_type, ld_type> >
|
|
extract_dt_intervals (const LayerMap::datatype_map &dt_map, int ll, bool &has_others)
|
|
{
|
|
std::vector<std::pair<ld_type, ld_type> > res;
|
|
|
|
for (LayerMap::datatype_map::const_iterator d = dt_map.begin (); d != dt_map.end (); ) {
|
|
|
|
if (d->second.find (ll) != d->second.end ()) {
|
|
|
|
std::pair<ld_type, ld_type> dpi = d->first;
|
|
|
|
if (d->second.size () > 1) {
|
|
has_others = true;
|
|
}
|
|
|
|
LayerMap::datatype_map::const_iterator dd = d;
|
|
++dd;
|
|
while (dd != dt_map.end () && dd->first.first == dpi.second && dd->second.find (ll) != dd->second.end ()) {
|
|
if (dd->second.size () > 1) {
|
|
has_others = true;
|
|
}
|
|
dpi.second = dd->first.second;
|
|
++dd;
|
|
}
|
|
|
|
d = dd;
|
|
|
|
res.push_back (dpi);
|
|
|
|
} else {
|
|
++d;
|
|
}
|
|
|
|
}
|
|
return res;
|
|
}
|
|
|
|
std::string
|
|
LayerMap::mapping_str (unsigned int ll) const
|
|
{
|
|
std::string s;
|
|
bool f1 = true;
|
|
bool is_mmap = false;
|
|
|
|
for (ld_map::const_iterator l = m_ld_map.begin (); l != m_ld_map.end (); ) {
|
|
|
|
std::pair<ld_type, ld_type> lti = l->first;
|
|
|
|
std::vector<std::pair<ld_type, ld_type> > dti = extract_dt_intervals (l->second, ll, is_mmap);
|
|
++l;
|
|
while (l != m_ld_map.end () && lti.second == l->first.first && extract_dt_intervals (l->second, ll, is_mmap) == dti) {
|
|
lti.second = l->first.second;
|
|
++l;
|
|
}
|
|
|
|
bool f2 = true;
|
|
for (std::vector<std::pair<ld_type, ld_type> >::const_iterator d = dti.begin (); d != dti.end (); ++d) {
|
|
|
|
// create a string representation
|
|
if (!f2) {
|
|
s += ",";
|
|
} else {
|
|
|
|
if (!f1) {
|
|
s += ";";
|
|
}
|
|
f1 = false;
|
|
|
|
s += format_interval (lti.first, lti.second);
|
|
s += "/";
|
|
|
|
}
|
|
f2 = false;
|
|
|
|
s += format_interval (d->first, d->second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (std::map <std::string, std::set<unsigned int> >::const_iterator l = m_name_map.begin (); l != m_name_map.end (); ++l) {
|
|
|
|
if (l->second.find (ll) != l->second.end ()) {
|
|
|
|
if (l->second.size () > 1) {
|
|
is_mmap = true;
|
|
}
|
|
|
|
if (!f1) {
|
|
s += ";";
|
|
}
|
|
f1 = false;
|
|
|
|
s += tl::to_word_or_quoted_string (l->first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::map<unsigned int, LayerProperties>::const_iterator t = m_target_layers.find (ll);
|
|
if (t != m_target_layers.end ()) {
|
|
s += " : ";
|
|
s += t->second.to_string (true);
|
|
}
|
|
|
|
if (is_mmap) {
|
|
return "+" + s;
|
|
} else {
|
|
return s;
|
|
}
|
|
}
|
|
|
|
void
|
|
LayerMap::prepare (db::Layout &layout)
|
|
{
|
|
m_placeholders.clear ();
|
|
unsigned int ph = std::numeric_limits<unsigned int>::max ();
|
|
|
|
std::map<unsigned int, unsigned int> real_layers;
|
|
std::set<unsigned int> mapped_layers;
|
|
|
|
// determine the mapping of existing layers to real layers and create layers if required
|
|
DirectLayerMapping layer_mapping (&layout);
|
|
|
|
std::vector<unsigned int> old_layers = get_layers ();
|
|
for (std::vector<unsigned int>::const_iterator l = old_layers.begin (); l != old_layers.end (); ++l) {
|
|
|
|
if (layout.is_valid_layer (*l)) {
|
|
|
|
real_layers.insert (std::make_pair (*l, *l));
|
|
mapped_layers.insert (*l);
|
|
|
|
} else {
|
|
|
|
db::LayerProperties lp = mapping (*l);
|
|
if (lp.is_named () || (db::is_static_ld (lp.layer) && db::is_static_ld (lp.datatype))) {
|
|
|
|
std::pair <bool, unsigned int> lm = layer_mapping.map_layer (lp);
|
|
if (lm.first) {
|
|
real_layers.insert (std::make_pair (*l, lm.second));
|
|
mapped_layers.insert (lm.second);
|
|
}
|
|
|
|
} else {
|
|
|
|
// install a placeholder index
|
|
m_placeholders.push_back (lp);
|
|
real_layers.insert (std::make_pair (*l, ph--));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Now remap the indexes
|
|
for (ld_map::iterator l = m_ld_map.begin (); l != m_ld_map.end (); ++l) {
|
|
for (datatype_map::iterator d = l->second.begin (); d != l->second.end (); ++d) {
|
|
std::set<unsigned int> dn;
|
|
for (std::set<unsigned int>::const_iterator i = d->second.begin (); i != d->second.end (); ++i) {
|
|
dn.insert (real_layers [*i]);
|
|
}
|
|
d->second = dn;
|
|
}
|
|
}
|
|
for (std::map<std::string, std::set<unsigned int> >::iterator n = m_name_map.begin (); n != m_name_map.end (); ++n) {
|
|
std::set<unsigned int> dn;
|
|
for (std::set<unsigned int>::const_iterator i = n->second.begin (); i != n->second.end (); ++i) {
|
|
dn.insert (real_layers [*i]);
|
|
}
|
|
n->second = dn;
|
|
}
|
|
|
|
std::map<unsigned int, LayerProperties> old_target_layers;
|
|
old_target_layers.swap (m_target_layers);
|
|
|
|
for (std::map<unsigned int, LayerProperties>::const_iterator tl = old_target_layers.begin (); tl != old_target_layers.end (); ++tl) {
|
|
m_target_layers[real_layers [tl->first]] = tl->second;
|
|
}
|
|
|
|
// In addition, map other existing layers as well, so merging of layout is somewhat better supported
|
|
for (db::Layout::layer_iterator l = layout.begin_layers (); l != layout.end_layers (); ++l) {
|
|
if (! (*l).second->is_null () && mapped_layers.find ((*l).first) == mapped_layers.end ()) {
|
|
map (*(*l).second, (*l).first);
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<unsigned int>
|
|
LayerMap::get_layers () const
|
|
{
|
|
std::set<unsigned int> layers;
|
|
|
|
for (ld_map::const_iterator l = m_ld_map.begin (); l != m_ld_map.end (); ++l) {
|
|
for (datatype_map::const_iterator d = l->second.begin (); d != l->second.end (); ++d) {
|
|
layers.insert (d->second.begin (), d->second.end ());
|
|
}
|
|
}
|
|
for (const_iterator_names n = m_name_map.begin (); n != m_name_map.end (); ++n) {
|
|
layers.insert(n->second.begin (), n->second.end ());
|
|
}
|
|
|
|
return std::vector<unsigned int> (layers.begin (), layers.end ());
|
|
}
|
|
|
|
LayerProperties
|
|
LayerMap::mapping (unsigned int ll) const
|
|
{
|
|
// try to combine source and target spec into a final specification (if for example, just a name is specified and
|
|
// layer/datatype are given in the source spec).
|
|
db::LayerProperties p;
|
|
|
|
std::map<unsigned int, LayerProperties>::const_iterator t = m_target_layers.find (ll);
|
|
if (t != m_target_layers.end ()) {
|
|
|
|
// a mapping is given. Use it.
|
|
p = t->second;
|
|
|
|
// special case: if it is a name mapping, add the layer mapping (for backward compatibility)
|
|
if (p.is_named ()) {
|
|
|
|
// no mapping is given. Use the lowest layer and datatype
|
|
for (ld_map::const_iterator l = m_ld_map.begin (); l != m_ld_map.end (); ++l) {
|
|
for (datatype_map::const_iterator d = l->second.begin (); d != l->second.end (); ++d) {
|
|
if (d->second.find (ll) != d->second.end ()) {
|
|
p.layer = l->first.first;
|
|
p.datatype = d->first.first;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// no mapping is given. Use the lowest layer and datatype
|
|
for (ld_map::const_iterator l = m_ld_map.begin (); l != m_ld_map.end (); ++l) {
|
|
for (datatype_map::const_iterator d = l->second.begin (); d != l->second.end (); ++d) {
|
|
if (d->second.find (ll) != d->second.end ()) {
|
|
p.layer = l->first.first;
|
|
p.datatype = d->first.first;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (p.name.empty ()) {
|
|
for (std::map <std::string, std::set<unsigned int> >::const_iterator l = m_name_map.begin (); l != m_name_map.end (); ++l) {
|
|
if (l->second.find (ll) != l->second.end ()) {
|
|
p.name = l->first;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// no layer found
|
|
return p;
|
|
}
|
|
|
|
void
|
|
LayerMap::mmap (const LDPair &p, unsigned int l)
|
|
{
|
|
insert (p, p, l, (const LayerProperties *) 0);
|
|
}
|
|
|
|
void
|
|
LayerMap::mmap (const std::string &name, unsigned int l)
|
|
{
|
|
insert (name, l, (const LayerProperties *) 0);
|
|
}
|
|
|
|
void
|
|
LayerMap::mmap (const LayerProperties &f, unsigned int l)
|
|
{
|
|
if (f.name.empty () || is_static_ld (f.layer) || is_static_ld (f.datatype)) {
|
|
mmap (db::LDPair (f.layer, f.datatype), l);
|
|
}
|
|
if (! f.name.empty ()) {
|
|
mmap (f.name, l);
|
|
}
|
|
}
|
|
|
|
void
|
|
LayerMap::mmap (const LDPair &p, unsigned int l, const LayerProperties &t)
|
|
{
|
|
insert (p, p, l, &t);
|
|
}
|
|
|
|
void
|
|
LayerMap::mmap (const std::string &name, unsigned int l, const LayerProperties &t)
|
|
{
|
|
insert (name, l, &t);
|
|
}
|
|
|
|
void
|
|
LayerMap::mmap (const LayerProperties &f, unsigned int l, const LayerProperties &t)
|
|
{
|
|
if (f.name.empty () || is_static_ld (f.layer) || is_static_ld (f.datatype)) {
|
|
mmap (db::LDPair (f.layer, f.datatype), l, t);
|
|
}
|
|
if (! f.name.empty ()) {
|
|
mmap (f.name, l, t);
|
|
}
|
|
}
|
|
|
|
void
|
|
LayerMap::mmap (const LDPair &p1, const LDPair &p2, unsigned int l)
|
|
{
|
|
insert (p1, p2, l, (const LayerProperties *) 0);
|
|
}
|
|
|
|
void
|
|
LayerMap::mmap (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties &lp)
|
|
{
|
|
insert (p1, p2, l, &lp);
|
|
}
|
|
|
|
/// Utility function for the expression parser:
|
|
/// Parse an interval
|
|
void
|
|
parse_interval (tl::Extractor &ex, ld_interval &p)
|
|
{
|
|
ld_type n1 = 0, n2 = 0;
|
|
|
|
if (ex.test ("*")) {
|
|
n1 = 0;
|
|
// NOTE: as the upper limit is stored as n2 + 1, this will map to max():
|
|
n2 = std::numeric_limits<ld_type>::max () - 1;
|
|
} else {
|
|
ex.try_read (n1);
|
|
if (ex.test ("-")) {
|
|
if (ex.test ("*")) {
|
|
// NOTE: as the upper limit is stored as n2 + 1, this will map to max():
|
|
n2 = std::numeric_limits<ld_type>::max () - 1;
|
|
} else {
|
|
ex.try_read (n2);
|
|
}
|
|
} else {
|
|
n2 = n1;
|
|
}
|
|
}
|
|
|
|
p.first = n1;
|
|
p.second = n2;
|
|
}
|
|
|
|
/// Utility function for the expression parser:
|
|
/// Parse an interval list
|
|
void
|
|
parse_intervals (tl::Extractor &ex, ld_interval_vector &v)
|
|
{
|
|
do {
|
|
v.push_back (ld_interval (0, 0));
|
|
parse_interval (ex, v.back ());
|
|
} while (ex.test (","));
|
|
}
|
|
|
|
void
|
|
LayerMap::mmap_expr (const std::string &expr, unsigned int l)
|
|
{
|
|
tl::Extractor ex (expr.c_str ());
|
|
mmap_expr (ex, l);
|
|
ex.expect_end ();
|
|
}
|
|
|
|
void
|
|
LayerMap::mmap_expr (tl::Extractor &ex, unsigned int l)
|
|
{
|
|
try {
|
|
|
|
do {
|
|
|
|
tl::Extractor ex_saved = ex;
|
|
|
|
std::string name;
|
|
ld_type n;
|
|
if (! ex.try_read (n) && ex.try_read_word_or_quoted (name)) {
|
|
|
|
m_name_map [name].insert (l);
|
|
|
|
} else {
|
|
|
|
ex = ex_saved;
|
|
ld_interval_vector vl, vd;
|
|
|
|
parse_intervals (ex, vl);
|
|
|
|
if (ex.test ("/")) {
|
|
parse_intervals (ex, vd);
|
|
} else {
|
|
vd.push_back (ld_interval (0, 0));
|
|
}
|
|
|
|
datatype_map dm;
|
|
for (ld_interval_vector::const_iterator di = vd.begin (); di != vd.end (); ++di) {
|
|
LmapJoinOp1 op1;
|
|
std::set<unsigned int> single;
|
|
single.insert (l);
|
|
dm.add (di->first, di->second + 1, single, op1);
|
|
}
|
|
for (ld_interval_vector::const_iterator li = vl.begin (); li != vl.end (); ++li) {
|
|
LmapJoinOp2 op2;
|
|
m_ld_map.add (li->first, li->second + 1, dm, op2);
|
|
}
|
|
|
|
}
|
|
|
|
} while (ex.test (";") || ex.test (","));
|
|
|
|
if (ex.test (":")) {
|
|
LayerProperties lp;
|
|
lp.read (ex, true);
|
|
m_target_layers[l] = lp;
|
|
}
|
|
|
|
} catch (...) {
|
|
throw LayerSpecFormatException (ex.skip ());
|
|
}
|
|
|
|
if (l >= m_next_index) {
|
|
m_next_index = l + 1;
|
|
}
|
|
}
|
|
|
|
void
|
|
LayerMap::insert (const std::string &name, unsigned int l, const LayerProperties *target)
|
|
{
|
|
if (target) {
|
|
m_target_layers[l] = *target;
|
|
}
|
|
|
|
m_name_map [name].insert (l);
|
|
|
|
if (l >= m_next_index) {
|
|
m_next_index = l + 1;
|
|
}
|
|
}
|
|
|
|
void
|
|
LayerMap::insert (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties *target)
|
|
{
|
|
if (target) {
|
|
m_target_layers[l] = *target;
|
|
}
|
|
|
|
std::set<unsigned int> single;
|
|
single.insert (l);
|
|
|
|
// create a single-interval list for the datatype range
|
|
LayerMap::datatype_map dt;
|
|
LmapJoinOp1 op1;
|
|
if (db::is_static_ld (p1.datatype) && db::is_static_ld (p2.datatype)) {
|
|
dt.add (p1.datatype, p2.datatype + 1, single, op1);
|
|
} else {
|
|
dt.add (0, std::numeric_limits<ld_type>::max (), single, op1);
|
|
}
|
|
|
|
// add this to the layers using the special join operator that
|
|
// combines the datatype intervals
|
|
LmapJoinOp2 op2;
|
|
if (db::is_static_ld (p1.layer) && db::is_static_ld (p2.layer)) {
|
|
m_ld_map.add (p1.layer, p2.layer + 1, dt, op2);
|
|
} else {
|
|
m_ld_map.add (0, std::numeric_limits<ld_type>::max (), dt, op2);
|
|
}
|
|
|
|
if (l >= m_next_index) {
|
|
m_next_index = l + 1;
|
|
}
|
|
}
|
|
|
|
void
|
|
LayerMap::unmap (const LDPair &f)
|
|
{
|
|
unmap (f, f);
|
|
}
|
|
|
|
void
|
|
LayerMap::unmap (const std::string &name)
|
|
{
|
|
m_name_map.erase (name);
|
|
}
|
|
|
|
void
|
|
LayerMap::unmap (const LayerProperties &f)
|
|
{
|
|
if (f.name.empty () || is_static_ld (f.layer) || is_static_ld (f.datatype)) {
|
|
unmap (db::LDPair (f.layer, f.datatype));
|
|
}
|
|
if (! f.name.empty ()) {
|
|
unmap (f.name);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
LayerMap::unmap (const LDPair &p1, const LDPair &p2)
|
|
{
|
|
if (m_ld_map.begin () == m_ld_map.end ()) {
|
|
return;
|
|
}
|
|
|
|
LmapEraseDatatypeInterval op (p1.datatype, p2.datatype);
|
|
if (db::is_static_ld (p1.layer) && db::is_static_ld (p2.layer)) {
|
|
m_ld_map.add (p1.layer, p2.layer + 1, LayerMap::datatype_map (), op);
|
|
} else {
|
|
m_ld_map.add (m_ld_map.begin ()->first.first, m_ld_map.end ()->first.second, LayerMap::datatype_map (), op);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
LayerMap::unmap_expr (const std::string &expr)
|
|
{
|
|
tl::Extractor ex (expr.c_str ());
|
|
unmap_expr (ex);
|
|
ex.expect_end ();
|
|
}
|
|
|
|
void
|
|
LayerMap::unmap_expr (tl::Extractor &ex)
|
|
{
|
|
try {
|
|
|
|
do {
|
|
|
|
tl::Extractor ex_saved = ex;
|
|
|
|
std::string name;
|
|
ld_type n;
|
|
if (! ex.try_read (n) && ex.try_read_word_or_quoted (name)) {
|
|
|
|
m_name_map.erase (name);
|
|
|
|
} else {
|
|
|
|
ex = ex_saved;
|
|
ld_interval_vector vl, vd;
|
|
|
|
parse_intervals (ex, vl);
|
|
|
|
if (ex.test ("/")) {
|
|
parse_intervals (ex, vd);
|
|
} else {
|
|
vd.push_back (ld_interval (0, 0));
|
|
}
|
|
|
|
for (ld_interval_vector::const_iterator li = vl.begin (); li != vl.end (); ++li) {
|
|
for (ld_interval_vector::const_iterator di = vd.begin (); di != vd.end (); ++di) {
|
|
unmap (LDPair (li->first, di->first), LDPair (li->second, di->second));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
} while (ex.test (";") || ex.test (","));
|
|
|
|
if (ex.test (":")) {
|
|
// ignore target layers
|
|
LayerProperties lp;
|
|
lp.read (ex, true);
|
|
}
|
|
|
|
} catch (...) {
|
|
throw LayerSpecFormatException (ex.skip ());
|
|
}
|
|
}
|
|
|
|
void
|
|
LayerMap::clear ()
|
|
{
|
|
m_ld_map.clear ();
|
|
m_name_map.clear ();
|
|
m_target_layers.clear ();
|
|
m_next_index = 0;
|
|
}
|
|
|
|
bool
|
|
LayerMap::is_empty () const
|
|
{
|
|
return m_name_map.empty () && m_ld_map.begin () == m_ld_map.end ();
|
|
}
|
|
|
|
std::string
|
|
LayerMap::to_string () const
|
|
{
|
|
std::vector<unsigned int> layers = get_layers ();
|
|
std::ostringstream os;
|
|
os << "layer_map(";
|
|
for (std::vector<unsigned int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
|
if (l != layers.begin ()) {
|
|
os << ";";
|
|
}
|
|
os << tl::to_quoted_string (mapping_str (*l));
|
|
}
|
|
os << ")";
|
|
return os.str ();
|
|
}
|
|
|
|
std::string
|
|
LayerMap::to_string_file_format () const
|
|
{
|
|
std::vector<unsigned int> layers = get_layers ();
|
|
std::ostringstream os;
|
|
for (std::vector<unsigned int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
|
os << mapping_str (*l);
|
|
os << "\n";
|
|
}
|
|
return os.str ();
|
|
}
|
|
|
|
void
|
|
LayerMap::add_expr (const std::string &expr, unsigned int l)
|
|
{
|
|
tl::Extractor ex (expr.c_str ());
|
|
add_expr (ex, l);
|
|
ex.expect_end ();
|
|
}
|
|
|
|
void
|
|
LayerMap::add_expr (tl::Extractor &ex, unsigned int l)
|
|
{
|
|
if (ex.test ("+")) {
|
|
mmap_expr (ex, l);
|
|
} else if (ex.test ("-")) {
|
|
unmap_expr (ex);
|
|
} else {
|
|
map_expr (ex, l);
|
|
}
|
|
}
|
|
|
|
db::LayerMap
|
|
LayerMap::from_string_file_format (const std::string &s)
|
|
{
|
|
db::LayerMap lm;
|
|
unsigned int l = 0;
|
|
|
|
int lnr = 0;
|
|
|
|
try {
|
|
|
|
std::vector<std::string> lines = tl::split (s, "\n");
|
|
|
|
for (std::vector<std::string>::const_iterator line = lines.begin (); line != lines.end (); ++line) {
|
|
|
|
++lnr;
|
|
|
|
tl::Extractor ex (line->c_str ());
|
|
if (ex.test ("#") || ex.test ("//")) {
|
|
// ignore comments
|
|
} else {
|
|
|
|
if (! ex.at_end ()) {
|
|
lm.add_expr (ex, l);
|
|
if (ex.test ("#") || ex.test ("//")) {
|
|
// ignore comments
|
|
} else {
|
|
ex.expect_end ();
|
|
}
|
|
++l;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (tl::Exception &ex) {
|
|
throw tl::Exception (ex.msg () + tl::to_string (tr (" in line ")) + tl::to_string (lnr));
|
|
}
|
|
|
|
return lm;
|
|
}
|
|
|
|
}
|
|
|
|
namespace tl
|
|
{
|
|
template<> DB_PUBLIC void extractor_impl (tl::Extractor &ex, db::LayerMap &t)
|
|
{
|
|
t = db::LayerMap ();
|
|
|
|
ex.test("layer_map");
|
|
ex.test("(");
|
|
|
|
unsigned int l = 0;
|
|
while (! ex.test (")") && ! ex.at_end ()) {
|
|
std::string m;
|
|
ex.read_word_or_quoted (m);
|
|
t.add_expr (m, l);
|
|
++l;
|
|
ex.test (";");
|
|
}
|
|
}
|
|
|
|
template<> DB_PUBLIC bool test_extractor_impl (tl::Extractor &ex, db::LayerMap &t)
|
|
{
|
|
t = db::LayerMap ();
|
|
|
|
if (!ex.test("layer_map")) {
|
|
return false;
|
|
}
|
|
|
|
ex.test("(");
|
|
|
|
unsigned int l = 0;
|
|
while (! ex.test (")") && ! ex.at_end ()) {
|
|
std::string m;
|
|
ex.read_word_or_quoted (m);
|
|
t.add_expr (m, l);
|
|
++l;
|
|
ex.test (";");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|