mirror of https://github.com/KLayout/klayout.git
Adding enhanced property types to OASIS. The writer options have a new flag that turns non-standard types of properties such as objects or nested lists into annotated strings.
This commit is contained in:
parent
96cf0b640d
commit
d24697a5e3
|
|
@ -101,7 +101,7 @@ public:
|
|||
* @brief The constructor
|
||||
*/
|
||||
OASISWriterOptions ()
|
||||
: compression_level (2), write_cblocks (true), strict_mode (true), recompress (false), permissive (false),
|
||||
: compression_level (2), enhanced_property_types (true), write_cblocks (true), strict_mode (true), recompress (false), permissive (false),
|
||||
write_std_properties (1), subst_char ("*"), tables_at_end (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
|
|
@ -116,7 +116,20 @@ public:
|
|||
* 1 - nearest neighbor shape array formation
|
||||
* 2++ - enhanced shape array search algorithm using 2nd and further neighbor distances as well
|
||||
*/
|
||||
int compression_level;
|
||||
int compression_level;
|
||||
|
||||
/**
|
||||
* @brief Enhanced property types
|
||||
*
|
||||
* If this option is set to true (the default), complex property types
|
||||
* such as lists or even objects can be embedded into OASIS files.
|
||||
* For this, KLayout uses strings with a special annotation
|
||||
* (i.e. "KLAYOUT_VALUE:...").
|
||||
*
|
||||
* This option also implies that only properties with string values
|
||||
* (and numerical keys) are written as S_GDS_PROPERTY properties.
|
||||
*/
|
||||
bool enhanced_property_types;
|
||||
|
||||
/**
|
||||
* @brief CBLOCK compression
|
||||
|
|
|
|||
|
|
@ -78,20 +78,6 @@ struct vector_cmp_y
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Determines whether a property shall be produced as S_GDS_PROPERTY
|
||||
*/
|
||||
static bool
|
||||
make_gds_property (const tl::Variant &name)
|
||||
{
|
||||
// We write S_GDS_PROPERTY properties, because that is the only way to write properties
|
||||
// with numerical keys
|
||||
return (name.is_longlong () && name.to_longlong () < 0x8000 && name.to_longlong () >= 0) ||
|
||||
(name.is_ulonglong () && name.to_ulonglong () < 0x8000) ||
|
||||
(name.is_long () && name.to_long () < 0x8000 && name.to_long () >= 0) ||
|
||||
(name.is_ulong () && name.to_ulong () < 0x8000);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
|
@ -970,15 +956,46 @@ 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)
|
||||
OASISWriter::make_prop_string (const tl::Variant &v) const
|
||||
{
|
||||
if (v.is_a_string ()) {
|
||||
if (! m_options.enhanced_property_types) {
|
||||
|
||||
return v.to_stdstring ();
|
||||
|
||||
} else if (v.is_a_string ()) {
|
||||
|
||||
std::string s = v.to_stdstring ();
|
||||
|
||||
// if the string starts with the prefix, encode it using the prefixed notation
|
||||
if (strncmp (s.c_str (), klayout_prop_string_prefix.c_str (), klayout_prop_string_prefix.size ()) == 0) {
|
||||
return klayout_prop_string_prefix + v.to_parsable_string ();
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
return klayout_prop_string_prefix + v.to_parsable_string ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
OASISWriter::make_gds_property (const tl::Variant &name, const tl::Variant &value) const
|
||||
{
|
||||
// Only strings will become GDS properties in enhanced properties mode
|
||||
if (m_options.enhanced_property_types && !value.is_a_string ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We write S_GDS_PROPERTY properties, because that is the only way to write properties
|
||||
// with numerical keys
|
||||
return (name.is_longlong () && name.to_longlong () < 0x8000 && name.to_longlong () >= 0) ||
|
||||
(name.is_ulonglong () && name.to_ulonglong () < 0x8000) ||
|
||||
(name.is_long () && name.to_long () < 0x8000 && name.to_long () >= 0) ||
|
||||
(name.is_ulong () && name.to_ulong () < 0x8000);
|
||||
}
|
||||
|
||||
void
|
||||
OASISWriter::emit_propname_def (db::properties_id_type prop_id)
|
||||
{
|
||||
|
|
@ -989,7 +1006,7 @@ OASISWriter::emit_propname_def (db::properties_id_type prop_id)
|
|||
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)) {
|
||||
if (! make_gds_property (name, value)) {
|
||||
name_str = make_prop_string (name);
|
||||
}
|
||||
|
||||
|
|
@ -1016,7 +1033,7 @@ OASISWriter::emit_propstring_def (db::properties_id_type prop_id)
|
|||
const tl::Variant &name = db::property_name (p->first);
|
||||
const tl::Variant &value = db::property_value (p->second);
|
||||
|
||||
if (! value.is_a_string () || ! make_gds_property (name)) {
|
||||
if (! make_gds_property (name, value)) {
|
||||
|
||||
if (value.is_list ()) {
|
||||
pvl = &value.get_list ();
|
||||
|
|
@ -2158,7 +2175,7 @@ OASISWriter::write_props (db::properties_id_type prop_id)
|
|||
pv_list.clear ();
|
||||
const std::vector<tl::Variant> *pvl = &pv_list;
|
||||
|
||||
if (! value.is_a_string () || ! make_gds_property (name)) {
|
||||
if (! make_gds_property (name, value)) {
|
||||
|
||||
name_str = make_prop_string (name);
|
||||
sflag = false;
|
||||
|
|
|
|||
|
|
@ -300,7 +300,9 @@ private:
|
|||
|
||||
void reset_modal_variables ();
|
||||
|
||||
static std::string make_prop_string (const tl::Variant &v);
|
||||
std::string make_prop_string (const tl::Variant &v) const;
|
||||
bool make_gds_property (const tl::Variant &name, const tl::Variant &value) const;
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -133,6 +133,16 @@ static int get_oasis_write_std_properties_ext (const db::SaveLayoutOptions *opti
|
|||
return options->get_options<db::OASISWriterOptions> ().write_std_properties;
|
||||
}
|
||||
|
||||
static bool get_oasis_enhanced_properties (const db::SaveLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::OASISWriterOptions> ().enhanced_property_types;
|
||||
}
|
||||
|
||||
static void set_oasis_enhanced_properties (db::SaveLayoutOptions *options, bool f)
|
||||
{
|
||||
options->get_options<db::OASISWriterOptions> ().enhanced_property_types = f;
|
||||
}
|
||||
|
||||
static void set_oasis_write_cell_bounding_boxes (db::SaveLayoutOptions *options, bool f)
|
||||
{
|
||||
db::OASISWriterOptions &oasis_options = options->get_options<db::OASISWriterOptions> ();
|
||||
|
|
@ -278,6 +288,21 @@ gsi::ClassExt<db::SaveLayoutOptions> oasis_writer_options (
|
|||
// this method is mainly provided as access point for the generic interface
|
||||
"@hide"
|
||||
) +
|
||||
gsi::method_ext ("oasis_enhanced_properties=", &set_oasis_enhanced_properties, gsi::arg ("flag"),
|
||||
"@brief Sets a value indicating whether to write enhanced property values\n"
|
||||
"With this option set to true (the default), non-standard types like lists or objects are supported "
|
||||
"for property names and values. These types are encoded in specially annotated strings.\n"
|
||||
"KLayout's OASIS reader will convert them back to the original types.\n"
|
||||
"With this option set to false, such values are translated into strings.\n"
|
||||
"\n"
|
||||
"This attribute has been introduced in version 0.30.7."
|
||||
) +
|
||||
gsi::method_ext ("oasis_enhanced_properties?", &get_oasis_enhanced_properties,
|
||||
"@brief Gets a value indicating whether to write enhanced property values\n"
|
||||
"See \\oasis_enhanced_properties= for details.\n"
|
||||
"\n"
|
||||
"This attribute has been introduced in version 0.30.7."
|
||||
) +
|
||||
gsi::method_ext ("oasis_compression_level=", &set_oasis_compression, gsi::arg ("level"),
|
||||
"@brief Set the OASIS compression level\n"
|
||||
"The OASIS compression level is an integer number between 0 and 10. 0 basically is no compression, "
|
||||
|
|
|
|||
|
|
@ -33,6 +33,37 @@
|
|||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace {
|
||||
|
||||
static std::string p2s (db::properties_id_type pid)
|
||||
{
|
||||
return db::properties (pid).to_dict_var ().to_parsable_string ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Installs a temporary repository instance for testing
|
||||
*
|
||||
* By using a temp instance, we do not disturb other tests.
|
||||
*/
|
||||
class TempPropertiesRepository
|
||||
{
|
||||
public:
|
||||
TempPropertiesRepository ()
|
||||
{
|
||||
db::PropertiesRepository::replace_instance_temporarily (&m_temp);
|
||||
}
|
||||
|
||||
~TempPropertiesRepository ()
|
||||
{
|
||||
db::PropertiesRepository::replace_instance_temporarily (0);
|
||||
}
|
||||
|
||||
private:
|
||||
db::PropertiesRepository m_temp;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void run_test (tl::TestBase *_this, const char *file, bool scaling_test, int compr, bool recompress, bool tables_at_end)
|
||||
{
|
||||
{
|
||||
|
|
@ -2100,3 +2131,68 @@ TEST(140)
|
|||
db::compare_layouts (_this, gg, tl::testdata () + "/oasis/dbOASISWriter40_au.gds", db::NoNormalization);
|
||||
}
|
||||
}
|
||||
|
||||
// Writing enhanced properties to OASIS
|
||||
TEST(150)
|
||||
{
|
||||
TempPropertiesRepository temp_pr;
|
||||
|
||||
db::Layout layout_org;
|
||||
|
||||
db::PropertiesSet ps;
|
||||
tl::Variant list = tl::Variant::empty_list ();
|
||||
list.push (tl::Variant (-1));
|
||||
list.push (tl::Variant (2.5));
|
||||
list.push (tl::Variant ("KLAYOUT_VALUE:h*ll*")); // a string that clashes with the annotation scheme
|
||||
ps.insert (tl::Variant (17), list);
|
||||
ps.insert (tl::Variant ("x"), tl::Variant (db::DBox (0, 0, 1.5, 2.5)));
|
||||
|
||||
db::properties_id_type ps_id = db::properties_id (ps);
|
||||
EXPECT_EQ (p2s (ps_id), "{#17=>(#-1,##2.5,'KLAYOUT_VALUE:h*ll*'),'x'=>[dbox:(0,0;1.5,2.5)]}");
|
||||
|
||||
layout_org.prop_id (ps_id);
|
||||
|
||||
std::string tmp_file = tl::TestBase::tmp_file (tl::sprintf ("tmp_dbOASISWriter150a.oas"));
|
||||
|
||||
{
|
||||
tl::OutputStream out (tmp_file);
|
||||
db::SaveLayoutOptions options;
|
||||
options.set_format ("OASIS");
|
||||
EXPECT_EQ (options.get_option_by_name ("oasis_enhanced_properties").to_bool (), true);
|
||||
db::Writer writer (options);
|
||||
writer.write (layout_org, out);
|
||||
}
|
||||
|
||||
{
|
||||
tl::InputStream in (tmp_file);
|
||||
db::Reader reader (in);
|
||||
db::Layout gg;
|
||||
reader.set_warnings_as_errors (true);
|
||||
reader.read (gg);
|
||||
|
||||
EXPECT_EQ (p2s (gg.prop_id ()), "{#17=>(#-1,##2.5,'KLAYOUT_VALUE:h*ll*'),'x'=>[dbox:(0,0;1.5,2.5)]}");
|
||||
|
||||
}
|
||||
|
||||
tmp_file = tl::TestBase::tmp_file (tl::sprintf ("tmp_dbOASISWriter150b.oas"));
|
||||
|
||||
{
|
||||
tl::OutputStream out (tmp_file);
|
||||
db::SaveLayoutOptions options;
|
||||
options.set_format ("OASIS");
|
||||
options.set_option_by_name ("oasis_enhanced_properties", false);
|
||||
EXPECT_EQ (options.get_option_by_name ("oasis_enhanced_properties").to_bool (), false);
|
||||
db::Writer writer (options);
|
||||
writer.write (layout_org, out);
|
||||
}
|
||||
|
||||
{
|
||||
tl::InputStream in (tmp_file);
|
||||
db::Reader reader (in);
|
||||
db::Layout gg;
|
||||
reader.read (gg);
|
||||
|
||||
EXPECT_EQ (p2s (gg.prop_id ()), "{#17=>'(-1,2.5,KLAYOUT_VALUE:h*ll*)','x'=>'(0,0;1.5,2.5)'}");
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue