X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fcondition.cpp;h=e9400c4c2721fe07ec4510db2ccb916d96119daa;hb=7d7eaf754af04f81bb1e7a8872272ea15e01d0c4;hp=42e9ee8f3f1360829d2b518d9d22e99a569f0a69;hpb=8b9d1f472e7bfbb1e097bb6d8bcad026e9636822;p=poefilter.git diff --git a/source/condition.cpp b/source/condition.cpp index 42e9ee8..e9400c4 100644 --- a/source/condition.cpp +++ b/source/condition.cpp @@ -16,16 +16,30 @@ void CompoundCondition::clone_to(CompoundCondition &other) const other.add((*i)->clone()); } +bool CompoundCondition::sub_equals(const CompoundCondition &other) const +{ + if(other.count()!=conditions.size()) + return false; + + for(unsigned i=0; iequals(other.get(i))) + return false; + + return true; +} + void CompoundCondition::add(Condition *cond) { + if(!cond) + throw invalid_argument("CompoundCondition::add"); conditions.push_back(cond); } -const Condition *CompoundCondition::get(unsigned i) const +const Condition &CompoundCondition::get(unsigned i) const { if(i>=conditions.size()) throw out_of_range("CompoundCondition::get"); - return conditions[i]; + return *conditions[i]; } Condition *CompoundCondition::flatten() const @@ -40,7 +54,10 @@ Condition *CompoundCondition::flatten() const merge = conditions.front()->can_merge(**i, *this); if(merge) - return conditions.front()->merge(conditions, *this); + { + vector merge_conds(conditions.begin(), conditions.end()); + return conditions.front()->merge(merge_conds, *this); + } else { Condition *result = 0; @@ -49,11 +66,15 @@ Condition *CompoundCondition::flatten() const Condition *sub = (*i)->flatten(); if(!result) result = sub; - else + else if(sub) result = dispatch_flatten(result, sub); } - return result; + if(result && result->is_viable()) + return result; + + delete result; + return 0; } } @@ -91,6 +112,69 @@ Condition *CompoundCondition::dispatch_flatten(Condition *cond1, Condition *cond throw logic_error("CompoundCondition::dispatch_flatten"); } +Condition *CompoundCondition::merge_two(Condition *cond1, Condition *cond2, const CompoundCondition &parent, bool del) +{ + vector parts(2); + parts[0] = cond1; + parts[1] = cond2; + Condition *result = cond1->merge(parts, parent); + + if(del) + { + delete cond1; + delete cond2; + + if(!result->is_viable()) + { + delete result; + return 0; + } + } + + return result; +} + +Condition *CompoundCondition::add_merged_to(Condition *cond, CompoundCondition *target, bool del) +{ + bool merged = false; + for(vector::iterator i=target->conditions.begin(); i!=target->conditions.end(); ++i) + if((*i)->can_merge(*cond, *target)) + { + Condition *m = merge_two(cond, *i, *target, false); + delete *i; + if(del) + delete cond; + *i = m; + merged = true; + break; + } + + if(!merged) + target->add(del ? cond : cond->clone()); + + if(del && !target->is_viable()) + { + delete target; + return 0; + } + + return target; +} + +Condition *CompoundCondition::merge_contents_to(CompoundCondition *cond, CompoundCondition *target) +{ + for(vector::iterator i=cond->conditions.begin(); i!=cond->conditions.end(); ++i) + add_merged_to(*i, target, false); + + delete cond; + + if(target->is_viable()) + return target; + + delete target; + return 0; +} + AndCondition *AndCondition::clone() const { @@ -99,8 +183,17 @@ AndCondition *AndCondition::clone() const return result; } +bool AndCondition::equals(const Condition &other) const +{ + const AndCondition *other_and = dynamic_cast(&other); + return (other_and ? sub_equals(*other_and) : false); +} + Condition *AndCondition::flatten(Condition *cond1, Condition *cond2) const { + if(cond1->can_merge(*cond2, *this)) + return merge_two(cond1, cond2, *this, true); + AndCondition *result = new AndCondition; result->add(cond1); result->add(cond2); @@ -109,17 +202,12 @@ Condition *AndCondition::flatten(Condition *cond1, Condition *cond2) const Condition *AndCondition::flatten(AndCondition *cond1, Condition *cond2) const { - cond1->add(cond2); - return cond1; + return add_merged_to(cond2, cond1, true); } Condition *AndCondition::flatten(AndCondition *cond1, AndCondition *cond2) const { - unsigned count2 = cond2->count(); - for(unsigned i=0; iadd(cond2->get(i)->clone()); - delete cond2; - return cond1; + return merge_contents_to(cond2, cond1); } Condition *AndCondition::flatten(OrCondition *cond1, Condition *cond2) const @@ -127,9 +215,15 @@ Condition *AndCondition::flatten(OrCondition *cond1, Condition *cond2) const OrCondition *result = new OrCondition; unsigned count = cond1->count(); for(unsigned i=0; iadd(dispatch_flatten(cond1->get(i)->clone(), (i+1clone() : cond2))); + if(Condition *sub = dispatch_flatten(cond1->get(i).clone(), (i+1clone() : cond2))) + result->add(sub); delete cond1; - return result; + + if(result->is_viable()) + return result; + + delete result; + return 0; } Condition *AndCondition::flatten(OrCondition *cond1, AndCondition *cond2) const @@ -144,10 +238,25 @@ Condition *AndCondition::flatten(OrCondition *cond1, OrCondition *cond2) const OrCondition *result = new OrCondition; for(unsigned i=0; iadd(dispatch_flatten(cond1->get(i)->clone(), cond2->get(j)->clone())); + if(Condition *sub = dispatch_flatten(cond1->get(i).clone(), cond2->get(j).clone())) + result->add(sub); + delete cond1; delete cond2; - return result; + + if(result->is_viable()) + return result; + + delete result; + return 0; +} + +bool AndCondition::is_viable() const +{ + for(vector::const_iterator i=conditions.begin(); i!=conditions.end(); ++i) + if(!(*i)->is_viable()) + return false; + return !conditions.empty(); } void AndCondition::add_lines(list &st) const @@ -164,8 +273,17 @@ OrCondition *OrCondition::clone() const return result; } +bool OrCondition::equals(const Condition &other) const +{ + const OrCondition *other_or = dynamic_cast(&other); + return (other_or ? sub_equals(*other_or) : false); +} + Condition *OrCondition::flatten(Condition *cond1, Condition *cond2) const { + if(cond1->can_merge(*cond2, *this)) + return merge_two(cond1, cond2, *this, true); + OrCondition *result = new OrCondition; result->add(cond1); result->add(cond2); @@ -184,8 +302,7 @@ Condition *OrCondition::flatten(AndCondition *cond1, AndCondition *cond2) const Condition *OrCondition::flatten(OrCondition *cond1, Condition *cond2) const { - cond1->add(cond2); - return cond1; + return add_merged_to(cond2, cond1, true); } Condition *OrCondition::flatten(OrCondition *cond1, AndCondition *cond2) const @@ -195,11 +312,15 @@ Condition *OrCondition::flatten(OrCondition *cond1, AndCondition *cond2) const Condition *OrCondition::flatten(OrCondition *cond1, OrCondition *cond2) const { - unsigned count2 = cond2->count(); - for(unsigned i=0; iadd(cond2->get(i)->clone()); - delete cond2; - return cond1; + return merge_contents_to(cond2, cond1); +} + +bool OrCondition::is_viable() const +{ + for(vector::const_iterator i=conditions.begin(); i!=conditions.end(); ++i) + if((*i)->is_viable()) + return true; + return false; } void OrCondition::add_lines(list &st) const @@ -224,6 +345,23 @@ LinkedColorsCondition *LinkedColorsCondition::clone() const return new LinkedColorsCondition(colors); } +bool LinkedColorsCondition::equals(const Condition &other) const +{ + const LinkedColorsCondition *other_linked = dynamic_cast(&other); + if(!other_linked) + return false; + + for(unsigned i=0; i<7; ++i) + { + if(colors.colors[i]!=other_linked->colors.colors[i]) + return false; + if(!colors.colors[i]) + break; + } + + return true; +} + void LinkedColorsCondition::add_lines(list &st) const { FilterStatement::add_line(st, format("SocketGroup %s", colors.colors));