]> git.tdb.fi Git - poefilter.git/commitdiff
Merge and conditions if they only differ in one sub-condition
authorMikko Rasa <tdb@tdb.fi>
Fri, 17 Aug 2018 17:26:51 +0000 (20:26 +0300)
committerMikko Rasa <tdb@tdb.fi>
Fri, 17 Aug 2018 17:26:51 +0000 (20:26 +0300)
source/condition.cpp
source/condition.h

index e9400c4c2721fe07ec4510db2ccb916d96119daa..5978250243f6e51b6fb1ebadeadbbd401f5003bf 100644 (file)
@@ -216,7 +216,7 @@ Condition *AndCondition::flatten(OrCondition *cond1, Condition *cond2) const
        unsigned count = cond1->count();
        for(unsigned i=0; i<count; ++i)
                if(Condition *sub = dispatch_flatten(cond1->get(i).clone(), (i+1<count ? cond2->clone() : cond2)))
-                       result->add(sub);
+                       add_merged_to(sub, result, true);
        delete cond1;
 
        if(result->is_viable())
@@ -239,7 +239,7 @@ Condition *AndCondition::flatten(OrCondition *cond1, OrCondition *cond2) const
        for(unsigned i=0; i<count1; ++i)
                for(unsigned j=0; j<count2; ++j)
                        if(Condition *sub = dispatch_flatten(cond1->get(i).clone(), cond2->get(j).clone()))
-                               result->add(sub);
+                               add_merged_to(sub, result, true);
 
        delete cond1;
        delete cond2;
@@ -251,6 +251,82 @@ Condition *AndCondition::flatten(OrCondition *cond1, OrCondition *cond2) const
        return 0;
 }
 
+bool AndCondition::can_merge(const Condition &other, const CompoundCondition &parent) const
+{
+       const AndCondition *other_and = dynamic_cast<const AndCondition *>(&other);
+       if(!other_and || !dynamic_cast<const OrCondition *>(&parent))
+               return false;
+
+       return merge(*this, *other_and, parent, 0);
+}
+
+AndCondition *AndCondition::merge(const vector<const Condition *> &conds, const CompoundCondition &parent) const
+{
+       if(conds.size()!=2)
+               return 0;
+
+       const AndCondition *and1 = dynamic_cast<const AndCondition *>(conds[0]);
+       const AndCondition *and2 = dynamic_cast<const AndCondition *>(conds[1]);
+       if(!and1 || !and2 || !dynamic_cast<const OrCondition *>(&parent))
+               return 0;
+
+       AndCondition *result = 0;
+       merge(*and1, *and2, parent, &result);
+       return result;
+}
+
+bool AndCondition::merge(const AndCondition &cond1, const AndCondition &cond2, const CompoundCondition &parent, AndCondition **result)
+{
+       if(cond1.count()!=cond2.count())
+               return false;
+
+       int merge1 = -1;
+       vector<bool> used(cond1.count(), false);
+       for(unsigned i=0; i<cond1.count(); ++i)
+       {
+               int match = -1;
+               for(unsigned j=0; (match<0 && j<cond2.count()); ++j)
+                       if(!used[j] && cond1.get(i).equals(cond2.get(j)))
+                               match = j;
+
+               if(match>=0)
+                       used[match] = true;
+               else if(merge1<0)
+                       merge1 = i;
+               else
+                       return false;
+       }
+
+       if(merge1>=0)
+       {
+               vector<const Condition *> merge_conds(2, 0);
+               merge_conds[0] = &cond1.get(merge1);
+               for(unsigned i=0; (!merge_conds[1] && i<cond2.count()); ++i)
+                       if(!used[i])
+                               merge_conds[1] = &cond2.get(i);
+
+               if(!merge_conds[1] || !merge_conds[0]->can_merge(*merge_conds[1], parent))
+                       return false;
+
+               if(result)
+               {
+                       *result = new AndCondition;
+                       (*result)->add(merge_conds[0]->merge(merge_conds, parent));
+               }
+       }
+       else if(result)
+               *result = new AndCondition;
+
+       if(result)
+       {
+               for(unsigned i=0; i<cond2.count(); ++i)
+                       if(used[i])
+                               (*result)->add(cond2.get(i).clone());
+       }
+
+       return true;
+}
+
 bool AndCondition::is_viable() const
 {
        for(vector<Condition *>::const_iterator i=conditions.begin(); i!=conditions.end(); ++i)
index 9d945c78eec8ffa3c123fb4ea9e8fdb3e42ef978..6b0cf6bda2831109cc7ef38b66fb08abf8a1bf7f 100644 (file)
@@ -74,6 +74,11 @@ protected:
        virtual Condition *flatten(OrCondition *, Condition *) const;
        virtual Condition *flatten(OrCondition *, AndCondition *) const;
        virtual Condition *flatten(OrCondition *, OrCondition *) const;
+public:
+       virtual bool can_merge(const Condition &, const CompoundCondition &) const;
+       virtual AndCondition *merge(const std::vector<const Condition *> &, const CompoundCondition &) const;
+private:
+       static bool merge(const AndCondition &, const AndCondition &, const CompoundCondition &, AndCondition **);
 public:
        virtual bool is_viable() const;
        virtual void add_lines(std::list<FilterStatement> &) const;