Code

store_lookup: Made logical operators public.
authorSebastian Harl <sh@tokkee.org>
Sun, 23 Feb 2014 04:12:05 +0000 (20:12 -0800)
committerSebastian Harl <sh@tokkee.org>
Sun, 23 Feb 2014 04:12:05 +0000 (20:12 -0800)
src/core/store_lookup.c
src/include/core/store.h
t/core/store_lookup_test.c

index 305a513f14dcde6d7d01b54992c5ca24ce9dc39a..d4fef03c39edc9015e37af5ad526d3e80b36c479 100644 (file)
@@ -433,6 +433,32 @@ host_matcher_destroy(sdb_object_t *obj)
        sdb_object_deref(SDB_OBJ(HOST_M(obj)->attr));
 } /* host_matcher_destroy */
 
        sdb_object_deref(SDB_OBJ(HOST_M(obj)->attr));
 } /* host_matcher_destroy */
 
+static int
+op_matcher_init(sdb_object_t *obj, va_list ap)
+{
+       M(obj)->type = va_arg(ap, int);
+       if ((M(obj)->type != MATCHER_OR) && (M(obj)->type != MATCHER_AND))
+               return -1;
+
+       OP_M(obj)->left = va_arg(ap, sdb_store_matcher_t *);
+       sdb_object_ref(SDB_OBJ(OP_M(obj)->left));
+       OP_M(obj)->right = va_arg(ap, sdb_store_matcher_t *);
+       sdb_object_ref(SDB_OBJ(OP_M(obj)->right));
+
+       if ((! OP_M(obj)->left) || (! OP_M(obj)->right))
+               return -1;
+       return 0;
+} /* op_matcher_init */
+
+static void
+op_matcher_destroy(sdb_object_t *obj)
+{
+       if (OP_M(obj)->left)
+               sdb_object_deref(SDB_OBJ(OP_M(obj)->left));
+       if (OP_M(obj)->right)
+               sdb_object_deref(SDB_OBJ(OP_M(obj)->right));
+} /* op_matcher_destroy */
+
 static sdb_type_t attr_type = {
        /* size = */ sizeof(attr_matcher_t),
        /* init = */ attr_matcher_init,
 static sdb_type_t attr_type = {
        /* size = */ sizeof(attr_matcher_t),
        /* init = */ attr_matcher_init,
@@ -451,6 +477,12 @@ static sdb_type_t host_type = {
        /* destroy = */ host_matcher_destroy,
 };
 
        /* destroy = */ host_matcher_destroy,
 };
 
+static sdb_type_t op_type = {
+       /* size = */ sizeof(op_matcher_t),
+       /* init = */ op_matcher_init,
+       /* destroy = */ op_matcher_destroy,
+};
+
 /*
  * public API
  */
 /*
  * public API
  */
@@ -480,6 +512,20 @@ sdb_store_host_matcher(const char *host_name, const char *host_name_re,
                                host_name, host_name_re, service_matcher, attr_matcher));
 } /* sdb_store_host_matcher */
 
                                host_name, host_name_re, service_matcher, attr_matcher));
 } /* sdb_store_host_matcher */
 
+sdb_store_matcher_t *
+sdb_store_dis_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right)
+{
+       return M(sdb_object_create("dis-matcher", op_type, MATCHER_OR,
+                               left, right));
+} /* sdb_store_dis_matcher */
+
+sdb_store_matcher_t *
+sdb_store_con_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right)
+{
+       return M(sdb_object_create("con-matcher", op_type, MATCHER_AND,
+                               left, right));
+} /* sdb_store_con_matcher */
+
 int
 sdb_store_matcher_matches(sdb_store_matcher_t *m, sdb_store_base_t *obj)
 {
 int
 sdb_store_matcher_matches(sdb_store_matcher_t *m, sdb_store_base_t *obj)
 {
index a327ae9d31ebd31744e4ce6d9d0786b0d183ae29..8c46eb740065cccde034cf39cab73e6e037e9c1e 100644 (file)
@@ -168,6 +168,20 @@ sdb_store_host_matcher(const char *host_name, const char *host_name_re,
                sdb_store_matcher_t *service_matcher,
                sdb_store_matcher_t *attr_matcher);
 
                sdb_store_matcher_t *service_matcher,
                sdb_store_matcher_t *attr_matcher);
 
+/*
+ * sdb_store_dis_matcher:
+ * Creates a matcher matching the disjunction (logical OR) of two matchers.
+ */
+sdb_store_matcher_t *
+sdb_store_dis_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right);
+
+/*
+ * sdb_store_con_matcher:
+ * Creates a matcher matching the conjunction (logical AND) of two matchers.
+ */
+sdb_store_matcher_t *
+sdb_store_con_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right);
+
 /*
  * sdb_store_matcher_matches:
  * Check whether the specified matcher matches the specified store object.
 /*
  * sdb_store_matcher_matches:
  * Check whether the specified matcher matches the specified store object.
index 3d567ac606edf35d475526b19447fe1359f64043..48bb4832f4b81e723743d27cefd1c705e40e93a5 100644 (file)
@@ -249,6 +249,72 @@ START_TEST(test_store_match)
 }
 END_TEST
 
 }
 END_TEST
 
+START_TEST(test_store_match_op)
+{
+       sdb_store_base_t *obj;
+
+       sdb_store_matcher_t *always = sdb_store_host_matcher(NULL, NULL, NULL, NULL);
+       sdb_store_matcher_t *never = sdb_store_host_matcher("a", "b", NULL, NULL);
+
+       struct {
+               const char *op;
+               sdb_store_matcher_t *left;
+               sdb_store_matcher_t *right;
+               int expected;
+       } golden_data[] = {
+               { "OR",  always, always,  0 },
+               { "OR",  always, never,   0 },
+               { "OR",  never,  always,  0 },
+               { "OR",  never,  never,  -1 },
+               { "AND", always, always,  0 },
+               { "AND", always, never,  -1 },
+               { "AND", never,  always, -1 },
+               { "AND", never,  never,  -1 },
+       };
+
+       int status;
+       size_t i;
+
+       obj = sdb_store_get_host("a");
+
+       status = sdb_store_matcher_matches(always, obj);
+       fail_unless(status == 0,
+                       "INTERNAL ERROR: 'always' did not match host");
+       status = sdb_store_matcher_matches(never, obj);
+       fail_unless(status < 0,
+                       "INTERNAL ERROR: 'never' matches host");
+
+       for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
+               sdb_store_matcher_t *m;
+
+               if (! strcmp(golden_data[i].op, "OR"))
+                       m = sdb_store_dis_matcher(golden_data[i].left,
+                                       golden_data[i].right);
+               else if (! strcmp(golden_data[i].op, "AND"))
+                       m = sdb_store_con_matcher(golden_data[i].left,
+                                       golden_data[i].right);
+               else
+                       fail("INTERNAL ERROR: unexpected operator %s", golden_data[i].op);
+
+#define TO_NAME(v) (((v) == always) ? "always" \
+               : ((v) == never) ? "never" : "<unknown>")
+
+               status = sdb_store_matcher_matches(m, obj);
+               fail_unless(status == golden_data[i].expected,
+                               "%s(%s, %s) = %d; expected: %d", golden_data[i].op,
+                               TO_NAME(golden_data[i].left), TO_NAME(golden_data[i].right),
+                               status, golden_data[i].expected);
+
+#undef TO_NAME
+
+               sdb_object_deref(SDB_OBJ(m));
+       }
+
+       sdb_object_deref(SDB_OBJ(always));
+       sdb_object_deref(SDB_OBJ(never));
+}
+END_TEST
+
 Suite *
 core_store_lookup_suite(void)
 {
 Suite *
 core_store_lookup_suite(void)
 {
@@ -258,6 +324,7 @@ core_store_lookup_suite(void)
        tc = tcase_create("core");
        tcase_add_checked_fixture(tc, populate, sdb_store_clear);
        tcase_add_test(tc, test_store_match);
        tc = tcase_create("core");
        tcase_add_checked_fixture(tc, populate, sdb_store_clear);
        tcase_add_test(tc, test_store_match);
+       tcase_add_test(tc, test_store_match_op);
        suite_add_tcase(s, tc);
 
        return s;
        suite_add_tcase(s, tc);
 
        return s;