diff --git a/src/db/db/dbLayoutQuery.cc b/src/db/db/dbLayoutQuery.cc index 0bc0c3997..8af7c679f 100644 --- a/src/db/db/dbLayoutQuery.cc +++ b/src/db/db/dbLayoutQuery.cc @@ -167,6 +167,16 @@ public: return m_pattern.match (s, mp_eval->match_substrings ()); } + bool is_catchall () const + { + return ! m_needs_eval && m_pattern.is_catchall (); + } + + bool is_const () const + { + return ! m_needs_eval && m_pattern.is_const (); + } + private: tl::GlobPattern m_pattern; tl::Expression m_expression; @@ -484,11 +494,30 @@ public: ChildCellFilterState (const FilterBase *filter, const NameFilterArgument &pattern, ChildCellFilterInstanceMode instance_mode, tl::Eval &eval, db::Layout *layout, bool reading, const ChildCellFilterPropertyIDs &pids) : FilterStateBase (filter, layout, eval), m_pattern (pattern, eval), m_instance_mode (instance_mode), mp_parent (0), m_pids (pids), - m_weight (0), m_references (0), m_weight_set (false), m_references_set (false), m_reading (reading) + m_weight (0), m_references (0), m_weight_set (false), m_references_set (false), m_reading (reading), + m_cell_index (std::numeric_limits::max ()) { // .. nothing yet .. } + bool cell_matches (db::cell_index_type ci) + { + if (m_pattern.is_catchall ()) { + return true; + } else if (m_cell_index != std::numeric_limits::max ()) { + return ci == db::cell_index_type (m_cell_index); + } else if (m_pattern.is_const ()) { + if (m_pattern.match (layout ()->cell (ci).get_qualified_name ())) { + m_cell_index = ci; + return true; + } else { + return false; + } + } else { + return (m_pattern.match (layout ()->cell (ci).get_qualified_name ())); + } + } + virtual void reset (FilterStateBase *previous) { FilterStateBase::reset (previous); @@ -511,7 +540,7 @@ public: m_top_cell = layout ()->begin_top_down (); m_top_cell_end = layout ()->end_top_cells (); - while (m_top_cell != m_top_cell_end && (!layout ()->is_valid_cell_index (*m_top_cell) || !m_pattern.match (layout ()->cell (*m_top_cell).get_qualified_name ()))) { + while (m_top_cell != m_top_cell_end && (!layout ()->is_valid_cell_index (*m_top_cell) || !cell_matches (*m_top_cell))) { ++m_top_cell; } @@ -524,7 +553,7 @@ public: if (m_instance_mode == NoInstances) { m_child_cell = mp_parent->begin_child_cells (); - while (! m_child_cell.at_end () && (!layout ()->is_valid_cell_index (*m_child_cell) || !m_pattern.match (layout ()->cell (*m_child_cell).get_qualified_name ()))) { + while (! m_child_cell.at_end () && (!layout ()->is_valid_cell_index (*m_child_cell) || !cell_matches (*m_child_cell))) { ++m_child_cell; } @@ -536,7 +565,7 @@ public: while (m_inst != m_inst_end) { db::cell_index_type cid = (*m_inst)->object ().cell_index (); - if (layout ()->is_valid_cell_index (cid) && m_pattern.match (layout ()->cell (cid).get_qualified_name ())) { + if (layout ()->is_valid_cell_index (cid) && cell_matches (cid)) { break; } @@ -576,7 +605,7 @@ public: do { ++m_child_cell; - } while (! m_child_cell.at_end () && (!layout ()->is_valid_cell_index (*m_child_cell) || !m_pattern.match (layout ()->cell (*m_child_cell).get_qualified_name ()))); + } while (! m_child_cell.at_end () && (!layout ()->is_valid_cell_index (*m_child_cell) || !cell_matches (*m_child_cell))); } else { @@ -600,7 +629,7 @@ public: while (m_inst != m_inst_end) { cid = (*m_inst)->object ().cell_index (); - if (layout ()->is_valid_cell_index (cid) && m_pattern.match (layout ()->cell (cid).get_qualified_name ())) { + if (layout ()->is_valid_cell_index (cid) && cell_matches (cid)) { break; } @@ -636,7 +665,7 @@ public: do { ++m_top_cell; - } while (m_top_cell != m_top_cell_end && (!layout ()->is_valid_cell_index (*m_top_cell) || !m_pattern.match (layout ()->cell (*m_top_cell).get_qualified_name ()))); + } while (m_top_cell != m_top_cell_end && (!layout ()->is_valid_cell_index (*m_top_cell) || !cell_matches (*m_top_cell))); } } @@ -1028,6 +1057,7 @@ private: bool m_reading; std::set m_ignored; db::Instance m_i; + db::cell_index_type m_cell_index; }; class DB_PUBLIC ChildCellFilter @@ -1126,11 +1156,30 @@ public: m_pids (pids), m_pattern (pattern, eval), mp_parent (0), - m_reading (reading) + m_reading (reading), + m_cell_index (std::numeric_limits::max ()) { // .. nothing yet .. } + bool cell_matches (db::cell_index_type ci) + { + if (m_pattern.is_catchall ()) { + return true; + } else if (m_cell_index != std::numeric_limits::max ()) { + return ci == db::cell_index_type (m_cell_index); + } else if (m_pattern.is_const ()) { + if (m_pattern.match (layout ()->cell (ci).get_qualified_name ())) { + m_cell_index = ci; + return true; + } else { + return false; + } + } else { + return (m_pattern.match (layout ()->cell (ci).get_qualified_name ())); + } + } + virtual void reset (FilterStateBase *previous) { FilterStateBase::reset (previous); @@ -1140,7 +1189,7 @@ public: m_cell = layout ()->begin_top_down (); m_cell_end = layout ()->end_top_down (); - while (m_cell != m_cell_end && !m_pattern.match (layout ()->cell (*m_cell).get_qualified_name ())) { + while (m_cell != m_cell_end && !cell_matches (*m_cell)) { ++m_cell; } @@ -1158,7 +1207,7 @@ public: { do { ++m_cell; - } while (m_cell != m_cell_end && !m_pattern.match (layout ()->cell (*m_cell).get_qualified_name ())); + } while (m_cell != m_cell_end && !cell_matches (*m_cell)); } virtual bool at_end () @@ -1275,6 +1324,7 @@ private: db::Layout::top_down_const_iterator m_cell, m_cell_end; std::auto_ptr m_cell_counter; bool m_reading; + db::cell_index_type m_cell_index; }; class DB_PUBLIC CellFilter diff --git a/src/tl/tl/tlGlobPattern.cc b/src/tl/tl/tlGlobPattern.cc index bebcb086e..cf27d70cb 100644 --- a/src/tl/tl/tlGlobPattern.cc +++ b/src/tl/tl/tlGlobPattern.cc @@ -108,6 +108,16 @@ public: return op; } + virtual bool is_const () const + { + return false; + } + + virtual bool is_catchall () const + { + return false; + } + virtual bool match (const char *s, std::vector *e) const { size_t n = e ? e->size () : 0; @@ -186,6 +196,11 @@ public: return op; } + virtual bool is_const () const + { + return next () == 0; + } + virtual bool match (const char *s, std::vector *e) const { if (! m_cs) { @@ -240,6 +255,11 @@ public: return op; } + virtual bool is_catchall () const + { + return true; + } + virtual bool match (const char *, std::vector *) const { return true; @@ -811,6 +831,16 @@ GlobPatternOp *GlobPattern::op () const return mp_op; } +bool GlobPattern::is_catchall () const +{ + return op ()->is_catchall (); +} + +bool GlobPattern::is_const () const +{ + return op ()->is_const (); +} + bool GlobPattern::match (const char *s) const { return op ()->match (s, 0); diff --git a/src/tl/tl/tlGlobPattern.h b/src/tl/tl/tlGlobPattern.h index 4b9d8ad44..39283fe07 100644 --- a/src/tl/tl/tlGlobPattern.h +++ b/src/tl/tl/tlGlobPattern.h @@ -106,6 +106,16 @@ public: return m_p; } + /** + * @brief Returns true, if the pattern is a catchall expression ("*") + */ + bool is_catchall () const; + + /** + * @brief Returns true, if the pattern is a const string + */ + bool is_const () const; + /** * @brief Match the given string * diff --git a/src/tl/unit_tests/tlGlobPattern.cc b/src/tl/unit_tests/tlGlobPatternTests.cc similarity index 92% rename from src/tl/unit_tests/tlGlobPattern.cc rename to src/tl/unit_tests/tlGlobPatternTests.cc index d73d5adf7..d53ef95e8 100644 --- a/src/tl/unit_tests/tlGlobPattern.cc +++ b/src/tl/unit_tests/tlGlobPatternTests.cc @@ -30,6 +30,15 @@ TEST(1) tl::GlobPattern a ("*"); tl::GlobPattern b ("a"); + EXPECT_EQ (a.is_catchall (), true); + EXPECT_EQ (a.is_const (), false); + EXPECT_EQ (tl::GlobPattern (a).is_catchall (), true); + EXPECT_EQ (tl::GlobPattern (a).is_const (), false); + EXPECT_EQ (b.is_catchall (), false); + EXPECT_EQ (b.is_const (), true); + EXPECT_EQ (tl::GlobPattern (b).is_catchall (), false); + EXPECT_EQ (tl::GlobPattern (b).is_const (), true); + EXPECT_EQ (a.match ("abc"), true); EXPECT_EQ (a.match ("a"), true); EXPECT_EQ (a.match (""), true); @@ -44,6 +53,13 @@ TEST(2) tl::GlobPattern b ("*a?"); tl::GlobPattern c ("*a\\?"); + EXPECT_EQ (a.is_catchall (), false); + EXPECT_EQ (a.is_const (), false); + EXPECT_EQ (b.is_catchall (), false); + EXPECT_EQ (b.is_const (), false); + EXPECT_EQ (c.is_catchall (), false); + EXPECT_EQ (c.is_const (), false); + EXPECT_EQ (a.match ("abc"), true); EXPECT_EQ (a.match ("a"), true); EXPECT_EQ (a.match (""), false); diff --git a/src/tl/unit_tests/unit_tests.pro b/src/tl/unit_tests/unit_tests.pro index 93c05ecb2..092699eef 100644 --- a/src/tl/unit_tests/unit_tests.pro +++ b/src/tl/unit_tests/unit_tests.pro @@ -15,7 +15,6 @@ SOURCES = \ tlEvents.cc \ tlExpression.cc \ tlFileUtils.cc \ - tlGlobPattern.cc \ tlIntervalMap.cc \ tlIntervalSet.cc \ tlKDTree.cc \ @@ -38,7 +37,8 @@ SOURCES = \ tlUniqueIdTests.cc \ tlListTests.cc \ tlEquivalenceClustersTests.cc \ - tlUniqueNameTests.cc + tlUniqueNameTests.cc \ + tlGlobPatternTests.cc !equals(HAVE_QT, "0") {