mirror of https://github.com/KLayout/klayout.git
Experimental: enhance OASIS reader/writer to preserve KLayout's extended property data types (uses S_GDS_PROPERTIES for numerical/string combinations and standard OASIS properties where possible, uses specially annotated strings to store other types)
This commit is contained in:
parent
618d94ab3b
commit
e654ef3012
|
|
@ -776,13 +776,13 @@ OASISReader::do_read (db::Layout &layout)
|
|||
get (id);
|
||||
}
|
||||
|
||||
if (! m_propnames.insert (std::make_pair (id, name)).second) {
|
||||
if (! m_propnames.insert (std::make_pair (id, make_prop_value (name))).second) {
|
||||
error (tl::sprintf (tl::to_string (tr ("A PROPNAME with id %ld is present already")), id));
|
||||
}
|
||||
|
||||
auto fw = m_propname_forward_references.find (id);
|
||||
if (fw != m_propname_forward_references.end ()) {
|
||||
fw->second = db::property_names_id (name);
|
||||
fw->second = db::property_names_id (make_prop_value (name));
|
||||
}
|
||||
|
||||
reset_modal_variables ();
|
||||
|
|
@ -818,13 +818,13 @@ OASISReader::do_read (db::Layout &layout)
|
|||
get (id);
|
||||
}
|
||||
|
||||
if (! m_propstrings.insert (std::make_pair (id, name)).second) {
|
||||
if (! m_propstrings.insert (std::make_pair (id, make_prop_value (name))).second) {
|
||||
error (tl::sprintf (tl::to_string (tr ("A PROPSTRING with id %ld is present already")), id));
|
||||
}
|
||||
|
||||
std::map<uint64_t, std::string>::iterator fw = m_propvalue_forward_references.find (id);
|
||||
auto fw = m_propvalue_forward_references.find (id);
|
||||
if (fw != m_propvalue_forward_references.end ()) {
|
||||
fw->second = name;
|
||||
fw->second = db::property_values_id (make_prop_value (name));
|
||||
}
|
||||
|
||||
reset_modal_variables ();
|
||||
|
|
@ -1028,6 +1028,13 @@ OASISReader::do_read (db::Layout &layout)
|
|||
}
|
||||
}
|
||||
|
||||
// all forward references to property values must be resolved
|
||||
for (std::map <uint64_t, db::property_values_id_type>::const_iterator fw = m_propvalue_forward_references.begin (); fw != m_propvalue_forward_references.end (); ++fw) {
|
||||
if (fw->second == 0) {
|
||||
error (tl::sprintf (tl::to_string (tr ("No property string defined for property string id %ld")), fw->first));
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve forward references for stored shape and instance prop_ids.
|
||||
// This makes these shape and instance property IDs valid
|
||||
|
||||
|
|
@ -1216,6 +1223,32 @@ OASISReader::has_forward_refs (const db::PropertiesSet &properties)
|
|||
return false;
|
||||
}
|
||||
|
||||
const std::string klayout_prop_string_prefix = "KLAYOUT_VALUE:";
|
||||
|
||||
tl::Variant
|
||||
OASISReader::make_prop_value (const std::string &s)
|
||||
{
|
||||
if (strncmp (s.c_str (), klayout_prop_string_prefix.c_str (), klayout_prop_string_prefix.size ()) == 0) {
|
||||
|
||||
tl::Extractor ex (s.c_str () + klayout_prop_string_prefix.size ());
|
||||
try {
|
||||
|
||||
tl::Variant v;
|
||||
ex.read (v);
|
||||
return v;
|
||||
|
||||
} catch (tl::Exception &) {
|
||||
|
||||
warn (tl::sprintf (tl::to_string (tr ("Unable to decode special value string (%s) - keeping as a string")), s));
|
||||
return tl::Variant (s);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
return tl::Variant (s);
|
||||
}
|
||||
}
|
||||
|
||||
properties_id_type OASISReader::make_forward_properties_id (const db::PropertiesSet &properties)
|
||||
{
|
||||
// NOTE: the forward properties ID scheme makes use of the fact that IDs
|
||||
|
|
@ -1331,9 +1364,9 @@ OASISReader::replace_forward_references_in_variant (tl::Variant &v)
|
|||
if (v.is_id ()) {
|
||||
|
||||
uint64_t id = (uint64_t) v.to_id ();
|
||||
std::map <uint64_t, std::string>::const_iterator fw = m_propvalue_forward_references.find (id);
|
||||
auto fw = m_propvalue_forward_references.find (id);
|
||||
if (fw != m_propvalue_forward_references.end ()) {
|
||||
v = tl::Variant (fw->second);
|
||||
v = db::property_value (fw->second);
|
||||
} else {
|
||||
error (tl::sprintf (tl::to_string (tr ("No property value defined for property value id %ld")), id));
|
||||
}
|
||||
|
|
@ -1355,9 +1388,9 @@ OASISReader::replace_forward_references_in_variant (tl::Variant &v)
|
|||
for (std::vector<tl::Variant>::iterator ll = new_list.begin (); ll != new_list.end (); ++ll) {
|
||||
if (ll->is_id ()) {
|
||||
uint64_t id = (uint64_t) ll->to_id ();
|
||||
std::map <uint64_t, std::string>::const_iterator fw = m_propvalue_forward_references.find (id);
|
||||
auto fw = m_propvalue_forward_references.find (id);
|
||||
if (fw != m_propvalue_forward_references.end ()) {
|
||||
*ll = tl::Variant (fw->second);
|
||||
*ll = db::property_value (fw->second);
|
||||
} else {
|
||||
error (tl::sprintf (tl::to_string (tr ("No property value defined for property value id %ld")), id));
|
||||
}
|
||||
|
|
@ -1484,12 +1517,12 @@ OASISReader::read_properties ()
|
|||
uint64_t id;
|
||||
get (id);
|
||||
|
||||
std::map <uint64_t, std::string>::const_iterator cid = m_propnames.find (id);
|
||||
auto cid = m_propnames.find (id);
|
||||
if (cid == m_propnames.end ()) {
|
||||
mm_last_property_name = db::property_names_id (tl::Variant (id, true /*dummy for id type*/));
|
||||
m_propname_forward_references.insert (std::make_pair (id, db::property_names_id_type (0)));
|
||||
} else {
|
||||
mm_last_property_name = db::property_names_id (tl::Variant (cid->second));
|
||||
mm_last_property_name = db::property_names_id (cid->second);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -1498,7 +1531,7 @@ OASISReader::read_properties ()
|
|||
warn (tl::to_string (tr ("PROPERTY names must be references to PROPNAME ids in strict mode")));
|
||||
}
|
||||
|
||||
mm_last_property_name = db::property_names_id (tl::Variant (get_str ()));
|
||||
mm_last_property_name = db::property_names_id (make_prop_value (get_str ()));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1547,7 +1580,7 @@ OASISReader::read_properties ()
|
|||
}
|
||||
|
||||
if (m_read_properties) {
|
||||
mm_last_value_list.get_non_const ().push_back (tl::Variant (get_str ()));
|
||||
mm_last_value_list.get_non_const ().push_back (make_prop_value (get_str ()));
|
||||
} else {
|
||||
get_str ();
|
||||
}
|
||||
|
|
@ -1557,12 +1590,12 @@ OASISReader::read_properties ()
|
|||
uint64_t id;
|
||||
get (id);
|
||||
if (m_read_properties) {
|
||||
std::map <uint64_t, std::string>::const_iterator sid = m_propstrings.find (id);
|
||||
auto sid = m_propstrings.find (id);
|
||||
if (sid == m_propstrings.end ()) {
|
||||
m_propvalue_forward_references.insert (std::make_pair (id, std::string ()));
|
||||
m_propvalue_forward_references.insert (std::make_pair (id, db::property_values_id_type (0)));
|
||||
mm_last_value_list.get_non_const ().push_back (tl::Variant (id, true /*dummy for id type*/));
|
||||
} else {
|
||||
mm_last_value_list.get_non_const ().push_back (tl::Variant (sid->second));
|
||||
mm_last_value_list.get_non_const ().push_back (sid->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -166,8 +166,8 @@ private:
|
|||
std::map <uint64_t, db::properties_id_type> m_cellname_properties;
|
||||
std::map <uint64_t, std::string> m_textstrings;
|
||||
std::map <uint64_t, const db::StringRef *> m_text_forward_references;
|
||||
std::map <uint64_t, std::string> m_propstrings;
|
||||
std::map <uint64_t, std::string> m_propnames;
|
||||
std::map <uint64_t, tl::Variant> m_propstrings;
|
||||
std::map <uint64_t, tl::Variant> m_propnames;
|
||||
|
||||
std::map <db::cell_index_type, std::vector<tl::Variant> > m_context_strings_per_cell;
|
||||
|
||||
|
|
@ -179,7 +179,7 @@ private:
|
|||
bool m_read_all_properties;
|
||||
|
||||
std::map <uint64_t, db::property_names_id_type> m_propname_forward_references;
|
||||
std::map <uint64_t, std::string> m_propvalue_forward_references;
|
||||
std::map <uint64_t, db::property_values_id_type> m_propvalue_forward_references;
|
||||
std::map <db::properties_id_type, std::set<db::Shapes *> > m_forward_properties_for_shapes;
|
||||
std::map <db::properties_id_type, std::set<db::Instances *> > m_forward_properties_for_instances;
|
||||
std::map <db::cell_index_type, db::PropertiesSet> m_future_cell_properties;
|
||||
|
|
@ -216,6 +216,8 @@ private:
|
|||
void replace_forward_references_in_variant (tl::Variant &v);
|
||||
void extract_context_strings (db::PropertiesSet &properties, std::vector<tl::Variant> &context_strings);
|
||||
bool has_forward_refs (const db::PropertiesSet &properties);
|
||||
|
||||
tl::Variant make_prop_value (const std::string &s);
|
||||
db::properties_id_type make_forward_properties_id (const db::PropertiesSet &properties);
|
||||
const db::PropertiesSet &forward_properties (db::properties_id_type id) const;
|
||||
bool is_forward_properties_id (db::properties_id_type id) const;
|
||||
|
|
|
|||
|
|
@ -967,20 +967,35 @@ OASISWriter::write_ucoord (db::Coord c)
|
|||
}
|
||||
}
|
||||
|
||||
const std::string klayout_prop_string_prefix = "KLAYOUT_VALUE:";
|
||||
|
||||
std::string
|
||||
OASISWriter::make_prop_string (const tl::Variant &v)
|
||||
{
|
||||
if (v.is_a_string ()) {
|
||||
return v.to_stdstring ();
|
||||
} else {
|
||||
return klayout_prop_string_prefix + v.to_parsable_string ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OASISWriter::emit_propname_def (db::properties_id_type prop_id)
|
||||
{
|
||||
auto props = db::properties (prop_id).to_map ();
|
||||
auto props = db::properties (prop_id);
|
||||
for (auto p = props.begin (); p != props.end (); ++p) {
|
||||
|
||||
const tl::Variant &name = p->first;
|
||||
const char *name_str = s_gds_property_name;
|
||||
if (! make_gds_property (name)) {
|
||||
name_str = name.to_string ();
|
||||
const tl::Variant &name = db::property_name (p->first);
|
||||
const tl::Variant &value = db::property_value (p->second);
|
||||
|
||||
std::string name_str (s_gds_property_name);
|
||||
if (! value.is_a_string () || ! make_gds_property (name)) {
|
||||
name_str = make_prop_string (name);
|
||||
}
|
||||
|
||||
if (m_propnames.insert (std::make_pair (name_str, m_propname_id)).second) {
|
||||
write_record_id (7);
|
||||
write_nstring (name_str);
|
||||
write_nstring (name_str.c_str ());
|
||||
++m_propname_id;
|
||||
}
|
||||
|
||||
|
|
@ -992,38 +1007,50 @@ OASISWriter::emit_propstring_def (db::properties_id_type prop_id)
|
|||
{
|
||||
std::vector<tl::Variant> pv_list;
|
||||
|
||||
auto props = db::properties (prop_id).to_map ();
|
||||
auto props = db::properties (prop_id);
|
||||
for (auto p = props.begin (); p != props.end (); ++p) {
|
||||
|
||||
pv_list.clear ();
|
||||
const std::vector<tl::Variant> *pvl = &pv_list;
|
||||
|
||||
const tl::Variant &name = p->first;
|
||||
if (! make_gds_property (name)) {
|
||||
const tl::Variant &name = db::property_name (p->first);
|
||||
const tl::Variant &value = db::property_value (p->second);
|
||||
|
||||
if (p->second.is_list ()) {
|
||||
pvl = &p->second.get_list ();
|
||||
} else if (!p->second.is_nil ()) {
|
||||
if (! value.is_a_string () || ! make_gds_property (name)) {
|
||||
|
||||
if (value.is_list ()) {
|
||||
pvl = &value.get_list ();
|
||||
} else if (!value.is_nil ()) {
|
||||
pv_list.reserve (1);
|
||||
pv_list.push_back (p->second);
|
||||
pv_list.push_back (value);
|
||||
}
|
||||
|
||||
for (std::vector<tl::Variant>::const_iterator pv = pvl->begin (); pv != pvl->end (); ++pv) {
|
||||
|
||||
if (!pv->is_double () && !pv->is_longlong () && !pv->is_ulonglong () && !pv->is_long () && !pv->is_ulong ()) {
|
||||
|
||||
std::string v = make_prop_string (*pv);
|
||||
|
||||
if (m_propstrings.insert (std::make_pair (v, m_propstring_id)).second) {
|
||||
write_record_id (9);
|
||||
write_bstring (v.c_str ());
|
||||
++m_propstring_id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
pv_list.reserve (2);
|
||||
pv_list.push_back (name.to_ulong ());
|
||||
pv_list.push_back (p->second.to_string ());
|
||||
std::string v = make_prop_string (value);
|
||||
|
||||
}
|
||||
|
||||
for (std::vector<tl::Variant>::const_iterator pv = pvl->begin (); pv != pvl->end (); ++pv) {
|
||||
if (!pv->is_double () && !pv->is_longlong () && !pv->is_ulonglong () && !pv->is_long () && !pv->is_ulong ()) {
|
||||
if (m_propstrings.insert (std::make_pair (pv->to_string (), m_propstring_id)).second) {
|
||||
write_record_id (9);
|
||||
write_bstring (pv->to_string ());
|
||||
++m_propstring_id;
|
||||
}
|
||||
if (m_propstrings.insert (std::make_pair (v, m_propstring_id)).second) {
|
||||
write_record_id (9);
|
||||
write_bstring (v.c_str ());
|
||||
++m_propstring_id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2117,37 +2144,37 @@ OASISWriter::write_props (db::properties_id_type prop_id)
|
|||
{
|
||||
std::vector<tl::Variant> pv_list;
|
||||
|
||||
auto props = db::properties (prop_id).to_map ();
|
||||
|
||||
auto props = db::properties (prop_id);
|
||||
for (auto p = props.begin (); p != props.end (); ++p) {
|
||||
|
||||
const tl::Variant &name = db::property_name (p->first);
|
||||
const tl::Variant &value = db::property_value (p->second);
|
||||
|
||||
m_progress.set (mp_stream->pos ());
|
||||
|
||||
const tl::Variant &name = p->first;
|
||||
|
||||
const char *name_str = s_gds_property_name;
|
||||
std::string name_str (s_gds_property_name);
|
||||
bool sflag = true;
|
||||
|
||||
pv_list.clear ();
|
||||
const std::vector<tl::Variant> *pvl = &pv_list;
|
||||
|
||||
if (! make_gds_property (name)) {
|
||||
if (! value.is_a_string () || ! make_gds_property (name)) {
|
||||
|
||||
name_str = name.to_string ();
|
||||
name_str = make_prop_string (name);
|
||||
sflag = false;
|
||||
|
||||
if (p->second.is_list ()) {
|
||||
pvl = &p->second.get_list ();
|
||||
} else if (!p->second.is_nil ()) {
|
||||
if (value.is_list ()) {
|
||||
pvl = &value.get_list ();
|
||||
} else if (!value.is_nil ()) {
|
||||
pv_list.reserve (1);
|
||||
pv_list.push_back (p->second);
|
||||
pv_list.push_back (value);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
pv_list.reserve (2);
|
||||
pv_list.push_back (name.to_ulong ());
|
||||
pv_list.push_back (p->second.to_string ());
|
||||
pv_list.push_back (value);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -2157,7 +2184,7 @@ OASISWriter::write_props (db::properties_id_type prop_id)
|
|||
}
|
||||
|
||||
void
|
||||
OASISWriter::write_property_def (const char *name_str, const tl::Variant &pv, bool sflag)
|
||||
OASISWriter::write_property_def (const std::string &name_str, const tl::Variant &pv, bool sflag)
|
||||
{
|
||||
std::vector<tl::Variant> pvl;
|
||||
pvl.reserve (1);
|
||||
|
|
@ -2166,7 +2193,7 @@ OASISWriter::write_property_def (const char *name_str, const tl::Variant &pv, bo
|
|||
}
|
||||
|
||||
void
|
||||
OASISWriter::write_property_def (const char *name_str, const std::vector<tl::Variant> &pvl, bool sflag)
|
||||
OASISWriter::write_property_def (const std::string &name_str, const std::vector<tl::Variant> &pvl, bool sflag)
|
||||
{
|
||||
bool same_name = (mm_last_property_name == name_str);
|
||||
bool same_value = (mm_last_value_list == pvl);
|
||||
|
|
@ -2203,7 +2230,7 @@ OASISWriter::write_property_def (const char *name_str, const std::vector<tl::Var
|
|||
if (pni == m_propnames.end ()) {
|
||||
// write the name itself, if not found in the property repository
|
||||
write_byte (info | 0x04);
|
||||
write_nstring (name_str);
|
||||
write_nstring (name_str.c_str ());
|
||||
} else {
|
||||
// write the property ID
|
||||
write_byte (info | 0x06);
|
||||
|
|
@ -2253,7 +2280,7 @@ OASISWriter::write_property_def (const char *name_str, const std::vector<tl::Var
|
|||
|
||||
} else {
|
||||
|
||||
const char *pvs = v.to_string ();
|
||||
std::string pvs = make_prop_string (v);
|
||||
std::map <std::string, uint64_t>::const_iterator pvi = m_propstrings.find (pvs);
|
||||
|
||||
// In strict mode always write property string ID's: before we have issued the table we can
|
||||
|
|
@ -2264,11 +2291,11 @@ OASISWriter::write_property_def (const char *name_str, const std::vector<tl::Var
|
|||
}
|
||||
|
||||
if (pvi != m_propstrings.end ()) {
|
||||
write_byte (13 + string_type (pvs));
|
||||
write_byte (13 + string_type (pvs.c_str ()));
|
||||
write (pvi->second);
|
||||
} else {
|
||||
write_byte (10 + string_type (pvs));
|
||||
write_bstring (pvs);
|
||||
write_byte (10 + string_type (pvs.c_str ()));
|
||||
write_bstring (pvs.c_str ());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -300,6 +300,7 @@ private:
|
|||
|
||||
void reset_modal_variables ();
|
||||
|
||||
static std::string make_prop_string (const tl::Variant &v);
|
||||
void emit_propname_def (db::properties_id_type prop_id);
|
||||
void emit_propstring_def (db::properties_id_type prop_id);
|
||||
void write_insts (const std::set <db::cell_index_type> &cell_set);
|
||||
|
|
@ -307,8 +308,8 @@ private:
|
|||
void write_shapes (const db::LayerProperties &lprops, const db::Shapes &shapes);
|
||||
|
||||
void write_props (db::properties_id_type prop_id);
|
||||
void write_property_def (const char *name_str, const std::vector<tl::Variant> &pvl, bool sflag);
|
||||
void write_property_def (const char *name_str, const tl::Variant &pv, bool sflag);
|
||||
void write_property_def (const std::string &name_str, const std::vector<tl::Variant> &pvl, bool sflag);
|
||||
void write_property_def (const std::string &name_str, const tl::Variant &pv, bool sflag);
|
||||
void write_pointlist (const std::vector<db::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);
|
||||
|
|
|
|||
|
|
@ -1533,14 +1533,14 @@ TEST(116)
|
|||
"set props {\n"
|
||||
" {42 {42}}\n"
|
||||
" {{S_BOUNDING_BOX} {(0,0,100,1000,1100)}}\n"
|
||||
" {{S_CELL_OFFSET} {231}}\n"
|
||||
" {{S_CELL_OFFSET} {247}}\n"
|
||||
"}\n"
|
||||
"begin_cellp $props {$1}\n"
|
||||
"path 1 0 0 0 0 {0 100} {1000 1200}\n"
|
||||
"end_cell\n"
|
||||
"set props {\n"
|
||||
" {{S_BOUNDING_BOX} {(2,0,0,0,0)}}\n"
|
||||
" {{S_CELL_OFFSET} {229}}\n"
|
||||
" {{S_CELL_OFFSET} {245}}\n"
|
||||
"}\n"
|
||||
"begin_cellp $props {$2}\n"
|
||||
"end_cell\n"
|
||||
|
|
@ -1598,13 +1598,13 @@ TEST(116)
|
|||
"begin_libp $props 0.001\n"
|
||||
"set props {\n"
|
||||
" {42 {42}}\n"
|
||||
" {{S_CELL_OFFSET} {182}}\n"
|
||||
" {{S_CELL_OFFSET} {198}}\n"
|
||||
"}\n"
|
||||
"begin_cellp $props {$1}\n"
|
||||
"path 1 0 0 0 0 {0 100} {1000 1200}\n"
|
||||
"end_cell\n"
|
||||
"set props {\n"
|
||||
" {{S_CELL_OFFSET} {180}}\n"
|
||||
" {{S_CELL_OFFSET} {196}}\n"
|
||||
"}\n"
|
||||
"begin_cellp $props {$2}\n"
|
||||
"end_cell\n"
|
||||
|
|
|
|||
Loading…
Reference in New Issue