val_same() compares passed @v1 and @v2 and returns 1 if they are same, 0 if not and 999 in case their types not comparable.
Change pm_path_compare() to return 1 - if @m1 and @m2 are the same and 0 overwise. Rename pm_path_compare() to pm_path_same() according to its return values. Use it in val_same() to compare path masks. --- filter/filter.c | 102 +++++++++++++++++++++++++++++-------------------------- filter/filter.h | 1 + 2 files changed, 54 insertions(+), 49 deletions(-) diff --git a/filter/filter.c b/filter/filter.c index 6f59193..c089d94 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -58,20 +58,6 @@ adata_empty(struct linpool *pool, int l) return res; } -static int -pm_path_compare(struct f_path_mask *m1, struct f_path_mask *m2) -{ - while (1) { - if ((!m1) || (!m2)) - return !((!m1) && (!m2)); - - /* FIXME: buggy, should return -1, 0, 1; but it doesn't matter */ - if ((m1->kind != m2->kind) || (m1->val != m2->val)) return 1; - m1 = m1->next; - m2 = m2->next; - } -} - u32 f_eval_asn(struct f_inst *expr); static void @@ -247,8 +233,6 @@ val_compare(struct f_val v1, struct f_val v2) if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip)) return rc; return int_cmp(v1.val.px.len, v2.val.px.len); - case T_PATH_MASK: - return pm_path_compare(v1.val.path_mask, v2.val.path_mask); case T_STRING: return strcmp(v1.val.s, v2.val.s); case T_CLIST: @@ -259,7 +243,50 @@ val_compare(struct f_val v1, struct f_val v2) case T_VOID: return 0; default: - debug( "Compare of unknown entities: %x\n", v1.type ); + return CMP_ERROR; + } +} + +static int +pm_path_same(struct f_path_mask *m1, struct f_path_mask *m2) +{ + while (1) { + if ((!m1) || (!m2)) + return (!m1) && (!m2); + + if ((m1->kind != m2->kind) || (m1->val != m2->val)) + return 0; + + m1 = m1->next; + m2 = m2->next; + } +} + +/** + * val_same - compare two values + * @v1: first value + * @v2: second value + * + * Compares two values and returns 1 if they are same, 0 if not + * and 999 on error. + */ +int +val_same(struct f_val v1, struct f_val v2) +{ + int rc; + + rc = val_compare(v1, v2); + if (rc != CMP_ERROR) + return !rc; + + switch (v1.type) { + case T_PATH_MASK: + return pm_path_same(v1.val.path_mask, v2.val.path_mask); + case T_SET: + return same_tree(v1.val.t, v2.val.t); + case T_PREFIX_SET: + return trie_same(v1.val.ti, v2.val.ti); + default: return CMP_ERROR; } } @@ -776,19 +803,19 @@ interpret(struct f_inst *what) /* Relational operators */ -#define COMPARE(x) \ +#define COMPARE(f,x) \ TWOARGS; \ - i = val_compare(v1, v2); \ - if (i==CMP_ERROR) \ + i = f(v1, v2); \ + if (i == CMP_ERROR) \ runtime( "Can't compare values of incompatible types" ); \ res.type = T_BOOL; \ res.val.i = (x); \ break; - case P('!','='): COMPARE(i!=0); - case P('=','='): COMPARE(i==0); - case '<': COMPARE(i==-1); - case P('<','='): COMPARE(i!=1); + case P('!','='): COMPARE(val_same, i == 0); + case P('=','='): COMPARE(val_same, i != 0); + case '<': COMPARE(val_compare, i < 0); + case P('<','='): COMPARE(val_compare, i <= 0); case '!': ONEARG; @@ -1478,31 +1505,8 @@ i_same(struct f_inst *f1, struct f_inst *f2) } break; case 'C': - { - struct f_val *v1 = (struct f_val *) f1->a1.p; - struct f_val *v2 = (struct f_val *) f2->a1.p; - - /* Handle some cases that are not handled by val_compare() - also T_PATH, T_CLIST and T_ECLIST does not work, - but you cannot easily create such constants */ - - if ((v1->type == T_SET) && (v2->type == T_SET)) - { - if (!same_tree(v1->val.t, v2->val.t)) - return 0; - break; - } - - if ((v1->type == T_PREFIX_SET) && (v2->type == T_PREFIX_SET)) - { - if (!trie_same(v1->val.ti, v2->val.ti)) - return 0; - break; - } - - if (val_compare(*v1 , *v2)) - return 0; - } + if (!val_same(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p)) + return 0; break; case 'V': if (strcmp((char *) f1->a2.p, (char *) f2->a2.p)) diff --git a/filter/filter.h b/filter/filter.h index dcac825..a3de530 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -116,6 +116,7 @@ int filter_same(struct filter *new, struct filter *old); int i_same(struct f_inst *f1, struct f_inst *f2); int val_compare(struct f_val v1, struct f_val v2); +int val_same(struct f_val v1, struct f_val v2); int tree_compare(const void *p1, const void *p2); void val_print(struct f_val v); -- 1.7.10.4