mirror of https://github.com/KLayout/klayout.git
Merge pull request #2163 from KLayout/bugfix/issue2156
More sanity checks for cell index on various Layout methods
This commit is contained in:
commit
d5c6b73ffa
|
|
@ -297,6 +297,20 @@ static void dump_mem_statistics (const db::Layout *layout, bool detailed)
|
|||
ms.print ();
|
||||
}
|
||||
|
||||
static void check_cell_index (const db::Layout *layout, db::cell_index_type ci)
|
||||
{
|
||||
if (! layout->is_valid_cell_index (ci)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Not a valid cell index: ")) + tl::to_string (ci));
|
||||
}
|
||||
}
|
||||
|
||||
static void check_layer (const db::Layout *layout, unsigned int layer)
|
||||
{
|
||||
if (! layout->is_valid_layer (layer) && ! layout->is_special_layer (layer)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Invalid layer index: ")) + tl::to_string (layer));
|
||||
}
|
||||
}
|
||||
|
||||
static bool layout_has_prop_id (const db::Layout *l)
|
||||
{
|
||||
return l->prop_id () != 0;
|
||||
|
|
@ -630,30 +644,45 @@ static tl::Variant get_property_from_id (db::properties_id_type id, const tl::Va
|
|||
static void
|
||||
delete_cells (db::Layout *layout, const std::vector<db::cell_index_type> &cell_indices)
|
||||
{
|
||||
for (auto ci = cell_indices.begin (); ci != cell_indices.end (); ++ci) {
|
||||
check_cell_index (layout, *ci);
|
||||
}
|
||||
layout->delete_cells (cell_indices.begin (), cell_indices.end ());
|
||||
}
|
||||
|
||||
static void
|
||||
delete_cell_rec (db::Layout *layout, db::cell_index_type cell_index)
|
||||
{
|
||||
check_cell_index (layout, cell_index);
|
||||
layout->delete_cell_rec (cell_index);
|
||||
}
|
||||
|
||||
static void
|
||||
prune_cell (db::Layout *layout, db::cell_index_type cell_index, int levels)
|
||||
{
|
||||
check_cell_index (layout, cell_index);
|
||||
layout->prune_cell (cell_index, levels);
|
||||
}
|
||||
|
||||
static void
|
||||
prune_subcells (db::Layout *layout, db::cell_index_type cell_index, int levels)
|
||||
{
|
||||
check_cell_index (layout, cell_index);
|
||||
layout->prune_subcells (cell_index, levels);
|
||||
}
|
||||
|
||||
static void
|
||||
flatten (db::Layout *layout, db::cell_index_type cell_index, int levels, bool prune)
|
||||
{
|
||||
check_cell_index (layout, cell_index);
|
||||
layout->flatten (layout->cell (cell_index), levels, prune);
|
||||
}
|
||||
|
||||
static void
|
||||
flatten_into (db::Layout *layout, db::cell_index_type cell_index, db::cell_index_type target_cell_index, const db::ICplxTrans &t, int levels)
|
||||
{
|
||||
check_cell_index (layout, cell_index);
|
||||
check_cell_index (layout, target_cell_index);
|
||||
layout->flatten (layout->cell (cell_index), layout->cell (target_cell_index), t, levels);
|
||||
}
|
||||
|
||||
|
|
@ -698,20 +727,11 @@ write_bytes (db::Layout *layout, const db::SaveLayoutOptions &options)
|
|||
return std::vector<char> (byte_stream.data (), byte_stream.data () + byte_stream.size ());
|
||||
}
|
||||
|
||||
static void check_layer (const db::Layout *layout, unsigned int layer)
|
||||
{
|
||||
if (! layout->is_valid_layer (layer) && ! layout->is_special_layer (layer)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Invalid layer index")));
|
||||
}
|
||||
}
|
||||
|
||||
static db::RecursiveShapeIterator
|
||||
begin_shapes (const db::Layout *layout, db::cell_index_type starting_cell, unsigned int layer)
|
||||
{
|
||||
if (! layout->is_valid_layer (layer)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Invalid layer index")));
|
||||
}
|
||||
check_layer (layout, layer);
|
||||
check_cell_index (layout, starting_cell);
|
||||
return db::RecursiveShapeIterator (*layout, layout->cell (starting_cell), layer);
|
||||
}
|
||||
|
||||
|
|
@ -725,9 +745,7 @@ static db::RecursiveShapeIterator
|
|||
begin_shapes_touching (const db::Layout *layout, db::cell_index_type starting_cell, unsigned int layer, db::Box region)
|
||||
{
|
||||
check_layer (layout, layer);
|
||||
if (! layout->is_valid_cell_index (starting_cell)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Invalid cell index")));
|
||||
}
|
||||
check_cell_index (layout, starting_cell);
|
||||
return db::RecursiveShapeIterator (*layout, layout->cell (starting_cell), layer, region, false);
|
||||
}
|
||||
|
||||
|
|
@ -741,9 +759,7 @@ static db::RecursiveShapeIterator
|
|||
begin_shapes_overlapping (const db::Layout *layout, db::cell_index_type starting_cell, unsigned int layer, db::Box region)
|
||||
{
|
||||
check_layer (layout, layer);
|
||||
if (! layout->is_valid_cell_index (starting_cell)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Invalid cell index")));
|
||||
}
|
||||
check_cell_index (layout, starting_cell);
|
||||
return db::RecursiveShapeIterator (*layout, layout->cell (starting_cell), layer, region, true);
|
||||
}
|
||||
|
||||
|
|
@ -757,9 +773,7 @@ static db::RecursiveShapeIterator
|
|||
begin_shapes_touching_um (const db::Layout *layout, db::cell_index_type starting_cell, unsigned int layer, db::DBox region)
|
||||
{
|
||||
check_layer (layout, layer);
|
||||
if (! layout->is_valid_cell_index (starting_cell)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Invalid cell index")));
|
||||
}
|
||||
check_cell_index (layout, starting_cell);
|
||||
return db::RecursiveShapeIterator (*layout, layout->cell (starting_cell), layer, db::CplxTrans (layout->dbu ()).inverted () * region, false);
|
||||
}
|
||||
|
||||
|
|
@ -773,9 +787,7 @@ static db::RecursiveShapeIterator
|
|||
begin_shapes_overlapping_um (const db::Layout *layout, db::cell_index_type starting_cell, unsigned int layer, db::DBox region)
|
||||
{
|
||||
check_layer (layout, layer);
|
||||
if (! layout->is_valid_cell_index (starting_cell)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Invalid cell index")));
|
||||
}
|
||||
check_cell_index (layout, starting_cell);
|
||||
return db::RecursiveShapeIterator (*layout, layout->cell (starting_cell), layer, db::CplxTrans (layout->dbu ()).inverted () * region, true);
|
||||
}
|
||||
|
||||
|
|
@ -847,11 +859,21 @@ static std::vector<std::string> pcell_names (const db::Layout *layout)
|
|||
return res;
|
||||
}
|
||||
|
||||
static void delete_cell (db::Layout *ly, db::cell_index_type ci)
|
||||
{
|
||||
check_cell_index (ly, ci);
|
||||
ly->delete_cell (ci);
|
||||
}
|
||||
|
||||
static void rename_cell (db::Layout *ly, db::cell_index_type ci, const std::string &name)
|
||||
{
|
||||
check_cell_index (ly, ci);
|
||||
ly->rename_cell (ci, name.c_str ());
|
||||
}
|
||||
|
||||
static db::Cell *cell_from_index (db::Layout *ly, db::cell_index_type ci)
|
||||
{
|
||||
if (! ly->is_valid_cell_index (ci)) {
|
||||
throw tl::Exception (tl::to_string (tr ("Not a valid cell index: ")) + tl::to_string (ci));
|
||||
}
|
||||
check_cell_index (ly, ci);
|
||||
return &ly->cell (ci);
|
||||
}
|
||||
|
||||
|
|
@ -1094,17 +1116,17 @@ static void set_properties (db::Layout *layout, unsigned int index, const db::La
|
|||
}
|
||||
}
|
||||
|
||||
void break_polygons2 (db::Layout *layout, unsigned int layer, size_t max_vertex_count, double max_area_ratio)
|
||||
static void break_polygons2 (db::Layout *layout, unsigned int layer, size_t max_vertex_count, double max_area_ratio)
|
||||
{
|
||||
db::break_polygons (*layout, layer, max_vertex_count, max_area_ratio);
|
||||
}
|
||||
|
||||
void break_polygons1 (db::Layout *layout, size_t max_vertex_count, double max_area_ratio)
|
||||
static void break_polygons1 (db::Layout *layout, size_t max_vertex_count, double max_area_ratio)
|
||||
{
|
||||
db::break_polygons (*layout, max_vertex_count, max_area_ratio);
|
||||
}
|
||||
|
||||
void delete_layer_from_info (db::Layout *layout, const db::LayerProperties &info)
|
||||
static void delete_layer_from_info (db::Layout *layout, const db::LayerProperties &info)
|
||||
{
|
||||
int li = layout->get_layer_maybe (info);
|
||||
if (li >= 0) {
|
||||
|
|
@ -1112,7 +1134,7 @@ void delete_layer_from_info (db::Layout *layout, const db::LayerProperties &info
|
|||
}
|
||||
}
|
||||
|
||||
void clear_layer_from_info (db::Layout *layout, const db::LayerProperties &info)
|
||||
static void clear_layer_from_info (db::Layout *layout, const db::LayerProperties &info)
|
||||
{
|
||||
int li = layout->get_layer_maybe (info);
|
||||
if (li >= 0) {
|
||||
|
|
@ -1120,7 +1142,7 @@ void clear_layer_from_info (db::Layout *layout, const db::LayerProperties &info)
|
|||
}
|
||||
}
|
||||
|
||||
void clear_layer_from_info_with_flags (db::Layout *layout, const db::LayerProperties &info, unsigned int flags)
|
||||
static void clear_layer_from_info_with_flags (db::Layout *layout, const db::LayerProperties &info, unsigned int flags)
|
||||
{
|
||||
int li = layout->get_layer_maybe (info);
|
||||
if (li >= 0) {
|
||||
|
|
@ -1128,6 +1150,34 @@ void clear_layer_from_info_with_flags (db::Layout *layout, const db::LayerProper
|
|||
}
|
||||
}
|
||||
|
||||
static void insert_region (db::Layout *layout, db::cell_index_type cell_index, int layer_index, const db::Region &r)
|
||||
{
|
||||
check_cell_index (layout, cell_index);
|
||||
check_layer (layout, layer_index);
|
||||
layout->insert (cell_index, layer_index, r);
|
||||
}
|
||||
|
||||
static void insert_edges (db::Layout *layout, db::cell_index_type cell_index, int layer_index, const db::Edges &e)
|
||||
{
|
||||
check_cell_index (layout, cell_index);
|
||||
check_layer (layout, layer_index);
|
||||
layout->insert (cell_index, layer_index, e);
|
||||
}
|
||||
|
||||
static void insert_texts (db::Layout *layout, db::cell_index_type cell_index, int layer_index, const db::Texts &t)
|
||||
{
|
||||
check_cell_index (layout, cell_index);
|
||||
check_layer (layout, layer_index);
|
||||
layout->insert (cell_index, layer_index, t);
|
||||
}
|
||||
|
||||
static void insert_edge_pairs (db::Layout *layout, db::cell_index_type cell_index, int layer_index, const db::EdgePairs &ep)
|
||||
{
|
||||
check_cell_index (layout, cell_index);
|
||||
check_layer (layout, layer_index);
|
||||
layout->insert (cell_index, layer_index, ep);
|
||||
}
|
||||
|
||||
Class<db::Layout> decl_Layout ("db", "Layout",
|
||||
gsi::constructor ("new", &layout_ctor_with_manager, gsi::arg ("manager"),
|
||||
"@brief Creates a layout object attached to a manager\n"
|
||||
|
|
@ -1584,13 +1634,13 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"From version 0.23 on this method is deprecated because another method exists which is more convenient because "
|
||||
"is returns a \\Cell object (\\create_cell).\n"
|
||||
) +
|
||||
gsi::method ("rename_cell", &db::Layout::rename_cell, gsi::arg ("index"), gsi::arg ("name"),
|
||||
gsi::method_ext ("rename_cell", &rename_cell, gsi::arg ("index"), gsi::arg ("name"),
|
||||
"@brief Renames the cell with given index\n"
|
||||
"The cell with the given index is renamed to the given name. NOTE: it is not ensured that the name is unique. "
|
||||
"This method allows assigning identical names to different cells which usually breaks things.\n"
|
||||
"Consider using \\unique_cell_name to generate truely unique names.\n"
|
||||
) +
|
||||
gsi::method ("delete_cell", &db::Layout::delete_cell, gsi::arg ("cell_index"),
|
||||
gsi::method_ext ("delete_cell", &delete_cell, gsi::arg ("cell_index"),
|
||||
"@brief Deletes a cell \n"
|
||||
"\n"
|
||||
"This deletes a cell but not the sub cells of the cell.\n"
|
||||
|
|
@ -1641,7 +1691,7 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.20.\n"
|
||||
) +
|
||||
gsi::method ("delete_cell_rec", &db::Layout::delete_cell_rec, gsi::arg ("cell_index"),
|
||||
gsi::method_ext ("delete_cell_rec", &delete_cell_rec, gsi::arg ("cell_index"),
|
||||
"@brief Deletes a cell plus all subcells\n"
|
||||
"\n"
|
||||
"This deletes a cell and also all sub cells of the cell.\n"
|
||||
|
|
@ -1651,7 +1701,7 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.20.\n"
|
||||
) +
|
||||
gsi::method ("insert", (void (db::Layout::*) (db::cell_index_type, int, const db::Region &)) &db::Layout::insert,
|
||||
gsi::method_ext ("insert", &insert_region,
|
||||
gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("region"),
|
||||
"@brief Inserts a region into the given cell and layer\n"
|
||||
"If the region is (conceptionally) a flat region, it will be inserted into the cell's shapes "
|
||||
|
|
@ -1663,7 +1713,7 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.26.\n"
|
||||
) +
|
||||
gsi::method ("insert", (void (db::Layout::*) (db::cell_index_type, int, const db::Edges &)) &db::Layout::insert,
|
||||
gsi::method_ext ("insert", &insert_edges,
|
||||
gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("edges"),
|
||||
"@brief Inserts an edge collection into the given cell and layer\n"
|
||||
"If the edge collection is (conceptionally) flat, it will be inserted into the cell's shapes "
|
||||
|
|
@ -1675,7 +1725,7 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.26.\n"
|
||||
) +
|
||||
gsi::method ("insert", (void (db::Layout::*) (db::cell_index_type, int, const db::EdgePairs &)) &db::Layout::insert,
|
||||
gsi::method_ext ("insert", &insert_edge_pairs,
|
||||
gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("edge_pairs"),
|
||||
"@brief Inserts an edge pair collection into the given cell and layer\n"
|
||||
"If the edge pair collection is (conceptionally) flat, it will be inserted into the cell's shapes "
|
||||
|
|
@ -1687,7 +1737,7 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("insert", (void (db::Layout::*) (db::cell_index_type, int, const db::Texts &)) &db::Layout::insert,
|
||||
gsi::method_ext ("insert", &insert_texts,
|
||||
gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("texts"),
|
||||
"@brief Inserts an text collection into the given cell and layer\n"
|
||||
"If the text collection is (conceptionally) flat, it will be inserted into the cell's shapes "
|
||||
|
|
|
|||
|
|
@ -315,6 +315,12 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
# delete_cell
|
||||
|
||||
l = RBA::Layout.new
|
||||
begin
|
||||
l.delete_cell(0) # must throw an exception
|
||||
assert_equal(true, false)
|
||||
rescue
|
||||
end
|
||||
|
||||
l.insert_layer_at(0, RBA::LayerInfo.new(1, 0))
|
||||
c0 = l.cell(l.add_cell("c0"))
|
||||
c1 = l.cell(l.add_cell("c1"))
|
||||
|
|
@ -371,6 +377,12 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
# delete_cells
|
||||
|
||||
l = RBA::Layout.new
|
||||
begin
|
||||
l.delete_cells([0, 1]) # must throw an exception
|
||||
assert_equal(true, false)
|
||||
rescue
|
||||
end
|
||||
|
||||
l.insert_layer_at(0, RBA::LayerInfo.new(1, 0))
|
||||
c0 = l.cell(l.add_cell("c0"))
|
||||
c1 = l.cell(l.add_cell("c1"))
|
||||
|
|
@ -412,6 +424,12 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
# prune_cell
|
||||
|
||||
l = RBA::Layout.new
|
||||
begin
|
||||
l.prune_cell(0) # must throw an exception
|
||||
assert_equal(true, false)
|
||||
rescue
|
||||
end
|
||||
|
||||
l.insert_layer_at(0, RBA::LayerInfo.new(1, 0))
|
||||
c0 = l.cell(l.add_cell("c0"))
|
||||
c1 = l.cell(l.add_cell("c1"))
|
||||
|
|
@ -488,6 +506,12 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
# delete_cell_rec
|
||||
|
||||
l = RBA::Layout.new
|
||||
begin
|
||||
l.delete_cell_rec(0) # must throw an exception
|
||||
assert_equal(true, false)
|
||||
rescue
|
||||
end
|
||||
|
||||
l.insert_layer_at(0, RBA::LayerInfo.new(1, 0))
|
||||
c0 = l.cell(l.add_cell("c0"))
|
||||
c1 = l.cell(l.add_cell("c1"))
|
||||
|
|
@ -643,6 +667,12 @@ class DBLayoutTests1_TestClass < TestBase
|
|||
# prune_subcells
|
||||
|
||||
l = RBA::Layout.new
|
||||
begin
|
||||
l.prune_subcells(0) # must throw an exception
|
||||
assert_equal(true, false)
|
||||
rescue
|
||||
end
|
||||
|
||||
l.insert_layer_at(0, RBA::LayerInfo.new(1, 0))
|
||||
c0 = l.cell(l.add_cell("c0"))
|
||||
c1 = l.cell(l.add_cell("c1"))
|
||||
|
|
|
|||
Loading…
Reference in New Issue