[PATCH 03/12] Introduce and use val_same() to decide if values are same or not

Sergey Popovich popovich_sergei at mail.ru
Mon Sep 30 20:27:24 CEST 2013


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



More information about the Bird-users mailing list